public async Task AllowedResponseHeadersModify() { var options = CreateOptionsAccessor(); options.CurrentValue.LoggingFields = HttpLoggingFields.ResponseHeaders; options.CurrentValue.ResponseHeaders.Clear(); options.CurrentValue.ResponseHeaders.Add("Test"); var middleware = new HttpLoggingMiddleware( c => { c.Response.Headers["Test"] = "Kestrel"; c.Response.Headers["Server"] = "Kestrel"; return(Task.CompletedTask); }, options, LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); await middleware.Invoke(httpContext); Assert.Contains(TestSink.Writes, w => w.Message.Contains("Test: Kestrel")); Assert.Contains(TestSink.Writes, w => w.Message.Contains("Server: [Redacted]")); }
public async Task PartialReadBodyStillLogs() { var input = string.Concat(new string('a', 60000), new string('b', 3000)); var options = CreateOptionsAccessor(); options.CurrentValue.LoggingFields = HttpLoggingFields.RequestBody; var middleware = new HttpLoggingMiddleware( async c => { var arr = new byte[4096]; var res = await c.Request.Body.ReadAsync(arr); }, options, LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); httpContext.Request.ContentType = "text/plain"; httpContext.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(input)); await middleware.Invoke(httpContext); var expected = input.Substring(0, 4096); Assert.Contains(TestSink.Writes, w => w.Message.Equals("RequestBody: " + expected)); }
public async Task ResponseHeadersLogs() { var options = CreateOptionsAccessor(); options.CurrentValue.LoggingFields = HttpLoggingFields.ResponseHeaders; var middleware = new HttpLoggingMiddleware( async c => { c.Response.StatusCode = 200; c.Response.Headers[HeaderNames.TransferEncoding] = "test"; c.Response.ContentType = "text/plain"; await c.Response.WriteAsync("test"); }, options, LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); await middleware.Invoke(httpContext); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("StatusCode: 200")); Assert.Contains(TestSink.Writes, w => w.Message.Contains("Transfer-Encoding: test")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("Body: test")); }
public async Task VerifyDefaultMediaTypeHeaders(string contentType) { // media headers that should work. var expected = new string('a', 1000); var options = CreateOptionsAccessor(); options.CurrentValue.LoggingFields = HttpLoggingFields.RequestBody; var middleware = new HttpLoggingMiddleware( async c => { var arr = new byte[4096]; while (true) { var res = await c.Request.Body.ReadAsync(arr); if (res == 0) { break; } } }, options, LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); httpContext.Request.ContentType = contentType; httpContext.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(expected)); await middleware.Invoke(httpContext); Assert.Contains(TestSink.Writes, w => w.Message.Contains(expected)); }
public async Task RequestBodyReadingWorks(string expected) { var options = CreateOptionsAccessor(); options.CurrentValue.LoggingFields = HttpLoggingFields.RequestBody; var middleware = new HttpLoggingMiddleware( async c => { var arr = new byte[4096]; while (true) { var res = await c.Request.Body.ReadAsync(arr); if (res == 0) { break; } } }, options, LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); httpContext.Request.ContentType = "text/plain"; httpContext.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(expected)); await middleware.Invoke(httpContext); Assert.Contains(TestSink.Writes, w => w.Message.Contains(expected)); }
public async Task CanConfigureRequestAllowList() { var options = CreateOptionsAccessor(); options.CurrentValue.RequestHeaders.Clear(); options.CurrentValue.RequestHeaders.Add("foo"); var middleware = new HttpLoggingMiddleware( c => { return(Task.CompletedTask); }, options, LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); // Header on the default allow list. httpContext.Request.Headers["Connection"] = "keep-alive"; httpContext.Request.Headers["foo"] = "bar"; await middleware.Invoke(httpContext); Assert.Contains(TestSink.Writes, w => w.Message.Contains("foo: bar")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("foo: [Redacted]")); Assert.Contains(TestSink.Writes, w => w.Message.Contains("Connection: [Redacted]")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("Connection: keep-alive")); }
public async Task UnknownRequestHeadersRedacted() { var middleware = new HttpLoggingMiddleware( async c => { var arr = new byte[4096]; while (true) { var res = await c.Request.Body.ReadAsync(arr); if (res == 0) { break; } } }, CreateOptionsAccessor(), LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); httpContext.Request.Headers["foo"] = "bar"; await middleware.Invoke(httpContext); Assert.Contains(TestSink.Writes, w => w.Message.Contains("foo: [Redacted]")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("foo: bar")); }
public async Task RequestHeadersLogs() { var options = CreateOptionsAccessor(); options.CurrentValue.LoggingFields = HttpLoggingFields.RequestHeaders; var middleware = new HttpLoggingMiddleware( async c => { var arr = new byte[4096]; while (true) { var res = await c.Request.Body.ReadAsync(arr); if (res == 0) { break; } } }, options, LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); httpContext.Request.Protocol = "HTTP/1.0"; httpContext.Request.Method = "GET"; httpContext.Request.Scheme = "http"; httpContext.Request.Path = new PathString("/foo"); httpContext.Request.PathBase = new PathString("/foo"); httpContext.Request.QueryString = new QueryString("?foo"); httpContext.Request.Headers["Connection"] = "keep-alive"; httpContext.Request.ContentType = "text/plain"; httpContext.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes("test")); await middleware.Invoke(httpContext); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("Protocol: HTTP/1.0")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("Method: GET")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("Scheme: http")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("Path: /foo")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("PathBase: /foo")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("QueryString: ?foo")); Assert.Contains(TestSink.Writes, w => w.Message.Contains("Connection: keep-alive")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("Body: test")); }
public async Task ResponseBodyWritingWorks(string expected) { var options = CreateOptionsAccessor(); options.CurrentValue.LoggingFields = HttpLoggingFields.ResponseBody; var middleware = new HttpLoggingMiddleware( c => { c.Response.ContentType = "text/plain"; return(c.Response.WriteAsync(expected)); }, options, LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); await middleware.Invoke(httpContext); Assert.Contains(TestSink.Writes, w => w.Message.Contains(expected)); }
public async Task UnrecognizedMediaType() { var expected = "Hello world"; var options = CreateOptionsAccessor(); options.CurrentValue.LoggingFields = HttpLoggingFields.ResponseBody; var middleware = new HttpLoggingMiddleware( c => { c.Response.ContentType = "foo/*"; return(c.Response.WriteAsync(expected)); }, options, LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); await middleware.Invoke(httpContext); Assert.Contains(TestSink.Writes, w => w.Message.Contains("Unrecognized Content-Type for body.")); }
public async Task DefaultResponseInfoOnlyHeadersAndRequestInfo() { var middleware = new HttpLoggingMiddleware( async c => { c.Response.StatusCode = 200; c.Response.Headers[HeaderNames.TransferEncoding] = "test"; c.Response.ContentType = "text/plain"; await c.Response.WriteAsync("test"); }, CreateOptionsAccessor(), LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); await middleware.Invoke(httpContext); Assert.Contains(TestSink.Writes, w => w.Message.Contains("StatusCode: 200")); Assert.Contains(TestSink.Writes, w => w.Message.Contains("Transfer-Encoding: test")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("Body: test")); }
public async Task NoopWhenLoggingDisabled() { var options = CreateOptionsAccessor(); options.CurrentValue.LoggingFields = HttpLoggingFields.None; var middleware = new HttpLoggingMiddleware( c => { c.Response.StatusCode = 200; return(Task.CompletedTask); }, options, LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); httpContext.Request.Protocol = "HTTP/1.0"; httpContext.Request.Method = "GET"; httpContext.Request.Scheme = "http"; httpContext.Request.Path = new PathString("/foo"); httpContext.Request.PathBase = new PathString("/foo"); httpContext.Request.QueryString = new QueryString("?foo"); httpContext.Request.Headers["Connection"] = "keep-alive"; httpContext.Request.ContentType = "text/plain"; httpContext.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes("test")); await middleware.Invoke(httpContext); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("Protocol: HTTP/1.0")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("Method: GET")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("Scheme: http")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("Path: /foo")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("PathBase: /foo")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("QueryString: ?foo")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("Connection: keep-alive")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("Body: test")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("StatusCode: 200")); }
public async Task DifferentEncodingsWork() { var encoding = Encoding.Unicode; var expected = new string('a', 1000); var options = CreateOptionsAccessor(); options.CurrentValue.LoggingFields = HttpLoggingFields.RequestBody; options.CurrentValue.MediaTypeOptions.Clear(); options.CurrentValue.MediaTypeOptions.AddText("text/plain", encoding); var middleware = new HttpLoggingMiddleware( async c => { var arr = new byte[4096]; var count = 0; while (true) { var res = await c.Request.Body.ReadAsync(arr); if (res == 0) { break; } count += res; } Assert.Equal(2000, count); }, options, LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); httpContext.Request.ContentType = "text/plain"; httpContext.Request.Body = new MemoryStream(encoding.GetBytes(expected)); await middleware.Invoke(httpContext); Assert.Contains(TestSink.Writes, w => w.Message.Contains(expected)); }
public async Task RequestBodyReadingLimitLongCharactersWorks() { var input = string.Concat(new string('あ', 5)); var options = CreateOptionsAccessor(); options.CurrentValue.LoggingFields = HttpLoggingFields.RequestBody; options.CurrentValue.RequestBodyLogLimit = 4; var middleware = new HttpLoggingMiddleware( async c => { var arr = new byte[4096]; var count = 0; while (true) { var res = await c.Request.Body.ReadAsync(arr); if (res == 0) { break; } count += res; } Assert.Equal(15, count); }, options, LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); httpContext.Request.ContentType = "text/plain"; httpContext.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(input)); await middleware.Invoke(httpContext); var expected = input.Substring(0, options.CurrentValue.RequestBodyLogLimit / 3); Assert.Contains(TestSink.Writes, w => w.Message.Equals("RequestBody: " + expected)); }
public async Task FirstWriteResponseHeadersLogged() { var options = CreateOptionsAccessor(); options.CurrentValue.LoggingFields = HttpLoggingFields.Response; var writtenHeaders = new TaskCompletionSource <object>(); var letBodyFinish = new TaskCompletionSource <object>(); var middleware = new HttpLoggingMiddleware( async c => { c.Response.StatusCode = 200; c.Response.Headers[HeaderNames.TransferEncoding] = "test"; c.Response.ContentType = "text/plain"; await c.Response.WriteAsync("test"); writtenHeaders.SetResult(null); await letBodyFinish.Task; }, options, LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); var middlewareTask = middleware.Invoke(httpContext); await writtenHeaders.Task; Assert.Contains(TestSink.Writes, w => w.Message.Contains("StatusCode: 200")); Assert.Contains(TestSink.Writes, w => w.Message.Contains("Transfer-Encoding: test")); Assert.DoesNotContain(TestSink.Writes, w => w.Message.Contains("Body: test")); letBodyFinish.SetResult(null); await middlewareTask; Assert.Contains(TestSink.Writes, w => w.Message.Contains("Body: test")); }
public async Task ResponseBodyWritingLimitWorks() { var input = string.Concat(new string('a', 30000), new string('b', 3000)); var options = CreateOptionsAccessor(); options.CurrentValue.LoggingFields = HttpLoggingFields.ResponseBody; var middleware = new HttpLoggingMiddleware( c => { c.Response.ContentType = "text/plain"; return(c.Response.WriteAsync(input)); }, options, LoggerFactory.CreateLogger <HttpLoggingMiddleware>()); var httpContext = new DefaultHttpContext(); await middleware.Invoke(httpContext); var expected = input.Substring(0, options.CurrentValue.ResponseBodyLogLimit); Assert.Contains(TestSink.Writes, w => w.Message.Contains(expected)); }