Browse Source

Merge pull request #19 from colinin/3.0

upgrade Ocelot to 16.0.1
pull/21/head
cKey 6 years ago
committed by GitHub
parent
commit
e1095a233c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN.ApiGateway.Host.csproj
  2. 13
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN/ApiGateway/ApiGatewayMapperProfile.cs
  3. 6
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Ocelot/Configuration/Repository/ApiHttpClientFileConfigurationRepository.cs
  4. 114
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Ocelot/Middleware/Multiplexer/AbpApiDefinitionAggregator.cs
  5. 89
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Ocelot/Ocelot/Extenssions/OcelotMiddlewareExtensions.cs

8
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN.ApiGateway.Host.csproj

@ -6,10 +6,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DotNetCore.CAP.Dashboard" Version="3.0.3" />
<PackageReference Include="DotNetCore.CAP.RabbitMQ" Version="3.0.3" />
<PackageReference Include="DotNetCore.CAP.InMemoryStorage" Version="3.0.3" />
<PackageReference Include="Ocelot.Provider.Polly" Version="15.0.6" />
<PackageReference Include="DotNetCore.CAP.Dashboard" Version="3.0.4" />
<PackageReference Include="DotNetCore.CAP.RabbitMQ" Version="3.0.4" />
<PackageReference Include="DotNetCore.CAP.InMemoryStorage" Version="3.0.4" />
<PackageReference Include="Ocelot.Provider.Polly" Version="16.0.1" />
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
<PackageReference Include="Serilog.Enrichers.Assembly" Version="2.0.0" />
<PackageReference Include="Serilog.Enrichers.Process" Version="2.0.1" />

13
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN/ApiGateway/ApiGatewayMapperProfile.cs

@ -33,7 +33,8 @@ namespace LINGYUN.ApiGateway
CreateMap<RateLimitOptionsDto, FileRateLimitOptions>()
.ForMember(flo => flo.HttpStatusCode, map => map.MapFrom(m => m.HttpStatusCode ?? 429));
CreateMap<ReRouteDto, FileReRoute>()
CreateMap<ReRouteDto, FileRoute>()
.ForMember(frr => frr.RouteIsCaseSensitive, map => map.MapFrom(m => m.ReRouteIsCaseSensitive))
.ForMember(frr => frr.FileCacheOptions, map => map.MapFrom(m => m.FileCacheOptions))
.ForMember(frr => frr.Priority, map => map.MapFrom(m => m.Priority ?? 0))
.ForMember(frr => frr.Timeout, map => map.MapFrom(m => m.Timeout ?? 0))
@ -46,11 +47,15 @@ namespace LINGYUN.ApiGateway
.ForMember(fgc => fgc.RateLimitOptions, map => map.MapFrom(m => m.RateLimitOptions))
.ForMember(fgc => fgc.ServiceDiscoveryProvider, map => map.MapFrom(m => m.ServiceDiscoveryProvider));
CreateMap<DynamicReRouteDto, FileDynamicReRoute>();
CreateMap<DynamicReRouteDto, FileDynamicRoute>();
CreateMap<AggregateReRouteConfigDto, AggregateReRouteConfig>();
CreateMap<AggregateReRouteConfigDto, AggregateRouteConfig>()
.ForMember(arc => arc.RouteKey, map => map.MapFrom(m => m.ReRouteKey));
CreateMap<AggregateReRouteDto, FileAggregateReRoute>();
CreateMap<AggregateReRouteDto, FileAggregateRoute>()
.ForMember(far => far.RouteKeys, map => map.MapFrom(m => m.ReRouteKeys))
.ForMember(far => far.RouteKeysConfig, map => map.MapFrom(m => m.ReRouteKeysConfig))
.ForMember(far => far.RouteIsCaseSensitive, map => map.MapFrom(m => m.ReRouteIsCaseSensitive));
}
private Dictionary<string, string> MapperDictionary(string sourceString)

6
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Ocelot/Configuration/Repository/ApiHttpClientFileConfigurationRepository.cs

