public async override Task Invoke(IOwinContext context) { //to intercept MVC responses, because they don't go through OWIN HttpResponse httpResponse = HttpContext.Current.Response; OutputCaptureStream outputCapture = new OutputCaptureStream(httpResponse.Filter); httpResponse.Filter = outputCapture; IOwinResponse owinResponse = context.Response; //buffer the response stream in order to intercept downstream writes Stream owinResponseStream = owinResponse.Body; owinResponse.Body = new MemoryStream(); await Next.Invoke(context); if (outputCapture.CapturedData.Length == 0) { //response is formed by OWIN //make sure the response we buffered is flushed to the client owinResponse.Body.Position = 0; await owinResponse.Body.CopyToAsync(owinResponseStream); } else { //response by MVC //write captured data to response body as if it was written by OWIN outputCapture.CapturedData.Position = 0; outputCapture.CapturedData.CopyTo(owinResponse.Body); } LogResponse(owinResponse); }
public override async Task Invoke(IOwinContext context) { HttpResponse httpResponse = HttpContext.Current.Response; OutputCaptureStream outputCapture = new OutputCaptureStream(httpResponse.Filter); httpResponse.Filter = outputCapture; IOwinResponse owinResponse = context.Response; //buffer the response stream in order to intercept downstream writes Stream owinResponseStream = owinResponse.Body; owinResponse.Body = new MemoryStream(); //开始记录 var requestLog = new ApiRequest(); HttpContext.Current.Items["api_request"] = requestLog; requestLog.Headers = context.Request.Headers; requestLog.URI = context.Request.Path.ToString(); requestLog.QueryString = context.Request.QueryString.HasValue ? context.Request.QueryString.Value : ""; using (var sr = new StreamReader(context.Request.Body)) { requestLog.RequestParams = sr.ReadToEnd(); } requestLog.Method = context.Request.Method; var wathch = new Stopwatch(); wathch.Start(); await Next.Invoke(context); if (outputCapture.CapturedData.Length == 0) { //response is formed by OWIN //make sure the response we buffered is flushed to the client owinResponse.Body.Position = 0; await owinResponse.Body.CopyToAsync(owinResponseStream); } else { //response by MVC //write captured data to response body as if it was written by OWIN outputCapture.CapturedData.Position = 0; outputCapture.CapturedData.CopyTo(owinResponse.Body); } byte[] b = ((MemoryStream)owinResponse.Body).ToArray(); requestLog.Result = System.Text.Encoding.UTF8.GetString(b, 0, b.Length); requestLog.Status = context.Response.StatusCode; wathch.Stop(); requestLog.ElapsedTime = wathch.Elapsed.TotalMilliseconds; Log(requestLog); }
public async override Task Invoke(IOwinContext context) { using (var stream = context.Response.Body) { using (var buffer = new MemoryStream()) { context.Response.Body = buffer; HttpResponse httpResponse = HttpContext.Current.Response; OutputCaptureStream outputCapture = new OutputCaptureStream(httpResponse.Filter); httpResponse.Filter = outputCapture; if (_options.Script.UseNonce || _options.Style.UseNonce) { _options.Nonce = createNonce(); context.Set <string>(_options.Nonce, "ScriptNonce"); } addCspHeaders(context, _options); await Next.Invoke(context); string currentNonce = _options.Nonce; var isHtml = context.Response.ContentType?.ToLower().Contains("text/html"); if (context.Response.StatusCode == 200 && isHtml.GetValueOrDefault()) { var capturedStream = outputCapture.CapturedData; capturedStream.Seek(0, SeekOrigin.Begin); using (var reader = new StreamReader(capturedStream)) { string responseBody = await reader.ReadToEndAsync(); if (responseBody != "") { string domSelector; HtmlDocument responsePage = new HtmlDocument(); capturedStream.Seek(0, SeekOrigin.Begin); responsePage.Load(capturedStream); domSelector = "//*[@data-nonceSecret]"; if (_options.Script.UseNonce) { domSelector += " | //script"; } if (_options.Style.UseNonce) { domSelector += " | //style | //link[@as='style'] | //link[@rel='stylesheet']"; } HtmlNodeCollection nodeCollection = responsePage.DocumentNode.SelectNodes(domSelector); if (nodeCollection != null) { foreach (HtmlNode currentNode in nodeCollection) { if (_options.NonceSecret != null) { if (currentNode.GetAttributeValue("data-nonceSecret", null) == _options.NonceSecret) { if (_options.Script.UseNonce) { if (currentNode.Name == "script") { currentNode.SetAttributeValue("nonce", currentNonce); } } if (_options.Style.UseNonce) { if (currentNode.Name == "link" || currentNode.Name == "style") { currentNode.SetAttributeValue("nonce", currentNonce); } } } } else { if (_options.Script.UseNonce) { if (currentNode.Name == "script") { currentNode.SetAttributeValue("nonce", currentNonce); } } if (_options.Style.UseNonce) { if (currentNode.Name == "link" || currentNode.Name == "style") { currentNode.SetAttributeValue("nonce", currentNonce); } } } if (currentNode.Attributes.Contains("data-nonceSecret")) { currentNode.Attributes["data-nonceSecret"].Remove(); } } } MemoryStream newOutputStream = new MemoryStream(); httpResponse.Clear(); responsePage.Save(newOutputStream); newOutputStream.Seek(0, SeekOrigin.Begin); newOutputStream.CopyTo(stream); } } } } } }