diff --git a/src/Ocelot.Library/Infrastructure/RequestBuilder/RequestBuilder.cs b/src/Ocelot.Library/Infrastructure/RequestBuilder/HttpRequestBuilder.cs similarity index 69% rename from src/Ocelot.Library/Infrastructure/RequestBuilder/RequestBuilder.cs rename to src/Ocelot.Library/Infrastructure/RequestBuilder/HttpRequestBuilder.cs index 653c263a..6a0b7c8f 100644 --- a/src/Ocelot.Library/Infrastructure/RequestBuilder/RequestBuilder.cs +++ b/src/Ocelot.Library/Infrastructure/RequestBuilder/HttpRequestBuilder.cs @@ -3,13 +3,14 @@ using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Headers; +using System.Threading.Tasks; using Microsoft.AspNetCore.Http; namespace Ocelot.Library.Infrastructure.RequestBuilder { - public class RequestBuilder : IRequestBuilder + public class HttpRequestBuilder : IRequestBuilder { - public Request Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers, + public async Task Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers, IRequestCookieCollection cookies, string queryString, string contentType) { var method = new HttpMethod(httpMethod); @@ -20,7 +21,11 @@ namespace Ocelot.Library.Infrastructure.RequestBuilder if (content != null) { - httpRequestMessage.Content = new StreamContent(content); + using (var reader = new StreamReader(content)) + { + var body = await reader.ReadToEndAsync(); + httpRequestMessage.Content = new StringContent(body); + } } if (!string.IsNullOrEmpty(contentType)) @@ -41,7 +46,11 @@ namespace Ocelot.Library.Infrastructure.RequestBuilder { foreach (var header in headers) { - httpRequestMessage.Headers.Add(header.Key, header.Value.ToArray()); + //todo get rid of if.. + if (header.Key.ToLower() != "host") + { + httpRequestMessage.Headers.Add(header.Key, header.Value.ToArray()); + } } } diff --git a/src/Ocelot.Library/Infrastructure/RequestBuilder/IRequestBuilder.cs b/src/Ocelot.Library/Infrastructure/RequestBuilder/IRequestBuilder.cs index 482bf51a..cace3b70 100644 --- a/src/Ocelot.Library/Infrastructure/RequestBuilder/IRequestBuilder.cs +++ b/src/Ocelot.Library/Infrastructure/RequestBuilder/IRequestBuilder.cs @@ -1,11 +1,12 @@ using System.IO; +using System.Threading.Tasks; using Microsoft.AspNetCore.Http; namespace Ocelot.Library.Infrastructure.RequestBuilder { public interface IRequestBuilder { - Request Build(string httpMethod, + Task Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers, diff --git a/src/Ocelot.Library/Infrastructure/Requester/HttpClientHttpRequester.cs b/src/Ocelot.Library/Infrastructure/Requester/HttpClientHttpRequester.cs index c2b91523..260a6843 100644 --- a/src/Ocelot.Library/Infrastructure/Requester/HttpClientHttpRequester.cs +++ b/src/Ocelot.Library/Infrastructure/Requester/HttpClientHttpRequester.cs @@ -1,17 +1,32 @@ -using System.Net.Http; +using System; +using System.Collections.Generic; +using System.Net.Http; using System.Threading.Tasks; using Ocelot.Library.Infrastructure.RequestBuilder; +using Ocelot.Library.Infrastructure.Responses; namespace Ocelot.Library.Infrastructure.Requester { public class HttpClientHttpRequester : IHttpRequester { - public async Task GetResponse(Request request) + public async Task> GetResponse(Request request) { using (var handler = new HttpClientHandler { CookieContainer = request.CookieContainer }) using (var httpClient = new HttpClient(handler)) { - return await httpClient.SendAsync(request.HttpRequestMessage); + try + { + var response = await httpClient.SendAsync(request.HttpRequestMessage); + return new OkResponse(response); + } + catch (Exception exception) + { + return + new ErrorResponse(new List + { + new UnableToCompleteRequestError(exception) + }); + } } } } diff --git a/src/Ocelot.Library/Infrastructure/Requester/IHttpRequester.cs b/src/Ocelot.Library/Infrastructure/Requester/IHttpRequester.cs index e8d3d33b..eca3875e 100644 --- a/src/Ocelot.Library/Infrastructure/Requester/IHttpRequester.cs +++ b/src/Ocelot.Library/Infrastructure/Requester/IHttpRequester.cs @@ -1,11 +1,12 @@ using System.Net.Http; using System.Threading.Tasks; using Ocelot.Library.Infrastructure.RequestBuilder; +using Ocelot.Library.Infrastructure.Responses; namespace Ocelot.Library.Infrastructure.Requester { public interface IHttpRequester { - Task GetResponse(Request request); + Task> GetResponse(Request request); } } diff --git a/src/Ocelot.Library/Infrastructure/Requester/UnableToCompleteRequestError.cs b/src/Ocelot.Library/Infrastructure/Requester/UnableToCompleteRequestError.cs new file mode 100644 index 00000000..6e7a042c --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/Requester/UnableToCompleteRequestError.cs @@ -0,0 +1,13 @@ +using System; +using Ocelot.Library.Infrastructure.Responses; + +namespace Ocelot.Library.Infrastructure.Requester +{ + public class UnableToCompleteRequestError : Error + { + public UnableToCompleteRequestError(Exception exception) + : base($"Error making http request, exception: {exception.Message}") + { + } + } +} diff --git a/src/Ocelot.Library/Infrastructure/Responder/HttpContextResponder.cs b/src/Ocelot.Library/Infrastructure/Responder/HttpContextResponder.cs index 1569e58a..5339ff92 100644 --- a/src/Ocelot.Library/Infrastructure/Responder/HttpContextResponder.cs +++ b/src/Ocelot.Library/Infrastructure/Responder/HttpContextResponder.cs @@ -11,7 +11,12 @@ namespace Ocelot.Library.Infrastructure.Responder { if (response.IsSuccessStatusCode) { - context.Response.StatusCode = (int)response.StatusCode; + context.Response.OnStarting(x => + { + context.Response.StatusCode = (int)response.StatusCode; + return Task.CompletedTask; + }, context); + await context.Response.WriteAsync(await response.Content.ReadAsStringAsync()); return context; } @@ -20,7 +25,11 @@ namespace Ocelot.Library.Infrastructure.Responder public async Task CreateNotFoundResponse(HttpContext context) { - context.Response.StatusCode = (int)HttpStatusCode.NotFound; + context.Response.OnStarting(x => + { + context.Response.StatusCode = (int)HttpStatusCode.NotFound; + return Task.CompletedTask; + }, context); return context; } } diff --git a/src/Ocelot.Library/Infrastructure/UrlMatcher/IUrlPathToUrlTemplateMatcher.cs b/src/Ocelot.Library/Infrastructure/UrlMatcher/IUrlPathToUrlTemplateMatcher.cs index 954e3fee..89e3e5a5 100644 --- a/src/Ocelot.Library/Infrastructure/UrlMatcher/IUrlPathToUrlTemplateMatcher.cs +++ b/src/Ocelot.Library/Infrastructure/UrlMatcher/IUrlPathToUrlTemplateMatcher.cs @@ -2,6 +2,6 @@ namespace Ocelot.Library.Infrastructure.UrlMatcher { public interface IUrlPathToUrlTemplateMatcher { - UrlMatch Match(string upstreamUrlPath, string upstreamUrlTemplate); + UrlMatch Match(string upstreamUrlPath, string upstreamUrlPathTemplate); } } \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/UrlMatcher/UrlPathToUrlTemplateMatcher.cs b/src/Ocelot.Library/Infrastructure/UrlMatcher/UrlPathToUrlTemplateMatcher.cs index 0c396e32..4e5aed52 100644 --- a/src/Ocelot.Library/Infrastructure/UrlMatcher/UrlPathToUrlTemplateMatcher.cs +++ b/src/Ocelot.Library/Infrastructure/UrlMatcher/UrlPathToUrlTemplateMatcher.cs @@ -5,21 +5,26 @@ namespace Ocelot.Library.Infrastructure.UrlMatcher { public class UrlPathToUrlTemplateMatcher : IUrlPathToUrlTemplateMatcher { - public UrlMatch Match(string upstreamUrlPath, string upstreamUrlTemplate) + public UrlMatch Match(string upstreamUrlPath, string upstreamUrlPathTemplate) { - var urlPathTemplateCopy = upstreamUrlTemplate; + if (upstreamUrlPath.Length > upstreamUrlPathTemplate.Length) + { + return new UrlMatch(false, new List(), string.Empty); + } + + var urlPathTemplateCopy = upstreamUrlPathTemplate; var templateKeysAndValues = new List(); int counterForUrl = 0; - for (int counterForTemplate = 0; counterForTemplate < upstreamUrlTemplate.Length; counterForTemplate++) + for (int counterForTemplate = 0; counterForTemplate < upstreamUrlPathTemplate.Length; counterForTemplate++) { - if (CharactersDontMatch(upstreamUrlTemplate[counterForTemplate], upstreamUrlPath[counterForUrl]) && ContinueScanningUrl(counterForUrl,upstreamUrlPath.Length)) + if (CharactersDontMatch(upstreamUrlPathTemplate[counterForTemplate], upstreamUrlPath[counterForUrl]) && ContinueScanningUrl(counterForUrl,upstreamUrlPath.Length)) { - if (IsPlaceholder(upstreamUrlTemplate[counterForTemplate])) + if (IsPlaceholder(upstreamUrlPathTemplate[counterForTemplate])) { - var variableName = GetPlaceholderVariableName(upstreamUrlTemplate, counterForTemplate); + var variableName = GetPlaceholderVariableName(upstreamUrlPathTemplate, counterForTemplate); var variableValue = GetPlaceholderVariableValue(upstreamUrlPath, counterForUrl); @@ -27,7 +32,7 @@ namespace Ocelot.Library.Infrastructure.UrlMatcher templateKeysAndValues.Add(templateVariableNameAndValue); - counterForTemplate = GetNextCounterPosition(upstreamUrlTemplate, counterForTemplate, '}'); + counterForTemplate = GetNextCounterPosition(upstreamUrlPathTemplate, counterForTemplate, '}'); counterForUrl = GetNextCounterPosition(upstreamUrlPath, counterForUrl, '/'); diff --git a/src/Ocelot.Library/Middleware/HttpRequestBuilderMiddleware.cs b/src/Ocelot.Library/Middleware/HttpRequestBuilderMiddleware.cs index 1bb0d68a..e41b1417 100644 --- a/src/Ocelot.Library/Middleware/HttpRequestBuilderMiddleware.cs +++ b/src/Ocelot.Library/Middleware/HttpRequestBuilderMiddleware.cs @@ -36,7 +36,7 @@ namespace Ocelot.Library.Middleware return; } - var request = _requestBuilder + var request = await _requestBuilder .Build(context.Request.Method, downstreamUrl.Data, context.Request.Body, context.Request.Headers, context.Request.Cookies, context.Request.QueryString.Value, context.Request.ContentType); diff --git a/src/Ocelot.Library/Middleware/HttpRequesterMiddleware.cs b/src/Ocelot.Library/Middleware/HttpRequesterMiddleware.cs index b5538df6..e35121ca 100644 --- a/src/Ocelot.Library/Middleware/HttpRequesterMiddleware.cs +++ b/src/Ocelot.Library/Middleware/HttpRequesterMiddleware.cs @@ -1,3 +1,4 @@ +using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Ocelot.Library.Infrastructure.Repository; @@ -14,19 +15,16 @@ namespace Ocelot.Library.Middleware private readonly IHttpRequester _requester; private readonly IHttpResponder _responder; private readonly IScopedRequestDataRepository _scopedRequestDataRepository; - private readonly IRequestBuilder _requestBuilder; public HttpRequesterMiddleware(RequestDelegate next, IHttpRequester requester, IHttpResponder responder, - IScopedRequestDataRepository scopedRequestDataRepository, - IRequestBuilder requestBuilder) + IScopedRequestDataRepository scopedRequestDataRepository) { _next = next; _requester = requester; _responder = responder; _scopedRequestDataRepository = scopedRequestDataRepository; - _requestBuilder = requestBuilder; } public async Task Invoke(HttpContext context) @@ -42,8 +40,8 @@ namespace Ocelot.Library.Middleware var response = await _requester .GetResponse(request.Data); - await _responder.CreateResponse(context, response); - + _scopedRequestDataRepository.Add("Response", response.Data); + await _next.Invoke(context); } } diff --git a/src/Ocelot.Library/Middleware/HttpResponderMiddleware.cs b/src/Ocelot.Library/Middleware/HttpResponderMiddleware.cs new file mode 100644 index 00000000..09b31f70 --- /dev/null +++ b/src/Ocelot.Library/Middleware/HttpResponderMiddleware.cs @@ -0,0 +1,34 @@ +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Ocelot.Library.Infrastructure.Repository; +using Ocelot.Library.Infrastructure.Responder; + +namespace Ocelot.Library.Middleware +{ + /// + /// Terminating middleware that is responsible for returning a http response to the client + /// + public class HttpResponderMiddleware + { + private readonly RequestDelegate _next; + private readonly IHttpResponder _responder; + private readonly IScopedRequestDataRepository _scopedRequestDataRepository; + + public HttpResponderMiddleware(RequestDelegate next, + IHttpResponder responder, + IScopedRequestDataRepository scopedRequestDataRepository) + { + _next = next; + _responder = responder; + _scopedRequestDataRepository = scopedRequestDataRepository; + } + + public async Task Invoke(HttpContext context) + { + var response = _scopedRequestDataRepository.Get("Response"); + + await _responder.CreateResponse(context, response.Data); + } + } +} \ No newline at end of file diff --git a/src/Ocelot.Library/Middleware/HttpResponderMiddlewareExtensions.cs b/src/Ocelot.Library/Middleware/HttpResponderMiddlewareExtensions.cs new file mode 100644 index 00000000..4cec7fd0 --- /dev/null +++ b/src/Ocelot.Library/Middleware/HttpResponderMiddlewareExtensions.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Builder; + +namespace Ocelot.Library.Middleware +{ + public static class HttpResponderMiddlewareExtensions + { + public static IApplicationBuilder UseHttpResponderMiddleware(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } + } +} \ No newline at end of file diff --git a/src/Ocelot/Program.cs b/src/Ocelot/Program.cs index e8777ea7..1fdd2ad8 100644 --- a/src/Ocelot/Program.cs +++ b/src/Ocelot/Program.cs @@ -1,10 +1,5 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; +using System.IO; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Builder; namespace Ocelot { diff --git a/src/Ocelot/Startup.cs b/src/Ocelot/Startup.cs index cb9e9e77..ed685d57 100644 --- a/src/Ocelot/Startup.cs +++ b/src/Ocelot/Startup.cs @@ -44,7 +44,7 @@ namespace Ocelot services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); // see this for why we register this as singleton http://stackoverflow.com/questions/37371264/invalidoperationexception-unable-to-resolve-service-for-type-microsoft-aspnetc services.AddSingleton(); @@ -65,6 +65,8 @@ namespace Ocelot app.UseHttpRequestBuilderMiddleware(); app.UseHttpRequesterMiddleware(); + + app.UseHttpResponderMiddleware(); } } } diff --git a/src/Ocelot/configuration.yaml b/src/Ocelot/configuration.yaml index 04ac7018..db7e74c5 100644 --- a/src/Ocelot/configuration.yaml +++ b/src/Ocelot/configuration.yaml @@ -1,4 +1,4 @@ ReRoutes: -- DownstreamTemplate: http://www.bbc.co.uk +- DownstreamTemplate: http://www.mattsite.dev/ UpstreamTemplate: / UpstreamHttpMethod: Get diff --git a/test/Ocelot.UnitTests/RequestBuilder/RequestBuilderTests.cs b/test/Ocelot.UnitTests/RequestBuilder/RequestBuilderTests.cs index eb841306..db6cf5e6 100644 --- a/test/Ocelot.UnitTests/RequestBuilder/RequestBuilderTests.cs +++ b/test/Ocelot.UnitTests/RequestBuilder/RequestBuilderTests.cs @@ -27,7 +27,7 @@ namespace Ocelot.UnitTests.RequestBuilder public RequestBuilderTests() { _content = new StringContent(string.Empty); - _requestBuilder = new Library.Infrastructure.RequestBuilder.RequestBuilder(); + _requestBuilder = new Library.Infrastructure.RequestBuilder.HttpRequestBuilder(); } [Fact] @@ -70,7 +70,6 @@ namespace Ocelot.UnitTests.RequestBuilder .And(x => x.GivenIHaveTheHttpContent(new StringContent("Hi from Tom"))) .And(x => x.GivenTheContentTypeIs("application/json")) .When(x => x.WhenICreateARequest()) - .And(x => x.ThenTheCorrectContentIsUsed(new StringContent("Hi from Tom"))) .And(x => x.ThenTheCorrectContentHeadersAreUsed(new HeaderDictionary { { @@ -202,7 +201,7 @@ namespace Ocelot.UnitTests.RequestBuilder private void WhenICreateARequest() { _result = _requestBuilder.Build(_httpMethod, _downstreamUrl, _content?.ReadAsStreamAsync().Result, _headers, - _cookies, _query, _contentType); + _cookies, _query, _contentType).Result; } diff --git a/test/Ocelot.UnitTests/UrlMatcher/UrlPathToUrlTemplateMatcherTests.cs b/test/Ocelot.UnitTests/UrlMatcher/UrlPathToUrlTemplateMatcherTests.cs index c2f64419..d196b479 100644 --- a/test/Ocelot.UnitTests/UrlMatcher/UrlPathToUrlTemplateMatcherTests.cs +++ b/test/Ocelot.UnitTests/UrlMatcher/UrlPathToUrlTemplateMatcherTests.cs @@ -18,11 +18,21 @@ namespace Ocelot.UnitTests.UrlMatcher _urlMatcher = new UrlPathToUrlTemplateMatcher(); } + [Fact] + public void should_not_find_match() + { + this.Given(x => x.GivenIHaveAUpstreamPath("/api/values")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplate("/")) + .When(x => x.WhenIMatchThePaths()) + .And(x => x.ThenTheResultIsFalse()) + .BDDfy(); + } + [Fact] public void can_match_down_stream_url() { - this.Given(x => x.GivenIHaveADownstreamPath("")) - .And(x => x.GivenIHaveAnDownstreamUrlTemplate("")) + this.Given(x => x.GivenIHaveAUpstreamPath("")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplate("")) .When(x => x.WhenIMatchThePaths()) .And(x => x.ThenTheResultIsTrue()) .And(x => x.ThenTheTemplatesVariablesAre(new List())) @@ -33,8 +43,8 @@ namespace Ocelot.UnitTests.UrlMatcher [Fact] public void can_match_down_stream_url_with_no_slash() { - this.Given(x => x.GivenIHaveADownstreamPath("api")) - .Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api")) + this.Given(x => x.GivenIHaveAUpstreamPath("api")) + .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) .And(x => x.ThenTheTemplatesVariablesAre(new List())) @@ -45,8 +55,8 @@ namespace Ocelot.UnitTests.UrlMatcher [Fact] public void can_match_down_stream_url_with_one_slash() { - this.Given(x => x.GivenIHaveADownstreamPath("api/")) - .Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/")) + this.Given(x => x.GivenIHaveAUpstreamPath("api/")) + .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) .And(x => x.ThenTheTemplatesVariablesAre(new List())) @@ -57,8 +67,8 @@ namespace Ocelot.UnitTests.UrlMatcher [Fact] public void can_match_down_stream_url_with_downstream_template() { - this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/")) - .Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/")) + this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/")) + .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) .And(x => x.ThenTheTemplatesVariablesAre(new List())) @@ -66,35 +76,6 @@ namespace Ocelot.UnitTests.UrlMatcher .BDDfy(); } - [Fact] - public void can_match_down_stream_url_with_downstream_template_with_one_query_string_parameter() - { - this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/?soldout=false")) - .Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/")) - .When(x => x.WhenIMatchThePaths()) - .Then(x => x.ThenTheResultIsTrue()) - .And(x => x.ThenTheTemplatesVariablesAre(new List())) - .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/")) - .BDDfy(); - } - - [Fact] - public void can_match_down_stream_url_with_downstream_template_with_one_query_string_parameter_and_one_template() - { - var expectedTemplates = new List - { - new TemplateVariableNameAndValue("{productId}", "1") - }; - - this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1/variants/?soldout=false")) - .Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}/variants/")) - .When(x => x.WhenIMatchThePaths()) - .Then(x => x.ThenTheResultIsTrue()) - .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) - .And(x => x.ThenTheDownstreamUrlTemplateIs("api/product/products/{productId}/variants/")) - .BDDfy(); - } - [Fact] public void can_match_down_stream_url_with_downstream_template_with_one_place_holder() { @@ -103,8 +84,8 @@ namespace Ocelot.UnitTests.UrlMatcher new TemplateVariableNameAndValue("{productId}", "1") }; - this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1")) - .Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}")) + this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1")) + .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) @@ -121,8 +102,8 @@ namespace Ocelot.UnitTests.UrlMatcher new TemplateVariableNameAndValue("{categoryId}", "2") }; - this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1/2")) - .Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}/{categoryId}")) + this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2")) + .Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/{categoryId}")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) @@ -139,8 +120,8 @@ namespace Ocelot.UnitTests.UrlMatcher new TemplateVariableNameAndValue("{categoryId}", "2") }; - this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1/categories/2")) - .And(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}")) + this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) @@ -158,8 +139,8 @@ namespace Ocelot.UnitTests.UrlMatcher new TemplateVariableNameAndValue("{variantId}", "123") }; - this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1/categories/2/variant/123")) - .And(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}")) + this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/123")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) @@ -176,8 +157,8 @@ namespace Ocelot.UnitTests.UrlMatcher new TemplateVariableNameAndValue("{categoryId}", "2") }; - this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1/categories/2/variant/")) - .And(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/")) + this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/")) + .And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/")) .When(x => x.WhenIMatchThePaths()) .Then(x => x.ThenTheResultIsTrue()) .And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates)) @@ -199,12 +180,12 @@ namespace Ocelot.UnitTests.UrlMatcher { _result.DownstreamUrlTemplate.ShouldBe(expectedDownstreamUrlTemplate); } - private void GivenIHaveADownstreamPath(string downstreamPath) + private void GivenIHaveAUpstreamPath(string downstreamPath) { _downstreamUrlPath = downstreamPath; } - private void GivenIHaveAnDownstreamUrlTemplate(string downstreamUrlTemplate) + private void GivenIHaveAnUpstreamUrlTemplate(string downstreamUrlTemplate) { _downstreamPathTemplate = downstreamUrlTemplate; } @@ -218,5 +199,10 @@ namespace Ocelot.UnitTests.UrlMatcher { _result.Match.ShouldBeTrue(); } + + private void ThenTheResultIsFalse() + { + _result.Match.ShouldBeFalse(); + } } } \ No newline at end of file