@ -48,7 +48,7 @@ namespace Ocelot.Configuration.Repository
{
foreach (var reRouteConfig in reRouteConfiguration.Items)
{
fileConfiguration.ReRoutes.Add(_objectMapper.Map<ReRouteDto, FileReRoute>(reRouteConfig));
fileConfiguration.Routes.Add(_objectMapper.Map<ReRouteDto, FileRoute>(reRouteConfig));
}
}
@ -58,7 +58,7 @@ namespace Ocelot.Configuration.Repository
{
foreach (var dynamicRouteConfig in dynamicReRouteConfiguration.Items)
{
fileConfiguration.DynamicReRoutes.Add(_objectMapper.Map<DynamicReRouteDto, FileDynamicReRoute>(dynamicRouteConfig));
fileConfiguration.DynamicRoutes.Add(_objectMapper.Map<DynamicReRouteDto, FileDynamicRoute>(dynamicRouteConfig));
}
}
@ -67,7 +67,7 @@ namespace Ocelot.Configuration.Repository
{
foreach (var aggregateRouteConfig in aggregateReRouteConfiguration.Items)
{
fileConfiguration.Aggregates.Add(_objectMapper.Map<AggregateReRouteDto, FileAggregateReRoute>(aggregateRouteConfig));
fileConfiguration.Aggregates.Add(_objectMapper.Map<AggregateReRouteDto, FileAggregateRoute>(aggregateRouteConfig));
}
}

114
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Ocelot/Middleware/Multiplexer/AbpApiDefinitionAggregator.cs

@ -1,42 +1,31 @@
using Newtonsoft.Json;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Ocelot.Multiplexer;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace Ocelot.Middleware.Multiplexer
{
public class AbpApiDefinitionAggregator : IDefinedAggregator
{
public async Task<DownstreamResponse> Aggregate(List<DownstreamContext> responses)
public async Task<DownstreamResponse> Aggregate(List<HttpContext> responses)
{
// Ocelot抛弃了下游主机返回的HttpHeaders,所以没法判断是否为abp返回格式
// var isAbpResponse = responses.Any(response => response.DownstreamResponse.Headers.Any(h => h.Key.Equals("_abperrorformat")));
return await MapAbpApiDefinitionAggregateContentAsync(responses);
}
protected virtual async Task<DownstreamResponse> MapAbpApiDefinitionAggregateContentAsync(List<DownstreamContext> downstreamContexts)
protected virtual async Task<DownstreamResponse> MapAbpApiDefinitionAggregateContentAsync(List<HttpContext> responses)
{
var responseKeys = downstreamContexts.Select(s => s.DownstreamReRoute.Key).Distinct().ToList();
JObject responseObject = null;
JsonMergeSettings mergeSetting = new JsonMergeSettings();
mergeSetting.MergeArrayHandling = MergeArrayHandling.Union;
mergeSetting.PropertyNameComparison = System.StringComparison.CurrentCultureIgnoreCase;
for (var k = 0; k < responseKeys.Count; k++)
foreach (var httpResponse in responses)
{
var contexts = downstreamContexts.Where(w => w.DownstreamReRoute.Key == responseKeys[k]).ToList();
if (contexts.Count == 1)
{
if (contexts[0].IsError)
{
return contexts[0].DownstreamResponse;
}
var content = await contexts[0].DownstreamResponse.Content.ReadAsStringAsync();
var content = await httpResponse.Items.DownstreamResponse().Content.ReadAsStringAsync();
var contentObject = JsonConvert.DeserializeObject(content);
if (responseObject == null)
{
@ -47,29 +36,6 @@ namespace Ocelot.Middleware.Multiplexer
responseObject.Merge(contentObject, mergeSetting);
}
}
else
{
for (var i = 0; i < contexts.Count; i++)
{
if (contexts[i].IsError)
{
return contexts[i].DownstreamResponse;
}
var content = await contexts[i].DownstreamResponse.Content.ReadAsStringAsync();
var contentObject = JsonConvert.DeserializeObject(content);
if (responseObject == null)
{
responseObject = JObject.FromObject(contentObject);
}
else
{
responseObject.Merge(contentObject, mergeSetting);
}
}
}
}
var stringContent = new StringContent(responseObject.ToString())
{
Headers = { ContentType = new MediaTypeHeaderValue("application/json") }
@ -79,71 +45,5 @@ namespace Ocelot.Middleware.Multiplexer
new List<KeyValuePair<string, IEnumerable<string>>>(), "OK");
}
protected virtual async Task<DownstreamResponse> MapSimpleJsonAggregateContentAsync(List<DownstreamContext> downstreamContexts)
{
var contentBuilder = new StringBuilder();
contentBuilder.Append("{");
var responseKeys = downstreamContexts.Select(s => s.DownstreamReRoute.Key).Distinct().ToList();
for (var k = 0; k < responseKeys.Count; k++)
{
var contexts = downstreamContexts.Where(w => w.DownstreamReRoute.Key == responseKeys[k]).ToList();
if (contexts.Count == 1)
{
if (contexts[0].IsError)
{
return contexts[0].DownstreamResponse;
}
var content = await contexts[0].DownstreamResponse.Content.ReadAsStringAsync();
contentBuilder.Append($"\"{responseKeys[k]}\":{content}");
}
else
{
contentBuilder.Append($"\"{responseKeys[k]}\":");
contentBuilder.Append("[");
for (var i = 0; i < contexts.Count; i++)
{
if (contexts[i].IsError)
{
return contexts[i].DownstreamResponse;
}
var content = await contexts[i].DownstreamResponse.Content.ReadAsStringAsync();
if (string.IsNullOrWhiteSpace(content))
{
continue;
}
contentBuilder.Append($"{content}");
if (i + 1 < contexts.Count)
{
contentBuilder.Append(",");
}
}
contentBuilder.Append("]");
}
if (k + 1 < responseKeys.Count)
{
contentBuilder.Append(",");
}
}
contentBuilder.Append("}");
var stringContent = new StringContent(contentBuilder.ToString())
{
Headers = { ContentType = new MediaTypeHeaderValue("application/json") }
};
return new DownstreamResponse(stringContent, HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "OK");
}
}
}

