Feature/#274 (#281)

* #274 added acceptance tests, need to work out failing unit tests but probably going to be a redesign where we hold a reference to the cookie container and empty it if needed

* #274 updated code coverage value

* #274 offloaded cache logic to builder in preparation for adding state

* #274 hacked something together but this is not right approach

* #274 updated defaults and docs

* #274 updated code coverage
This commit is contained in:
Tom Pallister
2018-03-17 11:35:16 +00:00
committed by GitHub
parent c1b315173f
commit ed11f3024c
15 changed files with 372 additions and 85 deletions

View File

@ -4,8 +4,8 @@
{
public FileHttpHandlerOptions()
{
AllowAutoRedirect = true;
UseCookieContainer = true;
AllowAutoRedirect = false;
UseCookieContainer = false;
}
public bool AllowAutoRedirect { get; set; }

View File

@ -0,0 +1,14 @@
using System.Net.Http;
namespace Ocelot.Requester
{
public class GlobalDelegatingHandler
{
public GlobalDelegatingHandler(DelegatingHandler delegatingHandler)
{
DelegatingHandler = delegatingHandler;
}
public DelegatingHandler DelegatingHandler { get; private set; }
}
}

View File

@ -1,25 +1,61 @@
using System.Linq;
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using Ocelot.Configuration;
using Ocelot.Logging;
using Ocelot.Middleware;
namespace Ocelot.Requester
{
public class HttpClientBuilder : IHttpClientBuilder
{
private readonly IDelegatingHandlerHandlerFactory _factory;
private readonly IHttpClientCache _cacheHandlers;
private readonly IOcelotLogger _logger;
private string _cacheKey;
private HttpClient _httpClient;
private IHttpClient _client;
private HttpClientHandler _httpclientHandler;
public HttpClientBuilder(IDelegatingHandlerHandlerFactory house)
public HttpClientBuilder(
IDelegatingHandlerHandlerFactory factory,
IHttpClientCache cacheHandlers,
IOcelotLogger logger)
{
_factory = house;
_factory = factory;
_cacheHandlers = cacheHandlers;
_logger = logger;
}
public IHttpClient Create(DownstreamReRoute request)
public IHttpClient Create(DownstreamContext request)
{
var httpclientHandler = new HttpClientHandler { AllowAutoRedirect = request.HttpHandlerOptions.AllowAutoRedirect, UseCookies = request.HttpHandlerOptions.UseCookieContainer};
var client = new HttpClient(CreateHttpMessageHandler(httpclientHandler, request));
return new HttpClientWrapper(client);
_cacheKey = GetCacheKey(request);
var httpClient = _cacheHandlers.Get(_cacheKey);
if (httpClient != null)
{
return httpClient;
}
_httpclientHandler = new HttpClientHandler
{
AllowAutoRedirect = request.DownstreamReRoute.HttpHandlerOptions.AllowAutoRedirect,
UseCookies = request.DownstreamReRoute.HttpHandlerOptions.UseCookieContainer,
CookieContainer = new CookieContainer()
};
_httpClient = new HttpClient(CreateHttpMessageHandler(_httpclientHandler, request.DownstreamReRoute));
_client = new HttpClientWrapper(_httpClient);
return _client;
}
public void Save()
{
_cacheHandlers.Set(_cacheKey, _client, TimeSpan.FromHours(24));
}
private HttpMessageHandler CreateHttpMessageHandler(HttpMessageHandler httpMessageHandler, DownstreamReRoute request)
@ -39,5 +75,12 @@ namespace Ocelot.Requester
});
return httpMessageHandler;
}
private string GetCacheKey(DownstreamContext request)
{
var baseUrl = $"{request.DownstreamRequest.RequestUri.Scheme}://{request.DownstreamRequest.RequestUri.Authority}{request.DownstreamRequest.RequestUri.AbsolutePath}";
return baseUrl;
}
}
}

View File

@ -24,17 +24,15 @@ namespace Ocelot.Requester
_factory = house;
}
public async Task<Response<HttpResponseMessage>> GetResponse(DownstreamContext request)
public async Task<Response<HttpResponseMessage>> GetResponse(DownstreamContext context)
{
var builder = new HttpClientBuilder(_factory);
var builder = new HttpClientBuilder(_factory, _cacheHandlers, _logger);
var cacheKey = GetCacheKey(request);
var httpClient = GetHttpClient(cacheKey, builder, request);
var httpClient = builder.Create(context);
try
{
var response = await httpClient.SendAsync(request.DownstreamRequest);
var response = await httpClient.SendAsync(context.DownstreamRequest);
return new OkResponse<HttpResponseMessage>(response);
}
catch (TimeoutRejectedException exception)
@ -51,43 +49,8 @@ namespace Ocelot.Requester
}
finally
{
_cacheHandlers.Set(cacheKey, httpClient, TimeSpan.FromHours(24));
builder.Save();
}
}
private IHttpClient GetHttpClient(string cacheKey, IHttpClientBuilder builder, DownstreamContext request)
{
var httpClient = _cacheHandlers.Get(cacheKey);
if (httpClient == null)
{
httpClient = builder.Create(request.DownstreamReRoute);
}
return httpClient;
}
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; }
}
}

View File

@ -6,7 +6,7 @@ namespace Ocelot.Requester
/// <summary>
/// This class was made to make unit testing easier when HttpClient is used.
/// </summary>
internal class HttpClientWrapper : IHttpClient
public class HttpClientWrapper : IHttpClient
{
public HttpClient Client { get; }

View File

@ -1,14 +1,10 @@
using System.Net.Http;
using Ocelot.Configuration;
using Ocelot.Middleware;
namespace Ocelot.Requester
{
public interface IHttpClientBuilder
{
/// <summary>
/// Creates the <see cref="HttpClient"/>
/// </summary>
/// <param name="request"></param>
IHttpClient Create(DownstreamReRoute request);
IHttpClient Create(DownstreamContext request);
void Save();
}
}

View File

@ -7,6 +7,6 @@ namespace Ocelot.Requester
{
public interface IHttpRequester
{
Task<Response<HttpResponseMessage>> GetResponse(DownstreamContext request);
Task<Response<HttpResponseMessage>> GetResponse(DownstreamContext context);
}
}

View File

@ -0,0 +1,10 @@
using System.Net.Http;
namespace Ocelot.Requester
{
public class ReRouteDelegatingHandler<T>
where T : DelegatingHandler
{
public T DelegatingHandler { get; private set; }
}
}