mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 00:38:16 +08:00
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:
@ -4,8 +4,8 @@
|
||||
{
|
||||
public FileHttpHandlerOptions()
|
||||
{
|
||||
AllowAutoRedirect = true;
|
||||
UseCookieContainer = true;
|
||||
AllowAutoRedirect = false;
|
||||
UseCookieContainer = false;
|
||||
}
|
||||
|
||||
public bool AllowAutoRedirect { get; set; }
|
||||
|
14
src/Ocelot/Requester/GlobalDelegatingHandler.cs
Normal file
14
src/Ocelot/Requester/GlobalDelegatingHandler.cs
Normal 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; }
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,6 @@ namespace Ocelot.Requester
|
||||
{
|
||||
public interface IHttpRequester
|
||||
{
|
||||
Task<Response<HttpResponseMessage>> GetResponse(DownstreamContext request);
|
||||
Task<Response<HttpResponseMessage>> GetResponse(DownstreamContext context);
|
||||
}
|
||||
}
|
||||
|
10
src/Ocelot/Requester/ReRouteDelegatingHandler.cs
Normal file
10
src/Ocelot/Requester/ReRouteDelegatingHandler.cs
Normal 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; }
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user