mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 06:48:16 +08:00
Feature/re route specific handlers (#269)
* #264 added handlers to config * #264 added global handlers object and defaut param for method, not sure this is correct api for users yet * #264 Can now add all sorts of delegating handlers in all sorts of ways * +semver: breaking #264
This commit is contained in:
@ -1,8 +0,0 @@
|
||||
namespace Ocelot.Authentication.Handler
|
||||
{
|
||||
public enum SupportedAuthenticationProviders
|
||||
{
|
||||
IdentityServer,
|
||||
Jwt
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Ocelot.Middleware.Pipeline;
|
||||
|
||||
namespace Ocelot.Authentication.Middleware
|
||||
|
@ -1,16 +1,12 @@
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Configuration;
|
||||
|
||||
namespace Ocelot.Authorisation.Middleware
|
||||
namespace Ocelot.Authorisation.Middleware
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Errors;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Ocelot.Middleware;
|
||||
using Logging;
|
||||
using Responses;
|
||||
using Configuration;
|
||||
|
||||
public class AuthorisationMiddleware : OcelotMiddleware
|
||||
{
|
||||
|
@ -2,8 +2,6 @@ using Ocelot.Middleware.Pipeline;
|
||||
|
||||
namespace Ocelot.Authorisation.Middleware
|
||||
{
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
||||
public static class AuthorisationMiddlewareMiddlewareExtensions
|
||||
{
|
||||
public static IOcelotPipelineBuilder UseAuthorisationMiddleware(this IOcelotPipelineBuilder builder)
|
||||
|
@ -34,9 +34,9 @@ namespace Ocelot.Authorisation
|
||||
|
||||
var userScopes = values.Data;
|
||||
|
||||
List<string> matchesScopes = routeAllowedScopes.Intersect(userScopes).ToList();
|
||||
var matchesScopes = routeAllowedScopes.Intersect(userScopes).ToList();
|
||||
|
||||
if (matchesScopes == null || matchesScopes.Count == 0)
|
||||
if (matchesScopes.Count == 0)
|
||||
{
|
||||
return new ErrorResponse<bool>(new List<Error>
|
||||
{
|
||||
@ -48,4 +48,4 @@ namespace Ocelot.Authorisation
|
||||
return new OkResponse<bool>(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,9 +36,12 @@ namespace Ocelot.Configuration.Builder
|
||||
private readonly List<DownstreamHostAndPort> _downstreamAddresses;
|
||||
private string _upstreamHost;
|
||||
private string _key;
|
||||
private List<string> _delegatingHandlers;
|
||||
|
||||
public DownstreamReRouteBuilder()
|
||||
{
|
||||
_downstreamAddresses = new List<DownstreamHostAndPort>();
|
||||
_delegatingHandlers = new List<string>();
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithDownstreamAddresses(List<DownstreamHostAndPort> downstreamAddresses)
|
||||
@ -215,6 +218,12 @@ namespace Ocelot.Configuration.Builder
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRouteBuilder WithDelegatingHandlers(List<string> delegatingHandlers)
|
||||
{
|
||||
_delegatingHandlers = delegatingHandlers;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownstreamReRoute Build()
|
||||
{
|
||||
return new DownstreamReRoute(
|
||||
@ -243,7 +252,8 @@ namespace Ocelot.Configuration.Builder
|
||||
_isAuthorised,
|
||||
_authenticationOptions,
|
||||
new PathTemplate(_downstreamPathTemplate),
|
||||
_reRouteKey);
|
||||
_reRouteKey,
|
||||
_delegatingHandlers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -212,6 +212,7 @@ namespace Ocelot.Configuration.Creator
|
||||
.WithUpstreamHeaderFindAndReplace(hAndRs.Upstream)
|
||||
.WithDownstreamHeaderFindAndReplace(hAndRs.Downstream)
|
||||
.WithUpstreamHost(fileReRoute.UpstreamHost)
|
||||
.WithDelegatingHandlers(fileReRoute.DelegatingHandlers)
|
||||
.Build();
|
||||
|
||||
return reRoute;
|
||||
|
@ -31,8 +31,10 @@ namespace Ocelot.Configuration
|
||||
bool isAuthorised,
|
||||
AuthenticationOptions authenticationOptions,
|
||||
PathTemplate downstreamPathTemplate,
|
||||
string reRouteKey)
|
||||
string reRouteKey,
|
||||
List<string> delegatingHandlers)
|
||||
{
|
||||
DelegatingHandlers = delegatingHandlers;
|
||||
Key = key;
|
||||
UpstreamPathTemplate = upstreamPathTemplate;
|
||||
UpstreamHeadersFindAndReplace = upstreamHeadersFindAndReplace ?? new List<HeaderFindAndReplace>();
|
||||
@ -87,5 +89,6 @@ namespace Ocelot.Configuration
|
||||
public AuthenticationOptions AuthenticationOptions { get; private set; }
|
||||
public PathTemplate DownstreamPathTemplate { get; private set; }
|
||||
public string ReRouteKey { get; private set; }
|
||||
public List<string> DelegatingHandlers {get;private set;}
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ namespace Ocelot.Configuration.File
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions();
|
||||
UpstreamHeaderTransform = new Dictionary<string, string>();
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>();
|
||||
DelegatingHandlers = new List<string>();
|
||||
}
|
||||
|
||||
public string DownstreamPathTemplate { get; set; }
|
||||
@ -44,5 +45,6 @@ namespace Ocelot.Configuration.File
|
||||
public List<FileHostAndPort> DownstreamHostAndPorts {get;set;}
|
||||
public string UpstreamHost { get; set; }
|
||||
public string Key { get;set; }
|
||||
public List<string> DelegatingHandlers {get;set;}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ using CacheManager.Core;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using IdentityServer4.AccessTokenValidation;
|
||||
using Ocelot.Requester;
|
||||
|
||||
namespace Ocelot.DependencyInjection
|
||||
{
|
||||
@ -19,6 +18,10 @@ namespace Ocelot.DependencyInjection
|
||||
|
||||
IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configOptions);
|
||||
|
||||
IOcelotBuilder AddDelegatingHandler<T>() where T : DelegatingHandler;
|
||||
IOcelotBuilder AddSingletonDelegatingHandler<T>(bool global = false)
|
||||
where T : DelegatingHandler;
|
||||
|
||||
IOcelotBuilder AddTransientDelegatingHandler<T>(bool global = false)
|
||||
where T : DelegatingHandler;
|
||||
}
|
||||
}
|
||||
|
@ -182,10 +182,41 @@ namespace Ocelot.DependencyInjection
|
||||
return new OcelotAdministrationBuilder(_services, _configurationRoot);
|
||||
}
|
||||
|
||||
public IOcelotBuilder AddDelegatingHandler<THandler>()
|
||||
public IOcelotBuilder AddSingletonDelegatingHandler<THandler>(bool global = false)
|
||||
where THandler : DelegatingHandler
|
||||
{
|
||||
if(global)
|
||||
{
|
||||
_services.AddSingleton<THandler>();
|
||||
_services.AddSingleton<GlobalDelegatingHandler>(s => {
|
||||
var service = s.GetService<THandler>();
|
||||
return new GlobalDelegatingHandler(service);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_services.AddSingleton<DelegatingHandler, THandler>();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public IOcelotBuilder AddTransientDelegatingHandler<THandler>(bool global = false)
|
||||
where THandler : DelegatingHandler
|
||||
{
|
||||
_services.AddSingleton<DelegatingHandler, THandler>();
|
||||
if(global)
|
||||
{
|
||||
_services.AddTransient<THandler>();
|
||||
_services.AddTransient<GlobalDelegatingHandler>(s => {
|
||||
var service = s.GetService<THandler>();
|
||||
return new GlobalDelegatingHandler(service);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_services.AddTransient<DelegatingHandler, THandler>();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,17 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Ocelot.Authentication
|
||||
{
|
||||
class BearerToken
|
||||
{
|
||||
[JsonProperty("access_token")]
|
||||
public string AccessToken { get; set; }
|
||||
|
||||
[JsonProperty("expires_in")]
|
||||
public int ExpiresIn { get; set; }
|
||||
|
||||
[JsonProperty("token_type")]
|
||||
public string TokenType { get; set; }
|
||||
}
|
||||
}
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Ocelot.Raft
|
||||
{
|
||||
[ExcludeFromCoverage]
|
||||
internal class BearerToken
|
||||
{
|
||||
[JsonProperty("access_token")]
|
||||
public string AccessToken { get; set; }
|
||||
|
||||
[JsonProperty("expires_in")]
|
||||
public int ExpiresIn { get; set; }
|
||||
|
||||
[JsonProperty("token_type")]
|
||||
public string TokenType { get; set; }
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Configuration;
|
||||
@ -29,13 +30,36 @@ namespace Ocelot.Requester
|
||||
|
||||
public Response<List<Func<DelegatingHandler>>> Get(DownstreamReRoute request)
|
||||
{
|
||||
var handlersAppliedToAll = _serviceProvider.GetServices<DelegatingHandler>();
|
||||
var globalDelegatingHandlers = _serviceProvider
|
||||
.GetServices<GlobalDelegatingHandler>()
|
||||
.ToList();
|
||||
|
||||
var reRouteSpecificHandlers = _serviceProvider
|
||||
.GetServices<DelegatingHandler>()
|
||||
.ToList();
|
||||
|
||||
var handlers = new List<Func<DelegatingHandler>>();
|
||||
|
||||
foreach (var handler in handlersAppliedToAll)
|
||||
foreach (var handler in globalDelegatingHandlers)
|
||||
{
|
||||
handlers.Add(() => handler);
|
||||
if (GlobalIsInHandlersConfig(request, handler))
|
||||
{
|
||||
reRouteSpecificHandlers.Add(handler.DelegatingHandler);
|
||||
}
|
||||
else
|
||||
{
|
||||
handlers.Add(() => handler.DelegatingHandler);
|
||||
}
|
||||
}
|
||||
|
||||
if (request.DelegatingHandlers.Any())
|
||||
{
|
||||
var sorted = SortByConfigOrder(request, reRouteSpecificHandlers);
|
||||
|
||||
foreach (var handler in sorted)
|
||||
{
|
||||
handlers.Add(() => handler);
|
||||
}
|
||||
}
|
||||
|
||||
if (request.HttpHandlerOptions.UseTracing)
|
||||
@ -57,5 +81,22 @@ namespace Ocelot.Requester
|
||||
|
||||
return new OkResponse<List<Func<DelegatingHandler>>>(handlers);
|
||||
}
|
||||
|
||||
private List<DelegatingHandler> SortByConfigOrder(DownstreamReRoute request, List<DelegatingHandler> reRouteSpecificHandlers)
|
||||
{
|
||||
return reRouteSpecificHandlers
|
||||
.Where(x => request.DelegatingHandlers.Contains(x.GetType().Name))
|
||||
.OrderBy(d =>
|
||||
{
|
||||
var type = d.GetType().Name;
|
||||
var pos = request.DelegatingHandlers.IndexOf(type);
|
||||
return pos;
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
private bool GlobalIsInHandlersConfig(DownstreamReRoute request, GlobalDelegatingHandler handler)
|
||||
{
|
||||
return request.DelegatingHandlers.Contains(handler.DelegatingHandler.GetType().Name);
|
||||
}
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@ namespace Ocelot.Requester
|
||||
private readonly IOcelotLogger _logger;
|
||||
private readonly IDelegatingHandlerHandlerFactory _factory;
|
||||
|
||||
public HttpClientHttpRequester(IOcelotLoggerFactory loggerFactory,
|
||||
public HttpClientHttpRequester(IOcelotLoggerFactory loggerFactory,
|
||||
IHttpClientCache cacheHandlers,
|
||||
IDelegatingHandlerHandlerFactory house)
|
||||
{
|
||||
@ -29,7 +29,7 @@ namespace Ocelot.Requester
|
||||
var builder = new HttpClientBuilder(_factory);
|
||||
|
||||
var cacheKey = GetCacheKey(request);
|
||||
|
||||
|
||||
var httpClient = GetHttpClient(cacheKey, builder, request);
|
||||
|
||||
try
|
||||
@ -72,8 +72,23 @@ namespace Ocelot.Requester
|
||||
private string GetCacheKey(DownstreamContext request)
|
||||
{
|
||||
var baseUrl = $"{request.DownstreamRequest.RequestUri.Scheme}://{request.DownstreamRequest.RequestUri.Authority}";
|
||||
|
||||
|
||||
return baseUrl;
|
||||
}
|
||||
}
|
||||
|
||||
public class ReRouteDelegatingHandler<T> where T : DelegatingHandler
|
||||
{
|
||||
public T DelegatingHandler { get; private set; }
|
||||
}
|
||||
|
||||
public class GlobalDelegatingHandler
|
||||
{
|
||||
public GlobalDelegatingHandler(DelegatingHandler delegatingHandler)
|
||||
{
|
||||
DelegatingHandler = delegatingHandler;
|
||||
}
|
||||
|
||||
public DelegatingHandler DelegatingHandler { get; private set; }
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user