#298 initial hacking around better aggregation (#310)

* #298 initial hacking around better aggregation

* #298 bit more hacking around

* #298 abstraction over httpresponsemessage

* #298 tidying up

* #298 docs

* #298 missed this
This commit is contained in:
Tom Pallister
2018-04-12 17:35:04 +01:00
committed by GitHub
parent 982eebfc74
commit a15f75dda8
63 changed files with 1203 additions and 410 deletions

View File

@ -2,12 +2,10 @@
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware;
using System.IO;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Middleware.Multiplexer;
namespace Ocelot.Cache.Middleware
{
@ -72,38 +70,31 @@ namespace Ocelot.Cache.Middleware
Logger.LogDebug($"finished response added to cache for {downstreamUrlKey}");
}
private void SetHttpResponseMessageThisRequest(DownstreamContext context, HttpResponseMessage response)
private void SetHttpResponseMessageThisRequest(DownstreamContext context, DownstreamResponse response)
{
context.DownstreamResponse = response;
}
internal HttpResponseMessage CreateHttpResponseMessage(CachedResponse cached)
internal DownstreamResponse CreateHttpResponseMessage(CachedResponse cached)
{
if (cached == null)
{
return null;
}
var response = new HttpResponseMessage(cached.StatusCode);
foreach (var header in cached.Headers)
{
response.Headers.Add(header.Key, header.Value);
}
var content = new MemoryStream(Convert.FromBase64String(cached.Body));
response.Content = new StreamContent(content);
var streamContent = new StreamContent(content);
foreach (var header in cached.ContentHeaders)
{
response.Content.Headers.Add(header.Key, header.Value);
streamContent.Headers.Add(header.Key, header.Value);
}
return response;
return new DownstreamResponse(streamContent, cached.StatusCode, cached.Headers.ToList());
}
internal async Task<CachedResponse> CreateCachedResponse(HttpResponseMessage response)
internal async Task<CachedResponse> CreateCachedResponse(DownstreamResponse response)
{
if (response == null)
{
@ -111,7 +102,7 @@ namespace Ocelot.Cache.Middleware
}
var statusCode = response.StatusCode;
var headers = response.Headers.ToDictionary(v => v.Key, v => v.Value);
var headers = response.Headers.ToDictionary(v => v.Key, v => v.Values);
string body = null;
if (response.Content != null)

View File

@ -14,6 +14,7 @@ namespace Ocelot.Configuration.Builder
private List<HttpMethod> _upstreamHttpMethod;
private string _upstreamHost;
private List<DownstreamReRoute> _downstreamReRoutes;
private string _aggregator;
public ReRouteBuilder()
{
@ -56,6 +57,12 @@ namespace Ocelot.Configuration.Builder
return this;
}
public ReRouteBuilder WithAggregator(string aggregator)
{
_aggregator = aggregator;
return this;
}
public ReRoute Build()
{
return new ReRoute(
@ -63,7 +70,8 @@ namespace Ocelot.Configuration.Builder
new PathTemplate(_upstreamTemplate),
_upstreamHttpMethod,
_upstreamTemplatePattern,
_upstreamHost
_upstreamHost,
_aggregator
);
}
}

View File

@ -132,6 +132,7 @@ namespace Ocelot.Configuration.Creator
.WithUpstreamTemplatePattern(upstreamTemplatePattern)
.WithDownstreamReRoutes(applicableReRoutes)
.WithUpstreamHost(aggregateReRoute.UpstreamHost)
.WithAggregator(aggregateReRoute.Aggregator)
.Build();
return reRoute;

View File

@ -8,6 +8,7 @@ namespace Ocelot.Configuration.File
public string UpstreamPathTemplate { get;set; }
public string UpstreamHost { get; set; }
public bool ReRouteIsCaseSensitive { get; set; }
public string Aggregator { get; set; }
// Only supports GET..are you crazy!! POST, PUT WOULD BE CRAZY!! :)
public List<string> UpstreamHttpMethod

View File

