Very hacky proof of concept

This commit is contained in:
Philip Wood 2017-04-17 21:25:04 +01:00
parent 8d31b40c21
commit eeb8f691c7
28 changed files with 615 additions and 356 deletions

View File

@ -27,7 +27,7 @@ namespace Ocelot.Cache.Middleware
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
{ {
var downstreamUrlKey = DownstreamUrl; var downstreamUrlKey = DownstreamRequest.RequestUri.OriginalString;
if (!DownstreamRoute.ReRoute.IsCached) if (!DownstreamRoute.ReRoute.IsCached)
{ {

View File

@ -4,6 +4,7 @@ using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
using System;
namespace Ocelot.DownstreamUrlCreator.Middleware namespace Ocelot.DownstreamUrlCreator.Middleware
{ {
@ -42,23 +43,31 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
return; return;
} }
var dsScheme = DownstreamRoute.ReRoute.DownstreamScheme; //var dsScheme = DownstreamRoute.ReRoute.DownstreamScheme;
var dsHostAndPort = HostAndPort; //var dsHostAndPort = HostAndPort;
var dsUrl = _urlBuilder.Build(dsPath.Data.Value, dsScheme, dsHostAndPort); //var dsUrl = _urlBuilder.Build(dsPath.Data.Value, dsScheme, dsHostAndPort);
if (dsUrl.IsError) //if (dsUrl.IsError)
//{
// _logger.LogDebug("IUrlBuilder returned an error, setting pipeline error");
// SetPipelineError(dsUrl.Errors);
// return;
//}
var uriBuilder = new UriBuilder(DownstreamRequest.RequestUri)
{ {
_logger.LogDebug("IUrlBuilder returned an error, setting pipeline error"); Path = dsPath.Data.Value,
Scheme = DownstreamRoute.ReRoute.DownstreamScheme
};
SetPipelineError(dsUrl.Errors); DownstreamRequest.RequestUri = uriBuilder.Uri;
return;
}
_logger.LogDebug("downstream url is {downstreamUrl.Data.Value}", dsUrl.Data.Value); _logger.LogDebug("downstream url is {downstreamUrl.Data.Value}", DownstreamRequest.RequestUri);
SetDownstreamUrlForThisRequest(dsUrl.Data.Value); //SetDownstreamUrlForThisRequest(dsUrl.Data.Value);
_logger.LogDebug("calling next middleware"); _logger.LogDebug("calling next middleware");

View File

@ -25,6 +25,7 @@ namespace Ocelot.DownstreamUrlCreator
return new ErrorResponse<DownstreamUrl>(new List<Error> { new DownstreamHostNullOrEmptyError() }); return new ErrorResponse<DownstreamUrl>(new List<Error> { new DownstreamHostNullOrEmptyError() });
} }
var builder = new UriBuilder var builder = new UriBuilder
{ {
Host = downstreamHostAndPort.DownstreamHost, Host = downstreamHostAndPort.DownstreamHost,

View File

@ -1,10 +1,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Infrastructure.Claims.Parser; using Ocelot.Infrastructure.Claims.Parser;
using Ocelot.Responses; using Ocelot.Responses;
using System.Net.Http;
namespace Ocelot.Headers namespace Ocelot.Headers
{ {
@ -17,25 +16,49 @@ namespace Ocelot.Headers
_claimsParser = claimsParser; _claimsParser = claimsParser;
} }
public Response SetHeadersOnContext(List<ClaimToThing> claimsToThings, HttpContext context) //public Response SetHeadersOnContext(List<ClaimToThing> claimsToThings, HttpContext context)
//{
// foreach (var config in claimsToThings)
// {
// var value = _claimsParser.GetValue(context.User.Claims, config.NewKey, config.Delimiter, config.Index);
// if (value.IsError)
// {
// return new ErrorResponse(value.Errors);
// }
// var exists = context.Request.Headers.FirstOrDefault(x => x.Key == config.ExistingKey);
// if (!string.IsNullOrEmpty(exists.Key))
// {
// context.Request.Headers.Remove(exists);
// }
// context.Request.Headers.Add(config.ExistingKey, new StringValues(value.Data));
// }
// return new OkResponse();
//}
public Response SetHeadersOnDownstreamRequest(List<ClaimToThing> claimsToThings, IEnumerable<System.Security.Claims.Claim> claims, HttpRequestMessage downstreamRequest)
{ {
foreach (var config in claimsToThings) foreach (var config in claimsToThings)
{ {
var value = _claimsParser.GetValue(context.User.Claims, config.NewKey, config.Delimiter, config.Index); var value = _claimsParser.GetValue(claims, config.NewKey, config.Delimiter, config.Index);
if (value.IsError) if (value.IsError)
{ {
return new ErrorResponse(value.Errors); return new ErrorResponse(value.Errors);
} }
var exists = context.Request.Headers.FirstOrDefault(x => x.Key == config.ExistingKey); var exists = downstreamRequest.Headers.FirstOrDefault(x => x.Key == config.ExistingKey);
if (!string.IsNullOrEmpty(exists.Key)) if (!string.IsNullOrEmpty(exists.Key))
{ {
context.Request.Headers.Remove(exists); downstreamRequest.Headers.Remove(exists.Key);
} }
context.Request.Headers.Add(config.ExistingKey, new StringValues(value.Data)); downstreamRequest.Headers.Add(config.ExistingKey, value.Data);
} }
return new OkResponse(); return new OkResponse();

View File

@ -2,12 +2,15 @@
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Responses; using Ocelot.Responses;
using System.Net.Http;
namespace Ocelot.Headers namespace Ocelot.Headers
{ {
public interface IAddHeadersToRequest public interface IAddHeadersToRequest
{ {
Response SetHeadersOnContext(List<ClaimToThing> claimsToThings, //Response SetHeadersOnContext(List<ClaimToThing> claimsToThings,
HttpContext context); // HttpContext context);
Response SetHeadersOnDownstreamRequest(List<ClaimToThing> claimsToThings, IEnumerable<System.Security.Claims.Claim> claims, HttpRequestMessage downstreamRequest);
} }
} }

View File

@ -32,7 +32,8 @@ namespace Ocelot.Headers.Middleware
{ {
_logger.LogDebug("this route has instructions to convert claims to headers"); _logger.LogDebug("this route has instructions to convert claims to headers");
var response = _addHeadersToRequest.SetHeadersOnContext(DownstreamRoute.ReRoute.ClaimsToHeaders, context); //var response = _addHeadersToRequest.SetHeadersOnContext(DownstreamRoute.ReRoute.ClaimsToHeaders, context);
var response = _addHeadersToRequest.SetHeadersOnDownstreamRequest(DownstreamRoute.ReRoute.ClaimsToHeaders, context.User.Claims, DownstreamRequest);
if (response.IsError) if (response.IsError)
{ {

View File

@ -44,7 +44,14 @@ namespace Ocelot.LoadBalancer.Middleware
return; return;
} }
SetHostAndPortForThisRequest(hostAndPort.Data); //SetHostAndPortForThisRequest(hostAndPort.Data);
var uriBuilder = new UriBuilder(DownstreamRequest.RequestUri);
uriBuilder.Host = hostAndPort.Data.DownstreamHost;
if (hostAndPort.Data.DownstreamPort > 0)
{
uriBuilder.Port = hostAndPort.Data.DownstreamPort;
}
DownstreamRequest.RequestUri = uriBuilder.Uri;
_logger.LogDebug("calling next middleware"); _logger.LogDebug("calling next middleware");

View File

@ -46,14 +46,16 @@ namespace Ocelot.Middleware
} }
} }
public string DownstreamUrl //public string DownstreamUrl
{ //{
get // get
{ // {
var downstreamUrl = _requestScopedDataRepository.Get<string>("DownstreamUrl"); // var downstreamUrl = _requestScopedDataRepository.Get<string>("DownstreamUrl");
return downstreamUrl.Data; // return downstreamUrl.Data;
} // }
} //}
public HttpRequestMessage DownstreamRequest => _requestScopedDataRepository.Get<HttpRequestMessage>("DownstreamRequest").Data;
public Request.Request Request public Request.Request Request
{ {
@ -73,18 +75,23 @@ namespace Ocelot.Middleware
} }
} }
public HostAndPort HostAndPort //public HostAndPort HostAndPort
{ //{
get // get
{ // {
var hostAndPort = _requestScopedDataRepository.Get<HostAndPort>("HostAndPort"); // var hostAndPort = _requestScopedDataRepository.Get<HostAndPort>("HostAndPort");
return hostAndPort.Data; // return hostAndPort.Data;
} // }
} //}
public void SetHostAndPortForThisRequest(HostAndPort hostAndPort) //public void SetHostAndPortForThisRequest(HostAndPort hostAndPort)
//{
// _requestScopedDataRepository.Add("HostAndPort", hostAndPort);
//}
public void SetDownstreamRequest(HttpRequestMessage request)
{ {
_requestScopedDataRepository.Add("HostAndPort", hostAndPort); _requestScopedDataRepository.Add("DownstreamRequest", request);
} }
public void SetDownstreamRouteForThisRequest(DownstreamRoute downstreamRoute) public void SetDownstreamRouteForThisRequest(DownstreamRoute downstreamRoute)
@ -92,10 +99,10 @@ namespace Ocelot.Middleware
_requestScopedDataRepository.Add("DownstreamRoute", downstreamRoute); _requestScopedDataRepository.Add("DownstreamRoute", downstreamRoute);
} }
public void SetDownstreamUrlForThisRequest(string downstreamUrl) //public void SetDownstreamUrlForThisRequest(string downstreamUrl)
{ //{
_requestScopedDataRepository.Add("DownstreamUrl", downstreamUrl); // _requestScopedDataRepository.Add("DownstreamUrl", downstreamUrl);
} //}
public void SetUpstreamRequestForThisRequest(Request.Request request) public void SetUpstreamRequestForThisRequest(Request.Request request)
{ {

View File

@ -53,6 +53,9 @@ namespace Ocelot.Middleware
{ {
await CreateAdministrationArea(builder); await CreateAdministrationArea(builder);
// Initialises downstream request
builder.UseDownstreamRequestInitialiser();
// This is registered to catch any global exceptions that are not handled // This is registered to catch any global exceptions that are not handled
builder.UseExceptionHandlerMiddleware(); builder.UseExceptionHandlerMiddleware();

View File

@ -4,6 +4,9 @@ using Microsoft.AspNetCore.Http;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Infrastructure.Claims.Parser; using Ocelot.Infrastructure.Claims.Parser;
using Ocelot.Responses; using Ocelot.Responses;
using System.Security.Claims;
using System.Net.Http;
using System;
namespace Ocelot.QueryStrings namespace Ocelot.QueryStrings
{ {
@ -16,13 +19,44 @@ namespace Ocelot.QueryStrings
_claimsParser = claimsParser; _claimsParser = claimsParser;
} }
public Response SetQueriesOnContext(List<ClaimToThing> claimsToThings, HttpContext context) //public Response SetQueriesOnContext(List<ClaimToThing> claimsToThings, HttpContext context)
//{
// var queryDictionary = ConvertQueryStringToDictionary(context.Request.QueryString);
// foreach (var config in claimsToThings)
// {
// var value = _claimsParser.GetValue(context.User.Claims, config.NewKey, config.Delimiter, config.Index);
// if (value.IsError)
// {
// return new ErrorResponse(value.Errors);
// }
// var exists = queryDictionary.FirstOrDefault(x => x.Key == config.ExistingKey);
// if (!string.IsNullOrEmpty(exists.Key))
// {
// queryDictionary[exists.Key] = value.Data;
// }
// else
// {
// queryDictionary.Add(config.ExistingKey, value.Data);
// }
// }
// context.Request.QueryString = ConvertDictionaryToQueryString(queryDictionary);
// return new OkResponse();
//}
public Response SetQueriesOnDownstreamRequest(List<ClaimToThing> claimsToThings, IEnumerable<Claim> claims, HttpRequestMessage downstreamRequest)
{ {
var queryDictionary = ConvertQueryStringToDictionary(context);
var queryDictionary = ConvertQueryStringToDictionary(downstreamRequest.RequestUri.Query);
foreach (var config in claimsToThings) foreach (var config in claimsToThings)
{ {
var value = _claimsParser.GetValue(context.User.Claims, config.NewKey, config.Delimiter, config.Index); var value = _claimsParser.GetValue(claims, config.NewKey, config.Delimiter, config.Index);
if (value.IsError) if (value.IsError)
{ {
@ -41,22 +75,37 @@ namespace Ocelot.QueryStrings
} }
} }
context.Request.QueryString = ConvertDictionaryToQueryString(queryDictionary); var uriBuilder = new UriBuilder(downstreamRequest.RequestUri);
uriBuilder.Query = ConvertDictionaryToQueryString(queryDictionary);
downstreamRequest.RequestUri = uriBuilder.Uri;
return new OkResponse(); return new OkResponse();
} }
private Dictionary<string, string> ConvertQueryStringToDictionary(HttpContext context) //private Dictionary<string, string> ConvertQueryStringToDictionary(HttpContext context)
//{
// return Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(context.Request.QueryString.Value)
// .ToDictionary(q => q.Key, q => q.Value.FirstOrDefault() ?? string.Empty);
//}
private Dictionary<string, string> ConvertQueryStringToDictionary(string queryString)
{ {
return Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(context.Request.QueryString.Value) return Microsoft.AspNetCore.WebUtilities.QueryHelpers
.ParseQuery(queryString)
.ToDictionary(q => q.Key, q => q.Value.FirstOrDefault() ?? string.Empty); .ToDictionary(q => q.Key, q => q.Value.FirstOrDefault() ?? string.Empty);
} }
private Microsoft.AspNetCore.Http.QueryString ConvertDictionaryToQueryString(Dictionary<string, string> queryDictionary) //private Microsoft.AspNetCore.Http.QueryString ConvertDictionaryToQueryString(Dictionary<string, string> queryDictionary)
{ //{
var newQueryString = Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString("", queryDictionary); // var newQueryString = Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString("", queryDictionary);
return new Microsoft.AspNetCore.Http.QueryString(newQueryString); // return new Microsoft.AspNetCore.Http.QueryString(newQueryString);
//}
private string ConvertDictionaryToQueryString(Dictionary<string, string> queryDictionary)
{
return Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString("", queryDictionary);
} }
} }
} }

