using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.ResponseCompression; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System.Linq; using System; using Microsoft.Extensions.Primitives; using System.Buffers; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.DataProtection.Repositories; using System.Collections.Generic; using Microsoft.AspNetCore.Razor.Language; using Blog3000.Server.MiddleWares; using Microsoft.Extensions.Logging; using Microsoft.AspNetCore.HttpOverrides; using AspNetCoreRateLimit; using Blog3000.Server.Controllers; using Microsoft.AspNetCore.Mvc; namespace Blog3000.Server { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { services.AddOptions(); // Read from appsettings.json, ForRateLimit services.AddControllersWithViews(); services.AddMemoryCache(); // For BlogPostRepo, RateLimit services.AddDataProtection(); // ASP.Net-Core variant of DPAPI // Next block sole for IP-Rate-Limiter //load rules from appsettings.json services.Configure(Configuration.GetSection("IpRateLimiting")); services.Configure(Configuration.GetSection("IpRateLimitPolicies")); // inject counter and rules stores services.AddSingleton(); services.AddSingleton(); // https://github.com/aspnet/Hosting/issues/793 // the IHttpContextAccessor service is not registered by default. // the clientId/clientIp resolvers use it. services.AddSingleton(); // configuration (resolvers, counter key builders) services.AddSingleton(); // Now add own services services.AddSingleton(typeof(BlogEnv)); services.AddSingleton(typeof(BlogPostRepo)); services.AddHostedService(); services.AddHostedService(); services.AddSingleton(); services.AddSingleton(typeof(SearchBotHandler)); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseIpRateLimiting(); app.UseForwardedHeaders(new ForwardedHeadersOptions { //ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto ForwardedHeaders = ForwardedHeaders.All }); // Add our custom headers app.Use(async (context, next) => { // ForwardedHeaders won't set this even for X-Forward-For: https//... ? // (because of proxied to http://localhost ??) // Therefore force to true now. So it won't break url-generation in sitemap etc.. // Perhaps make this configurable like "--publicUrl=...." context.Request.IsHttps = true; context.Response.Headers.Add("X-Blog3000-Build", Blog3000.Server.BuildVersion.BUILD_DATE); await next.Invoke(); }); // No Cache var cp = new NoCacheHeaderAdder(new string[] { "/robots.txt", "/config.json", "/manifest.json", "/favicon.ico" }); app.Use(async (context, next) => { cp.Process(context); await next.Invoke(); }); // Handle SearchBot requests app.Use(async (context, next) => { var sbh = context.RequestServices.GetService(); var res = await sbh.Process(context); if (res) return; // Request completly handling by SEO await next.Invoke(); }); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseWebAssemblyDebugging(); } else { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. // app.UseHsts(); } //app.UseHttpsRedirection(); app.UseBlazorFrameworkFiles(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "config", pattern: "/config.json", defaults: new { controller = "Config", action = "Get" } ); endpoints.MapControllers(); endpoints.MapFallbackToFile("index.html"); }); app.UseStaticFiles(); } } }