@ -12,13 +12,15 @@ namespace Ocelot.Configuration
PathTemplate upstreamPathTemplate,
List<HttpMethod> upstreamHttpMethod,
UpstreamPathTemplate upstreamTemplatePattern,
string upstreamHost)
string upstreamHost,
string aggregator)
{
UpstreamHost = upstreamHost;
DownstreamReRoute = downstreamReRoute;
UpstreamPathTemplate = upstreamPathTemplate;
UpstreamHttpMethod = upstreamHttpMethod;
UpstreamTemplatePattern = upstreamTemplatePattern;
Aggregator = aggregator;
}
public PathTemplate UpstreamPathTemplate { get; private set; }
@ -26,5 +28,6 @@ namespace Ocelot.Configuration
public List<HttpMethod> UpstreamHttpMethod { get; private set; }
public string UpstreamHost { get; private set; }
public List<DownstreamReRoute> DownstreamReRoute { get; private set; }
public string Aggregator {get; private set;}
}
}

View File

@ -3,6 +3,7 @@ using CacheManager.Core;
using System;
using System.Net.Http;
using IdentityServer4.AccessTokenValidation;
using Ocelot.Middleware.Multiplexer;
namespace Ocelot.DependencyInjection
{
@ -23,5 +24,10 @@ namespace Ocelot.DependencyInjection
IOcelotBuilder AddTransientDelegatingHandler<T>(bool global = false)
where T : DelegatingHandler;
IOcelotBuilder AddSingletonDefinedAggregator<T>()
where T : class, IDefinedAggregator;
IOcelotBuilder AddTransientDefinedAggregator<T>()
where T : class, IDefinedAggregator;
}
}

View File

@ -154,6 +154,8 @@ namespace Ocelot.DependencyInjection
_services.TryAddSingleton<IAddHeadersToResponse, AddHeadersToResponse>();
_services.TryAddSingleton<IPlaceholders, Placeholders>();
_services.TryAddSingleton<IConsulClientFactory, ConsulClientFactory>();
_services.TryAddSingleton<IResponseAggregatorFactory, InMemoryResponseAggregatorFactory>();
_services.TryAddSingleton<IDefinedAggregatorProvider, ServiceLocatorDefinedAggregatorProvider>();
}
public IOcelotAdministrationBuilder AddAdministration(string path, string secret)
@ -188,6 +190,20 @@ namespace Ocelot.DependencyInjection
return new OcelotAdministrationBuilder(_services, _configurationRoot);
}
public IOcelotBuilder AddSingletonDefinedAggregator<T>()
where T : class, IDefinedAggregator
{
_services.AddSingleton<IDefinedAggregator, T>();
return this;
}
public IOcelotBuilder AddTransientDefinedAggregator<T>()
where T : class, IDefinedAggregator
{
_services.AddTransient<IDefinedAggregator, T>();
return this;
}
public IOcelotBuilder AddSingletonDelegatingHandler<THandler>(bool global = false)
where THandler : DelegatingHandler
{

View File

@ -35,6 +35,7 @@
PathTemplateDoesntStartWithForwardSlash,
FileValidationFailedError,
UnableToFindDelegatingHandlerProviderError,
CouldNotFindPlaceholderError
CouldNotFindPlaceholderError,
CouldNotFindAggregatorError
}
}

View File

@ -1,10 +1,10 @@
namespace Ocelot.Headers
{
using System.Collections.Generic;
using System.Net.Http;
using Ocelot.Configuration.Creator;
using Ocelot.Infrastructure;
using Ocelot.Logging;
using Ocelot.Middleware;
public class AddHeadersToResponse : IAddHeadersToResponse
{
@ -17,7 +17,7 @@ namespace Ocelot.Headers
_placeholders = placeholders;
}
public void Add(List<AddHeader> addHeaders, HttpResponseMessage response)
public void Add(List<AddHeader> addHeaders, DownstreamResponse response)
{
foreach(var add in addHeaders)
{
@ -31,11 +31,11 @@ namespace Ocelot.Headers
continue;
}
response.Headers.TryAddWithoutValidation(add.Key, value.Data);
response.Headers.Add(new Header(add.Key, new List<string> { value.Data }));
}
else
{
response.Headers.TryAddWithoutValidation(add.Key, add.Value);
response.Headers.Add(new Header(add.Key, new List<string> { add.Value }));
}
}
}

View File

@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using Ocelot.Configuration;
using Ocelot.Infrastructure;
using Ocelot.Infrastructure.Extensions;
using Ocelot.Middleware;
using Ocelot.Middleware.Multiplexer;
using Ocelot.Request.Middleware;
using Ocelot.Responses;
@ -12,19 +12,21 @@ namespace Ocelot.Headers
{
public class HttpResponseHeaderReplacer : IHttpResponseHeaderReplacer
{
private IPlaceholders _placeholders;
private readonly IPlaceholders _placeholders;
public HttpResponseHeaderReplacer(IPlaceholders placeholders)
{
_placeholders = placeholders;
}
public Response Replace(HttpResponseMessage response, List<HeaderFindAndReplace> fAndRs, DownstreamRequest request)
public Response Replace(DownstreamResponse response, List<HeaderFindAndReplace> fAndRs, DownstreamRequest request)
{
foreach (var f in fAndRs)
{
var dict = response.Headers.ToDictionary(x => x.Key);
//if the response headers contain a matching find and replace
if(response.Headers.TryGetValues(f.Key, out var values))
if(dict.TryGetValue(f.Key, out var values))
{
//check to see if it is a placeholder in the find...
var placeholderValue = _placeholders.Get(f.Find, request);
@ -32,16 +34,17 @@ namespace Ocelot.Headers
if(!placeholderValue.IsError)
{
//if it is we need to get the value of the placeholder
//var find = replacePlaceholder(httpRequestMessage);
var replaced = values.ToList()[f.Index].Replace(placeholderValue.Data, f.Replace.LastCharAsForwardSlash());
response.Headers.Remove(f.Key);
response.Headers.Add(f.Key, replaced);
var replaced = values.Values.ToList()[f.Index].Replace(placeholderValue.Data, f.Replace.LastCharAsForwardSlash());
response.Headers.Remove(response.Headers.First(item => item.Key == f.Key));
response.Headers.Add(new Header(f.Key, new List<string> { replaced }));
}
else
{
var replaced = values.ToList()[f.Index].Replace(f.Find, f.Replace);
response.Headers.Remove(f.Key);
response.Headers.Add(f.Key, replaced);
var replaced = values.Values.ToList()[f.Index].Replace(f.Find, f.Replace);
response.Headers.Remove(response.Headers.First(item => item.Key == f.Key));
response.Headers.Add(new Header(f.Key, new List<string> { replaced }));
}
}
}

View File

@ -1,11 +1,13 @@
using Ocelot.Middleware;
namespace Ocelot.Headers
{
using System.Collections.Generic;
using System.Net.Http;
using Ocelot.Configuration.Creator;
using Ocelot.Middleware.Multiplexer;
public interface IAddHeadersToResponse
{
void Add(List<AddHeader> addHeaders, HttpResponseMessage response);
void Add(List<AddHeader> addHeaders, DownstreamResponse response);
}
}

View File

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Net.Http;
using Ocelot.Configuration;
using Ocelot.Middleware;
using Ocelot.Middleware.Multiplexer;
using Ocelot.Request.Middleware;
using Ocelot.Responses;
@ -8,6 +9,6 @@ namespace Ocelot.Headers
{
public interface IHttpResponseHeaderReplacer
{
Response Replace(HttpResponseMessage response, List<HeaderFindAndReplace> fAndRs, DownstreamRequest httpRequestMessage);
Response Replace(DownstreamResponse response, List<HeaderFindAndReplace> fAndRs, DownstreamRequest httpRequestMessage);
}
}
}

View File

@ -1,10 +1,12 @@
using System.Net.Http.Headers;
using System.Collections.Generic;
using Ocelot.Middleware;
using Ocelot.Middleware.Multiplexer;
using Ocelot.Responses;
namespace Ocelot.Headers
{
public interface IRemoveOutputHeaders
{
Response Remove(HttpResponseHeaders headers);
Response Remove(List<Header> headers);
}
}

View File

@ -1,7 +1,4 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware;

View File

@ -1,4 +1,7 @@
using System.Net.Http.Headers;
using System.Collections.Generic;
using System.Linq;
using Ocelot.Middleware;
using Ocelot.Middleware.Multiplexer;
using Ocelot.Responses;
namespace Ocelot.Headers
@ -14,14 +17,11 @@ namespace Ocelot.Headers
{
"Transfer-Encoding"
};
public Response Remove(HttpResponseHeaders headers)
{
foreach (var unsupported in _unsupportedRequestHeaders)
{
headers.Remove(unsupported);
}
public Response Remove(List<Header> headers)
{
headers.RemoveAll(x => _unsupportedRequestHeaders.Contains(x.Key));
return new OkResponse();
}
}
}
}