View File

@ -2,12 +2,16 @@
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Responses; using Ocelot.Responses;
using System.Net.Http;
using System.Security.Claims;
namespace Ocelot.QueryStrings namespace Ocelot.QueryStrings
{ {
public interface IAddQueriesToRequest public interface IAddQueriesToRequest
{ {
Response SetQueriesOnContext(List<ClaimToThing> claimsToThings, //Response SetQueriesOnContext(List<ClaimToThing> claimsToThings,
HttpContext context); // HttpContext context);
Response SetQueriesOnDownstreamRequest(List<ClaimToThing> claimsToThings, IEnumerable<Claim> claims, HttpRequestMessage downstreamRequest);
} }
} }

View File

@ -32,7 +32,8 @@ namespace Ocelot.QueryStrings.Middleware
{ {
_logger.LogDebug("this route has instructions to convert claims to queries"); _logger.LogDebug("this route has instructions to convert claims to queries");
var response = _addQueriesToRequest.SetQueriesOnContext(DownstreamRoute.ReRoute.ClaimsToQueries, context); //var response = _addQueriesToRequest.SetQueriesOnContext(DownstreamRoute.ReRoute.ClaimsToQueries, context);
var response = _addQueriesToRequest.SetQueriesOnDownstreamRequest(DownstreamRoute.ReRoute.ClaimsToQueries, context.User.Claims, DownstreamRequest);
if (response.IsError) if (response.IsError)
{ {

View File

@ -111,11 +111,7 @@ namespace Ocelot.RateLimit.Middleware
public bool IsWhitelisted(ClientRequestIdentity requestIdentity, RateLimitOptions option) public bool IsWhitelisted(ClientRequestIdentity requestIdentity, RateLimitOptions option)
{ {
if (option.ClientWhitelist.Contains(requestIdentity.ClientId)) return option.ClientWhitelist.Contains(requestIdentity.ClientId);
{
return true;
}
return false;
} }
public virtual void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule) public virtual void LogBlockedRequest(HttpContext httpContext, ClientRequestIdentity identity, RateLimitCounter counter, RateLimitRule rule)

View File

@ -4,35 +4,44 @@ using Microsoft.AspNetCore.Http;
using Ocelot.Responses; using Ocelot.Responses;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Requester.QoS; using Ocelot.Requester.QoS;
using System.Net.Http;
namespace Ocelot.Request.Builder namespace Ocelot.Request.Builder
{ {
public sealed class HttpRequestCreator : IRequestCreator public sealed class HttpRequestCreator : IRequestCreator
{ {
//public async Task<Response<Request>> Build(
// string httpMethod,
// string downstreamUrl,
// Stream content,
// IHeaderDictionary headers,
// QueryString queryString,
// string contentType,
// RequestId.RequestId requestId,
// bool isQos,
// IQoSProvider qosProvider)
//{
// var request = await new RequestBuilder()
// .WithHttpMethod(httpMethod)
// .WithDownstreamUrl(downstreamUrl)
// .WithQueryString(queryString)
// .WithContent(content)
// .WithContentType(contentType)
// .WithHeaders(headers)
// .WithRequestId(requestId)
// .WithIsQos(isQos)
// .WithQos(qosProvider)
// .Build();
// return new OkResponse<Request>(request);
//}
public async Task<Response<Request>> Build( public async Task<Response<Request>> Build(
string httpMethod, HttpRequestMessage httpRequestMessage,
string downstreamUrl,
Stream content,
IHeaderDictionary headers,
QueryString queryString,
string contentType,
RequestId.RequestId requestId,
bool isQos, bool isQos,
IQoSProvider qosProvider) IQoSProvider qosProvider)
{ {
var request = await new RequestBuilder() return new OkResponse<Request>(new Request(httpRequestMessage, isQos, qosProvider));
.WithHttpMethod(httpMethod)
.WithDownstreamUrl(downstreamUrl)
.WithQueryString(queryString)
.WithContent(content)
.WithContentType(contentType)
.WithHeaders(headers)
.WithRequestId(requestId)
.WithIsQos(isQos)
.WithQos(qosProvider)
.Build();
return new OkResponse<Request>(request);
} }
} }
} }

View File

@ -3,18 +3,24 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Ocelot.Requester.QoS; using Ocelot.Requester.QoS;
using Ocelot.Responses; using Ocelot.Responses;
using System.Net.Http;
namespace Ocelot.Request.Builder namespace Ocelot.Request.Builder
{ {
public interface IRequestCreator public interface IRequestCreator
{ {
Task<Response<Request>> Build(string httpMethod, //Task<Response<Request>> Build(string httpMethod,
string downstreamUrl, // string downstreamUrl,
Stream content, // Stream content,
IHeaderDictionary headers, // IHeaderDictionary headers,
QueryString queryString, // QueryString queryString,
string contentType, // string contentType,
RequestId.RequestId requestId, // RequestId.RequestId requestId,
// bool isQos,
// IQoSProvider qosProvider);
Task<Response<Request>> Build(
HttpRequestMessage httpRequestMessage,
bool isQos, bool isQos,
IQoSProvider qosProvider); IQoSProvider qosProvider);
} }

View File

@ -1,177 +1,177 @@
using System; //using System;
using System.Collections.Generic; //using System.Collections.Generic;
using System.IO; //using System.IO;
using System.Linq; //using System.Linq;
using System.Net; //using System.Net;
using System.Net.Http; //using System.Net.Http;
using System.Net.Http.Headers; //using System.Net.Http.Headers;
using System.Threading.Tasks; //using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; //using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives; //using Microsoft.Extensions.Primitives;
using Ocelot.Requester.QoS; //using Ocelot.Requester.QoS;
namespace Ocelot.Request.Builder //namespace Ocelot.Request.Builder
{ //{
internal sealed class RequestBuilder // internal sealed class RequestBuilder
{ // {
private HttpMethod _method; // private HttpMethod _method;
private string _downstreamUrl; // private string _downstreamUrl;
private QueryString _queryString; // private QueryString _queryString;
private Stream _content; // private Stream _content;
private string _contentType; // private string _contentType;
private IHeaderDictionary _headers; // private IHeaderDictionary _headers;
private RequestId.RequestId _requestId; // private RequestId.RequestId _requestId;
private readonly string[] _unsupportedHeaders = {"host"}; // private readonly string[] _unsupportedHeaders = {"host"};
private bool _isQos; // private bool _isQos;
private IQoSProvider _qoSProvider; // private IQoSProvider _qoSProvider;
public RequestBuilder WithHttpMethod(string httpMethod) // public RequestBuilder WithHttpMethod(string httpMethod)
{ // {
_method = new HttpMethod(httpMethod); // _method = new HttpMethod(httpMethod);
return this; // return this;
} // }
public RequestBuilder WithDownstreamUrl(string downstreamUrl) // public RequestBuilder WithDownstreamUrl(string downstreamUrl)
{ // {
_downstreamUrl = downstreamUrl; // _downstreamUrl = downstreamUrl;
return this; // return this;
} // }
public RequestBuilder WithQueryString(QueryString queryString) // public RequestBuilder WithQueryString(QueryString queryString)
{ // {
_queryString = queryString; // _queryString = queryString;
return this; // return this;
} // }
public RequestBuilder WithContent(Stream content) // public RequestBuilder WithContent(Stream content)
{ // {
_content = content; // _content = content;
return this; // return this;
} // }
public RequestBuilder WithContentType(string contentType) // public RequestBuilder WithContentType(string contentType)
{ // {
_contentType = contentType; // _contentType = contentType;
return this; // return this;
} // }
public RequestBuilder WithHeaders(IHeaderDictionary headers) // public RequestBuilder WithHeaders(IHeaderDictionary headers)
{ // {
_headers = headers; // _headers = headers;
return this; // return this;
} // }
public RequestBuilder WithRequestId(RequestId.RequestId requestId) // public RequestBuilder WithRequestId(RequestId.RequestId requestId)
{ // {
_requestId = requestId; // _requestId = requestId;
return this; // return this;
} // }
public RequestBuilder WithIsQos(bool isqos) // public RequestBuilder WithIsQos(bool isqos)
{ // {
_isQos = isqos; // _isQos = isqos;
return this; // return this;
} // }
public RequestBuilder WithQos(IQoSProvider qoSProvider) // public RequestBuilder WithQos(IQoSProvider qoSProvider)
{ // {
_qoSProvider = qoSProvider; // _qoSProvider = qoSProvider;
return this; // return this;
} // }
public async Task<Request> Build() // public async Task<Request> Build()
{ // {
var uri = CreateUri(); // var uri = CreateUri();
var httpRequestMessage = new HttpRequestMessage(_method, uri); // var httpRequestMessage = new HttpRequestMessage(_method, uri);
await AddContentToRequest(httpRequestMessage); // await AddContentToRequest(httpRequestMessage);
AddContentTypeToRequest(httpRequestMessage); // AddContentTypeToRequest(httpRequestMessage);
AddHeadersToRequest(httpRequestMessage); // AddHeadersToRequest(httpRequestMessage);
if (ShouldAddRequestId(_requestId, httpRequestMessage.Headers)) // if (ShouldAddRequestId(_requestId, httpRequestMessage.Headers))
{ // {
AddRequestIdHeader(_requestId, httpRequestMessage); // AddRequestIdHeader(_requestId, httpRequestMessage);
} // }
return new Request(httpRequestMessage,_isQos, _qoSProvider); // return new Request(httpRequestMessage,_isQos, _qoSProvider);
} // }
private Uri CreateUri() // private Uri CreateUri()
{ // {
var uri = new Uri(string.Format("{0}{1}", _downstreamUrl, _queryString.ToUriComponent())); // var uri = new Uri(string.Format("{0}{1}", _downstreamUrl, _queryString.ToUriComponent()));
return uri; // return uri;
} // }
private async Task AddContentToRequest(HttpRequestMessage httpRequestMessage) // private async Task AddContentToRequest(HttpRequestMessage httpRequestMessage)
{ // {
if (_content != null) // if (_content != null)
{ // {
httpRequestMessage.Content = new ByteArrayContent(await ToByteArray(_content)); // httpRequestMessage.Content = new ByteArrayContent(await ToByteArray(_content));
} // }
} // }
private void AddContentTypeToRequest(HttpRequestMessage httpRequestMessage) // private void AddContentTypeToRequest(HttpRequestMessage httpRequestMessage)
{ // {
if (!string.IsNullOrEmpty(_contentType)) // if (!string.IsNullOrEmpty(_contentType))
{ // {
httpRequestMessage.Content.Headers.Remove("Content-Type"); // httpRequestMessage.Content.Headers.Remove("Content-Type");
httpRequestMessage.Content.Headers.TryAddWithoutValidation("Content-Type", _contentType); // httpRequestMessage.Content.Headers.TryAddWithoutValidation("Content-Type", _contentType);
} // }
} // }
private void AddHeadersToRequest(HttpRequestMessage httpRequestMessage) // private void AddHeadersToRequest(HttpRequestMessage httpRequestMessage)
{ // {
if (_headers != null) // if (_headers != null)
{ // {
_headers.Remove("Content-Type"); // _headers.Remove("Content-Type");
foreach (var header in _headers) // foreach (var header in _headers)
{ // {
//todo get rid of if.. // //todo get rid of if..
if (IsSupportedHeader(header)) // if (IsSupportedHeader(header))
{ // {
httpRequestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); // httpRequestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
} // }
} // }
} // }
} // }
private bool IsSupportedHeader(KeyValuePair<string, StringValues> header) // private bool IsSupportedHeader(KeyValuePair<string, StringValues> header)
{ // {
return !_unsupportedHeaders.Contains(header.Key.ToLower()); // return !_unsupportedHeaders.Contains(header.Key.ToLower());
} // }
private void AddRequestIdHeader(RequestId.RequestId requestId, HttpRequestMessage httpRequestMessage) // private void AddRequestIdHeader(RequestId.RequestId requestId, HttpRequestMessage httpRequestMessage)
{ // {
httpRequestMessage.Headers.Add(requestId.RequestIdKey, requestId.RequestIdValue); // httpRequestMessage.Headers.Add(requestId.RequestIdKey, requestId.RequestIdValue);
} // }
private bool RequestIdInHeaders(RequestId.RequestId requestId, HttpRequestHeaders headers) // private bool RequestIdInHeaders(RequestId.RequestId requestId, HttpRequestHeaders headers)
{ // {
IEnumerable<string> value; // IEnumerable<string> value;
return headers.TryGetValues(requestId.RequestIdKey, out value); // return headers.TryGetValues(requestId.RequestIdKey, out value);
} // }
private bool ShouldAddRequestId(RequestId.RequestId requestId, HttpRequestHeaders headers) // private bool ShouldAddRequestId(RequestId.RequestId requestId, HttpRequestHeaders headers)
{ // {
return !string.IsNullOrEmpty(requestId?.RequestIdKey) // return !string.IsNullOrEmpty(requestId?.RequestIdKey)
&& !string.IsNullOrEmpty(requestId.RequestIdValue) // && !string.IsNullOrEmpty(requestId.RequestIdValue)
&& !RequestIdInHeaders(requestId, headers); // && !RequestIdInHeaders(requestId, headers);
} // }
private async Task<byte[]> ToByteArray(Stream stream) // private async Task<byte[]> ToByteArray(Stream stream)
{ // {
using (stream) // using (stream)
{ // {
using (var memStream = new MemoryStream()) // using (var memStream = new MemoryStream())
{ // {
await stream.CopyToAsync(memStream); // await stream.CopyToAsync(memStream);
return memStream.ToArray(); // return memStream.ToArray();
} // }
} // }
} // }
} // }
} //}

View File

@ -0,0 +1,37 @@
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
namespace Ocelot.Request
{
public class Mapper
{
public async Task<HttpRequestMessage> Map(Microsoft.AspNetCore.Http.HttpRequest request)
{
var requestMessage = new HttpRequestMessage()
{
Content = new ByteArrayContent(await ToByteArray(request.Body)),
//Headers = request.Headers,
//Method = request.Method,
//Properties = request.P,
//RequestUri = request.,
//Version = null
};
return requestMessage;
}
private async Task<byte[]> ToByteArray(Stream stream)
{
using (stream)
{
using (var memStream = new MemoryStream())
{
await stream.CopyToAsync(memStream);
return memStream.ToArray();
}
}
}
}
}

View File

@ -0,0 +1,46 @@
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
{
public class DownstreamRequestInitialiserMiddleware : OcelotMiddleware
{
private readonly RequestDelegate _next;
private readonly IRequestCreator _requestCreator;
private readonly IOcelotLogger _logger;
private readonly IQosProviderHouse _qosProviderHouse;
public DownstreamRequestInitialiserMiddleware(RequestDelegate next,
IOcelotLoggerFactory loggerFactory,
IRequestScopedDataRepository requestScopedDataRepository,
IRequestCreator requestCreator,
IQosProviderHouse qosProviderHouse)
:base(requestScopedDataRepository)
{
_next = next;
_requestCreator = requestCreator;
_qosProviderHouse = qosProviderHouse;
_logger = loggerFactory.CreateLogger<DownstreamRequestInitialiserMiddleware>();
}
public async Task Invoke(HttpContext context)
{
_logger.LogDebug("started calling request builder middleware");
var mapper = new Mapper();
SetDownstreamRequest(await mapper.Map(context.Request));
_logger.LogDebug("calling next middleware");
await _next.Invoke(context);
_logger.LogDebug("succesfully called next middleware");
}
}
}

View File

@ -43,14 +43,19 @@ namespace Ocelot.Request.Middleware
return; return;
} }
var buildResult = await _requestCreator //var buildResult = await _requestCreator
.Build(context.Request.Method, // .Build(context.Request.Method,
DownstreamUrl, // DownstreamUrl,
context.Request.Body, // context.Request.Body,
context.Request.Headers, // context.Request.Headers,
context.Request.QueryString, // context.Request.QueryString,
context.Request.ContentType, // context.Request.ContentType,
new RequestId.RequestId(DownstreamRoute?.ReRoute?.RequestIdKey, context.TraceIdentifier), // new RequestId.RequestId(DownstreamRoute?.ReRoute?.RequestIdKey, context.TraceIdentifier),
// DownstreamRoute.ReRoute.IsQos,
// qosProvider.Data);
var buildResult = await _requestCreator.Build(
DownstreamRequest,
DownstreamRoute.ReRoute.IsQos, DownstreamRoute.ReRoute.IsQos,
qosProvider.Data); qosProvider.Data);

View File

@ -8,5 +8,10 @@ namespace Ocelot.Request.Middleware
{ {
return builder.UseMiddleware<HttpRequestBuilderMiddleware>(); return builder.UseMiddleware<HttpRequestBuilderMiddleware>();
} }
public static IApplicationBuilder UseDownstreamRequestInitialiser(this IApplicationBuilder builder)
{
return builder.UseMiddleware<DownstreamRequestInitialiserMiddleware>();
}
} }
} }

