繁体   English   中英

OWIN中间件来关联和记录请求和响应?

[英]OWIN middleware to correlate and log requests and responses?

我正在编写一个自定义OWIN中间件来记录所有http请求及其响应。 我想用trackingId“关联”这些。 这是代码:

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-tracking-id添加到响应头(这里是这些行)时遇到了麻烦。

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

添加标题时,我有时会收到此错误:

HttpException未被用户代码处理。

附加信息:在发送HTTP标头后,服务器无法附加标头。


编辑1:我正在测试这个,只需运行api,打开chrome到我的http:// localhost:64051 / address。 例如,如果我浏览到任何实际的API( http:// localhost:64051 / api / Accounts / 21067 ),我就不会收到错误。 浏览到网站的根目录时,我应该以某种方式发回404吗?

我认为这可能是一个简单的修复。 请试试:

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

但不是在context.Response.OnSendingHeaders 与其他人一致。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM