Skip to content

Commit

Permalink
Merge pull request #129 from aringlot/feature/#128-cookie-proxying-an…
Browse files Browse the repository at this point in the history
…d-auto-redirect-configuration

Cookie proxying and auto redirect configuration #128
  • Loading branch information
TomPallister authored Oct 9, 2017
2 parents b5670e0 + 8bc5819 commit 4d0f389
Show file tree
Hide file tree
Showing 21 changed files with 269 additions and 28 deletions.
11 changes: 9 additions & 2 deletions src/Ocelot/Configuration/Builder/ReRouteBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public class ReRouteBuilder
private string _loadBalancer;
private ServiceProviderConfiguration _serviceProviderConfiguraion;
private bool _useQos;
private QoSOptions _qosOptions;
private QoSOptions _qosOptions;
private HttpHandlerOptions _httpHandlerOptions;
public bool _enableRateLimiting;
public RateLimitOptions _rateLimitOptions;

Expand Down Expand Up @@ -176,6 +177,11 @@ public ReRouteBuilder WithRateLimitOptions(RateLimitOptions input)
return this;
}

public ReRouteBuilder WithHttpHandlerOptions(HttpHandlerOptions input)
{
_httpHandlerOptions = input;
return this;
}

public ReRoute Build()
{
Expand Down Expand Up @@ -203,7 +209,8 @@ public ReRoute Build()
_useQos,
_qosOptions,
_enableRateLimiting,
_rateLimitOptions);
_rateLimitOptions,
_httpHandlerOptions);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class FileOcelotConfigurationCreator : IOcelotConfigurationCreator
private readonly IReRouteOptionsCreator _fileReRouteOptionsCreator;
private readonly IRateLimitOptionsCreator _rateLimitOptionsCreator;
private readonly IRegionCreator _regionCreator;
private readonly IHttpHandlerOptionsCreator _httpHandlerOptionsCreator;