View File

@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Http;
using Ocelot.Configuration;
using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Errors;
using Ocelot.Middleware.Multiplexer;
using Ocelot.Request.Middleware;
namespace Ocelot.Middleware
@ -27,9 +28,9 @@ namespace Ocelot.Middleware
public DownstreamRequest DownstreamRequest { get; set; }
public HttpResponseMessage DownstreamResponse { get; set; }
public DownstreamResponse DownstreamResponse { get; set; }
public List<Error> Errors { get;set; }
public List<Error> Errors { get; }
public bool IsError => Errors.Count > 0;
}

View File

@ -0,0 +1,31 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
namespace Ocelot.Middleware
{
public class DownstreamResponse
{
public DownstreamResponse(HttpContent content, HttpStatusCode statusCode, List<Header> headers)
{
Content = content;
StatusCode = statusCode;
Headers = headers ?? new List<Header>();
}
public DownstreamResponse(HttpResponseMessage response)
:this(response.Content, response.StatusCode, response.Headers.Select(x => new Header(x.Key, x.Value)).ToList())
{
}
public DownstreamResponse(HttpContent content, HttpStatusCode statusCode, IEnumerable<KeyValuePair<string, IEnumerable<string>>> headers)
:this(content, statusCode, headers.Select(x => new Header(x.Key, x.Value)).ToList())
{
}
public HttpContent Content { get; }
public HttpStatusCode StatusCode { get; }
public List<Header> Headers { get; }
}
}

View File

@ -0,0 +1,16 @@
using System.Collections.Generic;
namespace Ocelot.Middleware
{
public class Header
{
public Header(string key, IEnumerable<string> values)
{
Key = key;
Values = values ?? new List<string>();
}
public string Key { get; }
public IEnumerable<string> Values { get; }
}
}

View File

@ -0,0 +1,12 @@
using Ocelot.Errors;
namespace Ocelot.Middleware.Multiplexer
{
public class CouldNotFindAggregatorError : Error
{
public CouldNotFindAggregatorError(string aggregator)
: base($"Could not find Aggregator: {aggregator}", OcelotErrorCode.CouldNotFindAggregatorError)
{
}
}
}

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Ocelot.Middleware.Multiplexer
{
public interface IDefinedAggregator
{
Task<DownstreamResponse> Aggregate(List<DownstreamResponse> responses);
}
}

View File

@ -0,0 +1,10 @@
using Ocelot.Configuration;
using Ocelot.Responses;
namespace Ocelot.Middleware.Multiplexer
{
public interface IDefinedAggregatorProvider
{
Response<IDefinedAggregator> Get(ReRoute reRoute);
}
}

View File

@ -6,6 +6,6 @@ namespace Ocelot.Middleware.Multiplexer
{
public interface IResponseAggregator
{
Task Aggregate(ReRoute reRoute, DownstreamContext originalContext, List<DownstreamContext> downstreamContexts);
Task Aggregate(ReRoute reRoute, DownstreamContext originalContext, List<DownstreamContext> downstreamResponses);
}
}

View File

