mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 23:30:50 +08:00 
			
		
		
		
	#296 merged develop into this branch
This commit is contained in:
		@@ -39,12 +39,14 @@ namespace Ocelot.Configuration.Builder
 | 
			
		||||
        private string _key;
 | 
			
		||||
        private List<string> _delegatingHandlers;
 | 
			
		||||
        private List<AddHeader> _addHeadersToDownstream;
 | 
			
		||||
        private List<AddHeader> _addHeadersToUpstream;
 | 
			
		||||
 | 
			
		||||
        public DownstreamReRouteBuilder()
 | 
			
		||||
        {
 | 
			
		||||
            _downstreamAddresses = new List<DownstreamHostAndPort>();
 | 
			
		||||
            _delegatingHandlers = new List<string>();
 | 
			
		||||
            _addHeadersToDownstream = new List<AddHeader>();
 | 
			
		||||
            _addHeadersToUpstream = new List<AddHeader>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public DownstreamReRouteBuilder WithDownstreamAddresses(List<DownstreamHostAndPort> downstreamAddresses)
 | 
			
		||||
@@ -233,6 +235,12 @@ namespace Ocelot.Configuration.Builder
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public DownstreamReRouteBuilder WithAddHeadersToUpstream(List<AddHeader> addHeadersToUpstream)
 | 
			
		||||
        {
 | 
			
		||||
            _addHeadersToUpstream = addHeadersToUpstream;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public DownstreamReRoute Build()
 | 
			
		||||
        {
 | 
			
		||||
            return new DownstreamReRoute(
 | 
			
		||||
@@ -263,7 +271,8 @@ namespace Ocelot.Configuration.Builder
 | 
			
		||||
                new PathTemplate(_downstreamPathTemplate),
 | 
			
		||||
                _reRouteKey,
 | 
			
		||||
                _delegatingHandlers,
 | 
			
		||||
                _addHeadersToDownstream);
 | 
			
		||||
                _addHeadersToDownstream,
 | 
			
		||||
                _addHeadersToUpstream);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,227 +1,228 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.Extensions.Options;
 | 
			
		||||
using Ocelot.Cache;
 | 
			
		||||
using Ocelot.Configuration.Builder;
 | 
			
		||||
using Ocelot.Configuration.File;
 | 
			
		||||
using Ocelot.Configuration.Validator;
 | 
			
		||||
using Ocelot.DependencyInjection;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Configuration.Creator
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Register as singleton
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class FileInternalConfigurationCreator : IInternalConfigurationCreator
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IConfigurationValidator _configurationValidator;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly IClaimsToThingCreator _claimsToThingCreator;
 | 
			
		||||
        private readonly IAuthenticationOptionsCreator _authOptionsCreator;
 | 
			
		||||
        private readonly IUpstreamTemplatePatternCreator _upstreamTemplatePatternCreator;
 | 
			
		||||
        private readonly IRequestIdKeyCreator _requestIdKeyCreator;
 | 
			
		||||
        private readonly IServiceProviderConfigurationCreator _serviceProviderConfigCreator;
 | 
			
		||||
        private readonly IQoSOptionsCreator _qosOptionsCreator;
 | 
			
		||||
        private readonly IReRouteOptionsCreator _fileReRouteOptionsCreator;
 | 
			
		||||
        private readonly IRateLimitOptionsCreator _rateLimitOptionsCreator;
 | 
			
		||||
        private readonly IRegionCreator _regionCreator;
 | 
			
		||||
        private readonly IHttpHandlerOptionsCreator _httpHandlerOptionsCreator;
 | 
			
		||||
        private readonly IAdministrationPath _adminPath;
 | 
			
		||||
        private readonly IHeaderFindAndReplaceCreator _headerFAndRCreator;
 | 
			
		||||
        private readonly IDownstreamAddressesCreator _downstreamAddressesCreator;
 | 
			
		||||
 | 
			
		||||
        public FileInternalConfigurationCreator(
 | 
			
		||||
            IConfigurationValidator configurationValidator,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory,
 | 
			
		||||
            IClaimsToThingCreator claimsToThingCreator,
 | 
			
		||||
            IAuthenticationOptionsCreator authOptionsCreator,
 | 
			
		||||
            IUpstreamTemplatePatternCreator upstreamTemplatePatternCreator,
 | 
			
		||||
            IRequestIdKeyCreator requestIdKeyCreator,
 | 
			
		||||
            IServiceProviderConfigurationCreator serviceProviderConfigCreator,
 | 
			
		||||
            IQoSOptionsCreator qosOptionsCreator,
 | 
			
		||||
            IReRouteOptionsCreator fileReRouteOptionsCreator,
 | 
			
		||||
            IRateLimitOptionsCreator rateLimitOptionsCreator,
 | 
			
		||||
            IRegionCreator regionCreator,
 | 
			
		||||
            IHttpHandlerOptionsCreator httpHandlerOptionsCreator,
 | 
			
		||||
            IAdministrationPath adminPath,
 | 
			
		||||
            IHeaderFindAndReplaceCreator headerFAndRCreator,
 | 
			
		||||
            IDownstreamAddressesCreator downstreamAddressesCreator
 | 
			
		||||
            )
 | 
			
		||||
        {
 | 
			
		||||
            _downstreamAddressesCreator = downstreamAddressesCreator;
 | 
			
		||||
            _headerFAndRCreator = headerFAndRCreator;
 | 
			
		||||
            _adminPath = adminPath;
 | 
			
		||||
            _regionCreator = regionCreator;
 | 
			
		||||
            _rateLimitOptionsCreator = rateLimitOptionsCreator;
 | 
			
		||||
            _requestIdKeyCreator = requestIdKeyCreator;
 | 
			
		||||
            _upstreamTemplatePatternCreator = upstreamTemplatePatternCreator;
 | 
			
		||||
            _authOptionsCreator = authOptionsCreator;
 | 
			
		||||
            _configurationValidator = configurationValidator;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<FileInternalConfigurationCreator>();
 | 
			
		||||
            _claimsToThingCreator = claimsToThingCreator;
 | 
			
		||||
            _serviceProviderConfigCreator = serviceProviderConfigCreator;
 | 
			
		||||
            _qosOptionsCreator = qosOptionsCreator;
 | 
			
		||||
            _fileReRouteOptionsCreator = fileReRouteOptionsCreator;
 | 
			
		||||
            _httpHandlerOptionsCreator = httpHandlerOptionsCreator;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public async Task<Response<IInternalConfiguration>> Create(FileConfiguration fileConfiguration)
 | 
			
		||||
        {     
 | 
			
		||||
            var config = await SetUpConfiguration(fileConfiguration);
 | 
			
		||||
            return config;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task<Response<IInternalConfiguration>> SetUpConfiguration(FileConfiguration fileConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            var response = await _configurationValidator.IsValid(fileConfiguration);
 | 
			
		||||
 | 
			
		||||
            if (response.Data.IsError)
 | 
			
		||||
            {
 | 
			
		||||
                return new ErrorResponse<IInternalConfiguration>(response.Data.Errors);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var reRoutes = new List<ReRoute>();
 | 
			
		||||
 | 
			
		||||
            foreach (var reRoute in fileConfiguration.ReRoutes)
 | 
			
		||||
            {
 | 
			
		||||
                var downstreamReRoute = SetUpDownstreamReRoute(reRoute, fileConfiguration.GlobalConfiguration);
 | 
			
		||||
 | 
			
		||||
                var ocelotReRoute = SetUpReRoute(reRoute, downstreamReRoute);
 | 
			
		||||
                
 | 
			
		||||
                reRoutes.Add(ocelotReRoute);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (var aggregate in fileConfiguration.Aggregates)
 | 
			
		||||
            {
 | 
			
		||||
                var ocelotReRoute = SetUpAggregateReRoute(reRoutes, aggregate, fileConfiguration.GlobalConfiguration);
 | 
			
		||||
                reRoutes.Add(ocelotReRoute);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration);
 | 
			
		||||
            
 | 
			
		||||
            var config = new InternalConfiguration(reRoutes, _adminPath.Path, serviceProviderConfiguration, fileConfiguration.GlobalConfiguration.RequestIdKey);
 | 
			
		||||
 | 
			
		||||
            return new OkResponse<IInternalConfiguration>(config);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ReRoute SetUpAggregateReRoute(List<ReRoute> reRoutes, FileAggregateReRoute aggregateReRoute, FileGlobalConfiguration globalConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            var applicableReRoutes = reRoutes
 | 
			
		||||
                .SelectMany(x => x.DownstreamReRoute)
 | 
			
		||||
                .Where(r => aggregateReRoute.ReRouteKeys.Contains(r.Key))
 | 
			
		||||
                .ToList();
 | 
			
		||||
 | 
			
		||||
            if(applicableReRoutes.Count != aggregateReRoute.ReRouteKeys.Count)
 | 
			
		||||
            {
 | 
			
		||||
                //todo - log or throw or return error whatever?
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //make another re route out of these
 | 
			
		||||
            var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(aggregateReRoute);
 | 
			
		||||
 | 
			
		||||
            var reRoute = new ReRouteBuilder()
 | 
			
		||||
                .WithUpstreamPathTemplate(aggregateReRoute.UpstreamPathTemplate)
 | 
			
		||||
                .WithUpstreamHttpMethod(aggregateReRoute.UpstreamHttpMethod)
 | 
			
		||||
                .WithUpstreamTemplatePattern(upstreamTemplatePattern)
 | 
			
		||||
                .WithDownstreamReRoutes(applicableReRoutes)
 | 
			
		||||
                .WithUpstreamHost(aggregateReRoute.UpstreamHost)
 | 
			
		||||
                .WithAggregator(aggregateReRoute.Aggregator)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            return reRoute;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private ReRoute SetUpReRoute(FileReRoute fileReRoute, DownstreamReRoute downstreamReRoutes)
 | 
			
		||||
        {
 | 
			
		||||
            var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var reRoute = new ReRouteBuilder()
 | 
			
		||||
                .WithUpstreamPathTemplate(fileReRoute.UpstreamPathTemplate)
 | 
			
		||||
                .WithUpstreamHttpMethod(fileReRoute.UpstreamHttpMethod)
 | 
			
		||||
                .WithUpstreamTemplatePattern(upstreamTemplatePattern)
 | 
			
		||||
                .WithDownstreamReRoute(downstreamReRoutes)
 | 
			
		||||
                .WithUpstreamHost(fileReRoute.UpstreamHost)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            return reRoute;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
         private DownstreamReRoute SetUpDownstreamReRoute(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRouteOptions = _fileReRouteOptionsCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var requestIdKey = _requestIdKeyCreator.Create(fileReRoute, globalConfiguration);
 | 
			
		||||
 | 
			
		||||
            var reRouteKey = CreateReRouteKey(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var authOptionsForRoute = _authOptionsCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var claimsToHeaders = _claimsToThingCreator.Create(fileReRoute.AddHeadersToRequest);
 | 
			
		||||
 | 
			
		||||
            var claimsToClaims = _claimsToThingCreator.Create(fileReRoute.AddClaimsToRequest);
 | 
			
		||||
 | 
			
		||||
            var claimsToQueries = _claimsToThingCreator.Create(fileReRoute.AddQueriesToRequest);
 | 
			
		||||
 | 
			
		||||
            var qosOptions = _qosOptionsCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var rateLimitOption = _rateLimitOptionsCreator.Create(fileReRoute, globalConfiguration, fileReRouteOptions.EnableRateLimiting);
 | 
			
		||||
 | 
			
		||||
            var region = _regionCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var hAndRs = _headerFAndRCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var downstreamAddresses = _downstreamAddressesCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var reRoute = new DownstreamReRouteBuilder()
 | 
			
		||||
                .WithKey(fileReRoute.Key)
 | 
			
		||||
                .WithDownstreamPathTemplate(fileReRoute.DownstreamPathTemplate)
 | 
			
		||||
                .WithUpstreamPathTemplate(fileReRoute.UpstreamPathTemplate)
 | 
			
		||||
                .WithUpstreamHttpMethod(fileReRoute.UpstreamHttpMethod)
 | 
			
		||||
                .WithUpstreamTemplatePattern(upstreamTemplatePattern)
 | 
			
		||||
                .WithIsAuthenticated(fileReRouteOptions.IsAuthenticated)
 | 
			
		||||
                .WithAuthenticationOptions(authOptionsForRoute)
 | 
			
		||||
                .WithClaimsToHeaders(claimsToHeaders)
 | 
			
		||||
                .WithClaimsToClaims(claimsToClaims)
 | 
			
		||||
                .WithRouteClaimsRequirement(fileReRoute.RouteClaimsRequirement)
 | 
			
		||||
                .WithIsAuthorised(fileReRouteOptions.IsAuthorised)
 | 
			
		||||
                .WithClaimsToQueries(claimsToQueries)
 | 
			
		||||
                .WithRequestIdKey(requestIdKey)
 | 
			
		||||
                .WithIsCached(fileReRouteOptions.IsCached)
 | 
			
		||||
                .WithCacheOptions(new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds, region))
 | 
			
		||||
                .WithDownstreamScheme(fileReRoute.DownstreamScheme)
 | 
			
		||||
                .WithLoadBalancer(fileReRoute.LoadBalancer)
 | 
			
		||||
                .WithDownstreamAddresses(downstreamAddresses)
 | 
			
		||||
                .WithReRouteKey(reRouteKey)
 | 
			
		||||
                .WithIsQos(fileReRouteOptions.IsQos)
 | 
			
		||||
                .WithQosOptions(qosOptions)
 | 
			
		||||
                .WithEnableRateLimiting(fileReRouteOptions.EnableRateLimiting)
 | 
			
		||||
                .WithRateLimitOptions(rateLimitOption)
 | 
			
		||||
                .WithHttpHandlerOptions(httpHandlerOptions)
 | 
			
		||||
                .WithServiceName(fileReRoute.ServiceName)
 | 
			
		||||
                .WithUseServiceDiscovery(fileReRoute.UseServiceDiscovery)
 | 
			
		||||
                .WithUpstreamHeaderFindAndReplace(hAndRs.Upstream)
 | 
			
		||||
                .WithDownstreamHeaderFindAndReplace(hAndRs.Downstream)
 | 
			
		||||
                .WithUpstreamHost(fileReRoute.UpstreamHost)
 | 
			
		||||
                .WithDelegatingHandlers(fileReRoute.DelegatingHandlers)
 | 
			
		||||
                .WithAddHeadersToDownstream(hAndRs.AddHeadersToDownstream)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            return reRoute;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private string CreateReRouteKey(FileReRoute fileReRoute)
 | 
			
		||||
        {
 | 
			
		||||
            //note - not sure if this is the correct key, but this is probably the only unique key i can think of given my poor brain
 | 
			
		||||
            var loadBalancerKey = $"{fileReRoute.UpstreamPathTemplate}|{string.Join(",", fileReRoute.UpstreamHttpMethod)}";
 | 
			
		||||
            return loadBalancerKey;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.Extensions.Options;
 | 
			
		||||
using Ocelot.Cache;
 | 
			
		||||
using Ocelot.Configuration.Builder;
 | 
			
		||||
using Ocelot.Configuration.File;
 | 
			
		||||
using Ocelot.Configuration.Validator;
 | 
			
		||||
using Ocelot.DependencyInjection;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Configuration.Creator
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Register as singleton
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class FileInternalConfigurationCreator : IInternalConfigurationCreator
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IConfigurationValidator _configurationValidator;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
        private readonly IClaimsToThingCreator _claimsToThingCreator;
 | 
			
		||||
        private readonly IAuthenticationOptionsCreator _authOptionsCreator;
 | 
			
		||||
        private readonly IUpstreamTemplatePatternCreator _upstreamTemplatePatternCreator;
 | 
			
		||||
        private readonly IRequestIdKeyCreator _requestIdKeyCreator;
 | 
			
		||||
        private readonly IServiceProviderConfigurationCreator _serviceProviderConfigCreator;
 | 
			
		||||
        private readonly IQoSOptionsCreator _qosOptionsCreator;
 | 
			
		||||
        private readonly IReRouteOptionsCreator _fileReRouteOptionsCreator;
 | 
			
		||||
        private readonly IRateLimitOptionsCreator _rateLimitOptionsCreator;
 | 
			
		||||
        private readonly IRegionCreator _regionCreator;
 | 
			
		||||
        private readonly IHttpHandlerOptionsCreator _httpHandlerOptionsCreator;
 | 
			
		||||
        private readonly IAdministrationPath _adminPath;
 | 
			
		||||
        private readonly IHeaderFindAndReplaceCreator _headerFAndRCreator;
 | 
			
		||||
        private readonly IDownstreamAddressesCreator _downstreamAddressesCreator;
 | 
			
		||||
 | 
			
		||||
        public FileInternalConfigurationCreator(
 | 
			
		||||
            IConfigurationValidator configurationValidator,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory,
 | 
			
		||||
            IClaimsToThingCreator claimsToThingCreator,
 | 
			
		||||
            IAuthenticationOptionsCreator authOptionsCreator,
 | 
			
		||||
            IUpstreamTemplatePatternCreator upstreamTemplatePatternCreator,
 | 
			
		||||
            IRequestIdKeyCreator requestIdKeyCreator,
 | 
			
		||||
            IServiceProviderConfigurationCreator serviceProviderConfigCreator,
 | 
			
		||||
            IQoSOptionsCreator qosOptionsCreator,
 | 
			
		||||
            IReRouteOptionsCreator fileReRouteOptionsCreator,
 | 
			
		||||
            IRateLimitOptionsCreator rateLimitOptionsCreator,
 | 
			
		||||
            IRegionCreator regionCreator,
 | 
			
		||||
            IHttpHandlerOptionsCreator httpHandlerOptionsCreator,
 | 
			
		||||
            IAdministrationPath adminPath,
 | 
			
		||||
            IHeaderFindAndReplaceCreator headerFAndRCreator,
 | 
			
		||||
            IDownstreamAddressesCreator downstreamAddressesCreator
 | 
			
		||||
            )
 | 
			
		||||
        {
 | 
			
		||||
            _downstreamAddressesCreator = downstreamAddressesCreator;
 | 
			
		||||
            _headerFAndRCreator = headerFAndRCreator;
 | 
			
		||||
            _adminPath = adminPath;
 | 
			
		||||
            _regionCreator = regionCreator;
 | 
			
		||||
            _rateLimitOptionsCreator = rateLimitOptionsCreator;
 | 
			
		||||
            _requestIdKeyCreator = requestIdKeyCreator;
 | 
			
		||||
            _upstreamTemplatePatternCreator = upstreamTemplatePatternCreator;
 | 
			
		||||
            _authOptionsCreator = authOptionsCreator;
 | 
			
		||||
            _configurationValidator = configurationValidator;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<FileInternalConfigurationCreator>();
 | 
			
		||||
            _claimsToThingCreator = claimsToThingCreator;
 | 
			
		||||
            _serviceProviderConfigCreator = serviceProviderConfigCreator;
 | 
			
		||||
            _qosOptionsCreator = qosOptionsCreator;
 | 
			
		||||
            _fileReRouteOptionsCreator = fileReRouteOptionsCreator;
 | 
			
		||||
            _httpHandlerOptionsCreator = httpHandlerOptionsCreator;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public async Task<Response<IInternalConfiguration>> Create(FileConfiguration fileConfiguration)
 | 
			
		||||
        {     
 | 
			
		||||
            var config = await SetUpConfiguration(fileConfiguration);
 | 
			
		||||
            return config;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task<Response<IInternalConfiguration>> SetUpConfiguration(FileConfiguration fileConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            var response = await _configurationValidator.IsValid(fileConfiguration);
 | 
			
		||||
 | 
			
		||||
            if (response.Data.IsError)
 | 
			
		||||
            {
 | 
			
		||||
                return new ErrorResponse<IInternalConfiguration>(response.Data.Errors);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var reRoutes = new List<ReRoute>();
 | 
			
		||||
 | 
			
		||||
            foreach (var reRoute in fileConfiguration.ReRoutes)
 | 
			
		||||
            {
 | 
			
		||||
                var downstreamReRoute = SetUpDownstreamReRoute(reRoute, fileConfiguration.GlobalConfiguration);
 | 
			
		||||
 | 
			
		||||
                var ocelotReRoute = SetUpReRoute(reRoute, downstreamReRoute);
 | 
			
		||||
                
 | 
			
		||||
                reRoutes.Add(ocelotReRoute);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (var aggregate in fileConfiguration.Aggregates)
 | 
			
		||||
            {
 | 
			
		||||
                var ocelotReRoute = SetUpAggregateReRoute(reRoutes, aggregate, fileConfiguration.GlobalConfiguration);
 | 
			
		||||
                reRoutes.Add(ocelotReRoute);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration);
 | 
			
		||||
            
 | 
			
		||||
            var config = new InternalConfiguration(reRoutes, _adminPath.Path, serviceProviderConfiguration, fileConfiguration.GlobalConfiguration.RequestIdKey);
 | 
			
		||||
 | 
			
		||||
            return new OkResponse<IInternalConfiguration>(config);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ReRoute SetUpAggregateReRoute(List<ReRoute> reRoutes, FileAggregateReRoute aggregateReRoute, FileGlobalConfiguration globalConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            var applicableReRoutes = reRoutes
 | 
			
		||||
                .SelectMany(x => x.DownstreamReRoute)
 | 
			
		||||
                .Where(r => aggregateReRoute.ReRouteKeys.Contains(r.Key))
 | 
			
		||||
                .ToList();
 | 
			
		||||
 | 
			
		||||
            if(applicableReRoutes.Count != aggregateReRoute.ReRouteKeys.Count)
 | 
			
		||||
            {
 | 
			
		||||
                //todo - log or throw or return error whatever?
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //make another re route out of these
 | 
			
		||||
            var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(aggregateReRoute);
 | 
			
		||||
 | 
			
		||||
            var reRoute = new ReRouteBuilder()
 | 
			
		||||
                .WithUpstreamPathTemplate(aggregateReRoute.UpstreamPathTemplate)
 | 
			
		||||
                .WithUpstreamHttpMethod(aggregateReRoute.UpstreamHttpMethod)
 | 
			
		||||
                .WithUpstreamTemplatePattern(upstreamTemplatePattern)
 | 
			
		||||
                .WithDownstreamReRoutes(applicableReRoutes)
 | 
			
		||||
                .WithUpstreamHost(aggregateReRoute.UpstreamHost)
 | 
			
		||||
                .WithAggregator(aggregateReRoute.Aggregator)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            return reRoute;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private ReRoute SetUpReRoute(FileReRoute fileReRoute, DownstreamReRoute downstreamReRoutes)
 | 
			
		||||
        {
 | 
			
		||||
            var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var reRoute = new ReRouteBuilder()
 | 
			
		||||
                .WithUpstreamPathTemplate(fileReRoute.UpstreamPathTemplate)
 | 
			
		||||
                .WithUpstreamHttpMethod(fileReRoute.UpstreamHttpMethod)
 | 
			
		||||
                .WithUpstreamTemplatePattern(upstreamTemplatePattern)
 | 
			
		||||
                .WithDownstreamReRoute(downstreamReRoutes)
 | 
			
		||||
                .WithUpstreamHost(fileReRoute.UpstreamHost)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            return reRoute;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
         private DownstreamReRoute SetUpDownstreamReRoute(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
 | 
			
		||||
        {
 | 
			
		||||
            var fileReRouteOptions = _fileReRouteOptionsCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var requestIdKey = _requestIdKeyCreator.Create(fileReRoute, globalConfiguration);
 | 
			
		||||
 | 
			
		||||
            var reRouteKey = CreateReRouteKey(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var authOptionsForRoute = _authOptionsCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var claimsToHeaders = _claimsToThingCreator.Create(fileReRoute.AddHeadersToRequest);
 | 
			
		||||
 | 
			
		||||
            var claimsToClaims = _claimsToThingCreator.Create(fileReRoute.AddClaimsToRequest);
 | 
			
		||||
 | 
			
		||||
            var claimsToQueries = _claimsToThingCreator.Create(fileReRoute.AddQueriesToRequest);
 | 
			
		||||
 | 
			
		||||
            var qosOptions = _qosOptionsCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var rateLimitOption = _rateLimitOptionsCreator.Create(fileReRoute, globalConfiguration, fileReRouteOptions.EnableRateLimiting);
 | 
			
		||||
 | 
			
		||||
            var region = _regionCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var hAndRs = _headerFAndRCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var downstreamAddresses = _downstreamAddressesCreator.Create(fileReRoute);
 | 
			
		||||
 | 
			
		||||
            var reRoute = new DownstreamReRouteBuilder()
 | 
			
		||||
                .WithKey(fileReRoute.Key)
 | 
			
		||||
                .WithDownstreamPathTemplate(fileReRoute.DownstreamPathTemplate)
 | 
			
		||||
                .WithUpstreamPathTemplate(fileReRoute.UpstreamPathTemplate)
 | 
			
		||||
                .WithUpstreamHttpMethod(fileReRoute.UpstreamHttpMethod)
 | 
			
		||||
                .WithUpstreamTemplatePattern(upstreamTemplatePattern)
 | 
			
		||||
                .WithIsAuthenticated(fileReRouteOptions.IsAuthenticated)
 | 
			
		||||
                .WithAuthenticationOptions(authOptionsForRoute)
 | 
			
		||||
                .WithClaimsToHeaders(claimsToHeaders)
 | 
			
		||||
                .WithClaimsToClaims(claimsToClaims)
 | 
			
		||||
                .WithRouteClaimsRequirement(fileReRoute.RouteClaimsRequirement)
 | 
			
		||||
                .WithIsAuthorised(fileReRouteOptions.IsAuthorised)
 | 
			
		||||
                .WithClaimsToQueries(claimsToQueries)
 | 
			
		||||
                .WithRequestIdKey(requestIdKey)
 | 
			
		||||
                .WithIsCached(fileReRouteOptions.IsCached)
 | 
			
		||||
                .WithCacheOptions(new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds, region))
 | 
			
		||||
                .WithDownstreamScheme(fileReRoute.DownstreamScheme)
 | 
			
		||||
                .WithLoadBalancer(fileReRoute.LoadBalancer)
 | 
			
		||||
                .WithDownstreamAddresses(downstreamAddresses)
 | 
			
		||||
                .WithReRouteKey(reRouteKey)
 | 
			
		||||
                .WithIsQos(fileReRouteOptions.IsQos)
 | 
			
		||||
                .WithQosOptions(qosOptions)
 | 
			
		||||
                .WithEnableRateLimiting(fileReRouteOptions.EnableRateLimiting)
 | 
			
		||||
                .WithRateLimitOptions(rateLimitOption)
 | 
			
		||||
                .WithHttpHandlerOptions(httpHandlerOptions)
 | 
			
		||||
                .WithServiceName(fileReRoute.ServiceName)
 | 
			
		||||
                .WithUseServiceDiscovery(fileReRoute.UseServiceDiscovery)
 | 
			
		||||
                .WithUpstreamHeaderFindAndReplace(hAndRs.Upstream)
 | 
			
		||||
                .WithDownstreamHeaderFindAndReplace(hAndRs.Downstream)
 | 
			
		||||
                .WithUpstreamHost(fileReRoute.UpstreamHost)
 | 
			
		||||
                .WithDelegatingHandlers(fileReRoute.DelegatingHandlers)
 | 
			
		||||
                .WithAddHeadersToDownstream(hAndRs.AddHeadersToDownstream)
 | 
			
		||||
                .WithAddHeadersToUpstream(hAndRs.AddHeadersToUpstream)
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            return reRoute;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private string CreateReRouteKey(FileReRoute fileReRoute)
 | 
			
		||||
        {
 | 
			
		||||
            //note - not sure if this is the correct key, but this is probably the only unique key i can think of given my poor brain
 | 
			
		||||
            var loadBalancerKey = $"{fileReRoute.UpstreamPathTemplate}|{string.Join(",", fileReRoute.UpstreamHttpMethod)}";
 | 
			
		||||
            return loadBalancerKey;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,23 +22,31 @@ namespace Ocelot.Configuration.Creator
 | 
			
		||||
        public HeaderTransformations Create(FileReRoute fileReRoute)
 | 
			
		||||
        {
 | 
			
		||||
            var upstream = new List<HeaderFindAndReplace>();
 | 
			
		||||
            var addHeadersToUpstream = new List<AddHeader>();
 | 
			
		||||
 | 
			
		||||
            foreach(var input in fileReRoute.UpstreamHeaderTransform)
 | 
			
		||||
            {
 | 
			
		||||
                var hAndr = Map(input);
 | 
			
		||||
                if(!hAndr.IsError)
 | 
			
		||||
                if (input.Value.Contains(","))
 | 
			
		||||
                {
 | 
			
		||||
                    upstream.Add(hAndr.Data);
 | 
			
		||||
                    var hAndr = Map(input);
 | 
			
		||||
                    if (!hAndr.IsError)
 | 
			
		||||
                    {
 | 
			
		||||
                        upstream.Add(hAndr.Data);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        _logger.LogWarning($"Unable to add UpstreamHeaderTransform {input.Key}: {input.Value}");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    _logger.LogWarning($"Unable to add UpstreamHeaderTransform {input.Key}: {input.Value}");
 | 
			
		||||
                    addHeadersToUpstream.Add(new AddHeader(input.Key, input.Value));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var downstream = new List<HeaderFindAndReplace>();
 | 
			
		||||
            var addHeadersToDownstream = new List<AddHeader>();
 | 
			
		||||
 | 
			
		||||
            
 | 
			
		||||
            foreach(var input in fileReRoute.DownstreamHeaderTransform)
 | 
			
		||||
            {
 | 
			
		||||
                if(input.Value.Contains(","))
 | 
			
		||||
@@ -59,7 +67,7 @@ namespace Ocelot.Configuration.Creator
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            return new HeaderTransformations(upstream, downstream, addHeadersToDownstream);
 | 
			
		||||
            return new HeaderTransformations(upstream, downstream, addHeadersToDownstream, addHeadersToUpstream);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private Response<HeaderFindAndReplace> Map(KeyValuePair<string,string> input)
 | 
			
		||||
 
 | 
			
		||||
@@ -7,9 +7,11 @@ namespace Ocelot.Configuration.Creator
 | 
			
		||||
        public HeaderTransformations(
 | 
			
		||||
            List<HeaderFindAndReplace> upstream, 
 | 
			
		||||
            List<HeaderFindAndReplace> downstream,
 | 
			
		||||
            List<AddHeader> addHeader)
 | 
			
		||||
            List<AddHeader> addHeaderToDownstream,
 | 
			
		||||
            List<AddHeader> addHeaderToUpstream)
 | 
			
		||||
        {
 | 
			
		||||
            AddHeadersToDownstream = addHeader;
 | 
			
		||||
            AddHeadersToDownstream = addHeaderToDownstream;
 | 
			
		||||
            AddHeadersToUpstream = addHeaderToUpstream;
 | 
			
		||||
            Upstream = upstream;
 | 
			
		||||
            Downstream = downstream;
 | 
			
		||||
        }
 | 
			
		||||
@@ -19,5 +21,6 @@ namespace Ocelot.Configuration.Creator
 | 
			
		||||
        public List<HeaderFindAndReplace> Downstream { get; }
 | 
			
		||||
 | 
			
		||||
        public List<AddHeader> AddHeadersToDownstream { get; }
 | 
			
		||||
        public List<AddHeader> AddHeadersToUpstream { get; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,8 @@ namespace Ocelot.Configuration
 | 
			
		||||
            PathTemplate downstreamPathTemplate, 
 | 
			
		||||
            string reRouteKey,
 | 
			
		||||
            List<string> delegatingHandlers,
 | 
			
		||||
            List<AddHeader> addHeadersToDownstream)
 | 
			
		||||
            List<AddHeader> addHeadersToDownstream,
 | 
			
		||||
            List<AddHeader> addHeadersToUpstream)
 | 
			
		||||
        {
 | 
			
		||||
            AddHeadersToDownstream = addHeadersToDownstream;
 | 
			
		||||
            DelegatingHandlers = delegatingHandlers;
 | 
			
		||||
@@ -64,6 +65,7 @@ namespace Ocelot.Configuration
 | 
			
		||||
            AuthenticationOptions = authenticationOptions;
 | 
			
		||||
            DownstreamPathTemplate = downstreamPathTemplate;
 | 
			
		||||
            ReRouteKey = reRouteKey;
 | 
			
		||||
            AddHeadersToUpstream = addHeadersToUpstream;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string Key { get; private set; }
 | 
			
		||||
@@ -94,5 +96,6 @@ namespace Ocelot.Configuration
 | 
			
		||||
        public string ReRouteKey { get; private set; }
 | 
			
		||||
        public List<string> DelegatingHandlers {get;private set;}
 | 
			
		||||
        public List<AddHeader> AddHeadersToDownstream {get;private set;}
 | 
			
		||||
        public List<AddHeader> AddHeadersToUpstream { get; private set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Infrastructure.Claims.Parser;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Ocelot.Configuration.Creator;
 | 
			
		||||
using Ocelot.Request.Middleware;
 | 
			
		||||
 | 
			
		||||
@@ -41,5 +42,19 @@ namespace Ocelot.Headers
 | 
			
		||||
 | 
			
		||||
            return new OkResponse();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public void SetHeadersOnDownstreamRequest(IEnumerable<AddHeader> headers, HttpContext context)
 | 
			
		||||
        {
 | 
			
		||||
            var requestHeader = context.Request.Headers;
 | 
			
		||||
            foreach (var header in headers)
 | 
			
		||||
            {
 | 
			
		||||
                if (requestHeader.ContainsKey(header.Key))
 | 
			
		||||
                {
 | 
			
		||||
                    requestHeader.Remove(header.Key);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                requestHeader.Add(header.Key, header.Value);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
namespace Ocelot.Headers
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Headers
 | 
			
		||||
{
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using System.Net.Http;
 | 
			
		||||
@@ -12,5 +14,6 @@
 | 
			
		||||
    public interface IAddHeadersToRequest
 | 
			
		||||
    {
 | 
			
		||||
        Response SetHeadersOnDownstreamRequest(List<ClaimToThing> claimsToThings, IEnumerable<System.Security.Claims.Claim> claims, DownstreamRequest downstreamRequest);
 | 
			
		||||
        void SetHeadersOnDownstreamRequest(IEnumerable<AddHeader> headers, HttpContext context);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,16 +9,19 @@ namespace Ocelot.Headers.Middleware
 | 
			
		||||
        private readonly OcelotRequestDelegate _next;
 | 
			
		||||
        private readonly IHttpContextRequestHeaderReplacer _preReplacer;
 | 
			
		||||
        private readonly IHttpResponseHeaderReplacer _postReplacer;
 | 
			
		||||
        private readonly IAddHeadersToResponse _addHeaders;
 | 
			
		||||
        private readonly IAddHeadersToResponse _addHeadersToResponse;
 | 
			
		||||
        private readonly IAddHeadersToRequest _addHeadersToRequest;
 | 
			
		||||
 | 
			
		||||
        public HttpHeadersTransformationMiddleware(OcelotRequestDelegate next,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory,
 | 
			
		||||
            IHttpContextRequestHeaderReplacer preReplacer,
 | 
			
		||||
            IHttpResponseHeaderReplacer postReplacer,
 | 
			
		||||
            IAddHeadersToResponse addHeaders) 
 | 
			
		||||
            IAddHeadersToResponse addHeadersToResponse,
 | 
			
		||||
            IAddHeadersToRequest addHeadersToRequest) 
 | 
			
		||||
                :base(loggerFactory.CreateLogger<HttpHeadersTransformationMiddleware>())
 | 
			
		||||
        {
 | 
			
		||||
            _addHeaders = addHeaders;
 | 
			
		||||
            _addHeadersToResponse = addHeadersToResponse;
 | 
			
		||||
            _addHeadersToRequest = addHeadersToRequest;
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _postReplacer = postReplacer;
 | 
			
		||||
            _preReplacer = preReplacer;
 | 
			
		||||
@@ -31,13 +34,15 @@ namespace Ocelot.Headers.Middleware
 | 
			
		||||
            //todo - this should be on httprequestmessage not httpcontext?
 | 
			
		||||
            _preReplacer.Replace(context.HttpContext, preFAndRs);
 | 
			
		||||
 | 
			
		||||
            _addHeadersToRequest.SetHeadersOnDownstreamRequest(context.DownstreamReRoute.AddHeadersToUpstream, context.HttpContext);
 | 
			
		||||
 | 
			
		||||
            await _next.Invoke(context);
 | 
			
		||||
 | 
			
		||||
            var postFAndRs = context.DownstreamReRoute.DownstreamHeadersFindAndReplace;
 | 
			
		||||
 | 
			
		||||
            _postReplacer.Replace(context.DownstreamResponse, postFAndRs, context.DownstreamRequest);
 | 
			
		||||
 | 
			
		||||
            _addHeaders.Add(context.DownstreamReRoute.AddHeadersToDownstream, context.DownstreamResponse);
 | 
			
		||||
            _addHeadersToResponse.Add(context.DownstreamReRoute.AddHeadersToDownstream, context.DownstreamResponse);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user