From d1a547e6cc853d80b60ce50b4051f071d20922b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=86=9B?= <510423039@qq.com> Date: Sat, 6 Nov 2021 09:05:12 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20=E9=9B=86=E6=88=90Ocelot=E7=BD=91?= =?UTF-8?q?=E5=85=B3=EF=BC=8CConsul=20=E6=9C=8D=E5=8A=A1=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=E5=92=8C=E5=8F=91=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CompanyName.ProjectName.WebGateway.csproj | 3 +- .../Program.cs | 3 +- .../Properties/launchSettings.json | 21 +- .../Startup.cs | 35 +-- .../WebGatewayModule.cs | 98 ++++++++ .../appsettings.Consul.json | 48 ++++ .../appsettings.Development.json | 45 +++- .../appsettings.Production.json | 52 +++++ .../appsettings.json | 10 - ...ompanyName.ProjectName.HttpApi.Host.csproj | 1 + .../DefaultHttpExceptionStatusCodeFinder.cs | 73 ------ .../Extensions/Filters/EnumSchemaFilter.cs | 24 -- .../Filters/HiddenAbpDefaultApiFilter.cs | 56 ----- .../Extensions/Filters/SwaggerTagsFilter.cs | 36 --- .../ProjectNameHttpApiHostModule.cs | 220 ++++++------------ .../appsettings.Development.json | 6 + ...ProjectName.Shared.Hosting.Gateways.csproj | 2 + .../SharedHostingGatewayModule.cs | 4 +- .../Builder/ApplicationBuilderExtensions.cs | 1 - .../SharedHostingMicroserviceModule.cs | 26 ++- 20 files changed, 361 insertions(+), 403 deletions(-) create mode 100644 aspnet-core/gateways/CompanyName.ProjectName.WebGateway/WebGatewayModule.cs create mode 100644 aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Consul.json create mode 100644 aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Production.json delete mode 100644 aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.json delete mode 100644 aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/DefaultHttpExceptionStatusCodeFinder.cs delete mode 100644 aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/EnumSchemaFilter.cs delete mode 100644 aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/HiddenAbpDefaultApiFilter.cs delete mode 100644 aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/SwaggerTagsFilter.cs diff --git a/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/CompanyName.ProjectName.WebGateway.csproj b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/CompanyName.ProjectName.WebGateway.csproj index 11984f2d..5c2a3f4b 100644 --- a/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/CompanyName.ProjectName.WebGateway.csproj +++ b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/CompanyName.ProjectName.WebGateway.csproj @@ -4,8 +4,9 @@ net5.0 + - + diff --git a/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Program.cs b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Program.cs index b067d793..74b597a2 100644 --- a/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Program.cs +++ b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Program.cs @@ -18,6 +18,7 @@ namespace CompanyName.ProjectName.WebGateway public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); + .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }) + .UseAutofac(); } } \ No newline at end of file diff --git a/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Properties/launchSettings.json b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Properties/launchSettings.json index 793664c0..3a803e20 100644 --- a/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Properties/launchSettings.json +++ b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Properties/launchSettings.json @@ -1,30 +1,13 @@ { "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:2409", - "sslPort": 44302 - } - }, "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "launchUrl": "swagger", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, "CompanyName.ProjectName.WebGateway": { "commandName": "Project", - "dotnetRunMessages": "true", "launchBrowser": true, "launchUrl": "swagger", - "applicationUrl": "https://localhost:5001;http://localhost:5000", + "applicationUrl": "http://localhost:44314", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Consul" } } } diff --git a/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Startup.cs b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Startup.cs index 245a83b8..f7c37245 100644 --- a/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Startup.cs +++ b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Startup.cs @@ -16,43 +16,14 @@ namespace CompanyName.ProjectName.WebGateway { 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. public void ConfigureServices(IServiceCollection services) { - services.AddControllers(); - services.AddSwaggerGen(c => - { - c.SwaggerDoc("v1", - new OpenApiInfo - { Title = "CompanyName.ProjectName.WebGateway", Version = "v1" }); - }); + services.AddApplication(); } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + public void Configure(IApplicationBuilder app) { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - app.UseSwagger(); - app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", - "CompanyName.ProjectName.WebGateway v1")); - } - - app.UseHttpsRedirection(); - - app.UseRouting(); - - app.UseAuthorization(); - - app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); + app.InitializeApplication(); } } } \ No newline at end of file diff --git a/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/WebGatewayModule.cs b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/WebGatewayModule.cs new file mode 100644 index 00000000..a6173de7 --- /dev/null +++ b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/WebGatewayModule.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using CompanyName.ProjectName.Shared.Hosting.Gateways; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Cors; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi.Models; +using Ocelot.Middleware; +using Swashbuckle.AspNetCore.SwaggerUI; +using Volo.Abp; +using Volo.Abp.Modularity; + +namespace CompanyName.ProjectName.WebGateway +{ + [DependsOn( + typeof(SharedHostingGatewayModule))] + public class WebGatewayModule : AbpModule + { + private const string DefaultCorsPolicyName = "Default"; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + ConfigureCors(context); + ConfigureSwaggerServices(context); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + var env = context.GetEnvironment(); + app.UseCorrelationId(); + app.UseCors(DefaultCorsPolicyName); + app.UseRouting(); + app.UseSwagger(); + app.UseSwaggerUI(options => + { + options.SwaggerEndpoint("/ProjectName/swagger.json", "ProjectNameAPI"); + options.DefaultModelsExpandDepth(-1); + options.DocExpansion(DocExpansion.None); + }); + + app.UseConfiguredEndpoints(); + app.UseOcelot().Wait(); + } + + /// + /// 配置跨域 + /// + /// + private void ConfigureCors(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + context.Services.AddCors(options => + { + options.AddPolicy(DefaultCorsPolicyName, builder => + { + builder + .WithOrigins( + configuration["App:CorsOrigins"] + .Split(",", StringSplitOptions.RemoveEmptyEntries) + .Select(o => o.RemovePostFix("/")) + .ToArray() + ) + .WithAbpExposedHeaders() + .SetIsOriginAllowedToAllowWildcardSubdomains() + .AllowAnyHeader() + .AllowAnyMethod() + .AllowCredentials(); + }); + }); + } + + private static void ConfigureSwaggerServices(ServiceConfigurationContext context) + { + context.Services.AddSwaggerGen( + options => + { + options.SwaggerDoc("v1", new OpenApiInfo {Title = "WebGateway API", Version = "v1"}); + options.DocInclusionPredicate((docName, description) => true); + options.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, Id = "Bearer" + } + }, + new List() + } + }); + + }); + } + } +} \ No newline at end of file diff --git a/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Consul.json b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Consul.json new file mode 100644 index 00000000..af6745a1 --- /dev/null +++ b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Consul.json @@ -0,0 +1,48 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*", + "App": { + "SelfUrl": "http://localhost:44314", + "CorsOrigins": "http://localhost:4200" + }, + "GlobalConfiguration": { + }, + "Routes": [ + { + "DownstreamPathTemplate": "/swagger/ProjectName/swagger.json", + "DownstreamScheme": "http", + "ServiceName": "Project-Service", + "LoadBalancerOptions": { + "Type": "LeastConnection" + }, + "UpstreamPathTemplate": "/ProjectName/swagger.json", + "UpstreamHttpMethod": [ + "Get", + "Post", + "Put", + "Delete" + ] + }, + { + "DownstreamPathTemplate": "/{url}", + "DownstreamScheme": "http", + "ServiceName": "Project-Service", + "LoadBalancerOptions": { + "Type": "LeastConnection" + }, + "UpstreamPathTemplate": "/{url}", + "UpstreamHttpMethod": [ + "Get", + "Post", + "Put", + "Delete" + ] + } + ] +} diff --git a/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Development.json b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Development.json index 8983e0fc..3f557e88 100644 --- a/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Development.json +++ b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Development.json @@ -5,5 +5,48 @@ "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } - } + }, + "AllowedHosts": "*", + "App": { + "SelfUrl": "http://localhost:44314", + "CorsOrigins": "http://localhost:4200" + }, + "GlobalConfiguration": { + }, + "Routes": [ + { + "DownstreamPathTemplate": "/swagger/ProjectName/swagger.json", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 44315 + } + ], + "UpstreamPathTemplate": "/ProjectName/swagger.json", + "UpstreamHttpMethod": [ + "Get", + "Post", + "Put", + "Delete" + ] + }, + { + "DownstreamPathTemplate": "/{url}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 44315 + } + ], + "UpstreamPathTemplate": "/{url}", + "UpstreamHttpMethod": [ + "Get", + "Post", + "Put", + "Delete" + ] + } + ] } diff --git a/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Production.json b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Production.json new file mode 100644 index 00000000..3f557e88 --- /dev/null +++ b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Production.json @@ -0,0 +1,52 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*", + "App": { + "SelfUrl": "http://localhost:44314", + "CorsOrigins": "http://localhost:4200" + }, + "GlobalConfiguration": { + }, + "Routes": [ + { + "DownstreamPathTemplate": "/swagger/ProjectName/swagger.json", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 44315 + } + ], + "UpstreamPathTemplate": "/ProjectName/swagger.json", + "UpstreamHttpMethod": [ + "Get", + "Post", + "Put", + "Delete" + ] + }, + { + "DownstreamPathTemplate": "/{url}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 44315 + } + ], + "UpstreamPathTemplate": "/{url}", + "UpstreamHttpMethod": [ + "Get", + "Post", + "Put", + "Delete" + ] + } + ] +} diff --git a/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.json b/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.json deleted file mode 100644 index d9d9a9bf..00000000 --- a/aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*" -} diff --git a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/CompanyName.ProjectName.HttpApi.Host.csproj b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/CompanyName.ProjectName.HttpApi.Host.csproj index f291110c..a854124b 100644 --- a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/CompanyName.ProjectName.HttpApi.Host.csproj +++ b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/CompanyName.ProjectName.HttpApi.Host.csproj @@ -38,6 +38,7 @@ + diff --git a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/DefaultHttpExceptionStatusCodeFinder.cs b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/DefaultHttpExceptionStatusCodeFinder.cs deleted file mode 100644 index b125c71e..00000000 --- a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/DefaultHttpExceptionStatusCodeFinder.cs +++ /dev/null @@ -1,73 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Options; -using System; -using System.Net; -using Volo.Abp; -using Volo.Abp.AspNetCore.ExceptionHandling; -using Volo.Abp.Authorization; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Domain.Entities; -using Volo.Abp.ExceptionHandling; -using Volo.Abp.Validation; - - namespace CompanyName.ProjectName.Extensions.Filters -{ - [Dependency(ReplaceServices = true)] - public class DefaultHttpExceptionStatusCodeFinder : IHttpExceptionStatusCodeFinder, ITransientDependency - { - protected AbpExceptionHttpStatusCodeOptions Options { get; } - - public DefaultHttpExceptionStatusCodeFinder( - IOptions options) - { - Options = options.Value; - } - - public HttpStatusCode GetStatusCode(HttpContext httpContext, Exception exception) - { - if (exception is IHasHttpStatusCode exceptionWithHttpStatusCode && - exceptionWithHttpStatusCode.HttpStatusCode > 0) - { - return (HttpStatusCode)exceptionWithHttpStatusCode.HttpStatusCode; - } - - if (exception is IHasErrorCode exceptionWithErrorCode && - !exceptionWithErrorCode.Code.IsNullOrWhiteSpace()) - { - if (Options.ErrorCodeToHttpStatusCodeMappings.TryGetValue(exceptionWithErrorCode.Code, out var status)) - { - return status; - } - } - - if (exception is AbpAuthorizationException) - { - return HttpStatusCode.Forbidden; - } - - //TODO: Handle SecurityException..? - - if (exception is AbpValidationException) - { - return HttpStatusCode.BadRequest; - } - - if (exception is EntityNotFoundException) - { - return HttpStatusCode.NotFound; - } - - if (exception is NotImplementedException) - { - return HttpStatusCode.NotImplemented; - } - - if (exception is IBusinessException) - { - return HttpStatusCode.InternalServerError; - } - - return HttpStatusCode.InternalServerError; - } - } -} diff --git a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/EnumSchemaFilter.cs b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/EnumSchemaFilter.cs deleted file mode 100644 index 63753cfa..00000000 --- a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/EnumSchemaFilter.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Linq; -using Microsoft.OpenApi.Any; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; - -namespace CompanyName.ProjectName.Extensions.Filters -{ - public class EnumSchemaFilter : ISchemaFilter - { - public void Apply(OpenApiSchema schema, SchemaFilterContext context) - { - if (context.Type.IsEnum) - { - var array = new OpenApiArray(); - array.AddRange(Enum.GetNames(context.Type).Select(n => new OpenApiString(n))); - // NSwag - schema.Extensions.Add("x-enumNames", array); - // Openapi-generator - schema.Extensions.Add("x-enum-varnames", array); - } - } - } -} \ No newline at end of file diff --git a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/HiddenAbpDefaultApiFilter.cs b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/HiddenAbpDefaultApiFilter.cs deleted file mode 100644 index ec023a51..00000000 --- a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/HiddenAbpDefaultApiFilter.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Microsoft.AspNetCore.Mvc.ApiExplorer; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; - -namespace CompanyName.ProjectName.Extensions.Filters -{ - /// - /// 在使用nswag的时候,原生默认的api导致生产的代理类存在问题 - /// 所有隐藏原生的api,重写路由 - /// - public class HiddenAbpDefaultApiFilter : IDocumentFilter - { - public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) - { - - foreach (ApiDescription apiDescription in context.ApiDescriptions) - { - if (apiDescription.TryGetMethodInfo(out MethodInfo method)) - { - string key = "/" + apiDescription.RelativePath; - var reuslt = IsHidden(key); - if(reuslt) swaggerDoc.Paths.Remove(key); - } - } - } - - private bool IsHidden(string key) - { - var list = GetHiddenAbpDefaultApiList(); - foreach (var item in list) - { - if (key.Contains(item)) return true; - } - return false; - } - - private List GetHiddenAbpDefaultApiList() - { - return new List() { - "/api/abp/multi-tenancy/tenants", - "/api/account", - "/api/feature-management/features", - "/api/permission-management/permissions", - "/api/identity/my-profile", - "/api/identity", - "/api/multi-tenancy/tenants", - "/api/setting-management/emailing" - }; - } - } -} diff --git a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/SwaggerTagsFilter.cs b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/SwaggerTagsFilter.cs deleted file mode 100644 index 46638c45..00000000 --- a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/SwaggerTagsFilter.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Microsoft.AspNetCore.Mvc.Controllers; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace CompanyNameProjectName.Extensions.Filters -{ - /// - /// 把abp vnext 提供的api 归档 - /// - public class SwaggerTagsFilter : IOperationFilter - { - public const string DefaultTagName = "ABP Vnext 默认 Api"; - - public void Apply(OpenApiOperation operation, OperationFilterContext context) - { - var tag = GetChineseTag(context.ApiDescription.ActionDescriptor as ControllerActionDescriptor); - if (null != tag) - operation.Tags = new List { tag }; - } - - private static OpenApiTag GetChineseTag(ControllerActionDescriptor description) - { - if (null != description?.ControllerTypeInfo?.Namespace) - { - if (description.ControllerTypeInfo.Namespace.StartsWith("Volo.Abp") || description.ControllerTypeInfo.Namespace.StartsWith("Pages.Abp.MultiTenancy")) - return new OpenApiTag { Name = DefaultTagName }; - return null; - } - return null; - } - } -} diff --git a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs index c477a14d..8b3d3c2a 100644 --- a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs +++ b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs @@ -1,18 +1,15 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; using CompanyName.ProjectName.ConfigurationOptions; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using CompanyName.ProjectName.EntityFrameworkCore; -using CompanyName.ProjectName.Extensions.Filters; using CompanyNameProjectName.Extensions.Filters; using Hangfire; using Hangfire.MySql; @@ -29,18 +26,17 @@ using Volo.Abp.Autofac; using Volo.Abp.BackgroundJobs; using Volo.Abp.BackgroundJobs.Hangfire; using Volo.Abp.Caching.StackExchangeRedis; -using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.Swashbuckle; -using Volo.Abp.VirtualFileSystem; using System.Threading.Tasks; using CompanyName.ProjectName.Extensions; using CompanyName.ProjectName.MultiTenancy; +using DefaultNamespace; +using DefaultNamespace.Swaggers; using Lion.Abp.Cap; using Savorboard.CAP.InMemoryMessageQueue; using Serilog; using Swashbuckle.AspNetCore.SwaggerUI; -using Volo.Abp.AspNetCore.ExceptionHandling; using Volo.Abp.AspNetCore.MultiTenancy; using Volo.Abp.Caching; @@ -59,13 +55,15 @@ namespace CompanyName.ProjectName typeof(AbpAspNetCoreAuthenticationJwtBearerModule), typeof(AbpBackgroundJobsHangfireModule), typeof(LionAbpCapModule), - typeof(AbpAspNetCoreMultiTenancyModule) + typeof(AbpAspNetCoreMultiTenancyModule), + typeof(SharedHostingMicroserviceModule) )] public class ProjectNameHttpApiHostModule : AbpModule { private const string DefaultCorsPolicyName = "Default"; - public override void OnPostApplicationInitialization(ApplicationInitializationContext context) + public override void OnPostApplicationInitialization( + ApplicationInitializationContext context) { // context.CreateRecurringJob(); base.OnPostApplicationInitialization(context); @@ -74,77 +72,73 @@ namespace CompanyName.ProjectName public override void ConfigureServices(ServiceConfigurationContext context) { var configuration = context.Services.GetConfiguration(); - var hostingEnvironment = context.Services.GetHostingEnvironment(); - - //ConfigureConventionalControllers(); - //ConfigureAuthentication(context, configuration); - ConfigureLocalization(); ConfigureCache(context); - ConfigureVirtualFileSystem(context); - ConfigureCors(context, configuration); ConfigureSwaggerServices(context, configuration); ConfigureOptions(context); - ConfigureHealthChecks(context); ConfigureJwtAuthentication(context, configuration); ConfigureHangfireMysql(context); ConfigurationCap(context); ConfigurationStsHttpClient(context); - ConfigureAbpExceptions(context); } public override void OnApplicationInitialization(ApplicationInitializationContext context) { var app = context.GetApplicationBuilder(); + var configuration = context.GetConfiguration(); app.UseAbpRequestLocalization(); app.UseCorrelationId(); app.UseStaticFiles(); app.UseRouting(); app.UseCors(DefaultCorsPolicyName); app.UseAuthentication(); - + if (MultiTenancyConsts.IsEnabled) { app.UseMultiTenancy(); } - + app.UseAuthorization(); app.UseSwagger(); app.UseAbpSwaggerUI(options => { - options.SwaggerEndpoint("/swagger/v1/swagger.json", "ProjectName API"); + options.SwaggerEndpoint("/swagger/ProjectName/swagger.json", "ProjectName API"); options.DocExpansion(DocExpansion.None); options.DefaultModelsExpandDepth(-1); }); app.UseAuditing(); app.UseAbpSerilogEnrichers(); - app.UseSerilogRequestLogging(opts => { opts.EnrichDiagnosticContext = SerilogToEsExtensions.EnrichFromRequest; }); + app.UseSerilogRequestLogging(opts => + { + opts.EnrichDiagnosticContext = SerilogToEsExtensions.EnrichFromRequest; + }); app.UseUnitOfWork(); app.UseConfiguredEndpoints(); app.UseEndpoints(endpoints => { endpoints.MapHealthChecks("/health"); }); app.UseHangfireDashboard("/hangfire", new DashboardOptions() { - Authorization = new[] {new CustomHangfireAuthorizeFilter()}, + Authorization = new[] { new CustomHangfireAuthorizeFilter() }, IgnoreAntiforgeryToken = true }); - } - /// - /// 异常处理 - /// - /// - private void ConfigureAbpExceptions(ServiceConfigurationContext context) - { - context.Services.Configure(options => { options.SendExceptionsDetailsToClients = true; }); + if (configuration.GetValue("Consul:Enabled", false)) + { + app.UseConsul(); + } } - public void ConfigureHangfireMysql(ServiceConfigurationContext context) + + private void ConfigureHangfireMysql(ServiceConfigurationContext context) { - Configure(options => { options.IsJobExecutionEnabled = true; }); + Configure(options => + { + options.IsJobExecutionEnabled = true; + }); context.Services.AddHangfire(config => { - config.UseStorage(new MySqlStorage(context.Services.GetConfiguration().GetConnectionString("Default"), + config.UseStorage(new MySqlStorage( + context.Services.GetConfiguration().GetConnectionString("Default"), new MySqlStorageOptions() { //CommandBatchMaxTimeout = TimeSpan.FromMinutes(5), @@ -162,7 +156,8 @@ namespace CompanyName.ProjectName /// /// /// - private void ConfigureJwtAuthentication(ServiceConfigurationContext context, IConfiguration configuration) + private void ConfigureJwtAuthentication(ServiceConfigurationContext context, + IConfiguration configuration) { context.Services.AddAuthentication(options => { @@ -171,19 +166,21 @@ namespace CompanyName.ProjectName }) .AddJwtBearer(options => { - options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters() - { - // 是否开启签名认证 - ValidateIssuerSigningKey = true, - ValidateIssuer = true, - ValidateAudience = true, - ValidateLifetime = true, - //ClockSkew = TimeSpan.Zero, - ValidIssuer = configuration["Jwt:Issuer"], - ValidAudience = configuration["Jwt:Audience"], - IssuerSigningKey = - new SymmetricSecurityKey(Encoding.ASCII.GetBytes(configuration["Jwt:SecurityKey"])) - }; + options.TokenValidationParameters = + new Microsoft.IdentityModel.Tokens.TokenValidationParameters() + { + // 是否开启签名认证 + ValidateIssuerSigningKey = true, + ValidateIssuer = true, + ValidateAudience = true, + ValidateLifetime = true, + //ClockSkew = TimeSpan.Zero, + ValidIssuer = configuration["Jwt:Issuer"], + ValidAudience = configuration["Jwt:Audience"], + IssuerSigningKey = + new SymmetricSecurityKey( + Encoding.ASCII.GetBytes(configuration["Jwt:SecurityKey"])) + }; options.Events = new JwtBearerEvents { @@ -198,9 +195,11 @@ namespace CompanyName.ProjectName } // 如果请求来自hangfire 或者cap - if (path.ToString().StartsWith("/hangfire") || path.ToString().StartsWith("/cap")) + if (path.ToString().StartsWith("/hangfire") || + path.ToString().StartsWith("/cap")) { - currentContext.HttpContext.Response.Headers.Remove("X-Frame-Options"); + currentContext.HttpContext.Response.Headers.Remove( + "X-Frame-Options"); if (!string.IsNullOrEmpty(accessToken)) { currentContext.Token = accessToken; @@ -229,7 +228,8 @@ namespace CompanyName.ProjectName /// private void ConfigureOptions(ServiceConfigurationContext context) { - context.Services.Configure(context.Services.GetConfiguration().GetSection("Jwt")); + context.Services.Configure(context.Services.GetConfiguration() + .GetSection("Jwt")); } /// @@ -237,7 +237,8 @@ namespace CompanyName.ProjectName /// private void ConfigureCache(ServiceConfigurationContext context) { - Configure(options => { options.KeyPrefix = "ProjectName:"; }); + Configure( + options => { options.KeyPrefix = "ProjectName:"; }); var configuration = context.Services.GetConfiguration(); var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); context.Services @@ -245,31 +246,6 @@ namespace CompanyName.ProjectName .PersistKeysToStackExchangeRedis(redis, "ProjectName-Protection-Keys"); } - private void ConfigureVirtualFileSystem(ServiceConfigurationContext context) - { - Configure(options => { options.FileSets.AddEmbedded(); }); - - // var hostingEnvironment = context.Services.GetHostingEnvironment(); - // - // if (hostingEnvironment.IsDevelopment()) - // { - // Configure(options => - // { - // options.FileSets.ReplaceEmbeddedByPhysical( - // Path.Combine(hostingEnvironment.ContentRootPath, - // $"..{Path.DirectorySeparatorChar}CompanyName.ProjectName.Domain.Shared")); - // options.FileSets.ReplaceEmbeddedByPhysical( - // Path.Combine(hostingEnvironment.ContentRootPath, - // $"..{Path.DirectorySeparatorChar}CompanyName.ProjectName.Domain")); - // options.FileSets.ReplaceEmbeddedByPhysical( - // Path.Combine(hostingEnvironment.ContentRootPath, - // $"..{Path.DirectorySeparatorChar}CompanyName.ProjectName.Application.Contracts")); - // options.FileSets.ReplaceEmbeddedByPhysical( - // Path.Combine(hostingEnvironment.ContentRootPath, - // $"..{Path.DirectorySeparatorChar}CompanyName.ProjectName.Application")); - // }); - // } - } private void ConfigurationStsHttpClient(ServiceConfigurationContext context) { @@ -277,7 +253,8 @@ namespace CompanyName.ProjectName options => { options.BaseAddress = - new Uri(context.Services.GetConfiguration().GetSection("HttpClient:Sts:Url").Value); + new Uri(context.Services.GetConfiguration().GetSection("HttpClient:Sts:Url") + .Value); }); } @@ -285,31 +262,19 @@ namespace CompanyName.ProjectName { Configure(options => { - options.ConventionalControllers.Create(typeof(ProjectNameApplicationModule).Assembly); + options.ConventionalControllers.Create(typeof(ProjectNameApplicationModule) + .Assembly); }); } - - /// - /// 健康检查 - /// - /// - private void ConfigureHealthChecks(ServiceConfigurationContext context) - { - var redisConnectionString = - context.Services.GetConfiguration().GetValue("Cache:Redis:ConnectionString"); - var redisDatabaseId = context.Services.GetConfiguration().GetValue("Cache:Redis:DatabaseId"); - var password = context.Services.GetConfiguration().GetValue("Cache:Redis:Password"); - var connectString = $"{redisConnectionString},password={password},defaultdatabase={redisDatabaseId}"; - context.Services.AddHealthChecks().AddRedis(redisConnectionString).AddMySql(connectString); - } - - private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration) + private static void ConfigureSwaggerServices(ServiceConfigurationContext context, + IConfiguration configuration) { context.Services.AddSwaggerGen( options => { - options.SwaggerDoc("v1", new OpenApiInfo {Title = "CompanyNameProjectName API", Version = "v1"}); + options.SwaggerDoc("ProjectName", + new OpenApiInfo { Title = "CompanyNameProjectName API", Version = "v1" }); options.DocInclusionPredicate((docName, description) => true); options.EnableAnnotations(); // 启用注解 options.DocumentFilter(); @@ -321,15 +286,17 @@ namespace CompanyName.ProjectName options.IncludeXmlComments(xml, true); } - options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new OpenApiSecurityScheme() - { - Description = "Please enter into field the word 'Bearer' followed by a space and the JWT value", - Name = "Authorization", - In = ParameterLocation.Header, - Type = SecuritySchemeType.Http, - Scheme = JwtBearerDefaults.AuthenticationScheme, - BearerFormat = "JWT" - }); + options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, + new OpenApiSecurityScheme() + { + Description = + "Please enter into field the word 'Bearer' followed by a space and the JWT value", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + Scheme = JwtBearerDefaults.AuthenticationScheme, + BearerFormat = "JWT" + }); options.AddSecurityRequirement(new OpenApiSecurityRequirement { { @@ -357,7 +324,8 @@ namespace CompanyName.ProjectName { new OpenApiSecurityScheme { - Reference = new OpenApiReference {Type = ReferenceType.SecurityScheme, Id = "ApiKey"} + Reference = new OpenApiReference + { Type = ReferenceType.SecurityScheme, Id = "ApiKey" } }, new string[] { } } @@ -365,48 +333,6 @@ namespace CompanyName.ProjectName }); } - private void ConfigureLocalization() - { - Configure(options => - { - options.Languages.Add(new LanguageInfo("ar", "ar", "العربية")); - options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); - options.Languages.Add(new LanguageInfo("en", "en", "English")); - options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)")); - options.Languages.Add(new LanguageInfo("fr", "fr", "Français")); - options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar")); - options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português")); - options.Languages.Add(new LanguageInfo("ru", "ru", "Русский")); - options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); - options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); - options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); - options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch", "de")); - options.Languages.Add(new LanguageInfo("es", "es", "Español", "es")); - }); - } - - private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration) - { - context.Services.AddAntiforgery(o => o.SuppressXFrameOptionsHeader = true); - context.Services.AddCors(options => - { - options.AddPolicy(DefaultCorsPolicyName, builder => - { - builder - .WithOrigins( - configuration["App:CorsOrigins"] - .Split(",", StringSplitOptions.RemoveEmptyEntries) - .Select(o => o.RemovePostFix("/")) - .ToArray() - ) - .WithAbpExposedHeaders() - .SetIsOriginAllowedToAllowWildcardSubdomains() - .AllowAnyHeader() - .AllowAnyMethod() - .AllowCredentials(); - }); - }); - } private void ConfigurationCap(ServiceConfigurationContext context) { diff --git a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/appsettings.Development.json b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/appsettings.Development.json index cb3e6c63..07768ac3 100644 --- a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/appsettings.Development.json +++ b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/appsettings.Development.json @@ -12,6 +12,7 @@ } }, "App": { + "SelfUrl": "http://localhost:44315", "CorsOrigins": "https://*.ProjectName.com,http://localhost:4200,http://localhost:3100" }, "ConnectionStrings": { @@ -51,5 +52,10 @@ "Sts": { "Url": "http://localhost:44354" } + }, + "Consul": { + "Enabled": true, + "Host": "http://localhost:8500", + "Service": "Project-Service" } } \ No newline at end of file diff --git a/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Gateways/CompanyName.ProjectName.Shared.Hosting.Gateways.csproj b/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Gateways/CompanyName.ProjectName.Shared.Hosting.Gateways.csproj index 77428998..d24e8bae 100644 --- a/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Gateways/CompanyName.ProjectName.Shared.Hosting.Gateways.csproj +++ b/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Gateways/CompanyName.ProjectName.Shared.Hosting.Gateways.csproj @@ -5,6 +5,8 @@ + + diff --git a/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Gateways/SharedHostingGatewayModule.cs b/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Gateways/SharedHostingGatewayModule.cs index ba2958cc..f5585b39 100644 --- a/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Gateways/SharedHostingGatewayModule.cs +++ b/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Gateways/SharedHostingGatewayModule.cs @@ -1,5 +1,7 @@ using Microsoft.Extensions.DependencyInjection; using Ocelot.DependencyInjection; +using Ocelot.Provider.Consul; +using Ocelot.Provider.Polly; using Volo.Abp.Autofac; using Volo.Abp.Modularity; using Volo.Abp.Swashbuckle; @@ -23,7 +25,7 @@ namespace CompanyName.ProjectName.Shared.Hosting.Gateways private static void ConfigureOcelot(ServiceConfigurationContext context) { var configuration = context.Services.GetConfiguration(); - context.Services.AddOcelot(configuration); + context.Services.AddOcelot(configuration).AddConsul().AddPolly(); } } diff --git a/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Microservices/Microsoft/AspNetCore/Builder/ApplicationBuilderExtensions.cs b/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Microservices/Microsoft/AspNetCore/Builder/ApplicationBuilderExtensions.cs index da755ea1..64b8d1c3 100644 --- a/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Microservices/Microsoft/AspNetCore/Builder/ApplicationBuilderExtensions.cs +++ b/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Microservices/Microsoft/AspNetCore/Builder/ApplicationBuilderExtensions.cs @@ -36,7 +36,6 @@ namespace Microsoft.AspNetCore.Builder Port = appUrl.Port, Check = new AgentServiceCheck { - Status = HealthStatus.Passing, DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务停止多久后注销 Interval = TimeSpan.FromSeconds(3),//健康检查时间间隔,或者称为心跳 间隔 HTTP = $"http://{appUrl.Host}:{appUrl.Port}/health",//健康检查地址 diff --git a/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Microservices/SharedHostingMicroserviceModule.cs b/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Microservices/SharedHostingMicroserviceModule.cs index abc11db6..ef46b244 100644 --- a/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Microservices/SharedHostingMicroserviceModule.cs +++ b/aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Microservices/SharedHostingMicroserviceModule.cs @@ -3,6 +3,7 @@ using System.Linq; using Microsoft.AspNetCore.Cors; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AspNetCore.ExceptionHandling; using Volo.Abp.Autofac; using Volo.Abp.Localization; using Volo.Abp.Modularity; @@ -26,7 +27,29 @@ namespace DefaultNamespace ConfigureLocalization(); ConfigureCors(context); ConfigureUrls(configuration); - + ConfigureAbpExceptions(context); + ConfigureConsul(context, configuration); + } + + private void ConfigureConsul(ServiceConfigurationContext context, + IConfiguration configuration) + { + if (configuration.GetValue("Consul:Enabled", false)) + { + context.Services.AddConsulConfig(configuration); + } + } + + /// + /// 异常处理 + /// + /// + private void ConfigureAbpExceptions(ServiceConfigurationContext context) + { + context.Services.Configure(options => + { + options.SendExceptionsDetailsToClients = true; + }); } /// @@ -98,6 +121,7 @@ namespace DefaultNamespace private void ConfigureHealthChecks(ServiceConfigurationContext context) { // TODO 检查数据库和redis是否正常 AspNetCore.HealthChecks.Redis AspNetCore.HealthChecks.MySql + // context.Services.AddHealthChecks().AddRedis(redisConnectionString).AddMySql(connectString); context.Services.AddHealthChecks(); } }