@ -0,0 +1,9 @@
using Ocelot.Configuration;
namespace Ocelot.Middleware.Multiplexer
{
public interface IResponseAggregatorFactory
{
IResponseAggregator Get(ReRoute reRoute);
}
}

View File

@ -0,0 +1,26 @@
using Ocelot.Configuration;
namespace Ocelot.Middleware.Multiplexer
{
public class InMemoryResponseAggregatorFactory : IResponseAggregatorFactory
{
private readonly UserDefinedResponseAggregator _userDefined;
private readonly SimpleJsonResponseAggregator _simple;
public InMemoryResponseAggregatorFactory(IDefinedAggregatorProvider provider)
{
_userDefined = new UserDefinedResponseAggregator(provider);
_simple = new SimpleJsonResponseAggregator();
}
public IResponseAggregator Get(ReRoute reRoute)
{
if(!string.IsNullOrEmpty(reRoute.Aggregator))
{
return _userDefined;
}
return _simple;
}
}
}

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Ocelot.Configuration;
@ -6,11 +7,11 @@ namespace Ocelot.Middleware.Multiplexer
{
public class Multiplexer : IMultiplexer
{
private readonly IResponseAggregator _aggregator;
private readonly IResponseAggregatorFactory _factory;
public Multiplexer(IResponseAggregator aggregator)
public Multiplexer(IResponseAggregatorFactory factory)
{
_aggregator = aggregator;
_factory = factory;
}
public async Task Multiplex(DownstreamContext context, ReRoute reRoute, OcelotRequestDelegate next)
@ -31,15 +32,40 @@ namespace Ocelot.Middleware.Multiplexer
await Task.WhenAll(tasks);
var downstreamContexts = new List<DownstreamContext>();
var contexts = new List<DownstreamContext>();
foreach (var task in tasks)
{
var finished = await task;
downstreamContexts.Add(finished);
contexts.Add(finished);
}
await _aggregator.Aggregate(reRoute, context, downstreamContexts);
await Map(reRoute, context, contexts);
}
private async Task Map(ReRoute reRoute, DownstreamContext context, List<DownstreamContext> contexts)
{
if (reRoute.DownstreamReRoute.Count > 1)
{
var aggregator = _factory.Get(reRoute);
await aggregator.Aggregate(reRoute, context, contexts);
}
else
{
MapNotAggregate(context, contexts);
}
}
private void MapNotAggregate(DownstreamContext originalContext, List<DownstreamContext> downstreamContexts)
{
//assume at least one..if this errors then it will be caught by global exception handler
var finished = downstreamContexts.First();
originalContext.Errors.AddRange(finished.Errors);
originalContext.DownstreamRequest = finished.DownstreamRequest;
originalContext.DownstreamResponse = finished.DownstreamResponse;
}
private async Task<DownstreamContext> Fire(DownstreamContext context, OcelotRequestDelegate next)

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.Configuration;
using Ocelot.Responses;
namespace Ocelot.Middleware.Multiplexer
{
public class ServiceLocatorDefinedAggregatorProvider : IDefinedAggregatorProvider
{
private readonly Dictionary<string, IDefinedAggregator> _aggregators;
public ServiceLocatorDefinedAggregatorProvider(IServiceProvider services)
{
_aggregators = services.GetServices<IDefinedAggregator>().ToDictionary(x => x.GetType().Name);
}
public Response<IDefinedAggregator> Get(ReRoute reRoute)
{
if(_aggregators.ContainsKey(reRoute.Aggregator))
{
return new OkResponse<IDefinedAggregator>(_aggregators[reRoute.Aggregator]);
}
return new ErrorResponse<IDefinedAggregator>(new CouldNotFindAggregatorError(reRoute.Aggregator));
}
}
}

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
@ -12,18 +11,6 @@ namespace Ocelot.Middleware.Multiplexer
public class SimpleJsonResponseAggregator : IResponseAggregator
{
public async Task Aggregate(ReRoute reRoute, DownstreamContext originalContext, List<DownstreamContext> downstreamContexts)
{
if (reRoute.DownstreamReRoute.Count > 1)
{
await MapAggregtes(originalContext, downstreamContexts);
}
else
{
MapNotAggregate(originalContext, downstreamContexts);
}
}
private async Task MapAggregtes(DownstreamContext originalContext, List<DownstreamContext> downstreamContexts)
{
await MapAggregateContent(originalContext, downstreamContexts);
}
@ -34,7 +21,7 @@ namespace Ocelot.Middleware.Multiplexer
contentBuilder.Append("{");
for (int i = 0; i < downstreamContexts.Count; i++)
for (var i = 0; i < downstreamContexts.Count; i++)
{
if (downstreamContexts[i].IsError)
{
@ -54,13 +41,12 @@ namespace Ocelot.Middleware.Multiplexer
contentBuilder.Append("}");
originalContext.DownstreamResponse = new HttpResponseMessage(HttpStatusCode.OK)
var stringContent = new StringContent(contentBuilder.ToString())
{
Content = new StringContent(contentBuilder.ToString())
{
Headers = {ContentType = new MediaTypeHeaderValue("application/json")}
}
Headers = {ContentType = new MediaTypeHeaderValue("application/json")}
};
originalContext.DownstreamResponse = new DownstreamResponse(stringContent, HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>());
}
private static void MapAggregateError(DownstreamContext originalContext, List<DownstreamContext> downstreamContexts, int i)
@ -68,17 +54,5 @@ namespace Ocelot.Middleware.Multiplexer
originalContext.Errors.AddRange(downstreamContexts[i].Errors);
originalContext.DownstreamResponse = downstreamContexts[i].DownstreamResponse;
}
private void MapNotAggregate(DownstreamContext originalContext, List<DownstreamContext> downstreamContexts)
{
//assume at least one..if this errors then it will be caught by global exception handler
var finished = downstreamContexts.First();
originalContext.Errors = finished.Errors;
originalContext.DownstreamRequest = finished.DownstreamRequest;
originalContext.DownstreamResponse = finished.DownstreamResponse;
}
}
}

