Ejemplo n.º 1
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
        {
            //Set the injected loggerFactory (which is used by ASP.NET logging messages) as the singleton instance to use everywhere
            NewAlbumsLogging.ConfigureLogger(loggerFactory);

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                app.UseHsts();

                var options = new RewriteOptions()
                              .AddRedirectToHttps(301)
                              .Add(new NonWwwRule());

                app.UseRewriter(options);
            }

            //NWebSec extensions
            //Other headers, from: https://damienbod.com/2018/02/08/adding-http-headers-to-improve-security-in-an-asp-net-mvc-core-application/
            app.UseXContentTypeOptions();
            app.UseReferrerPolicy(opts => opts.OriginWhenCrossOrigin());
            app.UseXXssProtection(opts => opts.EnabledWithBlockMode());
            app.UseXfo(options => options.Deny());

            app.UseCsp(opts => opts
                       .BlockAllMixedContent()
                       .StyleSources(s => s.Self())
                       .StyleSources(s => s.CustomSources("https://fonts.googleapis.com"))
                       .StyleSources(s => s.UnsafeInline())
                       .FontSources(s => s.Self())
                       .FontSources(s => s.CustomSources("https://fonts.gstatic.com"))
                       .FormActions(s => s.Self())
                       .FrameAncestors(s => s.Self())
                       .ImageSources(s => s.Self())
                       .ImageSources(s => s.CustomSources("https://i.scdn.co", "https://www.google-analytics.com"))
                       //.ImageSources(s => s.CustomSources("data:"))
                       .ScriptSources(s => s.Self())
                       //Needed for webpackHotDevClient in development, and when compiled for production.
                       //TODO implement nonces instead
                       .ScriptSources(s => s.UnsafeInline())
                       .ScriptSources(s => s.CustomSources("https://www.google-analytics.com", "https://storage.googleapis.com"))
                       );

            app.UseHttpsRedirection();

            //10 mins in dev, 365 days in production
            var maxAge = env.IsDevelopment() ? TimeSpan.FromMinutes(10) : TimeSpan.FromDays(365);

            app.UseStaticFiles(new StaticFileOptions
            {
                OnPrepareResponse = ctx =>
                {
                    var headers = ctx.Context.Response.GetTypedHeaders();

                    headers.CacheControl = new CacheControlHeaderValue
                    {
                        Public = true,
                        MaxAge = maxAge
                    };
                }
            });

            app.UseSpaStaticFiles(new StaticFileOptions
            {
                OnPrepareResponse = ctx =>
                {
                    var headers = ctx.Context.Response.GetTypedHeaders();

                    headers.CacheControl = new CacheControlHeaderValue
                    {
                        Public = true,
                        MaxAge = maxAge
                    };
                }
            });

            //From: https://code-maze.com/aspnetcore-webapi-best-practices/
            app.UseExceptionHandler(config =>
            {
                config.Run(async context =>
                {
                    context.Response.StatusCode  = 500;
                    context.Response.ContentType = "application/json";

                    var error = context.Features.Get <IExceptionHandlerFeature>();
                    if (error != null)
                    {
                        var ex          = error.Error;
                        var apiResponse = new ApiResponse(500, ex.Message);
                        string json     = JsonConvert.SerializeObject(apiResponse);

                        await context.Response.WriteAsync(json);
                    }
                });
            });

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });

            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseReactDevelopmentServer(npmScript: "start");
                }
            });

            //Set the App_Data directory so we can retrieve it later. https://stackoverflow.com/a/48357218
            AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(env.ContentRootPath, "App_Data"));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// See appsettings.json for where to configure various settings required by this console app
        /// (user-secrets in dev, Azure app service Connection Strings and Application Settings in production)
        /// </summary>
        static async Task Main(string[] args)
        {
            var builder = new HostBuilder();

            IConfiguration configuration = null;

            builder.ConfigureHostConfiguration(configHost =>
            {
                configHost.SetBasePath(Directory.GetCurrentDirectory());
                configHost.AddJsonFile("hostsettings.json", optional: true);

                //Need to manually read ASPNETCORE_ENVIRONMENT or else it'll default to Production
                //See: https://github.com/aspnet/AspNetCore/issues/4150
                configHost.AddInMemoryCollection(new[] { new KeyValuePair <string, string>(
                                                             HostDefaults.EnvironmentKey, System.Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")) });
                configHost.AddEnvironmentVariables();
            });

            builder.ConfigureAppConfiguration((hostContext, configApp) =>
            {
                configApp.SetBasePath(Directory.GetCurrentDirectory());
                configApp.AddJsonFile("appsettings.json", optional: true);
                configApp.AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true);
                configApp.AddEnvironmentVariables();

                if (hostContext.HostingEnvironment.EnvironmentName.ToLower() == "development")
                {
                    configApp.AddUserSecrets <Program>();
                }

                configuration = configApp.Build();
            });

            builder.ConfigureWebJobs(b =>
            {
                b.AddAzureStorageCoreServices();
                b.AddAzureStorage();
            });

            builder.ConfigureLogging((context, b) =>
            {
                b.AddConsole();
            });

            builder.ConfigureServices((context, serviceCollection) =>
            {
                //Need to do this or later when IConfiguration is injected, it'll be missing our user secrets configured for dev above
                serviceCollection.AddSingleton <IConfiguration>(configuration);

                serviceCollection.AddDbContext <NewAlbumsDbContext>(options =>
                                                                    options.UseSqlServer(configuration.GetConnectionString("Default")));

                serviceCollection.GenericServicesSimpleSetup <NewAlbumsDbContext>(
                    new GenericServicesConfig
                {
                    NoErrorOnReadSingleNull = true
                },
                    Assembly.GetAssembly(typeof(BaseAppService))
                    );

                serviceCollection.AddAutoMapper(typeof(IArtistAppService));

                //NewsAlbums.Application services
                serviceCollection.AddTransient <ISpotifyAppService, SpotifyAppService>();
                serviceCollection.AddTransient <IArtistAppService, ArtistAppService>();
                serviceCollection.AddTransient <IAlbumAppService, AlbumAppService>();
                serviceCollection.AddTransient <ISubscriberAppService, SubscriberAppService>();
                serviceCollection.AddTransient <ISubscriptionAppService, SubscriptionAppService>();

                //NewAlbums.Core managers
                serviceCollection.AddTransient <EmailManager>();
                serviceCollection.AddTransient <TemplateManager>();
                serviceCollection.AddTransient <IPathProvider, PathProvider>();

                var serviceProvider = serviceCollection.BuildServiceProvider();

                var loggerFactory = serviceProvider.GetService <ILoggerFactory>();

                string configFileName = "log4net.config";
                if (context.HostingEnvironment.EnvironmentName.ToLower() != "development")
                {
                    configFileName = "log4net.azure.config";
                }

                //Set the retrieved loggerFactory (which is used by ASP.NET logging messages) as the singleton instance to use everywhere
                NewAlbumsLogging.ConfigureLogger(loggerFactory, configFileName);
            });

            //Set the App_Data directory so we can retrieve it later. https://stackoverflow.com/a/48357218
            //string currentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(Directory.GetCurrentDirectory(), "App_Data"));

            var host = builder.Build();

            using (host)
            {
                await host.StartAsync();

                var jobHost = host.Services.GetService(typeof(IJobHost)) as JobHost;
                await jobHost.CallAsync(typeof(Functions).GetMethod("ProcessNewSpotifyAlbums"));

                await host.StopAsync();
            }
        }