View File

@ -5,6 +5,9 @@ using Microsoft.Extensions.Primitives;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Collections.Generic;
namespace Ocelot.RequestId.Middleware namespace Ocelot.RequestId.Middleware
{ {
@ -30,8 +33,6 @@ namespace Ocelot.RequestId.Middleware
SetOcelotRequestId(context); SetOcelotRequestId(context);
_logger.LogDebug("set requestId");
_logger.TraceInvokeNext(); _logger.TraceInvokeNext();
await _next.Invoke(context); await _next.Invoke(context);
_logger.TraceInvokeNextCompleted(); _logger.TraceInvokeNextCompleted();
@ -47,14 +48,27 @@ namespace Ocelot.RequestId.Middleware
key = DownstreamRoute.ReRoute.RequestIdKey; key = DownstreamRoute.ReRoute.RequestIdKey;
} }
StringValues requestId; StringValues requestIds;
if (context.Request.Headers.TryGetValue(key, out requestId)) if (context.Request.Headers.TryGetValue(key, out requestIds))
{ {
_requestScopedDataRepository.Add("RequestId", requestId.First()); var requestId = requestIds.First();
var downstreamRequestHeaders = DownstreamRequest.Headers;
if (!string.IsNullOrEmpty(requestId) &&
!HeaderExists(key, downstreamRequestHeaders))
{
downstreamRequestHeaders.Add(key, requestId);
}
context.TraceIdentifier = requestId; context.TraceIdentifier = requestId;
} }
} }
private bool HeaderExists(string headerKey, HttpRequestHeaders headers)
{
IEnumerable<string> value;
return headers.TryGetValues(headerKey, out value);
}
} }
} }

