2015-09-01 7 views
7

मैं सभी http अनुरोधों और उनके उत्तरों को लॉग इन करने के लिए कस्टम ओविन मिडलवेयर का एक टुकड़ा लिख ​​रहा हूं। मैं ट्रैकिंग आईडी के साथ इन्हें "सहसंबंध" करना चाहता हूं। यहां कोड है:OWIN मिडलवेयर सहसंबंध और लॉग और अनुरोध लॉग इन करने के लिए?

public class PacketTrackingMiddleware 
{ 
    private readonly AppFunc _next; 

    public PacketTrackingMiddleware(AppFunc next) 
    { 
     _next = next; 
    } 

    public async Task Invoke(IDictionary<string, object> environment) 
    { 
     IOwinContext context = new OwinContext(environment);    
     var request = context.Request; 
     var response = context.Response; 

     //capture details about the caller identity 

     var identity = (request.User != null && request.User.Identity.IsAuthenticated) 
      ? request.User.Identity.Name 
      : "(anonymous)"; 

     var apiPacket = new ApiPacket 
     { 
      CallerIdentity = identity 
     }; 

     //buffer the request stream in order to intercept downstream reads 
     var requestBuffer = new MemoryStream(); 
     request.Body = requestBuffer; 

     //buffer the response stream in order to intercept downstream writes 
     var responseStream = response.Body; 
     var responseBuffer = new MemoryStream(); 
     response.Body = responseBuffer; 

     //add the "Http-Tracking-Id" response header 
     context.Response.OnSendingHeaders(state => 
     { 
      var ctx = state as IOwinContext; 
      if (ctx == null) return; 
      var resp = ctx.Response; 

      //adding the tracking id response header so that the user 
      //of the API can correlate the call back to this entry 
      resp.Headers.Add("http-tracking-id", new[] { apiPacket.TrackingId.ToString("d") }); 
     }, context); 

     //invoke the next middleware in the pipeline 
     await _next.Invoke(environment); 

     //rewind the request and response buffers to record their content 
     WriteRequestHeaders(request, apiPacket); 
     requestBuffer.Seek(0, SeekOrigin.Begin); 
     var requestReader = new StreamReader(requestBuffer); 
     apiPacket.Request = await requestReader.ReadToEndAsync(); 

     WriteResponseHeaders(response, apiPacket); 
     responseBuffer.Seek(0, SeekOrigin.Begin); 
     var reader = new StreamReader(responseBuffer); 
     apiPacket.Response = await reader.ReadToEndAsync(); 

     //write the apiPacket to the database 
     //await database.InsterRecordAsync(apiPacket); 
     System.Diagnostics.Debug.WriteLine("TrackingId: " + apiPacket.TrackingId); 

     //make sure the response we buffered is flushed to the client 
     responseBuffer.Seek(0, SeekOrigin.Begin); 
     await responseBuffer.CopyToAsync(responseStream); 
    } 
    private static void WriteRequestHeaders(IOwinRequest request, ApiPacket packet) 
    { 
     packet.Verb = request.Method; 
     packet.RequestUri = request.Uri; 
     packet.RequestHeaders = request.Headers; 
    } 
    private static void WriteResponseHeaders(IOwinResponse response, ApiPacket packet) 
    { 
     packet.StatusCode = response.StatusCode; 
     packet.ReasonPhrase = response.ReasonPhrase; 
     packet.ResponseHeaders = response.Headers; 
    } 
} 

मुझे प्रतिक्रिया शीर्षलेख (यहां इन पंक्तियों) में http-ट्रैकिंग-आईडी जोड़ने में समस्या हो रही है।

HttpException was unhandled by user code.

Additional information: Server cannot append header after HTTP headers have been sent.


संपादित करें: 1: मैं बस एपीआई, जो मेरी http://localhost:64051/ पता करने के लिए क्रोम खोलता चलाकर इस परीक्षण कर रहा हूँ

context.Response.OnSendingHeaders(state => 
{ 
    var ctx = state as IOwinContext; 
    if (ctx == null) return; 
    var resp = ctx.Response; 

    resp.Headers.Add("http-tracking-id", new[] { apiPacket.TrackingId.ToString("d") }); 
}, context); 

जब हेडर को जोड़े मैं कभी कभी यह त्रुटि प्राप्त । यदि मैं किसी भी वास्तविक API (http://localhost:64051/api/Accounts/21067) पर ब्राउज़ करता हूं उदाहरण के लिए, मुझे त्रुटि प्राप्त नहीं होती है। साइट की जड़ पर ब्राउज़ करते समय क्या मुझे किसी 404 को वापस भेजना चाहिए?

+0

जो मैंने पढ़ा है, उससे यह हो सकता है कि ओविन पाइपलाइन के बाहर कुछ पहले से ही हेडर भेज चुका है। शायद एक विरासत एएसपीएक्स पृष्ठ फ्लशिंग और प्रतिक्रिया समाप्त हो रहा है। – Sneal

उत्तर

1

मुझे लगता है कि यह एक साधारण फिक्स हो सकता है। कृपया प्रयास करें:

var responseHeaders = (IDictionary<string, string[]>)environment["owin.ResponseHeaders"]; 
responseHeaders["http-tracking-id"] = new[] {apiPacket.TrackingId.ToString("d")}; 

लेकिन context.Response.OnSendingHeaders में नहीं। बाकी के साथ बस इनलाइन करें।

+0

यह बहुत अच्छा काम करता है। बहुत बहुत धन्यवाद। मैं इसे अपने जीवन के लिए हल नहीं कर सका और यह पता चला कि यह काफी सरल था। एक बार फिर धन्यवाद! – BBauer42

संबंधित मुद्दे