2015-09-01 31 views
7

Tüm http isteklerini ve yanıtlarını günlüğe kaydetmek için bir parça özel OWIN katman yazılımı yazıyorum. Bunları bir trackingId ile ilişkilendirmek istiyorum.OWIN ara katman yazılımı mı?

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; 
    } 
} 

ben cevap başlığında http izleme-id ekleyerek (bu satırları burada) sorun yaşıyorum: İşte kodudur.

HttpException was unhandled by user code.

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


Edit 1: ben sadece benim http://localhost:64051/ adrese krom açar api, çalıştırarak bu test ediyorum başlığı eklerken

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); 

Bazen bu hatayı alabilirsiniz . Örneğin, herhangi bir gerçek API'ye (http://localhost:64051/api/Accounts/21067) göz atarsam, hatayı alamıyorum. Bir şekilde sitenin köküne göz atarken 404'ü geri yollamalı mıyım?

+0

Bunu okuduğumdan, eğer OWIN boru hattının dışında bir şey başlıkları zaten göndermişse, bu durum gerçekleşebilir. Yanıtı durduran ve biten eski bir ASPX sayfası olabilir. – Sneal

cevap

1

Basit bir düzeltme olabileceğini düşünüyorum. Lütfen, context.Response.OnSendingHeaders numaralı telefondan değil,

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

deneyin. Geri kalan ile sadece inline.

+0

Bu harika çalışıyor. Çok teşekkürler. Bunu hayatım boyunca çözemedim ve çok basit çıktı. Tekrar teşekkürler! – BBauer42

İlgili konular