View File

@ -129,7 +129,9 @@ namespace Ocelot.UnitTests.Headers
private void WhenIAddHeadersToTheRequest() private void WhenIAddHeadersToTheRequest()
{ {
_result = _addHeadersToRequest.SetHeadersOnContext(_configuration, _context); //_result = _addHeadersToRequest.SetHeadersOnContext(_configuration, _context);
//TODO: pass in DownstreamRequest
_result = _addHeadersToRequest.SetHeadersOnDownstreamRequest(_configuration, _context.User.Claims, null);
} }
private void ThenTheResultIsSuccess() private void ThenTheResultIsSuccess()

View File

@ -84,17 +84,28 @@ namespace Ocelot.UnitTests.Headers
private void GivenTheAddHeadersToRequestReturns() private void GivenTheAddHeadersToRequestReturns()
{ {
//_addHeaders
// .Setup(x => x.SetHeadersOnContext(It.IsAny<List<ClaimToThing>>(),
// It.IsAny<HttpContext>()))
// .Returns(new OkResponse());
_addHeaders _addHeaders
.Setup(x => x.SetHeadersOnContext(It.IsAny<List<ClaimToThing>>(), .Setup(x => x.SetHeadersOnDownstreamRequest(
It.IsAny<HttpContext>())) It.IsAny<List<ClaimToThing>>(),
It.IsAny<IEnumerable<System.Security.Claims.Claim>>(),
It.IsAny<HttpRequestMessage>()))
.Returns(new OkResponse()); .Returns(new OkResponse());
} }
private void ThenTheAddHeadersToRequestIsCalledCorrectly() private void ThenTheAddHeadersToRequestIsCalledCorrectly()
{ {
//_addHeaders
// .Verify(x => x.SetHeadersOnContext(It.IsAny<List<ClaimToThing>>(),
// It.IsAny<HttpContext>()), Times.Once);
_addHeaders _addHeaders
.Verify(x => x.SetHeadersOnContext(It.IsAny<List<ClaimToThing>>(), .Verify(x => x.SetHeadersOnDownstreamRequest(
It.IsAny<HttpContext>()), Times.Once); It.IsAny<List<ClaimToThing>>(),
It.IsAny<IEnumerable<System.Security.Claims.Claim>>(),
It.IsAny<HttpRequestMessage>()), Times.Once);
} }
private void WhenICallTheMiddleware() private void WhenICallTheMiddleware()