public FileOcelotConfigurationCreator(
IOptions<FileConfiguration> options,
Expand All @@ -55,7 +56,8 @@ public FileOcelotConfigurationCreator(
IQoSOptionsCreator qosOptionsCreator,
IReRouteOptionsCreator fileReRouteOptionsCreator,
IRateLimitOptionsCreator rateLimitOptionsCreator,
IRegionCreator regionCreator
IRegionCreator regionCreator,
IHttpHandlerOptionsCreator httpHandlerOptionsCreator
)
{
_regionCreator = regionCreator;
Expand All @@ -74,6 +76,7 @@ IRegionCreator regionCreator
_serviceProviderConfigCreator = serviceProviderConfigCreator;
_qosOptionsCreator = qosOptionsCreator;
_fileReRouteOptionsCreator = fileReRouteOptionsCreator;
_httpHandlerOptionsCreator = httpHandlerOptionsCreator;
}

public async Task<Response<IOcelotConfiguration>> Create()
Expand Down Expand Up @@ -143,6 +146,8 @@ private async Task<ReRoute> SetUpReRoute(FileReRoute fileReRoute, FileGlobalConf

var region = _regionCreator.Create(fileReRoute);

var httpHandlerOptions = _httpHandlerOptionsCreator.Create(fileReRoute);

var reRoute = new ReRouteBuilder()
.WithDownstreamPathTemplate(fileReRoute.DownstreamPathTemplate)
.WithUpstreamPathTemplate(fileReRoute.UpstreamPathTemplate)
Expand All @@ -168,6 +173,7 @@ private async Task<ReRoute> SetUpReRoute(FileReRoute fileReRoute, FileGlobalConf
.WithQosOptions(qosOptions)
.WithEnableRateLimiting(fileReRouteOptions.EnableRateLimiting)
.WithRateLimitOptions(rateLimitOption)
.WithHttpHandlerOptions(httpHandlerOptions)
.Build();

await SetupLoadBalancer(reRoute);
Expand Down
13 changes: 13 additions & 0 deletions src/Ocelot/Configuration/Creator/HttpHandlerOptionsCreator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Ocelot.Configuration.File;

namespace Ocelot.Configuration.Creator
{
public class HttpHandlerOptionsCreator : IHttpHandlerOptionsCreator
{
public HttpHandlerOptions Create(FileReRoute fileReRoute)
{
return new HttpHandlerOptions(fileReRoute.HttpHandlerOptions.AllowAutoRedirect,
fileReRoute.HttpHandlerOptions.UseCookieContainer);
}
}
}
12 changes: 12 additions & 0 deletions src/Ocelot/Configuration/Creator/IHttpHandlerOptionsCreator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Ocelot.Configuration.File;

namespace Ocelot.Configuration.Creator
{
/// <summary>
/// Describes creation of HttpHandlerOptions
/// </summary>
public interface IHttpHandlerOptionsCreator
{
HttpHandlerOptions Create(FileReRoute fileReRoute);
}
}
15 changes: 15 additions & 0 deletions src/Ocelot/Configuration/File/FileHttpHandlerOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Ocelot.Configuration.File
{
public class FileHttpHandlerOptions
{
public FileHttpHandlerOptions()
{
AllowAutoRedirect = true;
UseCookieContainer = true;
}

public bool AllowAutoRedirect { get; set; }

public bool UseCookieContainer { get; set; }
}
}
2 changes: 2 additions & 0 deletions src/Ocelot/Configuration/File/FileReRoute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public FileReRoute()
FileCacheOptions = new FileCacheOptions();
QoSOptions = new FileQoSOptions();
RateLimitOptions = new FileRateLimitRule();
HttpHandlerOptions = new FileHttpHandlerOptions();
}

public string DownstreamPathTemplate { get; set; }
Expand All @@ -35,5 +36,6 @@ public FileReRoute()
public FileQoSOptions QoSOptions { get; set; }
public string LoadBalancer {get;set;}
public FileRateLimitRule RateLimitOptions { get; set; }
public FileHttpHandlerOptions HttpHandlerOptions { get; set; }
}
}
25 changes: 25 additions & 0 deletions src/Ocelot/Configuration/HttpHandlerOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace Ocelot.Configuration
{
/// <summary>
/// Describes configuration parameters for http handler,
/// that is created to handle a request to service
/// </summary>
public class HttpHandlerOptions
{
public HttpHandlerOptions(bool allowAutoRedirect, bool useCookieContainer)
{
AllowAutoRedirect = allowAutoRedirect;
UseCookieContainer = useCookieContainer;
}

/// <summary>
/// Specify if auto redirect is enabled
/// </summary>
public bool AllowAutoRedirect { get; private set; }

/// <summary>
/// Specify is handler has to use a cookie container
/// </summary>
public bool UseCookieContainer { get; private set; }
}
}
5 changes: 4 additions & 1 deletion src/Ocelot/Configuration/ReRoute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ public ReRoute(PathTemplate downstreamPathTemplate,
bool isQos,
QoSOptions qosOptions,
bool enableEndpointRateLimiting,
RateLimitOptions ratelimitOptions)
RateLimitOptions ratelimitOptions,
HttpHandlerOptions httpHandlerOptions)
{
ReRouteKey = reRouteKey;
ServiceProviderConfiguraion = serviceProviderConfiguraion;
Expand Down Expand Up @@ -58,6 +59,7 @@ public ReRoute(PathTemplate downstreamPathTemplate,
QosOptionsOptions = qosOptions;
EnableEndpointEndpointRateLimiting = enableEndpointRateLimiting;
RateLimitOptions = ratelimitOptions;
HttpHandlerOptions = httpHandlerOptions;
}

public string ReRouteKey {get;private set;}
Expand All @@ -84,5 +86,6 @@ public ReRoute(PathTemplate downstreamPathTemplate,
public ServiceProviderConfiguration ServiceProviderConfiguraion { get; private set; }
public bool EnableEndpointEndpointRateLimiting { get; private set; }
public RateLimitOptions RateLimitOptions { get; private set; }
public HttpHandlerOptions HttpHandlerOptions { get; private set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public static IServiceCollection AddOcelot(this IServiceCollection services, ICo
services.TryAddSingleton<IQoSOptionsCreator, QoSOptionsCreator>();
services.TryAddSingleton<IReRouteOptionsCreator, ReRouteOptionsCreator>();
services.TryAddSingleton<IRateLimitOptionsCreator, RateLimitOptionsCreator>();
services.TryAddSingleton<IHttpHandlerOptionsCreator, HttpHandlerOptionsCreator>();

var identityServerConfiguration = IdentityServerConfigurationCreator.GetIdentityServerConfiguration();

Expand Down
6 changes: 4 additions & 2 deletions src/Ocelot/Request/Builder/HttpRequestCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ public sealed class HttpRequestCreator : IRequestCreator
public async Task<Response<Request>> Build(
HttpRequestMessage httpRequestMessage,
bool isQos,
IQoSProvider qosProvider)
IQoSProvider qosProvider,
bool useCookieContainer,
bool allowAutoRedirect)
{
return new OkResponse<Request>(new Request(httpRequestMessage, isQos, qosProvider));
return new OkResponse<Request>(new Request(httpRequestMessage, isQos, qosProvider, useCookieContainer, allowAutoRedirect));
}
}
}
4 changes: 3 additions & 1 deletion src/Ocelot/Request/Builder/IRequestCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public interface IRequestCreator
Task<Response<Request>> Build(
HttpRequestMessage httpRequestMessage,
bool isQos,
IQoSProvider qosProvider);
IQoSProvider qosProvider,
bool useCookieContainer,
bool allowAutoRedirect);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ public async Task Invoke(HttpContext context)
var buildResult = await _requestCreator.Build(
DownstreamRequest,
DownstreamRoute.ReRoute.IsQos,
qosProvider.Data);
qosProvider.Data,
DownstreamRoute.ReRoute.HttpHandlerOptions.UseCookieContainer,
DownstreamRoute.ReRoute.HttpHandlerOptions.AllowAutoRedirect);