89
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Ocelot/Ocelot/Extenssions/OcelotMiddlewareExtensions.cs

@ -1,17 +1,14 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.Configuration;
using Ocelot.Configuration.Creator;
using Ocelot.Configuration.Repository;
using Ocelot.Errors;
using Ocelot.DependencyInjection;
using Ocelot.Logging;
using Ocelot.Middleware;
using Ocelot.Middleware.Pipeline;
using Ocelot.Responses;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
@ -28,61 +25,52 @@ namespace Ocelot.Extenssions
public static async Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder builder, Action<OcelotPipelineConfiguration> pipelineConfiguration)
{
OcelotPipelineConfiguration ocelotPipelineConfiguration = new OcelotPipelineConfiguration();
pipelineConfiguration?.Invoke(ocelotPipelineConfiguration);
return await builder.UseOcelot(ocelotPipelineConfiguration);
var config = new OcelotPipelineConfiguration();
pipelineConfiguration?.Invoke(config);
return await builder.UseOcelot(config);
}
public static async Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder builder, OcelotPipelineConfiguration pipelineConfiguration)
{
await CreateConfiguration(builder);
var configuration = await CreateConfiguration(builder);
ConfigureDiagnosticListener(builder);
return CreateOcelotPipeline(builder, pipelineConfiguration);
}
public static Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder app, Action<IOcelotPipelineBuilder, OcelotPipelineConfiguration> builderAction)
{
return app.UseOcelot(builderAction, new OcelotPipelineConfiguration());
}
public static Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder app, Action<IApplicationBuilder, OcelotPipelineConfiguration> builderAction)
=> UseOcelot(app, builderAction, new OcelotPipelineConfiguration());
public static async Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder app, Action<IOcelotPipelineBuilder, OcelotPipelineConfiguration> builderAction, OcelotPipelineConfiguration configuration)
public static async Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder app, Action<IApplicationBuilder, OcelotPipelineConfiguration> builderAction, OcelotPipelineConfiguration configuration)
{
await CreateConfiguration(app);
ConfigureDiagnosticListener(app);
OcelotPipelineBuilder ocelotPipelineBuilder = new OcelotPipelineBuilder(app.ApplicationServices);
builderAction?.Invoke(ocelotPipelineBuilder, configuration ?? new OcelotPipelineConfiguration());
OcelotRequestDelegate ocelotDelegate = ocelotPipelineBuilder.Build();
builderAction?.Invoke(app, configuration ?? new OcelotPipelineConfiguration());
app.Properties["analysis.NextMiddlewareName"] = "TransitionToOcelotMiddleware";
app.Use(async delegate (HttpContext context, Func<Task> task)
{
DownstreamContext downstreamContext = new DownstreamContext(context);
await ocelotDelegate(downstreamContext);
});
return app;
}
private static IApplicationBuilder CreateOcelotPipeline(IApplicationBuilder builder, OcelotPipelineConfiguration pipelineConfiguration)
{
OcelotPipelineBuilder ocelotPipelineBuilder = new OcelotPipelineBuilder(builder.ApplicationServices);
ocelotPipelineBuilder.BuildOcelotPipeline(pipelineConfiguration);
OcelotRequestDelegate firstDelegate = ocelotPipelineBuilder.Build();
builder.BuildOcelotPipeline(pipelineConfiguration);
/*
inject first delegate into first piece of asp.net middleware..maybe not like this
then because we are updating the http context in ocelot it comes out correct for
rest of asp.net..
*/
builder.Properties["analysis.NextMiddlewareName"] = "TransitionToOcelotMiddleware";
builder.Use(async delegate (HttpContext context, Func<Task> task)
{
DownstreamContext downstreamContext = new DownstreamContext(context);
await firstDelegate(downstreamContext);
});
return builder;
}
private static async Task<IInternalConfiguration> CreateConfiguration(IApplicationBuilder builder)
{
/* ABP框架中,Abp.HttpClient这个模块里面
* RemoteServiceOptions IOptionsSnapshot注入的,
* RemoteService服务必须在一个请求范围内
* DynamicHttpProxyInterceptor类,IOptions<RemoteServiceOptions>
*
*/
var fileConfigRepo = builder.ApplicationServices.GetRequiredService<IFileConfigurationRepository>();
var fileConfig = await fileConfigRepo.Get();
// IOptionsMonitor<FileConfiguration> fileConfig = builder.ApplicationServices.GetService<IOptionsMonitor<FileConfiguration>>();
@ -97,26 +85,39 @@ namespace Ocelot.Extenssions
return GetOcelotConfigAndReturn(internalConfigRepo);
}
private static bool AdministrationApiInUse(IAdministrationPath adminPath)
{
return adminPath != null;
}
private static bool IsError(Response response)
{
return response == null || response.IsError;
}
private static IInternalConfiguration GetOcelotConfigAndReturn(IInternalConfigurationRepository provider)
{
Response<IInternalConfiguration> response = provider.Get();
if (response?.Data == null || response.IsError)
var ocelotConfiguration = provider.Get();
if (ocelotConfiguration?.Data == null || ocelotConfiguration.IsError)
{
ThrowToStopOcelotStarting(response);
ThrowToStopOcelotStarting(ocelotConfiguration);
}
return response.Data;
return ocelotConfiguration.Data;
}
private static void ThrowToStopOcelotStarting(Response config)
{
throw new Exception("Unable to start Ocelot, errors are: " + string.Join(",", ((IEnumerable<Error>)config.Errors).Select((Func<Error, string>)((Error x) => x.ToString()))));
throw new Exception($"Unable to start Ocelot, errors are: {string.Join(",", config.Errors.Select(x => x.ToString()))}");
}
private static void ConfigureDiagnosticListener(IApplicationBuilder builder)
{
builder.ApplicationServices.GetService<IWebHostEnvironment>();
OcelotDiagnosticListener service = builder.ApplicationServices.GetService<OcelotDiagnosticListener>();
builder.ApplicationServices.GetService<DiagnosticListener>().SubscribeWithAdapter(service);
var env = builder.ApplicationServices.GetService<IWebHostEnvironment>();
var listener = builder.ApplicationServices.GetService<OcelotDiagnosticListener>();
var diagnosticListener = builder.ApplicationServices.GetService<DiagnosticListener>();
diagnosticListener.SubscribeWithAdapter(listener);
}
}
}
Loading…
Cancel
Save