Made changes based on PR comments. Also added lots more tests!

This commit is contained in:
Philip Wood
2017-04-19 20:12:08 +01:00
parent 878eacf1db
commit 80e728aa00
9 changed files with 478 additions and 44 deletions

View File

@ -31,6 +31,7 @@ using Ocelot.Middleware;
using Ocelot.QueryStrings;
using Ocelot.RateLimit;
using Ocelot.Request.Builder;
using Ocelot.Request.Mapper;
using Ocelot.Requester;
using Ocelot.Requester.QoS;
using Ocelot.Responder;
@ -160,6 +161,7 @@ namespace Ocelot.DependencyInjection
services.TryAddSingleton<IAuthenticationHandlerCreator, AuthenticationHandlerCreator>();
services.TryAddSingleton<IRateLimitCounterHandler, MemoryCacheRateLimitCounterHandler>();
services.TryAddSingleton<IHttpClientCache, MemoryHttpClientCache>();
services.TryAddSingleton<IRequestMapper, RequestMapper>();
// see this for why we register this as singleton http://stackoverflow.com/questions/37371264/invalidoperationexception-unable-to-resolve-service-for-type-microsoft-aspnetc
// could maybe use a scoped data repository

View File

@ -28,6 +28,7 @@
UnableToFindLoadBalancerError,
RequestTimedOutError,
UnableToFindQoSProviderError,
UnableToSetConfigInConsulError
UnableToSetConfigInConsulError,
UnmappableRequestError
}
}

View File

@ -53,9 +53,6 @@ namespace Ocelot.Middleware
{
await CreateAdministrationArea(builder);
// Initialises downstream request
builder.UseDownstreamRequestInitialiser();
// This is registered to catch any global exceptions that are not handled
builder.UseExceptionHandlerMiddleware();
@ -65,6 +62,9 @@ namespace Ocelot.Middleware
// This is registered first so it can catch any errors and issue an appropriate response
builder.UseResponderMiddleware();
// Initialises downstream request
builder.UseDownstreamRequestInitialiser();
// Then we get the downstream route information
builder.UseDownstreamRouteFinderMiddleware();

View File

@ -0,0 +1,12 @@
namespace Ocelot.Request.Mapper
{
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Ocelot.Responses;
public interface IRequestMapper
{
Task<Response<HttpRequestMessage>> Map(HttpRequest request);
}
}

View File

@ -1,33 +1,40 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Primitives;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
namespace Ocelot.Request
namespace Ocelot.Request.Mapper
{
public class Mapper
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Primitives;
using Ocelot.Responses;
public class RequestMapper : IRequestMapper
{
private readonly string[] _unsupportedHeaders = { "host" };
public async Task<HttpRequestMessage> Map(HttpRequest request)
public async Task<Response<HttpRequestMessage>> Map(HttpRequest request)
{
var requestMessage = new HttpRequestMessage()
try
{
Content = await MapContent(request),
Method = MapMethod(request),
RequestUri = MapUri(request),
//Properties = null
//Version = null
};
var requestMessage = new HttpRequestMessage()
{
Content = await MapContent(request),
Method = MapMethod(request),
RequestUri = MapUri(request)
};
MapHeaders(request, requestMessage);
MapHeaders(request, requestMessage);
return requestMessage;
return new OkResponse<HttpRequestMessage>(requestMessage);
}
catch (Exception ex)
{
return new ErrorResponse<HttpRequestMessage>(new UnmappableRequestError(ex));
}
}
private async Task<HttpContent> MapContent(HttpRequest request)
@ -37,7 +44,6 @@ namespace Ocelot.Request
return null;
}
return new ByteArrayContent(await ToByteArray(request.Body));
}

View File

@ -0,0 +1,12 @@
namespace Ocelot.Request.Mapper
{
using Ocelot.Errors;
using System;
public class UnmappableRequestError : Error
{
public UnmappableRequestError(Exception ex) : base($"Error when parsing incoming request, exception: {ex.Message}", OcelotErrorCode.UnmappableRequestError)
{
}
}
}

View File

@ -1,40 +1,41 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware;
using Ocelot.Request.Builder;
using Ocelot.Requester.QoS;
namespace Ocelot.Request.Middleware
{
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Middleware;
public class DownstreamRequestInitialiserMiddleware : OcelotMiddleware
{
private readonly RequestDelegate _next;
private readonly IRequestCreator _requestCreator;
private readonly IOcelotLogger _logger;
private readonly IQosProviderHouse _qosProviderHouse;
private readonly Mapper.IRequestMapper _requestMapper;
public DownstreamRequestInitialiserMiddleware(RequestDelegate next,
IOcelotLoggerFactory loggerFactory,
IRequestScopedDataRepository requestScopedDataRepository,
IRequestCreator requestCreator,
IQosProviderHouse qosProviderHouse)
IRequestScopedDataRepository requestScopedDataRepository,
Mapper.IRequestMapper requestMapper)
:base(requestScopedDataRepository)
{
_next = next;
_requestCreator = requestCreator;
_qosProviderHouse = qosProviderHouse;
_logger = loggerFactory.CreateLogger<DownstreamRequestInitialiserMiddleware>();
_requestMapper = requestMapper;
}
public async Task Invoke(HttpContext context)
{
_logger.LogDebug("started calling request builder middleware");
var mapper = new Mapper();
var downstreamRequest = await _requestMapper.Map(context.Request);
if (downstreamRequest.IsError)
{
SetPipelineError(downstreamRequest.Errors);
return;
}
SetDownstreamRequest(await mapper.Map(context.Request));
SetDownstreamRequest(downstreamRequest.Data);
_logger.LogDebug("calling next middleware");