View File

@ -128,7 +128,9 @@ namespace Ocelot.UnitTests.QueryStrings
private void WhenIAddQueriesToTheRequest() private void WhenIAddQueriesToTheRequest()
{ {
_result = _addQueriesToRequest.SetQueriesOnContext(_configuration, _context); //_result = _addQueriesToRequest.SetQueriesOnContext(_configuration, _context);
//TODO: set downstreamRequest
_result = _addQueriesToRequest.SetQueriesOnDownstreamRequest(_configuration, _context.User.Claims, null);
} }
private void ThenTheResultIsSuccess() private void ThenTheResultIsSuccess()

View File

@ -20,6 +20,7 @@ using Ocelot.QueryStrings.Middleware;
using Ocelot.Responses; using Ocelot.Responses;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
using System.Security.Claims;
namespace Ocelot.UnitTests.QueryStrings namespace Ocelot.UnitTests.QueryStrings
{ {
@ -82,17 +83,28 @@ namespace Ocelot.UnitTests.QueryStrings
private void GivenTheAddHeadersToRequestReturns() private void GivenTheAddHeadersToRequestReturns()
{ {
//_addQueries
// .Setup(x => x.SetQueriesOnContext(It.IsAny<List<ClaimToThing>>(),
// It.IsAny<HttpContext>()))
// .Returns(new OkResponse());
_addQueries _addQueries
.Setup(x => x.SetQueriesOnContext(It.IsAny<List<ClaimToThing>>(), .Setup(x => x.SetQueriesOnDownstreamRequest(
It.IsAny<HttpContext>())) It.IsAny<List<ClaimToThing>>(),
It.IsAny<IEnumerable<Claim>>(),
It.IsAny<HttpRequestMessage>()))
.Returns(new OkResponse()); .Returns(new OkResponse());
} }
private void ThenTheAddQueriesToRequestIsCalledCorrectly() private void ThenTheAddQueriesToRequestIsCalledCorrectly()
{ {
//_addQueries
// .Verify(x => x.SetQueriesOnContext(It.IsAny<List<ClaimToThing>>(),
// It.IsAny<HttpContext>()), Times.Once);
_addQueries _addQueries
.Verify(x => x.SetQueriesOnContext(It.IsAny<List<ClaimToThing>>(), .Verify(x => x.SetQueriesOnDownstreamRequest(
It.IsAny<HttpContext>()), Times.Once); It.IsAny<List<ClaimToThing>>(),
It.IsAny<IEnumerable<Claim>>(),
It.IsAny<HttpRequestMessage>()), Times.Once);
} }
private void WhenICallTheMiddleware() private void WhenICallTheMiddleware()

View File

@ -103,9 +103,12 @@ namespace Ocelot.UnitTests.Request
private void GivenTheRequestBuilderReturns(Ocelot.Request.Request request) private void GivenTheRequestBuilderReturns(Ocelot.Request.Request request)
{ {
_request = new OkResponse<Ocelot.Request.Request>(request); _request = new OkResponse<Ocelot.Request.Request>(request);
//_requestBuilder
// .Setup(x => x.Build(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<IHeaderDictionary>(),
// It.IsAny<QueryString>(), It.IsAny<string>(), It.IsAny<Ocelot.RequestId.RequestId>(),It.IsAny<bool>(), It.IsAny<IQoSProvider>()))
// .ReturnsAsync(_request);
_requestBuilder _requestBuilder
.Setup(x => x.Build(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<IHeaderDictionary>(), .Setup(x => x.Build(It.IsAny<HttpRequestMessage>(), It.IsAny<bool>(), It.IsAny<IQoSProvider>()))
It.IsAny<QueryString>(), It.IsAny<string>(), It.IsAny<Ocelot.RequestId.RequestId>(),It.IsAny<bool>(), It.IsAny<IQoSProvider>()))
.ReturnsAsync(_request); .ReturnsAsync(_request);
} }

View File

@ -287,8 +287,11 @@ namespace Ocelot.UnitTests.Request
private void WhenICreateARequest() private void WhenICreateARequest()
{ {
_result = _requestCreator.Build(_httpMethod, _downstreamUrl, _content?.ReadAsStreamAsync().Result, _headers, //_result = _requestCreator.Build(_httpMethod, _downstreamUrl, _content?.ReadAsStreamAsync().Result, _headers,
_query, _contentType, _requestId,_isQos,_qoSProvider).Result; // _query, _contentType, _requestId,_isQos,_qoSProvider).Result;
//todo: add httprequestmessage
_result = _requestCreator.Build(null, _isQos, _qoSProvider).Result;
} }