if (buildResult.IsError)
{
Expand Down
8 changes: 7 additions & 1 deletion src/Ocelot/Request/Request.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,21 @@ public class Request
public Request(
HttpRequestMessage httpRequestMessage,
bool isQos,
IQoSProvider qosProvider)
IQoSProvider qosProvider,
bool allowAutoRedirect,
bool useCookieContainer)
{
HttpRequestMessage = httpRequestMessage;
IsQos = isQos;
QosProvider = qosProvider;
AllowAutoRedirect = allowAutoRedirect;
UseCookieContainer = useCookieContainer;
}

public HttpRequestMessage HttpRequestMessage { get; private set; }
public bool IsQos { get; private set; }
public IQoSProvider QosProvider { get; private set; }
public bool AllowAutoRedirect { get; private set; }
public bool UseCookieContainer { get; private set; }
}
}
4 changes: 2 additions & 2 deletions src/Ocelot/Requester/HttpClientBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public IHttpClientBuilder WithQos(IQoSProvider qosProvider, IOcelotLogger logge
return this;
}

public IHttpClient Create()
public IHttpClient Create(bool useCookies, bool allowAutoRedirect)
{
var httpclientHandler = new HttpClientHandler();
var httpclientHandler = new HttpClientHandler { AllowAutoRedirect = allowAutoRedirect, UseCookies = useCookies};

var client = new HttpClient(CreateHttpMessageHandler(httpclientHandler));

Expand Down
12 changes: 7 additions & 5 deletions src/Ocelot/Requester/HttpClientHttpRequester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Concurrent;
using System.Net.Http;
using System.Threading.Tasks;
using Ocelot.Configuration;
using Ocelot.Logging;
using Ocelot.Responses;
using Polly.CircuitBreaker;
Expand All @@ -14,7 +15,8 @@ public class HttpClientHttpRequester : IHttpRequester
private readonly IHttpClientCache _cacheHandlers;
private readonly IOcelotLogger _logger;

public HttpClientHttpRequester(IOcelotLoggerFactory loggerFactory, IHttpClientCache cacheHandlers)
public HttpClientHttpRequester(IOcelotLoggerFactory loggerFactory,
IHttpClientCache cacheHandlers)
{
_logger = loggerFactory.CreateLogger<HttpClientHttpRequester>();
_cacheHandlers = cacheHandlers;
Expand All @@ -25,8 +27,8 @@ public async Task<Response<HttpResponseMessage>> GetResponse(Request.Request req
var builder = new HttpClientBuilder();

var cacheKey = GetCacheKey(request, builder);

var httpClient = GetHttpClient(cacheKey, builder);
var httpClient = GetHttpClient(cacheKey, builder, request.UseCookieContainer, request.AllowAutoRedirect);

try
{
Expand Down Expand Up @@ -54,13 +56,13 @@ public async Task<Response<HttpResponseMessage>> GetResponse(Request.Request req

}

private IHttpClient GetHttpClient(string cacheKey, IHttpClientBuilder builder)
private IHttpClient GetHttpClient(string cacheKey, IHttpClientBuilder builder, bool useCookieContainer, bool allowAutoRedirect)
{
var httpClient = _cacheHandlers.Get(cacheKey);

if (httpClient == null)
{
httpClient = builder.Create();
httpClient = builder.Create(useCookieContainer, allowAutoRedirect);
}
return httpClient;
}
Expand Down
12 changes: 7 additions & 5 deletions src/Ocelot/Requester/IHttpClientBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ public interface IHttpClientBuilder
/// <summary>
/// Sets a PollyCircuitBreakingDelegatingHandler .
/// </summary>
IHttpClientBuilder WithQos(IQoSProvider qosProvider, IOcelotLogger logger);

/// <summary>
IHttpClientBuilder WithQos(IQoSProvider qosProvider, IOcelotLogger logger);

/// <summary>
/// Creates the <see cref="HttpClient"/>
/// </summary>
IHttpClient Create();
/// </summary>
/// <param name="useCookies">Defines if http client should use cookie container</param>
/// <param name="allowAutoRedirect">Defines if http client should allow auto redirect</param>
IHttpClient Create(bool useCookies, bool allowAutoRedirect);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class FileConfigurationCreatorTests
private Mock<IReRouteOptionsCreator> _fileReRouteOptionsCreator;
private Mock<IRateLimitOptionsCreator> _rateLimitOptions;
private Mock<IRegionCreator> _regionCreator;
private Mock<IHttpHandlerOptionsCreator> _httpHandlerOptionsCreator;

public FileConfigurationCreatorTests()
{
Expand All @@ -66,14 +67,15 @@ public FileConfigurationCreatorTests()
_fileReRouteOptionsCreator = new Mock<IReRouteOptionsCreator>();
_rateLimitOptions = new Mock<IRateLimitOptionsCreator>();
_regionCreator = new Mock<IRegionCreator>();
_httpHandlerOptionsCreator = new Mock<IHttpHandlerOptionsCreator>();

_ocelotConfigurationCreator = new FileOcelotConfigurationCreator(
_fileConfig.Object, _validator.Object, _logger.Object,
_loadBalancerFactory.Object, _loadBalancerHouse.Object,
_qosProviderFactory.Object, _qosProviderHouse.Object, _claimsToThingCreator.Object,
_authOptionsCreator.Object, _upstreamTemplatePatternCreator.Object, _requestIdKeyCreator.Object,
_serviceProviderConfigCreator.Object, _qosOptionsCreator.Object, _fileReRouteOptionsCreator.Object,
_rateLimitOptions.Object, _regionCreator.Object);
_rateLimitOptions.Object, _regionCreator.Object, _httpHandlerOptionsCreator.Object);
}

[Fact]
Expand Down Expand Up @@ -444,6 +446,45 @@ public void should_call_request_id_creator()
.BDDfy();
}

[Fact]
public void should_call_httpHandler_creator()
{
var reRouteOptions = new ReRouteOptionsBuilder()
.Build();
var httpHandlerOptions = new HttpHandlerOptions(true, true);

this.Given(x => x.GivenTheConfigIs(new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamHost = "127.0.0.1",
UpstreamPathTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = new List<string> { "Get" }
}
},
}))
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
.And(x => x.GivenTheConfigIsValid())
.And(x => x.GivenTheFollowingHttpHandlerOptionsAreReturned(httpHandlerOptions))
.When(x => x.WhenICreateTheConfig())
.Then(x => x.ThenTheHttpHandlerOptionsCreatorIsCalledCorrectly())
.BDDfy();
}

private void GivenTheFollowingHttpHandlerOptionsAreReturned(HttpHandlerOptions httpHandlerOptions)
{
_httpHandlerOptionsCreator.Setup(x => x.Create(It.IsAny<FileReRoute>()))
.Returns(httpHandlerOptions);
}

private void ThenTheHttpHandlerOptionsCreatorIsCalledCorrectly()
{
_httpHandlerOptionsCreator.Verify(x => x.Create(_fileConfiguration.ReRoutes[0]), Times.Once());
}

[Theory]
[MemberData(nameof(AuthenticationConfigTestData.GetAuthenticationData), MemberType = typeof(AuthenticationConfigTestData))]
public void should_create_with_headers_to_extract(string provider, IAuthenticationConfig config, FileConfiguration fileConfig)
Expand Down
Loading

0 comments on commit 4d0f389

Please sign in to comment.