/// <summary> /// Processes the incoming HTTP call and capture details about /// the request, the response, the identity of the caller and the /// call duration to persistent storage. /// </summary> /// <param name="context">A reference to the Owin context.</param> /// <returns /> public override async Task Invoke(IOwinContext context) { 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 record = new HttpEntry { CallerIdentity = identity, }; // replace the request stream in order to intercept downstream reads var requestBuffer = new MemoryStream(); var requestStream = new ContentStream(requestBuffer, request.Body); request.Body = requestStream; // replace the response stream in order to intercept downstream writes var responseBuffer = new MemoryStream(); var responseStream = new ContentStream(responseBuffer, response.Body); response.Body = responseStream; // 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(_trackingIdPropertyName, new[] { record.LoggingId.ToString("d"), }); }, context); // invoke the next middleware in the pipeline await Next.Invoke(context); // rewind the request and response buffers // and record their content WriteRequestHeaders(request, record); record.RequestLength = requestStream.ContentLength; record.Request = await WriteContentAsync(requestStream, record.RequestHeaders, _maxRequestLength); WriteResponseHeaders(response, record); record.ResponseLength = responseStream.ContentLength; record.Response = await WriteContentAsync(responseStream, record.ResponseHeaders, _maxResponseLength); // persist details of the call to durable storage await HttpLoggingStore.InsertRecordAsync(record); }
private static async Task<string> WriteContentAsync(ContentStream stream, IDictionary<string, string[]> headers, long maxLength) { var contentType = headers.ContainsKey(ContentType) ? headers[ContentType][0] : null ; return await stream.ReadContentAsync(contentType, maxLength); }