public async Task Invoke(HttpContext context) { RequestLog requestLog = await LogRequest(context); _logger.LogInformation(requestLog.ToString()); ResponseLog responseLog = await LogResponse(context); _logger.LogInformation(responseLog.ToString()); }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime, IServiceProvider serviceProvider, IAntiforgery antiforgery) { ILogger <Program> logger = serviceProvider.GetRequiredService <ILogger <Program> >(); string pathBase = Configuration["PATH_BASE"]; logger.LogInformation($"Using PathBase: {pathBase}"); app.Use(async(context, next) => { // Request method, scheme, and path //_logger.LogInformation($"Method: {context.Request.Method}, Scheme: {context.Request.Scheme}, PathBase: {context.Request.PathBase}, Path: {context.Request.Path}, IP: {context.Connection.RemoteIpAddress}, Host: {context.Request.Host}, ContentLength: {context.Request.ContentLength}"); RequestLog requestLog = new RequestLog(context?.Request?.Method, context?.Request?.Scheme, context?.Request?.PathBase, context?.Request?.Path, context?.Request?.Host.ToString(), context?.Request?.ContentLength, context?.Connection?.RemoteIpAddress?.ToString(), context?.Request?.QueryString.ToString(), context?.Request?.ContentType, context?.Request?.Protocol, context?.Request?.Headers ); logger.LogInformation(requestLog.ToString()); // Headers //foreach (var header in context.Request.Headers) // _logger.LogInformation("Header: {KEY}: {VALUE}", header.Key, header.Value); // Connection: RemoteIp context.Request.PathBase = new PathString(pathBase); // Kubernetes ingress rule context.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); context.Response.Headers.Add("X-Content-Type-Options", "nosniff"); context.Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue() { Public = true, MaxAge = TimeSpan.FromSeconds(10) }; context.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.Vary] = new string[] { "Accept-Encoding" }; if (string.Equals(context.Request.Path.Value, "/", StringComparison.OrdinalIgnoreCase) || string.Equals(context.Request.Path.Value, "/index.html", StringComparison.OrdinalIgnoreCase)) { // The request token can be sent as a JavaScript-readable cookie, // and Angular uses it by default. var tokens = antiforgery.GetAndStoreTokens(context); context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false }); } await next(); }); // https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.1 //app.UsePathBase(pathBase); app.UseExceptionHandler(builder => builder.Run(async context => { context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; context.Response.Headers.Add("Access-Control-Allow-Origin", "*"); var error = context.Features.Get <IExceptionHandlerFeature>(); if (error != null) { context.Response.AddApplicationError(error.Error.Message); await context.Response.WriteAsync(error.Error.Message).ConfigureAwait(false); } })); // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), // specifying the Swagger JSON endpoint. app.UseSwagger().UseSwaggerUI(c => { c.SwaggerEndpoint($"{pathBase}/swagger/v3/swagger.json", "AspNetCoreApiStarter V3"); }); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } // Enable middleware to serve generated Swagger as a JSON endpoint. app.UseResponseCaching(); app.UseForwardedHeaders(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(new CookiePolicyOptions() { HttpOnly = HttpOnlyPolicy.Always, Secure = CookieSecurePolicy.Always }); app.UseRouting(); // The order in which you register the ASP.NET Core authentication middleware matters. Always call UseAuthentication and UseAuthorization after UseRouting and before UseEndpoints. //app.UseCors(); app.UseAuthentication(); // The order in which you register the SignalR and ASP.NET Core authentication middleware matters. Always call UseAuthentication before UseSignalR so that SignalR has a user on the HttpContext. app.UseAuthorization(); app.UseWebSockets(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); //.RequireAuthorization(); // attribute-routed controllers //endpoints.MapDefaultControllerRoute().RequireAuthorization(); //conventional route for controllers. endpoints.MapHub <ChatHub>("/chatHub", options => { if (!_isIntegrationTests) // Websockets is currently unmockable. https://github.com/dotnet/aspnetcore/issues/28108 { options.Transports = HttpTransportType.WebSockets; } }); //endpoints.MapGrpcService<GreeterService>("/greet"); endpoints.MapGrpcService <AccountsService>(); endpoints.MapGrpcService <AuthService>(); endpoints.MapHealthChecks($"/health/live", new HealthCheckOptions() { Predicate = check => check.Name == "Liveness" }); endpoints.MapHealthChecks($"/health/ready", new HealthCheckOptions() { Predicate = check => check.Name == "Readiness" }); endpoints.MapRazorPages(); }); ReadinessHealthCheck readinessHealthCheck = serviceProvider.GetRequiredService <ReadinessHealthCheck>(); lifetime.ApplicationStarted.Register(() => AppStarted(logger, readinessHealthCheck)); lifetime.ApplicationStopping.Register(() => logger.LogInformation("ApplicationStopping")); lifetime.ApplicationStopped.Register(() => logger.LogInformation("ApplicationStopped")); }
private async Task LogToFile(RequestLog message) { await using var writer = File.AppendText(_fileName); Console.WriteLine(message.ToString()); await writer.WriteLineAsync(message.ToString()); }