diff --git a/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs b/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs index e204a6f4..39d70e38 100644 --- a/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs +++ b/src/Ocelot/Authentication/Middleware/AuthenticationMiddleware.cs @@ -4,7 +4,6 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Ocelot.Authentication.Handler.Factory; using Ocelot.Configuration; -using Ocelot.DownstreamRouteFinder; using Ocelot.Errors; using Ocelot.Infrastructure.RequestData; using Ocelot.Middleware; @@ -14,7 +13,6 @@ namespace Ocelot.Authentication.Middleware public class AuthenticationMiddleware : OcelotMiddleware { private readonly RequestDelegate _next; - private readonly IRequestScopedDataRepository _requestScopedDataRepository; private readonly IApplicationBuilder _app; private readonly IAuthenticationHandlerFactory _authHandlerFactory; @@ -25,32 +23,23 @@ namespace Ocelot.Authentication.Middleware : base(requestScopedDataRepository) { _next = next; - _requestScopedDataRepository = requestScopedDataRepository; _authHandlerFactory = authHandlerFactory; _app = app; } public async Task Invoke(HttpContext context) { - var downstreamRoute = _requestScopedDataRepository.Get("DownstreamRoute"); - - if (downstreamRoute.IsError) + if (IsAuthenticatedRoute(DownstreamRoute.ReRoute)) { - SetPipelineError(downstreamRoute.Errors); - return; - } + var authenticationHandler = _authHandlerFactory.Get(_app, DownstreamRoute.ReRoute.AuthenticationOptions); - if (IsAuthenticatedRoute(downstreamRoute.Data.ReRoute)) - { - var authenticationNext = _authHandlerFactory.Get(_app, downstreamRoute.Data.ReRoute.AuthenticationOptions); - - if (!authenticationNext.IsError) + if (!authenticationHandler.IsError) { - await authenticationNext.Data.Handler.Invoke(context); + await authenticationHandler.Data.Handler.Invoke(context); } else { - SetPipelineError(authenticationNext.Errors); + SetPipelineError(authenticationHandler.Errors); } if (context.User.Identity.IsAuthenticated) diff --git a/src/Ocelot/Authorisation/Middleware/AuthorisationMiddleware.cs b/src/Ocelot/Authorisation/Middleware/AuthorisationMiddleware.cs index 0a020f8e..574cd431 100644 --- a/src/Ocelot/Authorisation/Middleware/AuthorisationMiddleware.cs +++ b/src/Ocelot/Authorisation/Middleware/AuthorisationMiddleware.cs @@ -1,10 +1,10 @@ using Ocelot.Infrastructure.RequestData; +using Ocelot.Responses; namespace Ocelot.Authorisation.Middleware { using System.Collections.Generic; using System.Threading.Tasks; - using DownstreamRouteFinder; using Errors; using Microsoft.AspNetCore.Http; using Ocelot.Middleware; @@ -12,7 +12,6 @@ namespace Ocelot.Authorisation.Middleware public class AuthorisationMiddleware : OcelotMiddleware { private readonly RequestDelegate _next; - private readonly IRequestScopedDataRepository _requestScopedDataRepository; private readonly IAuthoriser _authoriser; public AuthorisationMiddleware(RequestDelegate next, @@ -21,23 +20,14 @@ namespace Ocelot.Authorisation.Middleware : base(requestScopedDataRepository) { _next = next; - _requestScopedDataRepository = requestScopedDataRepository; _authoriser = authoriser; } public async Task Invoke(HttpContext context) { - var downstreamRoute = _requestScopedDataRepository.Get("DownstreamRoute"); - - if (downstreamRoute.IsError) + if (DownstreamRoute.ReRoute.IsAuthorised) { - SetPipelineError(downstreamRoute.Errors); - return; - } - - if (downstreamRoute.Data.ReRoute.IsAuthorised) - { - var authorised = _authoriser.Authorise(context.User, downstreamRoute.Data.ReRoute.RouteClaimsRequirement); + var authorised = _authoriser.Authorise(context.User, DownstreamRoute.ReRoute.RouteClaimsRequirement); if (authorised.IsError) { @@ -45,7 +35,7 @@ namespace Ocelot.Authorisation.Middleware return; } - if (authorised.Data) + if (IsAuthorised(authorised)) { await _next.Invoke(context); } @@ -54,7 +44,7 @@ namespace Ocelot.Authorisation.Middleware SetPipelineError(new List { new UnauthorisedError( - $"{context.User.Identity.Name} unable to access {downstreamRoute.Data.ReRoute.UpstreamTemplate}") + $"{context.User.Identity.Name} unable to access {DownstreamRoute.ReRoute.UpstreamTemplate}") }); } } @@ -63,5 +53,10 @@ namespace Ocelot.Authorisation.Middleware await _next.Invoke(context); } } + + private static bool IsAuthorised(Response authorised) + { + return authorised.Data; + } } } diff --git a/src/Ocelot/ClaimsBuilder/AddClaimsToRequest.cs b/src/Ocelot/Claims/AddClaimsToRequest.cs similarity index 75% rename from src/Ocelot/ClaimsBuilder/AddClaimsToRequest.cs rename to src/Ocelot/Claims/AddClaimsToRequest.cs index f5be6a9f..120b0003 100644 --- a/src/Ocelot/ClaimsBuilder/AddClaimsToRequest.cs +++ b/src/Ocelot/Claims/AddClaimsToRequest.cs @@ -1,13 +1,13 @@ -namespace Ocelot.ClaimsBuilder -{ - using System.Collections.Generic; - using System.Linq; - using System.Security.Claims; - using Configuration; - using Infrastructure.Claims.Parser; - using Microsoft.AspNetCore.Http; - using Responses; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using Microsoft.AspNetCore.Http; +using Ocelot.Configuration; +using Ocelot.Infrastructure.Claims.Parser; +using Ocelot.Responses; +namespace Ocelot.Claims +{ public class AddClaimsToRequest : IAddClaimsToRequest { private readonly IClaimsParser _claimsParser; @@ -37,7 +37,7 @@ identity?.RemoveClaim(exists); } - identity?.AddClaim(new Claim(config.ExistingKey, value.Data)); + identity?.AddClaim(new System.Security.Claims.Claim(config.ExistingKey, value.Data)); } return new OkResponse(); diff --git a/src/Ocelot/ClaimsBuilder/IAddClaimsToRequest.cs b/src/Ocelot/Claims/IAddClaimsToRequest.cs similarity index 51% rename from src/Ocelot/ClaimsBuilder/IAddClaimsToRequest.cs rename to src/Ocelot/Claims/IAddClaimsToRequest.cs index 9069bfe3..02ae85e9 100644 --- a/src/Ocelot/ClaimsBuilder/IAddClaimsToRequest.cs +++ b/src/Ocelot/Claims/IAddClaimsToRequest.cs @@ -1,10 +1,10 @@ -namespace Ocelot.ClaimsBuilder -{ - using System.Collections.Generic; - using Configuration; - using Microsoft.AspNetCore.Http; - using Responses; +using System.Collections.Generic; +using Microsoft.AspNetCore.Http; +using Ocelot.Configuration; +using Ocelot.Responses; +namespace Ocelot.Claims +{ public interface IAddClaimsToRequest { Response SetClaimsOnContext(List claimsToThings, diff --git a/src/Ocelot/ClaimsBuilder/Middleware/ClaimsBuilderMiddleware.cs b/src/Ocelot/Claims/Middleware/ClaimsBuilderMiddleware.cs similarity index 58% rename from src/Ocelot/ClaimsBuilder/Middleware/ClaimsBuilderMiddleware.cs rename to src/Ocelot/Claims/Middleware/ClaimsBuilderMiddleware.cs index 2ff11c56..488fbadd 100644 --- a/src/Ocelot/ClaimsBuilder/Middleware/ClaimsBuilderMiddleware.cs +++ b/src/Ocelot/Claims/Middleware/ClaimsBuilderMiddleware.cs @@ -1,18 +1,15 @@ -using Ocelot.Infrastructure.RequestData; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Ocelot.Infrastructure.RequestData; +using Ocelot.Middleware; -namespace Ocelot.ClaimsBuilder.Middleware +namespace Ocelot.Claims.Middleware { - using System.Linq; - using System.Threading.Tasks; - using DownstreamRouteFinder; - using Microsoft.AspNetCore.Http; - using Ocelot.Middleware; - public class ClaimsBuilderMiddleware : OcelotMiddleware { private readonly RequestDelegate _next; private readonly IAddClaimsToRequest _addClaimsToRequest; - private readonly IRequestScopedDataRepository _requestScopedDataRepository; public ClaimsBuilderMiddleware(RequestDelegate next, IRequestScopedDataRepository requestScopedDataRepository, @@ -21,16 +18,13 @@ namespace Ocelot.ClaimsBuilder.Middleware { _next = next; _addClaimsToRequest = addClaimsToRequest; - _requestScopedDataRepository = requestScopedDataRepository; } public async Task Invoke(HttpContext context) { - var downstreamRoute = _requestScopedDataRepository.Get("DownstreamRoute"); - - if (downstreamRoute.Data.ReRoute.ClaimsToClaims.Any()) + if (DownstreamRoute.ReRoute.ClaimsToClaims.Any()) { - var result = _addClaimsToRequest.SetClaimsOnContext(downstreamRoute.Data.ReRoute.ClaimsToClaims, context); + var result = _addClaimsToRequest.SetClaimsOnContext(DownstreamRoute.ReRoute.ClaimsToClaims, context); if (result.IsError) { diff --git a/src/Ocelot/ClaimsBuilder/Middleware/ClaimsBuilderMiddlewareExtensions.cs b/src/Ocelot/Claims/Middleware/ClaimsBuilderMiddlewareExtensions.cs similarity index 75% rename from src/Ocelot/ClaimsBuilder/Middleware/ClaimsBuilderMiddlewareExtensions.cs rename to src/Ocelot/Claims/Middleware/ClaimsBuilderMiddlewareExtensions.cs index 4da29e83..fd3bef39 100644 --- a/src/Ocelot/ClaimsBuilder/Middleware/ClaimsBuilderMiddlewareExtensions.cs +++ b/src/Ocelot/Claims/Middleware/ClaimsBuilderMiddlewareExtensions.cs @@ -1,7 +1,7 @@ -namespace Ocelot.ClaimsBuilder.Middleware -{ - using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Builder; +namespace Ocelot.Claims.Middleware +{ public static class ClaimsBuilderMiddlewareExtensions { public static IApplicationBuilder UseClaimsBuilderMiddleware(this IApplicationBuilder builder) diff --git a/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs b/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs index db3aa617..cf780650 100644 --- a/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs +++ b/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs @@ -19,6 +19,7 @@ namespace Ocelot.Configuration.Builder private List _claimToClaims; private Dictionary _routeClaimRequirement; private bool _isAuthorised; + private List _claimToQueries; public ReRouteBuilder() { @@ -113,9 +114,15 @@ namespace Ocelot.Configuration.Builder return this; } + public ReRouteBuilder WithClaimsToQueries(List input) + { + _claimToQueries = input; + return this; + } + public ReRoute Build() { - return new ReRoute(_downstreamTemplate, _upstreamTemplate, _upstreamHttpMethod, _upstreamTemplatePattern, _isAuthenticated, new AuthenticationOptions(_authenticationProvider, _authenticationProviderUrl, _scopeName, _requireHttps, _additionalScopes, _scopeSecret), _configHeaderExtractorProperties, _claimToClaims, _routeClaimRequirement, _isAuthorised); + return new ReRoute(_downstreamTemplate, _upstreamTemplate, _upstreamHttpMethod, _upstreamTemplatePattern, _isAuthenticated, new AuthenticationOptions(_authenticationProvider, _authenticationProviderUrl, _scopeName, _requireHttps, _additionalScopes, _scopeSecret), _configHeaderExtractorProperties, _claimToClaims, _routeClaimRequirement, _isAuthorised, _claimToQueries); } } } diff --git a/src/Ocelot/Configuration/Creator/YamlOcelotConfigurationCreator.cs b/src/Ocelot/Configuration/Creator/YamlOcelotConfigurationCreator.cs index e0efd611..c9755d27 100644 --- a/src/Ocelot/Configuration/Creator/YamlOcelotConfigurationCreator.cs +++ b/src/Ocelot/Configuration/Creator/YamlOcelotConfigurationCreator.cs @@ -100,15 +100,16 @@ namespace Ocelot.Configuration.Creator var claimsToHeaders = GetAddThingsToRequest(reRoute.AddHeadersToRequest); var claimsToClaims = GetAddThingsToRequest(reRoute.AddClaimsToRequest); + var claimsToQueries = GetAddThingsToRequest(reRoute.AddQueriesToRequest); return new ReRoute(reRoute.DownstreamTemplate, reRoute.UpstreamTemplate, reRoute.UpstreamHttpMethod, upstreamTemplate, isAuthenticated, - authOptionsForRoute, claimsToHeaders, claimsToClaims, reRoute.RouteClaimsRequirement, isAuthorised + authOptionsForRoute, claimsToHeaders, claimsToClaims, reRoute.RouteClaimsRequirement, isAuthorised, claimsToQueries ); } return new ReRoute(reRoute.DownstreamTemplate, reRoute.UpstreamTemplate, reRoute.UpstreamHttpMethod, - upstreamTemplate, isAuthenticated, null, new List(), new List(), reRoute.RouteClaimsRequirement, isAuthorised); + upstreamTemplate, isAuthenticated, null, new List(), new List(), reRoute.RouteClaimsRequirement, isAuthorised, new List()); } private List GetAddThingsToRequest(Dictionary thingBeingAdded) diff --git a/src/Ocelot/Configuration/ReRoute.cs b/src/Ocelot/Configuration/ReRoute.cs index 0a8b7ce5..7d0a1600 100644 --- a/src/Ocelot/Configuration/ReRoute.cs +++ b/src/Ocelot/Configuration/ReRoute.cs @@ -4,7 +4,7 @@ namespace Ocelot.Configuration { public class ReRoute { - public ReRoute(string downstreamTemplate, string upstreamTemplate, string upstreamHttpMethod, string upstreamTemplatePattern, bool isAuthenticated, AuthenticationOptions authenticationOptions, List configurationHeaderExtractorProperties, List claimsToClaims, Dictionary routeClaimsRequirement, bool isAuthorised) + public ReRoute(string downstreamTemplate, string upstreamTemplate, string upstreamHttpMethod, string upstreamTemplatePattern, bool isAuthenticated, AuthenticationOptions authenticationOptions, List configurationHeaderExtractorProperties, List claimsToClaims, Dictionary routeClaimsRequirement, bool isAuthorised, List claimsToQueries) { DownstreamTemplate = downstreamTemplate; UpstreamTemplate = upstreamTemplate; @@ -14,6 +14,8 @@ namespace Ocelot.Configuration AuthenticationOptions = authenticationOptions; RouteClaimsRequirement = routeClaimsRequirement; IsAuthorised = isAuthorised; + ClaimsToQueries = claimsToQueries + ?? new List(); ClaimsToClaims = claimsToClaims ?? new List(); ClaimsToHeaders = configurationHeaderExtractorProperties @@ -27,6 +29,7 @@ namespace Ocelot.Configuration public bool IsAuthenticated { get; private set; } public bool IsAuthorised { get; private set; } public AuthenticationOptions AuthenticationOptions { get; private set; } + public List ClaimsToQueries { get; private set; } public List ClaimsToHeaders { get; private set; } public List ClaimsToClaims { get; private set; } public Dictionary RouteClaimsRequirement { get; private set; } diff --git a/src/Ocelot/Configuration/Yaml/YamlReRoute.cs b/src/Ocelot/Configuration/Yaml/YamlReRoute.cs index f3297c4c..8e5bbd70 100644 --- a/src/Ocelot/Configuration/Yaml/YamlReRoute.cs +++ b/src/Ocelot/Configuration/Yaml/YamlReRoute.cs @@ -9,6 +9,7 @@ namespace Ocelot.Configuration.Yaml AddHeadersToRequest = new Dictionary(); AddClaimsToRequest = new Dictionary(); RouteClaimsRequirement = new Dictionary(); + AddQueriesToRequest = new Dictionary(); } public string DownstreamTemplate { get; set; } @@ -18,5 +19,6 @@ namespace Ocelot.Configuration.Yaml public Dictionary AddHeadersToRequest { get; set; } public Dictionary AddClaimsToRequest { get; set; } public Dictionary RouteClaimsRequirement { get; set; } + public Dictionary AddQueriesToRequest { get; set; } } } \ No newline at end of file diff --git a/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs b/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs index 1aac38cc..4805df55 100644 --- a/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection; using Ocelot.Authentication.Handler.Creator; using Ocelot.Authentication.Handler.Factory; using Ocelot.Authorisation; +using Ocelot.Claims; using Ocelot.Configuration.Creator; using Ocelot.Configuration.Parser; using Ocelot.Configuration.Provider; @@ -14,15 +15,15 @@ using Ocelot.Configuration.Yaml; using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; -using Ocelot.HeaderBuilder; +using Ocelot.Headers; using Ocelot.Infrastructure.RequestData; -using Ocelot.RequestBuilder.Builder; +using Ocelot.QueryStrings; +using Ocelot.Request.Builder; using Ocelot.Requester; using Ocelot.Responder; namespace Ocelot.DependencyInjection { - using ClaimsBuilder; using Infrastructure.Claims.Parser; public static class ServiceCollectionExtensions @@ -52,6 +53,7 @@ namespace Ocelot.DependencyInjection services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs index 4622eec1..04f3ff2e 100644 --- a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs +++ b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs @@ -34,7 +34,7 @@ namespace Ocelot.DownstreamRouteFinder.Middleware return; } - _requestScopedDataRepository.Add("DownstreamRoute", downstreamRoute.Data); + SetDownstreamRouteForThisRequest(downstreamRoute.Data); await _next.Invoke(context); } diff --git a/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs b/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs index 8dd56598..264993c3 100644 --- a/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs +++ b/src/Ocelot/DownstreamUrlCreator/Middleware/DownstreamUrlCreatorMiddleware.cs @@ -11,7 +11,6 @@ namespace Ocelot.DownstreamUrlCreator.Middleware { private readonly RequestDelegate _next; private readonly IDownstreamUrlPathPlaceholderReplacer _urlReplacer; - private readonly IRequestScopedDataRepository _requestScopedDataRepository; public DownstreamUrlCreatorMiddleware(RequestDelegate next, IDownstreamUrlPathPlaceholderReplacer urlReplacer, @@ -20,20 +19,11 @@ namespace Ocelot.DownstreamUrlCreator.Middleware { _next = next; _urlReplacer = urlReplacer; - _requestScopedDataRepository = requestScopedDataRepository; } public async Task Invoke(HttpContext context) { - var downstreamRoute = _requestScopedDataRepository.Get("DownstreamRoute"); - - if (downstreamRoute.IsError) - { - SetPipelineError(downstreamRoute.Errors); - return; - } - - var downstreamUrl = _urlReplacer.Replace(downstreamRoute.Data.ReRoute.DownstreamTemplate, downstreamRoute.Data.TemplatePlaceholderNameAndValues); + var downstreamUrl = _urlReplacer.Replace(DownstreamRoute.ReRoute.DownstreamTemplate, DownstreamRoute.TemplatePlaceholderNameAndValues); if (downstreamUrl.IsError) { @@ -41,8 +31,8 @@ namespace Ocelot.DownstreamUrlCreator.Middleware return; } - _requestScopedDataRepository.Add("DownstreamUrl", downstreamUrl.Data.Value); - + SetDownstreamUrlForThisRequest(downstreamUrl.Data.Value); + await _next.Invoke(context); } } diff --git a/src/Ocelot/HeaderBuilder/AddHeadersToRequest.cs b/src/Ocelot/Headers/AddHeadersToRequest.cs similarity index 94% rename from src/Ocelot/HeaderBuilder/AddHeadersToRequest.cs rename to src/Ocelot/Headers/AddHeadersToRequest.cs index 57ff4103..97cd3e69 100644 --- a/src/Ocelot/HeaderBuilder/AddHeadersToRequest.cs +++ b/src/Ocelot/Headers/AddHeadersToRequest.cs @@ -3,12 +3,11 @@ using System.Linq; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; using Ocelot.Configuration; +using Ocelot.Infrastructure.Claims.Parser; using Ocelot.Responses; -namespace Ocelot.HeaderBuilder +namespace Ocelot.Headers { - using Infrastructure.Claims.Parser; - public class AddHeadersToRequest : IAddHeadersToRequest { private readonly IClaimsParser _claimsParser; diff --git a/src/Ocelot/HeaderBuilder/IAddHeadersToRequest.cs b/src/Ocelot/Headers/IAddHeadersToRequest.cs similarity index 90% rename from src/Ocelot/HeaderBuilder/IAddHeadersToRequest.cs rename to src/Ocelot/Headers/IAddHeadersToRequest.cs index f12709ca..3bf786a4 100644 --- a/src/Ocelot/HeaderBuilder/IAddHeadersToRequest.cs +++ b/src/Ocelot/Headers/IAddHeadersToRequest.cs @@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Http; using Ocelot.Configuration; using Ocelot.Responses; -namespace Ocelot.HeaderBuilder +namespace Ocelot.Headers { public interface IAddHeadersToRequest { diff --git a/src/Ocelot/HeaderBuilder/Middleware/HttpRequestHeadersBuilderMiddleware.cs b/src/Ocelot/Headers/Middleware/HttpRequestHeadersBuilderMiddleware.cs similarity index 62% rename from src/Ocelot/HeaderBuilder/Middleware/HttpRequestHeadersBuilderMiddleware.cs rename to src/Ocelot/Headers/Middleware/HttpRequestHeadersBuilderMiddleware.cs index 08a0f599..9bf9618a 100644 --- a/src/Ocelot/HeaderBuilder/Middleware/HttpRequestHeadersBuilderMiddleware.cs +++ b/src/Ocelot/Headers/Middleware/HttpRequestHeadersBuilderMiddleware.cs @@ -1,17 +1,15 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; -using Ocelot.DownstreamRouteFinder; using Ocelot.Infrastructure.RequestData; using Ocelot.Middleware; -namespace Ocelot.HeaderBuilder.Middleware +namespace Ocelot.Headers.Middleware { public class HttpRequestHeadersBuilderMiddleware : OcelotMiddleware { private readonly RequestDelegate _next; private readonly IAddHeadersToRequest _addHeadersToRequest; - private readonly IRequestScopedDataRepository _requestScopedDataRepository; public HttpRequestHeadersBuilderMiddleware(RequestDelegate next, IRequestScopedDataRepository requestScopedDataRepository, @@ -20,16 +18,13 @@ namespace Ocelot.HeaderBuilder.Middleware { _next = next; _addHeadersToRequest = addHeadersToRequest; - _requestScopedDataRepository = requestScopedDataRepository; } public async Task Invoke(HttpContext context) { - var downstreamRoute = _requestScopedDataRepository.Get("DownstreamRoute"); - - if (downstreamRoute.Data.ReRoute.ClaimsToHeaders.Any()) + if (DownstreamRoute.ReRoute.ClaimsToHeaders.Any()) { - _addHeadersToRequest.SetHeadersOnContext(downstreamRoute.Data.ReRoute.ClaimsToHeaders, context); + _addHeadersToRequest.SetHeadersOnContext(DownstreamRoute.ReRoute.ClaimsToHeaders, context); } await _next.Invoke(context); diff --git a/src/Ocelot/HeaderBuilder/Middleware/HttpRequestHeadersBuilderMiddlewareExtensions.cs b/src/Ocelot/Headers/Middleware/HttpRequestHeadersBuilderMiddlewareExtensions.cs similarity index 89% rename from src/Ocelot/HeaderBuilder/Middleware/HttpRequestHeadersBuilderMiddlewareExtensions.cs rename to src/Ocelot/Headers/Middleware/HttpRequestHeadersBuilderMiddlewareExtensions.cs index 9b58408a..ce010b14 100644 --- a/src/Ocelot/HeaderBuilder/Middleware/HttpRequestHeadersBuilderMiddlewareExtensions.cs +++ b/src/Ocelot/Headers/Middleware/HttpRequestHeadersBuilderMiddlewareExtensions.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Builder; -namespace Ocelot.HeaderBuilder.Middleware +namespace Ocelot.Headers.Middleware { public static class HttpRequestHeadersBuilderMiddlewareExtensions { diff --git a/src/Ocelot/Middleware/OcelotMiddleware.cs b/src/Ocelot/Middleware/OcelotMiddleware.cs index 714cebda..6cabce87 100644 --- a/src/Ocelot/Middleware/OcelotMiddleware.cs +++ b/src/Ocelot/Middleware/OcelotMiddleware.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Ocelot.DownstreamRouteFinder; using Ocelot.Errors; using Ocelot.Infrastructure.RequestData; @@ -30,5 +31,47 @@ namespace Ocelot.Middleware var response = _requestScopedDataRepository.Get>("OcelotMiddlewareErrors"); return response.Data; } + + public DownstreamRoute DownstreamRoute + { + get + { + var downstreamRoute = _requestScopedDataRepository.Get("DownstreamRoute"); + return downstreamRoute.Data; + } + } + + public string DownstreamUrl + { + get + { + var downstreamUrl = _requestScopedDataRepository.Get("DownstreamUrl"); + return downstreamUrl.Data; + } + } + + public Request.Request Request + { + get + { + var request = _requestScopedDataRepository.Get("Request"); + return request.Data; + } + } + + public void SetDownstreamRouteForThisRequest(DownstreamRoute downstreamRoute) + { + _requestScopedDataRepository.Add("DownstreamRoute", downstreamRoute); + } + + public void SetDownstreamUrlForThisRequest(string downstreamUrl) + { + _requestScopedDataRepository.Add("DownstreamUrl", downstreamUrl); + } + + public void SetUpstreamRequestForThisRequest(Request.Request request) + { + _requestScopedDataRepository.Add("Request", request); + } } } diff --git a/src/Ocelot/Middleware/OcelotMiddlewareConfiguration.cs b/src/Ocelot/Middleware/OcelotMiddlewareConfiguration.cs index 798c4577..ca9ad965 100644 --- a/src/Ocelot/Middleware/OcelotMiddlewareConfiguration.cs +++ b/src/Ocelot/Middleware/OcelotMiddlewareConfiguration.cs @@ -5,23 +5,10 @@ using Microsoft.AspNetCore.Http; public class OcelotMiddlewareConfiguration - { - public Func, Task> PreHttpResponderMiddleware { get; set; } - public Func, Task> PostHttpResponderMiddleware { get; set; } - public Func, Task> PreDownstreamRouteFinderMiddleware { get; set; } - public Func, Task> PostDownstreamRouteFinderMiddleware { get; set; } + { public Func, Task> PreAuthenticationMiddleware { get; set; } - public Func, Task> PostAuthenticationMiddleware { get; set; } - public Func, Task> PreClaimsBuilderMiddleware { get; set; } - public Func, Task> PostClaimsBuilderMiddleware { get; set; } + public Func, Task> AuthenticationMiddleware { get; set; } public Func, Task> PreAuthorisationMiddleware { get; set; } - public Func, Task> PostAuthorisationMiddleware { get; set; } - public Func, Task> PreHttpRequestHeadersBuilderMiddleware { get; set; } - public Func, Task> PostHttpRequestHeadersBuilderMiddleware { get; set; } - public Func, Task> PreDownstreamUrlCreatorMiddleware { get; set; } - public Func, Task> PostDownstreamUrlCreatorMiddleware { get; set; } - public Func, Task> PreHttpRequestBuilderMiddleware { get; set; } - public Func, Task> PostHttpRequestBuilderMiddleware { get; set; } - public Func, Task> PreHttpRequesterMiddleware { get; set; } + public Func, Task> AuthorisationMiddleware { get; set; } } } \ No newline at end of file diff --git a/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs b/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs index ba5e6782..2ef92ab2 100644 --- a/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs +++ b/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs @@ -1,9 +1,11 @@ using Microsoft.AspNetCore.Builder; using Ocelot.Authentication.Middleware; +using Ocelot.Claims.Middleware; using Ocelot.DownstreamRouteFinder.Middleware; using Ocelot.DownstreamUrlCreator.Middleware; -using Ocelot.HeaderBuilder.Middleware; -using Ocelot.RequestBuilder.Middleware; +using Ocelot.Headers.Middleware; +using Ocelot.QueryStrings.Middleware; +using Ocelot.Request.Middleware; using Ocelot.Requester.Middleware; using Ocelot.Responder.Middleware; @@ -12,12 +14,17 @@ namespace Ocelot.Middleware using System; using System.Threading.Tasks; using Authorisation.Middleware; - using ClaimsBuilder.Middleware; using Microsoft.AspNetCore.Http; public static class OcelotMiddlewareExtensions { public static IApplicationBuilder UseOcelot(this IApplicationBuilder builder) + { + builder.UseOcelot(new OcelotMiddlewareConfiguration()); + return builder; + } + + public static IApplicationBuilder UseOcelot(this IApplicationBuilder builder, OcelotMiddlewareConfiguration middlewareConfiguration) { // This is registered to catch any global exceptions that are not handled builder.UseExceptionHandlerMiddleware(); @@ -28,18 +35,46 @@ namespace Ocelot.Middleware // Then we get the downstream route information builder.UseDownstreamRouteFinderMiddleware(); - // Now we know where the client is going to go we can authenticate them - builder.UseAuthenticationMiddleware(); + // Allow pre authentication logic. The idea being people might want to run something custom before what is built in. + builder.UseIfNotNull(middlewareConfiguration.PreAuthenticationMiddleware); + + // Now we know where the client is going to go we can authenticate them. + // We allow the ocelot middleware to be overriden by whatever the + // user wants + if (middlewareConfiguration.AuthenticationMiddleware == null) + { + builder.UseAuthenticationMiddleware(); + } + else + { + builder.Use(middlewareConfiguration.AuthenticationMiddleware); + } // The next thing we do is look at any claims transforms in case this is important for authorisation builder.UseClaimsBuilderMiddleware(); - // Now we have authenticated and done any claims transformation we can authorise the request - builder.UseAuthorisationMiddleware(); + // Allow pre authorisation logic. The idea being people might want to run something custom before what is built in. + builder.UseIfNotNull(middlewareConfiguration.PreAuthorisationMiddleware); + + // Now we have authenticated and done any claims transformation we + // can authorise the request + // We allow the ocelot middleware to be overriden by whatever the + // user wants + if (middlewareConfiguration.AuthorisationMiddleware == null) + { + builder.UseAuthorisationMiddleware(); + } + else + { + builder.Use(middlewareConfiguration.AuthorisationMiddleware); + } // Now we can run any header transformation logic builder.UseHttpRequestHeadersBuilderMiddleware(); + // Now we can run any query string transformation logic + builder.UseQueryStringBuilderMiddleware(); + // This takes the downstream route we retrieved earlier and replaces any placeholders with the variables that should be used builder.UseDownstreamUrlCreatorMiddleware(); @@ -52,63 +87,6 @@ namespace Ocelot.Middleware return builder; } - public static IApplicationBuilder UseOcelot(this IApplicationBuilder builder, OcelotMiddlewareConfiguration middlewareConfiguration) - { - builder.UseIfNotNull(middlewareConfiguration.PreHttpResponderMiddleware); - - builder.UseHttpErrorResponderMiddleware(); - - builder.UseIfNotNull(middlewareConfiguration.PostHttpResponderMiddleware); - - builder.UseIfNotNull(middlewareConfiguration.PreDownstreamRouteFinderMiddleware); - - builder.UseDownstreamRouteFinderMiddleware(); - - builder.UseIfNotNull(middlewareConfiguration.PostDownstreamRouteFinderMiddleware); - - builder.UseIfNotNull(middlewareConfiguration.PreAuthenticationMiddleware); - - builder.UseAuthenticationMiddleware(); - - builder.UseIfNotNull(middlewareConfiguration.PostAuthenticationMiddleware); - - builder.UseIfNotNull(middlewareConfiguration.PreClaimsBuilderMiddleware); - - builder.UseClaimsBuilderMiddleware(); - - builder.UseIfNotNull(middlewareConfiguration.PostClaimsBuilderMiddleware); - - builder.UseIfNotNull(middlewareConfiguration.PreAuthorisationMiddleware); - - builder.UseAuthorisationMiddleware(); - - builder.UseIfNotNull(middlewareConfiguration.PostAuthorisationMiddleware); - - builder.UseIfNotNull(middlewareConfiguration.PreHttpRequestHeadersBuilderMiddleware); - - builder.UseHttpRequestHeadersBuilderMiddleware(); - - builder.UseIfNotNull(middlewareConfiguration.PostHttpRequestHeadersBuilderMiddleware); - - builder.UseIfNotNull(middlewareConfiguration.PreDownstreamUrlCreatorMiddleware); - - builder.UseDownstreamUrlCreatorMiddleware(); - - builder.UseIfNotNull(middlewareConfiguration.PostDownstreamUrlCreatorMiddleware); - - builder.UseIfNotNull(middlewareConfiguration.PreHttpRequestBuilderMiddleware); - - builder.UseHttpRequestBuilderMiddleware(); - - builder.UseIfNotNull(middlewareConfiguration.PostHttpRequestBuilderMiddleware); - - builder.UseIfNotNull(middlewareConfiguration.PreHttpRequesterMiddleware); - - builder.UseHttpRequesterMiddleware(); - - return builder; - } - private static void UseIfNotNull(this IApplicationBuilder builder, Func, Task> middleware) { if (middleware != null) diff --git a/src/Ocelot/QueryStrings/AddQueriesToRequest.cs b/src/Ocelot/QueryStrings/AddQueriesToRequest.cs new file mode 100644 index 00000000..02fcb63d --- /dev/null +++ b/src/Ocelot/QueryStrings/AddQueriesToRequest.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Http; +using Ocelot.Configuration; +using Ocelot.Infrastructure.Claims.Parser; +using Ocelot.Responses; + +namespace Ocelot.QueryStrings +{ + public class AddQueriesToRequest : IAddQueriesToRequest + { + private readonly IClaimsParser _claimsParser; + + public AddQueriesToRequest(IClaimsParser claimsParser) + { + _claimsParser = claimsParser; + } + + public Response SetQueriesOnContext(List claimsToThings, HttpContext context) + { + var queryDictionary = ConvertQueryStringToDictionary(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 = 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(); + } + + private Dictionary ConvertQueryStringToDictionary(HttpContext context) + { + return Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(context.Request.QueryString.Value) + .ToDictionary(q => q.Key, q => q.Value.FirstOrDefault() ?? string.Empty); + } + + private Microsoft.AspNetCore.Http.QueryString ConvertDictionaryToQueryString(Dictionary queryDictionary) + { + var newQueryString = Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString("", queryDictionary); + + return new Microsoft.AspNetCore.Http.QueryString(newQueryString); + } + } +} \ No newline at end of file diff --git a/src/Ocelot/QueryStrings/IAddQueriesToRequest.cs b/src/Ocelot/QueryStrings/IAddQueriesToRequest.cs new file mode 100644 index 00000000..6fa1b8da --- /dev/null +++ b/src/Ocelot/QueryStrings/IAddQueriesToRequest.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using Microsoft.AspNetCore.Http; +using Ocelot.Configuration; +using Ocelot.Responses; + +namespace Ocelot.QueryStrings +{ + public interface IAddQueriesToRequest + { + Response SetQueriesOnContext(List claimsToThings, + HttpContext context); + } +} diff --git a/src/Ocelot/QueryStrings/Middleware/QueryStringBuilderMiddleware.cs b/src/Ocelot/QueryStrings/Middleware/QueryStringBuilderMiddleware.cs new file mode 100644 index 00000000..da308eb3 --- /dev/null +++ b/src/Ocelot/QueryStrings/Middleware/QueryStringBuilderMiddleware.cs @@ -0,0 +1,33 @@ +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Ocelot.Infrastructure.RequestData; +using Ocelot.Middleware; + +namespace Ocelot.QueryStrings.Middleware +{ + public class QueryStringBuilderMiddleware : OcelotMiddleware + { + private readonly RequestDelegate _next; + private readonly IAddQueriesToRequest _addQueriesToRequest; + + public QueryStringBuilderMiddleware(RequestDelegate next, + IRequestScopedDataRepository requestScopedDataRepository, + IAddQueriesToRequest addQueriesToRequest) + : base(requestScopedDataRepository) + { + _next = next; + _addQueriesToRequest = addQueriesToRequest; + } + + public async Task Invoke(HttpContext context) + { + if (DownstreamRoute.ReRoute.ClaimsToQueries.Any()) + { + _addQueriesToRequest.SetQueriesOnContext(DownstreamRoute.ReRoute.ClaimsToQueries, context); + } + + await _next.Invoke(context); + } + } +} diff --git a/src/Ocelot/QueryStrings/Middleware/QueryStringBuilderMiddlewareExtensions.cs b/src/Ocelot/QueryStrings/Middleware/QueryStringBuilderMiddlewareExtensions.cs new file mode 100644 index 00000000..8ff39be2 --- /dev/null +++ b/src/Ocelot/QueryStrings/Middleware/QueryStringBuilderMiddlewareExtensions.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Builder; + +namespace Ocelot.QueryStrings.Middleware +{ + public static class QueryStringBuilderMiddlewareExtensions + { + public static IApplicationBuilder UseQueryStringBuilderMiddleware(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } + } +} \ No newline at end of file diff --git a/src/Ocelot/RequestBuilder/Builder/HttpRequestBuilder.cs b/src/Ocelot/Request/Builder/HttpRequestBuilder.cs similarity index 93% rename from src/Ocelot/RequestBuilder/Builder/HttpRequestBuilder.cs rename to src/Ocelot/Request/Builder/HttpRequestBuilder.cs index 401f6792..a1b437f1 100644 --- a/src/Ocelot/RequestBuilder/Builder/HttpRequestBuilder.cs +++ b/src/Ocelot/Request/Builder/HttpRequestBuilder.cs @@ -2,23 +2,21 @@ using System.IO; using System.Net; using System.Net.Http; -using System.Net.Http.Headers; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Ocelot.Responses; -namespace Ocelot.RequestBuilder.Builder +namespace Ocelot.Request.Builder { public class HttpRequestBuilder : IRequestBuilder { public async Task> Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers, - IRequestCookieCollection cookies, QueryString queryString, string contentType) + IRequestCookieCollection cookies, Microsoft.AspNetCore.Http.QueryString queryString, string contentType) { var method = new HttpMethod(httpMethod); var uri = new Uri(string.Format("{0}{1}", downstreamUrl, queryString.ToUriComponent())); - var httpRequestMessage = new HttpRequestMessage(method, uri); if (content != null) diff --git a/src/Ocelot/RequestBuilder/Builder/IRequestBuilder.cs b/src/Ocelot/Request/Builder/IRequestBuilder.cs similarity index 80% rename from src/Ocelot/RequestBuilder/Builder/IRequestBuilder.cs rename to src/Ocelot/Request/Builder/IRequestBuilder.cs index 67f88b04..efb8f31a 100644 --- a/src/Ocelot/RequestBuilder/Builder/IRequestBuilder.cs +++ b/src/Ocelot/Request/Builder/IRequestBuilder.cs @@ -3,7 +3,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Ocelot.Responses; -namespace Ocelot.RequestBuilder.Builder +namespace Ocelot.Request.Builder { public interface IRequestBuilder { @@ -12,7 +12,7 @@ namespace Ocelot.RequestBuilder.Builder Stream content, IHeaderDictionary headers, IRequestCookieCollection cookies, - QueryString queryString, + Microsoft.AspNetCore.Http.QueryString queryString, string contentType); } } diff --git a/src/Ocelot/RequestBuilder/Middleware/HttpRequestBuilderMiddleware.cs b/src/Ocelot/Request/Middleware/HttpRequestBuilderMiddleware.cs similarity index 62% rename from src/Ocelot/RequestBuilder/Middleware/HttpRequestBuilderMiddleware.cs rename to src/Ocelot/Request/Middleware/HttpRequestBuilderMiddleware.cs index 876fe9c2..d4e75bf3 100644 --- a/src/Ocelot/RequestBuilder/Middleware/HttpRequestBuilderMiddleware.cs +++ b/src/Ocelot/Request/Middleware/HttpRequestBuilderMiddleware.cs @@ -2,14 +2,13 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Ocelot.Infrastructure.RequestData; using Ocelot.Middleware; -using Ocelot.RequestBuilder.Builder; +using Ocelot.Request.Builder; -namespace Ocelot.RequestBuilder.Middleware +namespace Ocelot.Request.Middleware { public class HttpRequestBuilderMiddleware : OcelotMiddleware { private readonly RequestDelegate _next; - private readonly IRequestScopedDataRepository _requestScopedDataRepository; private readonly IRequestBuilder _requestBuilder; public HttpRequestBuilderMiddleware(RequestDelegate next, @@ -18,22 +17,13 @@ namespace Ocelot.RequestBuilder.Middleware :base(requestScopedDataRepository) { _next = next; - _requestScopedDataRepository = requestScopedDataRepository; _requestBuilder = requestBuilder; } public async Task Invoke(HttpContext context) { - var downstreamUrl = _requestScopedDataRepository.Get("DownstreamUrl"); - - if (downstreamUrl.IsError) - { - SetPipelineError(downstreamUrl.Errors); - return; - } - var request = await _requestBuilder - .Build(context.Request.Method, downstreamUrl.Data, context.Request.Body, + .Build(context.Request.Method, DownstreamUrl, context.Request.Body, context.Request.Headers, context.Request.Cookies, context.Request.QueryString, context.Request.ContentType); if (request.IsError) @@ -42,7 +32,7 @@ namespace Ocelot.RequestBuilder.Middleware return; } - _requestScopedDataRepository.Add("Request", request.Data); + SetUpstreamRequestForThisRequest(request.Data); await _next.Invoke(context); } diff --git a/src/Ocelot/RequestBuilder/Middleware/HttpRequestBuilderMiddlewareExtensions.cs b/src/Ocelot/Request/Middleware/HttpRequestBuilderMiddlewareExtensions.cs similarity index 88% rename from src/Ocelot/RequestBuilder/Middleware/HttpRequestBuilderMiddlewareExtensions.cs rename to src/Ocelot/Request/Middleware/HttpRequestBuilderMiddlewareExtensions.cs index 3a4c6b26..4c08afec 100644 --- a/src/Ocelot/RequestBuilder/Middleware/HttpRequestBuilderMiddlewareExtensions.cs +++ b/src/Ocelot/Request/Middleware/HttpRequestBuilderMiddlewareExtensions.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Builder; -namespace Ocelot.RequestBuilder.Middleware +namespace Ocelot.Request.Middleware { public static class HttpRequestBuilderMiddlewareExtensions { diff --git a/src/Ocelot/RequestBuilder/Request.cs b/src/Ocelot/Request/Request.cs similarity index 93% rename from src/Ocelot/RequestBuilder/Request.cs rename to src/Ocelot/Request/Request.cs index 99149497..d43071e1 100644 --- a/src/Ocelot/RequestBuilder/Request.cs +++ b/src/Ocelot/Request/Request.cs @@ -1,7 +1,7 @@ using System.Net; using System.Net.Http; -namespace Ocelot.RequestBuilder +namespace Ocelot.Request { public class Request { diff --git a/src/Ocelot/Requester/HttpClientHttpRequester.cs b/src/Ocelot/Requester/HttpClientHttpRequester.cs index 19b3b6fd..0167ef6a 100644 --- a/src/Ocelot/Requester/HttpClientHttpRequester.cs +++ b/src/Ocelot/Requester/HttpClientHttpRequester.cs @@ -3,14 +3,13 @@ using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; using Ocelot.Errors; -using Ocelot.RequestBuilder; using Ocelot.Responses; namespace Ocelot.Requester { public class HttpClientHttpRequester : IHttpRequester { - public async Task> GetResponse(Request request) + public async Task> GetResponse(Request.Request request) { using (var handler = new HttpClientHandler { CookieContainer = request.CookieContainer }) using (var httpClient = new HttpClient(handler)) diff --git a/src/Ocelot/Requester/IHttpRequester.cs b/src/Ocelot/Requester/IHttpRequester.cs index 6072b0e5..201c3add 100644 --- a/src/Ocelot/Requester/IHttpRequester.cs +++ b/src/Ocelot/Requester/IHttpRequester.cs @@ -1,12 +1,11 @@ using System.Net.Http; using System.Threading.Tasks; -using Ocelot.RequestBuilder; using Ocelot.Responses; namespace Ocelot.Requester { public interface IHttpRequester { - Task> GetResponse(Request request); + Task> GetResponse(Request.Request request); } } diff --git a/src/Ocelot/Requester/Middleware/HttpRequesterMiddleware.cs b/src/Ocelot/Requester/Middleware/HttpRequesterMiddleware.cs index 0bec7ff4..10422819 100644 --- a/src/Ocelot/Requester/Middleware/HttpRequesterMiddleware.cs +++ b/src/Ocelot/Requester/Middleware/HttpRequesterMiddleware.cs @@ -2,7 +2,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Ocelot.Infrastructure.RequestData; using Ocelot.Middleware; -using Ocelot.RequestBuilder; using Ocelot.Responder; namespace Ocelot.Requester.Middleware @@ -11,7 +10,6 @@ namespace Ocelot.Requester.Middleware { private readonly RequestDelegate _next; private readonly IHttpRequester _requester; - private readonly IRequestScopedDataRepository _requestScopedDataRepository; private readonly IHttpResponder _responder; public HttpRequesterMiddleware(RequestDelegate next, @@ -22,21 +20,13 @@ namespace Ocelot.Requester.Middleware { _next = next; _requester = requester; - _requestScopedDataRepository = requestScopedDataRepository; _responder = responder; } public async Task Invoke(HttpContext context) { - var request = _requestScopedDataRepository.Get("Request"); - if (request.IsError) - { - SetPipelineError(request.Errors); - return; - } - - var response = await _requester.GetResponse(request.Data); + var response = await _requester.GetResponse(Request); if (response.IsError) { diff --git a/src/Ocelot/Responder/Middleware/HttpErrorResponderMiddleware.cs b/src/Ocelot/Responder/Middleware/HttpErrorResponderMiddleware.cs index aaa67d6b..79967714 100644 --- a/src/Ocelot/Responder/Middleware/HttpErrorResponderMiddleware.cs +++ b/src/Ocelot/Responder/Middleware/HttpErrorResponderMiddleware.cs @@ -10,7 +10,6 @@ namespace Ocelot.Responder.Middleware { private readonly RequestDelegate _next; private readonly IHttpResponder _responder; - private readonly IRequestScopedDataRepository _requestScopedDataRepository; private readonly IErrorsToHttpStatusCodeMapper _codeMapper; public HttpErrorResponderMiddleware(RequestDelegate next, @@ -21,7 +20,6 @@ namespace Ocelot.Responder.Middleware { _next = next; _responder = responder; - _requestScopedDataRepository = requestScopedDataRepository; _codeMapper = codeMapper; } diff --git a/test/Ocelot.AcceptanceTests/ClaimsToQueryStringForwardingTests.cs b/test/Ocelot.AcceptanceTests/ClaimsToQueryStringForwardingTests.cs new file mode 100644 index 00000000..a98031ec --- /dev/null +++ b/test/Ocelot.AcceptanceTests/ClaimsToQueryStringForwardingTests.cs @@ -0,0 +1,194 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Security.Claims; +using IdentityServer4.Models; +using IdentityServer4.Services.InMemory; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Primitives; +using Ocelot.Configuration.Yaml; +using TestStack.BDDfy; +using Xunit; + +namespace Ocelot.AcceptanceTests +{ + public class ClaimsToQueryStringForwardingTests : IDisposable + { + private IWebHost _servicebuilder; + private IWebHost _identityServerBuilder; + private readonly Steps _steps; + + public ClaimsToQueryStringForwardingTests() + { + _steps = new Steps(); + } + + [Fact] + public void should_return_response_200_and_foward_claim_as_query_string() + { + var user = new InMemoryUser + { + Username = "test", + Password = "test", + Enabled = true, + Subject = "registered|1231231", + Claims = new List + { + new Claim("CustomerId", "123"), + new Claim("LocationId", "1") + } + }; + + var yamlConfiguration = new YamlConfiguration + { + ReRoutes = new List + { + new YamlReRoute + { + DownstreamTemplate = "http://localhost:57876/", + UpstreamTemplate = "/", + UpstreamHttpMethod = "Get", + AuthenticationOptions = new YamlAuthenticationOptions + { + AdditionalScopes = new List + { + "openid", "offline_access" + }, + Provider = "IdentityServer", + ProviderRootUrl = "http://localhost:57888", + RequireHttps = false, + ScopeName = "api", + ScopeSecret = "secret", + }, + AddQueriesToRequest = + { + {"CustomerId", "Claims[CustomerId] > value"}, + {"LocationId", "Claims[LocationId] > value"}, + {"UserType", "Claims[sub] > value[0] > |"}, + {"UserId", "Claims[sub] > value[1] > |"} + } + } + } + }; + + this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:57888", "api", AccessTokenType.Jwt, user)) + .And(x => x.GivenThereIsAServiceRunningOn("http://localhost:57876", 200)) + .And(x => _steps.GivenIHaveAToken("http://localhost:57888")) + .And(x => _steps.GivenThereIsAConfiguration(yamlConfiguration)) + .And(x => _steps.GivenOcelotIsRunning()) + .And(x => _steps.GivenIHaveAddedATokenToMyRequest()) + .When(x => _steps.WhenIGetUrlOnTheApiGateway("/")) + .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) + .And(x => _steps.ThenTheResponseBodyShouldBe("CustomerId: 123 LocationId: 1 UserType: registered UserId: 1231231")) + .BDDfy(); + } + + private void GivenThereIsAServiceRunningOn(string url, int statusCode) + { + _servicebuilder = new WebHostBuilder() + .UseUrls(url) + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseUrls(url) + .Configure(app => + { + app.Run(async context => + { + StringValues customerId; + context.Request.Query.TryGetValue("CustomerId", out customerId); + + StringValues locationId; + context.Request.Query.TryGetValue("LocationId", out locationId); + + StringValues userType; + context.Request.Query.TryGetValue("UserType", out userType); + + StringValues userId; + context.Request.Query.TryGetValue("UserId", out userId); + + var responseBody = $"CustomerId: {customerId} LocationId: {locationId} UserType: {userType} UserId: {userId}"; + context.Response.StatusCode = statusCode; + await context.Response.WriteAsync(responseBody); + }); + }) + .Build(); + + _servicebuilder.Start(); + } + + private void GivenThereIsAnIdentityServerOn(string url, string scopeName, AccessTokenType tokenType, InMemoryUser user) + { + _identityServerBuilder = new WebHostBuilder() + .UseUrls(url) + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseUrls(url) + .ConfigureServices(services => + { + services.AddLogging(); + services.AddDeveloperIdentityServer() + .AddInMemoryScopes(new List + { + new Scope + { + Name = scopeName, + Description = "My API", + Enabled = true, + AllowUnrestrictedIntrospection = true, + ScopeSecrets = new List() + { + new Secret + { + Value = "secret".Sha256() + } + }, + IncludeAllClaimsForUser = true + }, + + StandardScopes.OpenId, + StandardScopes.OfflineAccess + }) + .AddInMemoryClients(new List + { + new Client + { + ClientId = "client", + AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, + ClientSecrets = new List {new Secret("secret".Sha256())}, + AllowedScopes = new List { scopeName, "openid", "offline_access" }, + AccessTokenType = tokenType, + Enabled = true, + RequireClientSecret = false + } + }) + .AddInMemoryUsers(new List + { + user + }); + }) + .Configure(app => + { + app.UseIdentityServer(); + }) + .Build(); + + _identityServerBuilder.Start(); + + _steps.VerifyIdentiryServerStarted(url); + } + + public void Dispose() + { + _servicebuilder?.Dispose(); + _steps.Dispose(); + _identityServerBuilder?.Dispose(); + } + } +} diff --git a/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs b/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs index 9f8d0392..abc7f9b8 100644 --- a/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs +++ b/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs @@ -29,11 +29,11 @@ namespace Ocelot.AcceptanceTests } [Fact] - public void response_should_come_from_pre_http_responder_middleware() + public void response_should_come_from_pre_authorisation_middleware() { var configuration = new OcelotMiddlewareConfiguration { - PreHttpResponderMiddleware = async (ctx, next) => + PreAuthorisationMiddleware = async (ctx, next) => { await ctx.Response.WriteAsync("PreHttpResponderMiddleware"); } @@ -62,11 +62,11 @@ namespace Ocelot.AcceptanceTests } [Fact] - public void response_should_come_from_pre_http_requester_middleware() + public void response_should_come_from_pre_http_authentication_middleware() { var configuration = new OcelotMiddlewareConfiguration { - PreHttpRequesterMiddleware = async (ctx, next) => + PreAuthenticationMiddleware = async (ctx, next) => { await ctx.Response.WriteAsync("PreHttpRequesterMiddleware"); } diff --git a/test/Ocelot.AcceptanceTests/configuration.yaml b/test/Ocelot.AcceptanceTests/configuration.yaml index feba804e..82266808 100644 --- a/test/Ocelot.AcceptanceTests/configuration.yaml +++ b/test/Ocelot.AcceptanceTests/configuration.yaml @@ -5,3 +5,4 @@ ReRoutes: AddHeadersToRequest: {} AddClaimsToRequest: {} RouteClaimsRequirement: {} + AddQueriesToRequest: {} diff --git a/test/Ocelot.ManualTest/configuration.yaml b/test/Ocelot.ManualTest/configuration.yaml index 9ff9f6d1..5e755363 100644 --- a/test/Ocelot.ManualTest/configuration.yaml +++ b/test/Ocelot.ManualTest/configuration.yaml @@ -1,11 +1,11 @@ ReRoutes: -# the url we are forwarding the request to +# The url we are forwarding the request to - DownstreamTemplate: http://localhost:52876/ -# the path we are listening on for this re route +# The path we are listening on for this re route UpstreamTemplate: /identityserverexample -# the method we are listening for on this re route +# The method we are listening for on this re route UpstreamHttpMethod: Get -# only support identity server at the moment +# Only support identity server at the moment AuthenticationOptions: Provider: IdentityServer ProviderRootUrl: http://localhost:52888 @@ -13,14 +13,44 @@ ReRoutes: AdditionalScopes: - openid - offline_access -#require if using reference tokens +# Required if using reference tokens ScopeSecret: secret -# WARNING - will overwrite any headers already in the request with these values +# WARNING - will overwrite any headers already in the request with these values. +# Ocelot will look in the user claims for the key in [] then return the value and save +# it as a header with the given key before the colon (:). The index selection on value +# means that Ocelot will use the delimiter specified after the next > to split the +# claim value and return the index specified. AddHeadersToRequest: CustomerId: Claims[CustomerId] > value LocationId: Claims[LocationId] > value UserType: Claims[sub] > value[0] > | UserId: Claims[sub] > value[1] > | +# WARNING - will overwrite any claims already in the request with these values. +# Ocelot will look in the user claims for the key in [] then return the value and save +# it as a claim with the given key before the colon (:). The index selection on value +# means that Ocelot will use the delimiter specified after the next > to split the +# claim value and return the index specified. +AddClaimsToRequest: + CustomerId: Claims[CustomerId] > value + LocationId: Claims[LocationId] > value + UserType: Claims[sub] > value[0] > | + UserId: Claims[sub] > value[1] > | +# WARNING - will overwrite any query string entries already in the request with these values. +# Ocelot will look in the user claims for the key in [] then return the value and save +# it as a query string with the given key before the colon (:). The index selection on value +# means that Ocelot will use the delimiter specified after the next > to split the +# claim value and return the index specified. +AddQueriesToRequest: + CustomerId: Claims[CustomerId] > value + LocationId: Claims[LocationId] > value + UserType: Claims[sub] > value[0] > | + UserId: Claims[sub] > value[1] > | +# This specifies any claims that are required for the user to access this re route. +# In this example the user must have the claim type UserType and +# the value must be registered +RouteClaimsRequirement: + UserType: registered +# The next re route... - DownstreamTemplate: http://jsonplaceholder.typicode.com/posts UpstreamTemplate: /posts UpstreamHttpMethod: Get diff --git a/test/Ocelot.UnitTests/ClaimsBuilder/AddClaimsToRequestTests.cs b/test/Ocelot.UnitTests/Claims/AddClaimsToRequestTests.cs similarity index 90% rename from test/Ocelot.UnitTests/ClaimsBuilder/AddClaimsToRequestTests.cs rename to test/Ocelot.UnitTests/Claims/AddClaimsToRequestTests.cs index 6e4d5339..e88fc773 100644 --- a/test/Ocelot.UnitTests/ClaimsBuilder/AddClaimsToRequestTests.cs +++ b/test/Ocelot.UnitTests/Claims/AddClaimsToRequestTests.cs @@ -1,19 +1,18 @@ -namespace Ocelot.UnitTests.ClaimsBuilder -{ - using System.Collections.Generic; - using System.Linq; - using System.Security.Claims; - using Errors; - using Microsoft.AspNetCore.Http; - using Moq; - using Ocelot.ClaimsBuilder; - using Ocelot.Configuration; - using Ocelot.Infrastructure.Claims.Parser; - using Responses; - using Shouldly; - using TestStack.BDDfy; - using Xunit; +using System.Collections.Generic; +using System.Security.Claims; +using Microsoft.AspNetCore.Http; +using Moq; +using Ocelot.Claims; +using Ocelot.Configuration; +using Ocelot.Errors; +using Ocelot.Infrastructure.Claims.Parser; +using Ocelot.Responses; +using Shouldly; +using TestStack.BDDfy; +using Xunit; +namespace Ocelot.UnitTests.Claims +{ public class AddClaimsToRequestTests { private readonly AddClaimsToRequest _addClaimsToRequest; diff --git a/test/Ocelot.UnitTests/ClaimsBuilder/ClaimsBuilderMiddlewareTests.cs b/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs similarity index 82% rename from test/Ocelot.UnitTests/ClaimsBuilder/ClaimsBuilderMiddlewareTests.cs rename to test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs index 708b5107..01cb606f 100644 --- a/test/Ocelot.UnitTests/ClaimsBuilder/ClaimsBuilderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Claims/ClaimsBuilderMiddlewareTests.cs @@ -1,26 +1,25 @@ -using Ocelot.Infrastructure.RequestData; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Http; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using Ocelot.Claims; +using Ocelot.Claims.Middleware; +using Ocelot.Configuration; +using Ocelot.Configuration.Builder; +using Ocelot.DownstreamRouteFinder; +using Ocelot.DownstreamRouteFinder.UrlMatcher; +using Ocelot.Infrastructure.RequestData; +using Ocelot.Responses; +using TestStack.BDDfy; +using Xunit; -namespace Ocelot.UnitTests.ClaimsBuilder +namespace Ocelot.UnitTests.Claims { - using System; - using System.Collections.Generic; - using System.IO; - using System.Net.Http; - using Microsoft.AspNetCore.Hosting; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.TestHost; - using Microsoft.Extensions.DependencyInjection; - using Moq; - using Ocelot.ClaimsBuilder; - using Ocelot.ClaimsBuilder.Middleware; - using Ocelot.Configuration; - using Ocelot.Configuration.Builder; - using Ocelot.DownstreamRouteFinder; - using Ocelot.DownstreamRouteFinder.UrlMatcher; - using Responses; - using TestStack.BDDfy; - using Xunit; - public class ClaimsBuilderMiddlewareTests : IDisposable { private readonly Mock _scopedRepository; diff --git a/test/Ocelot.UnitTests/HeaderBuilder/AddHeadersToRequestTests.cs b/test/Ocelot.UnitTests/Headers/AddHeadersToRequestTests.cs similarity index 97% rename from test/Ocelot.UnitTests/HeaderBuilder/AddHeadersToRequestTests.cs rename to test/Ocelot.UnitTests/Headers/AddHeadersToRequestTests.cs index fb12dba4..47951859 100644 --- a/test/Ocelot.UnitTests/HeaderBuilder/AddHeadersToRequestTests.cs +++ b/test/Ocelot.UnitTests/Headers/AddHeadersToRequestTests.cs @@ -6,16 +6,15 @@ using Microsoft.Extensions.Primitives; using Moq; using Ocelot.Configuration; using Ocelot.Errors; -using Ocelot.HeaderBuilder; +using Ocelot.Headers; +using Ocelot.Infrastructure.Claims.Parser; using Ocelot.Responses; using Shouldly; using TestStack.BDDfy; using Xunit; -namespace Ocelot.UnitTests.HeaderBuilder +namespace Ocelot.UnitTests.Headers { - using Ocelot.Infrastructure.Claims.Parser; - public class AddHeadersToRequestTests { private readonly AddHeadersToRequest _addHeadersToRequest; diff --git a/test/Ocelot.UnitTests/HeaderBuilder/HttpRequestHeadersBuilderMiddlewareTests.cs b/test/Ocelot.UnitTests/Headers/HttpRequestHeadersBuilderMiddlewareTests.cs similarity index 97% rename from test/Ocelot.UnitTests/HeaderBuilder/HttpRequestHeadersBuilderMiddlewareTests.cs rename to test/Ocelot.UnitTests/Headers/HttpRequestHeadersBuilderMiddlewareTests.cs index e3f8b771..e6b6c068 100644 --- a/test/Ocelot.UnitTests/HeaderBuilder/HttpRequestHeadersBuilderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Headers/HttpRequestHeadersBuilderMiddlewareTests.cs @@ -11,14 +11,14 @@ using Ocelot.Configuration; using Ocelot.Configuration.Builder; using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder.UrlMatcher; -using Ocelot.HeaderBuilder; -using Ocelot.HeaderBuilder.Middleware; +using Ocelot.Headers; +using Ocelot.Headers.Middleware; using Ocelot.Infrastructure.RequestData; using Ocelot.Responses; using TestStack.BDDfy; using Xunit; -namespace Ocelot.UnitTests.HeaderBuilder +namespace Ocelot.UnitTests.Headers { public class HttpRequestHeadersBuilderMiddlewareTests : IDisposable { diff --git a/test/Ocelot.UnitTests/QueryStrings/AddQueriesToRequestTests.cs b/test/Ocelot.UnitTests/QueryStrings/AddQueriesToRequestTests.cs new file mode 100644 index 00000000..99cf68b8 --- /dev/null +++ b/test/Ocelot.UnitTests/QueryStrings/AddQueriesToRequestTests.cs @@ -0,0 +1,153 @@ +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using Microsoft.AspNetCore.Http; +using Moq; +using Ocelot.Configuration; +using Ocelot.Errors; +using Ocelot.Infrastructure.Claims.Parser; +using Ocelot.QueryStrings; +using Ocelot.Responses; +using Shouldly; +using TestStack.BDDfy; +using Xunit; + +namespace Ocelot.UnitTests.QueryStrings +{ + public class AddQueriesToRequestTests + { + private readonly AddQueriesToRequest _addQueriesToRequest; + private readonly Mock _parser; + private List _configuration; + private HttpContext _context; + private Response _result; + private Response _claimValue; + + public AddQueriesToRequestTests() + { + _parser = new Mock(); + _addQueriesToRequest = new AddQueriesToRequest(_parser.Object); + } + + [Fact] + public void should_add_queries_to_context() + { + var context = new DefaultHttpContext + { + User = new ClaimsPrincipal(new ClaimsIdentity(new List + { + new Claim("test", "data") + })) + }; + + this.Given( + x => x.GivenAClaimToThing(new List + { + new ClaimToThing("query-key", "", "", 0) + })) + .Given(x => x.GivenHttpContext(context)) + .And(x => x.GivenTheClaimParserReturns(new OkResponse("value"))) + .When(x => x.WhenIAddQueriesToTheRequest()) + .Then(x => x.ThenTheResultIsSuccess()) + .And(x => x.ThenTheQueryIsAdded()) + .BDDfy(); + } + + [Fact] + public void if_query_exists_should_replace_it() + { + var context = new DefaultHttpContext + { + User = new ClaimsPrincipal(new ClaimsIdentity(new List + { + new Claim("test", "data") + })), + }; + + context.Request.QueryString = context.Request.QueryString.Add("query-key", "initial"); + + this.Given( + x => x.GivenAClaimToThing(new List + { + new ClaimToThing("query-key", "", "", 0) + })) + .Given(x => x.GivenHttpContext(context)) + .And(x => x.GivenTheClaimParserReturns(new OkResponse("value"))) + .When(x => x.WhenIAddQueriesToTheRequest()) + .Then(x => x.ThenTheResultIsSuccess()) + .And(x => x.ThenTheQueryIsAdded()) + .BDDfy(); + } + + [Fact] + public void should_return_error() + { + this.Given( + x => x.GivenAClaimToThing(new List + { + new ClaimToThing("", "", "", 0) + })) + .Given(x => x.GivenHttpContext(new DefaultHttpContext())) + .And(x => x.GivenTheClaimParserReturns(new ErrorResponse(new List + { + new AnyError() + }))) + .When(x => x.WhenIAddQueriesToTheRequest()) + .Then(x => x.ThenTheResultIsError()) + .BDDfy(); + } + + private void ThenTheQueryIsAdded() + { + var query = _context.Request.Query.First(x => x.Key == "query-key"); + query.Value.First().ShouldBe(_claimValue.Data); + } + + private void GivenAClaimToThing(List configuration) + { + _configuration = configuration; + } + + private void GivenHttpContext(HttpContext context) + { + _context = context; + } + + private void GivenTheClaimParserReturns(Response claimValue) + { + _claimValue = claimValue; + _parser + .Setup( + x => + x.GetValue(It.IsAny>(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Returns(_claimValue); + } + + private void WhenIAddQueriesToTheRequest() + { + _result = _addQueriesToRequest.SetQueriesOnContext(_configuration, _context); + } + + private void ThenTheResultIsSuccess() + { + _result.IsError.ShouldBe(false); + } + + private void ThenTheResultIsError() + { + + _result.IsError.ShouldBe(true); + } + + class AnyError : Error + { + public AnyError() + : base("blahh", OcelotErrorCode.UnknownError) + { + } + } + } +} diff --git a/test/Ocelot.UnitTests/QueryStrings/QueryStringBuilderMiddlewareTests.cs b/test/Ocelot.UnitTests/QueryStrings/QueryStringBuilderMiddlewareTests.cs new file mode 100644 index 00000000..0a481731 --- /dev/null +++ b/test/Ocelot.UnitTests/QueryStrings/QueryStringBuilderMiddlewareTests.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Http; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using Ocelot.Configuration; +using Ocelot.Configuration.Builder; +using Ocelot.DownstreamRouteFinder; +using Ocelot.DownstreamRouteFinder.UrlMatcher; +using Ocelot.Infrastructure.RequestData; +using Ocelot.QueryStrings; +using Ocelot.QueryStrings.Middleware; +using Ocelot.Responses; +using TestStack.BDDfy; +using Xunit; + +namespace Ocelot.UnitTests.QueryStrings +{ + public class QueryStringBuilderMiddlewareTests : IDisposable + { + private readonly Mock _scopedRepository; + private readonly Mock _addQueries; + private readonly string _url; + private readonly TestServer _server; + private readonly HttpClient _client; + private Response _downstreamRoute; + private HttpResponseMessage _result; + + public QueryStringBuilderMiddlewareTests() + { + _url = "http://localhost:51879"; + _scopedRepository = new Mock(); + _addQueries = new Mock(); + var builder = new WebHostBuilder() + .ConfigureServices(x => + { + x.AddSingleton(_addQueries.Object); + x.AddSingleton(_scopedRepository.Object); + }) + .UseUrls(_url) + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseUrls(_url) + .Configure(app => + { + app.UseQueryStringBuilderMiddleware(); + }); + + _server = new TestServer(builder); + _client = _server.CreateClient(); + } + + [Fact] + public void happy_path() + { + var downstreamRoute = new DownstreamRoute(new List(), + new ReRouteBuilder() + .WithDownstreamTemplate("any old string") + .WithClaimsToQueries(new List + { + new ClaimToThing("UserId", "Subject", "", 0) + }) + .Build()); + + this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) + .And(x => x.GivenTheAddHeadersToRequestReturns()) + .When(x => x.WhenICallTheMiddleware()) + .Then(x => x.ThenTheAddHeadersToRequestIsCalledCorrectly()) + .BDDfy(); + } + + private void GivenTheAddHeadersToRequestReturns() + { + _addQueries + .Setup(x => x.SetQueriesOnContext(It.IsAny>(), + It.IsAny())) + .Returns(new OkResponse()); + } + + private void ThenTheAddHeadersToRequestIsCalledCorrectly() + { + _addQueries + .Verify(x => x.SetQueriesOnContext(It.IsAny>(), + It.IsAny()), Times.Once); + } + + private void WhenICallTheMiddleware() + { + _result = _client.GetAsync(_url).Result; + } + + private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute) + { + _downstreamRoute = new OkResponse(downstreamRoute); + _scopedRepository + .Setup(x => x.Get(It.IsAny())) + .Returns(_downstreamRoute); + } + + public void Dispose() + { + _client.Dispose(); + _server.Dispose(); + } + } +} diff --git a/test/Ocelot.UnitTests/RequestBuilder/HttpRequestBuilderMiddlewareTests.cs b/test/Ocelot.UnitTests/Request/HttpRequestBuilderMiddlewareTests.cs similarity index 87% rename from test/Ocelot.UnitTests/RequestBuilder/HttpRequestBuilderMiddlewareTests.cs rename to test/Ocelot.UnitTests/Request/HttpRequestBuilderMiddlewareTests.cs index 7c6cf323..f894b63f 100644 --- a/test/Ocelot.UnitTests/RequestBuilder/HttpRequestBuilderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Request/HttpRequestBuilderMiddlewareTests.cs @@ -8,14 +8,13 @@ using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using Moq; using Ocelot.Infrastructure.RequestData; -using Ocelot.RequestBuilder; -using Ocelot.RequestBuilder.Builder; -using Ocelot.RequestBuilder.Middleware; +using Ocelot.Request.Builder; +using Ocelot.Request.Middleware; using Ocelot.Responses; using TestStack.BDDfy; using Xunit; -namespace Ocelot.UnitTests.RequestBuilder +namespace Ocelot.UnitTests.Request { public class HttpRequestBuilderMiddlewareTests : IDisposable { @@ -25,7 +24,7 @@ namespace Ocelot.UnitTests.RequestBuilder private readonly TestServer _server; private readonly HttpClient _client; private HttpResponseMessage _result; - private OkResponse _request; + private OkResponse _request; private OkResponse _downstreamUrl; public HttpRequestBuilderMiddlewareTests() @@ -58,15 +57,15 @@ namespace Ocelot.UnitTests.RequestBuilder public void happy_path() { this.Given(x => x.GivenTheDownStreamUrlIs("any old string")) - .And(x => x.GivenTheRequestBuilderReturns(new Request(new HttpRequestMessage(), new CookieContainer()))) + .And(x => x.GivenTheRequestBuilderReturns(new Ocelot.Request.Request(new HttpRequestMessage(), new CookieContainer()))) .When(x => x.WhenICallTheMiddleware()) .Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly()) .BDDfy(); } - private void GivenTheRequestBuilderReturns(Request request) + private void GivenTheRequestBuilderReturns(Ocelot.Request.Request request) { - _request = new OkResponse(request); + _request = new OkResponse(request); _requestBuilder .Setup(x => x.Build(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) diff --git a/test/Ocelot.UnitTests/RequestBuilder/RequestBuilderTests.cs b/test/Ocelot.UnitTests/Request/RequestBuilderTests.cs similarity index 98% rename from test/Ocelot.UnitTests/RequestBuilder/RequestBuilderTests.cs rename to test/Ocelot.UnitTests/Request/RequestBuilderTests.cs index 0bcec40a..7b6a1688 100644 --- a/test/Ocelot.UnitTests/RequestBuilder/RequestBuilderTests.cs +++ b/test/Ocelot.UnitTests/Request/RequestBuilderTests.cs @@ -5,14 +5,13 @@ using System.Net; using System.Net.Http; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Internal; -using Ocelot.RequestBuilder; -using Ocelot.RequestBuilder.Builder; +using Ocelot.Request.Builder; using Ocelot.Responses; using Shouldly; using TestStack.BDDfy; using Xunit; -namespace Ocelot.UnitTests.RequestBuilder +namespace Ocelot.UnitTests.Request { public class RequestBuilderTests { @@ -24,7 +23,7 @@ namespace Ocelot.UnitTests.RequestBuilder private QueryString _query; private string _contentType; private readonly IRequestBuilder _requestBuilder; - private Response _result; + private Response _result; public RequestBuilderTests() { diff --git a/test/Ocelot.UnitTests/Requester/HttpRequesterMiddlewareTests.cs b/test/Ocelot.UnitTests/Requester/HttpRequesterMiddlewareTests.cs index 56e03b83..d15a57ab 100644 --- a/test/Ocelot.UnitTests/Requester/HttpRequesterMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Requester/HttpRequesterMiddlewareTests.cs @@ -8,7 +8,6 @@ using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using Moq; using Ocelot.Infrastructure.RequestData; -using Ocelot.RequestBuilder; using Ocelot.Requester; using Ocelot.Requester.Middleware; using Ocelot.Responder; @@ -27,7 +26,7 @@ namespace Ocelot.UnitTests.Requester private readonly HttpClient _client; private HttpResponseMessage _result; private OkResponse _response; - private OkResponse _request; + private OkResponse _request; private readonly Mock _responder; public HttpRequesterMiddlewareTests() @@ -61,7 +60,7 @@ namespace Ocelot.UnitTests.Requester [Fact] public void happy_path() { - this.Given(x => x.GivenTheRequestIs(new Request(new HttpRequestMessage(),new CookieContainer()))) + this.Given(x => x.GivenTheRequestIs(new Ocelot.Request.Request(new HttpRequestMessage(),new CookieContainer()))) .And(x => x.GivenTheRequesterReturns(new HttpResponseMessage())) .And(x => x.GivenTheResponderReturns()) .When(x => x.WhenICallTheMiddleware()) @@ -73,7 +72,7 @@ namespace Ocelot.UnitTests.Requester { _response = new OkResponse(response); _requester - .Setup(x => x.GetResponse(It.IsAny())) + .Setup(x => x.GetResponse(It.IsAny())) .ReturnsAsync(_response); } @@ -95,11 +94,11 @@ namespace Ocelot.UnitTests.Requester _result = _client.GetAsync(_url).Result; } - private void GivenTheRequestIs(Request request) + private void GivenTheRequestIs(Ocelot.Request.Request request) { - _request = new OkResponse(request); + _request = new OkResponse(request); _scopedRepository - .Setup(x => x.Get(It.IsAny())) + .Setup(x => x.Get(It.IsAny())) .Returns(_request); }