View File

@ -0,0 +1,34 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Ocelot.Configuration;
namespace Ocelot.Middleware.Multiplexer
{
public class UserDefinedResponseAggregator : IResponseAggregator
{
private readonly IDefinedAggregatorProvider _provider;
public UserDefinedResponseAggregator(IDefinedAggregatorProvider provider)
{
_provider = provider;
}
public async Task Aggregate(ReRoute reRoute, DownstreamContext originalContext, List<DownstreamContext> downstreamResponses)
{
var aggregator = _provider.Get(reRoute);
if (!aggregator.IsError)
{
var aggregateResponse = await aggregator.Data
.Aggregate(downstreamResponses.Select(x => x.DownstreamResponse).ToList());
originalContext.DownstreamResponse = aggregateResponse;
}
else
{
originalContext.Errors.AddRange(aggregator.Errors);
}
}
}
}

View File

@ -22,11 +22,6 @@
public static class OcelotMiddlewareExtensions
{
/// <summary>
/// Registers the Ocelot default middlewares
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
public static async Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder builder)
{
await builder.UseOcelot(new OcelotPipelineConfiguration());
@ -34,12 +29,6 @@
return builder;
}
/// <summary>
/// Registers Ocelot with a combination of default middlewares and optional middlewares in the configuration
/// </summary>
/// <param name="builder"></param>
/// <param name="pipelineConfiguration"></param>
/// <returns></returns>
public static async Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder builder, OcelotPipelineConfiguration pipelineConfiguration)
{
var configuration = await CreateConfiguration(builder);
@ -230,26 +219,14 @@
});
}
}
private static void UseIfNotNull(this IApplicationBuilder builder, Func<HttpContext, Func<Task>, Task> middleware)
{
if (middleware != null)
{
builder.Use(middleware);
}
}
/// <summary>
/// Configure a DiagnosticListener to listen for diagnostic events when the middleware starts and ends
/// </summary>
/// <param name="builder"></param>
private static void ConfigureDiagnosticListener(IApplicationBuilder builder)
{
private static void ConfigureDiagnosticListener(IApplicationBuilder builder)
{
var env = (IHostingEnvironment)builder.ApplicationServices.GetService(typeof(IHostingEnvironment));
var listener = (OcelotDiagnosticListener)builder.ApplicationServices.GetService(typeof(OcelotDiagnosticListener));
var diagnosticListener = (DiagnosticListener)builder.ApplicationServices.GetService(typeof(DiagnosticListener));
diagnosticListener.SubscribeWithAdapter(listener);
}
}
private static void OnShutdown(IApplicationBuilder app)
{

View File

@ -5,9 +5,7 @@
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Primitives;
@ -83,7 +81,6 @@
{
foreach (var header in request.Headers)
{
//todo get rid of if..
if (IsSupportedHeader(header))
{
requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());

View File

@ -1,10 +1,6 @@
using Microsoft.AspNetCore.Http;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware;
using System.Threading.Tasks;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Requester.QoS;
namespace Ocelot.Requester.Middleware
{
@ -36,7 +32,7 @@ namespace Ocelot.Requester.Middleware
Logger.LogDebug("setting http response message");
context.DownstreamResponse = response.Data;
context.DownstreamResponse = new DownstreamResponse(response.Data);
}
}
}

View File

@ -1,17 +1,14 @@
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Ocelot.Headers;
using Ocelot.Responses;
using Ocelot.Middleware;
namespace Ocelot.Responder
{
using System.Collections.Generic;
/// <summary>
/// Cannot unit test things in this class due to methods not being implemented
/// on .net concretes used for testing
@ -25,7 +22,7 @@ namespace Ocelot.Responder
_removeOutputHeaders = removeOutputHeaders;
}
public async Task SetResponseOnHttpContext(HttpContext context, HttpResponseMessage response)
public async Task SetResponseOnHttpContext(HttpContext context, DownstreamResponse response)
{
_removeOutputHeaders.Remove(response.Headers);
@ -36,12 +33,12 @@ namespace Ocelot.Responder
foreach (var httpResponseHeader in response.Content.Headers)
{
AddHeaderIfDoesntExist(context, httpResponseHeader);
AddHeaderIfDoesntExist(context, new Header(httpResponseHeader.Key, httpResponseHeader.Value));
}
var content = await response.Content.ReadAsByteArrayAsync();
AddHeaderIfDoesntExist(context, new KeyValuePair<string, IEnumerable<string>>("Content-Length", new []{ content.Length.ToString() }) );
AddHeaderIfDoesntExist(context, new Header("Content-Length", new []{ content.Length.ToString() }) );
context.Response.OnStarting(state =>
{
@ -70,11 +67,11 @@ namespace Ocelot.Responder
}, context);
}
private static void AddHeaderIfDoesntExist(HttpContext context, KeyValuePair<string, IEnumerable<string>> httpResponseHeader)
private static void AddHeaderIfDoesntExist(HttpContext context, Header httpResponseHeader)
{
if (!context.Response.Headers.ContainsKey(httpResponseHeader.Key))
{
context.Response.Headers.Add(httpResponseHeader.Key, new StringValues(httpResponseHeader.Value.ToArray()));
context.Response.Headers.Add(httpResponseHeader.Key, new StringValues(httpResponseHeader.Values.ToArray()));
}
}
}

View File

@ -1,12 +1,13 @@
using System.Net.Http;
using System.Threading.Tasks;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Ocelot.Middleware;
using Ocelot.Middleware.Multiplexer;
namespace Ocelot.Responder
{
public interface IHttpResponder
{
Task SetResponseOnHttpContext(HttpContext context, HttpResponseMessage response);
Task SetResponseOnHttpContext(HttpContext context, DownstreamResponse response);
void SetErrorResponseOnContext(HttpContext context, int statusCode);
}
}

View File

@ -1,11 +1,9 @@
using Microsoft.AspNetCore.Http;
using Ocelot.Errors;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware;
using System.Collections.Generic;
using System.Threading.Tasks;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Infrastructure.Extensions;
namespace Ocelot.Responder.Middleware