mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:22:50 +08:00
made a response middlware as terminating middleware...
This commit is contained in:
parent
3685efec05
commit
a7a1143823
@ -3,13 +3,14 @@ using System.IO;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.RequestBuilder
|
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<Request> Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers,
|
||||||
IRequestCookieCollection cookies, string queryString, string contentType)
|
IRequestCookieCollection cookies, string queryString, string contentType)
|
||||||
{
|
{
|
||||||
var method = new HttpMethod(httpMethod);
|
var method = new HttpMethod(httpMethod);
|
||||||
@ -20,7 +21,11 @@ namespace Ocelot.Library.Infrastructure.RequestBuilder
|
|||||||
|
|
||||||
if (content != null)
|
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))
|
if (!string.IsNullOrEmpty(contentType))
|
||||||
@ -41,7 +46,11 @@ namespace Ocelot.Library.Infrastructure.RequestBuilder
|
|||||||
{
|
{
|
||||||
foreach (var header in headers)
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,11 +1,12 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.RequestBuilder
|
namespace Ocelot.Library.Infrastructure.RequestBuilder
|
||||||
{
|
{
|
||||||
public interface IRequestBuilder
|
public interface IRequestBuilder
|
||||||
{
|
{
|
||||||
Request Build(string httpMethod,
|
Task<Request> Build(string httpMethod,
|
||||||
string downstreamUrl,
|
string downstreamUrl,
|
||||||
Stream content,
|
Stream content,
|
||||||
IHeaderDictionary headers,
|
IHeaderDictionary headers,
|
||||||
|
@ -1,17 +1,32 @@
|
|||||||
using System.Net.Http;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ocelot.Library.Infrastructure.RequestBuilder;
|
using Ocelot.Library.Infrastructure.RequestBuilder;
|
||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.Requester
|
namespace Ocelot.Library.Infrastructure.Requester
|
||||||
{
|
{
|
||||||
public class HttpClientHttpRequester : IHttpRequester
|
public class HttpClientHttpRequester : IHttpRequester
|
||||||
{
|
{
|
||||||
public async Task<HttpResponseMessage> GetResponse(Request request)
|
public async Task<Response<HttpResponseMessage>> GetResponse(Request request)
|
||||||
{
|
{
|
||||||
using (var handler = new HttpClientHandler { CookieContainer = request.CookieContainer })
|
using (var handler = new HttpClientHandler { CookieContainer = request.CookieContainer })
|
||||||
using (var httpClient = new HttpClient(handler))
|
using (var httpClient = new HttpClient(handler))
|
||||||
{
|
{
|
||||||
return await httpClient.SendAsync(request.HttpRequestMessage);
|
try
|
||||||
|
{
|
||||||
|
var response = await httpClient.SendAsync(request.HttpRequestMessage);
|
||||||
|
return new OkResponse<HttpResponseMessage>(response);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
new ErrorResponse<HttpResponseMessage>(new List<Error>
|
||||||
|
{
|
||||||
|
new UnableToCompleteRequestError(exception)
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ocelot.Library.Infrastructure.RequestBuilder;
|
using Ocelot.Library.Infrastructure.RequestBuilder;
|
||||||
|
using Ocelot.Library.Infrastructure.Responses;
|
||||||
|
|
||||||
namespace Ocelot.Library.Infrastructure.Requester
|
namespace Ocelot.Library.Infrastructure.Requester
|
||||||
{
|
{
|
||||||
public interface IHttpRequester
|
public interface IHttpRequester
|
||||||
{
|
{
|
||||||
Task<HttpResponseMessage> GetResponse(Request request);
|
Task<Response<HttpResponseMessage>> GetResponse(Request request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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}")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,12 @@ namespace Ocelot.Library.Infrastructure.Responder
|
|||||||
{
|
{
|
||||||
if (response.IsSuccessStatusCode)
|
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());
|
await context.Response.WriteAsync(await response.Content.ReadAsStringAsync());
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
@ -20,7 +25,11 @@ namespace Ocelot.Library.Infrastructure.Responder
|
|||||||
|
|
||||||
public async Task<HttpContext> CreateNotFoundResponse(HttpContext context)
|
public async Task<HttpContext> 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;
|
return context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,6 @@ namespace Ocelot.Library.Infrastructure.UrlMatcher
|
|||||||
{
|
{
|
||||||
public interface IUrlPathToUrlTemplateMatcher
|
public interface IUrlPathToUrlTemplateMatcher
|
||||||
{
|
{
|
||||||
UrlMatch Match(string upstreamUrlPath, string upstreamUrlTemplate);
|
UrlMatch Match(string upstreamUrlPath, string upstreamUrlPathTemplate);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,21 +5,26 @@ namespace Ocelot.Library.Infrastructure.UrlMatcher
|
|||||||
{
|
{
|
||||||
public class UrlPathToUrlTemplateMatcher : IUrlPathToUrlTemplateMatcher
|
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<TemplateVariableNameAndValue>(), string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
var urlPathTemplateCopy = upstreamUrlPathTemplate;
|
||||||
|
|
||||||
var templateKeysAndValues = new List<TemplateVariableNameAndValue>();
|
var templateKeysAndValues = new List<TemplateVariableNameAndValue>();
|
||||||
|
|
||||||
int counterForUrl = 0;
|
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);
|
var variableValue = GetPlaceholderVariableValue(upstreamUrlPath, counterForUrl);
|
||||||
|
|
||||||
@ -27,7 +32,7 @@ namespace Ocelot.Library.Infrastructure.UrlMatcher
|
|||||||
|
|
||||||
templateKeysAndValues.Add(templateVariableNameAndValue);
|
templateKeysAndValues.Add(templateVariableNameAndValue);
|
||||||
|
|
||||||
counterForTemplate = GetNextCounterPosition(upstreamUrlTemplate, counterForTemplate, '}');
|
counterForTemplate = GetNextCounterPosition(upstreamUrlPathTemplate, counterForTemplate, '}');
|
||||||
|
|
||||||
counterForUrl = GetNextCounterPosition(upstreamUrlPath, counterForUrl, '/');
|
counterForUrl = GetNextCounterPosition(upstreamUrlPath, counterForUrl, '/');
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ namespace Ocelot.Library.Middleware
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var request = _requestBuilder
|
var request = await _requestBuilder
|
||||||
.Build(context.Request.Method, downstreamUrl.Data, context.Request.Body,
|
.Build(context.Request.Method, downstreamUrl.Data, context.Request.Body,
|
||||||
context.Request.Headers, context.Request.Cookies, context.Request.QueryString.Value, context.Request.ContentType);
|
context.Request.Headers, context.Request.Cookies, context.Request.QueryString.Value, context.Request.ContentType);
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Ocelot.Library.Infrastructure.Repository;
|
using Ocelot.Library.Infrastructure.Repository;
|
||||||
@ -14,19 +15,16 @@ namespace Ocelot.Library.Middleware
|
|||||||
private readonly IHttpRequester _requester;
|
private readonly IHttpRequester _requester;
|
||||||
private readonly IHttpResponder _responder;
|
private readonly IHttpResponder _responder;
|
||||||
private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
|
private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
|
||||||
private readonly IRequestBuilder _requestBuilder;
|
|
||||||
|
|
||||||
public HttpRequesterMiddleware(RequestDelegate next,
|
public HttpRequesterMiddleware(RequestDelegate next,
|
||||||
IHttpRequester requester,
|
IHttpRequester requester,
|
||||||
IHttpResponder responder,
|
IHttpResponder responder,
|
||||||
IScopedRequestDataRepository scopedRequestDataRepository,
|
IScopedRequestDataRepository scopedRequestDataRepository)
|
||||||
IRequestBuilder requestBuilder)
|
|
||||||
{
|
{
|
||||||
_next = next;
|
_next = next;
|
||||||
_requester = requester;
|
_requester = requester;
|
||||||
_responder = responder;
|
_responder = responder;
|
||||||
_scopedRequestDataRepository = scopedRequestDataRepository;
|
_scopedRequestDataRepository = scopedRequestDataRepository;
|
||||||
_requestBuilder = requestBuilder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
@ -42,7 +40,7 @@ namespace Ocelot.Library.Middleware
|
|||||||
var response = await _requester
|
var response = await _requester
|
||||||
.GetResponse(request.Data);
|
.GetResponse(request.Data);
|
||||||
|
|
||||||
await _responder.CreateResponse(context, response);
|
_scopedRequestDataRepository.Add("Response", response.Data);
|
||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
}
|
}
|
||||||
|
34
src/Ocelot.Library/Middleware/HttpResponderMiddleware.cs
Normal file
34
src/Ocelot.Library/Middleware/HttpResponderMiddleware.cs
Normal file
@ -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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Terminating middleware that is responsible for returning a http response to the client
|
||||||
|
/// </summary>
|
||||||
|
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<HttpResponseMessage>("Response");
|
||||||
|
|
||||||
|
await _responder.CreateResponse(context, response.Data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<HttpResponderMiddleware>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,5 @@
|
|||||||
using System;
|
using System.IO;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
|
|
||||||
namespace Ocelot
|
namespace Ocelot
|
||||||
{
|
{
|
||||||
|
@ -44,7 +44,7 @@ namespace Ocelot
|
|||||||
services.AddSingleton<IDownstreamRouteFinder, DownstreamRouteFinder>();
|
services.AddSingleton<IDownstreamRouteFinder, DownstreamRouteFinder>();
|
||||||
services.AddSingleton<IHttpRequester, HttpClientHttpRequester>();
|
services.AddSingleton<IHttpRequester, HttpClientHttpRequester>();
|
||||||
services.AddSingleton<IHttpResponder, HttpContextResponder>();
|
services.AddSingleton<IHttpResponder, HttpContextResponder>();
|
||||||
services.AddSingleton<IRequestBuilder, RequestBuilder>();
|
services.AddSingleton<IRequestBuilder, HttpRequestBuilder>();
|
||||||
|
|
||||||
// see this for why we register this as singleton http://stackoverflow.com/questions/37371264/invalidoperationexception-unable-to-resolve-service-for-type-microsoft-aspnetc
|
// 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<IHttpContextAccessor, HttpContextAccessor>();
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
@ -65,6 +65,8 @@ namespace Ocelot
|
|||||||
app.UseHttpRequestBuilderMiddleware();
|
app.UseHttpRequestBuilderMiddleware();
|
||||||
|
|
||||||
app.UseHttpRequesterMiddleware();
|
app.UseHttpRequesterMiddleware();
|
||||||
|
|
||||||
|
app.UseHttpResponderMiddleware();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
ReRoutes:
|
ReRoutes:
|
||||||
- DownstreamTemplate: http://www.bbc.co.uk
|
- DownstreamTemplate: http://www.mattsite.dev/
|
||||||
UpstreamTemplate: /
|
UpstreamTemplate: /
|
||||||
UpstreamHttpMethod: Get
|
UpstreamHttpMethod: Get
|
||||||
|
@ -27,7 +27,7 @@ namespace Ocelot.UnitTests.RequestBuilder
|
|||||||
public RequestBuilderTests()
|
public RequestBuilderTests()
|
||||||
{
|
{
|
||||||
_content = new StringContent(string.Empty);
|
_content = new StringContent(string.Empty);
|
||||||
_requestBuilder = new Library.Infrastructure.RequestBuilder.RequestBuilder();
|
_requestBuilder = new Library.Infrastructure.RequestBuilder.HttpRequestBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -70,7 +70,6 @@ namespace Ocelot.UnitTests.RequestBuilder
|
|||||||
.And(x => x.GivenIHaveTheHttpContent(new StringContent("Hi from Tom")))
|
.And(x => x.GivenIHaveTheHttpContent(new StringContent("Hi from Tom")))
|
||||||
.And(x => x.GivenTheContentTypeIs("application/json"))
|
.And(x => x.GivenTheContentTypeIs("application/json"))
|
||||||
.When(x => x.WhenICreateARequest())
|
.When(x => x.WhenICreateARequest())
|
||||||
.And(x => x.ThenTheCorrectContentIsUsed(new StringContent("Hi from Tom")))
|
|
||||||
.And(x => x.ThenTheCorrectContentHeadersAreUsed(new HeaderDictionary
|
.And(x => x.ThenTheCorrectContentHeadersAreUsed(new HeaderDictionary
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@ -202,7 +201,7 @@ namespace Ocelot.UnitTests.RequestBuilder
|
|||||||
private void WhenICreateARequest()
|
private void WhenICreateARequest()
|
||||||
{
|
{
|
||||||
_result = _requestBuilder.Build(_httpMethod, _downstreamUrl, _content?.ReadAsStreamAsync().Result, _headers,
|
_result = _requestBuilder.Build(_httpMethod, _downstreamUrl, _content?.ReadAsStreamAsync().Result, _headers,
|
||||||
_cookies, _query, _contentType);
|
_cookies, _query, _contentType).Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,11 +18,21 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
_urlMatcher = new UrlPathToUrlTemplateMatcher();
|
_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]
|
[Fact]
|
||||||
public void can_match_down_stream_url()
|
public void can_match_down_stream_url()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveADownstreamPath(""))
|
this.Given(x => x.GivenIHaveAUpstreamPath(""))
|
||||||
.And(x => x.GivenIHaveAnDownstreamUrlTemplate(""))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplate(""))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.And(x => x.ThenTheResultIsTrue())
|
.And(x => x.ThenTheResultIsTrue())
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
||||||
@ -33,8 +43,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void can_match_down_stream_url_with_no_slash()
|
public void can_match_down_stream_url_with_no_slash()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveADownstreamPath("api"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api"))
|
||||||
.Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api"))
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
||||||
@ -45,8 +55,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void can_match_down_stream_url_with_one_slash()
|
public void can_match_down_stream_url_with_one_slash()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveADownstreamPath("api/"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/"))
|
||||||
.Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/"))
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
||||||
@ -57,8 +67,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void can_match_down_stream_url_with_downstream_template()
|
public void can_match_down_stream_url_with_downstream_template()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/"))
|
||||||
.Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/"))
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
|
||||||
@ -66,35 +76,6 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
.BDDfy();
|
.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<TemplateVariableNameAndValue>()))
|
|
||||||
.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<TemplateVariableNameAndValue>
|
|
||||||
{
|
|
||||||
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]
|
[Fact]
|
||||||
public void can_match_down_stream_url_with_downstream_template_with_one_place_holder()
|
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")
|
new TemplateVariableNameAndValue("{productId}", "1")
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1"))
|
||||||
.Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}"))
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
||||||
@ -121,8 +102,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
new TemplateVariableNameAndValue("{categoryId}", "2")
|
new TemplateVariableNameAndValue("{categoryId}", "2")
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1/2"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2"))
|
||||||
.Given(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}/{categoryId}"))
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/{categoryId}"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
||||||
@ -139,8 +120,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
new TemplateVariableNameAndValue("{categoryId}", "2")
|
new TemplateVariableNameAndValue("{categoryId}", "2")
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1/categories/2"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2"))
|
||||||
.And(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}"))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
||||||
@ -158,8 +139,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
new TemplateVariableNameAndValue("{variantId}", "123")
|
new TemplateVariableNameAndValue("{variantId}", "123")
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1/categories/2/variant/123"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/123"))
|
||||||
.And(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}"))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/{variantId}"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
||||||
@ -176,8 +157,8 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
new TemplateVariableNameAndValue("{categoryId}", "2")
|
new TemplateVariableNameAndValue("{categoryId}", "2")
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenIHaveADownstreamPath("api/product/products/1/categories/2/variant/"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/"))
|
||||||
.And(x => x.GivenIHaveAnDownstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/"))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/{productId}/categories/{categoryId}/variant/"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
||||||
@ -199,12 +180,12 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
{
|
{
|
||||||
_result.DownstreamUrlTemplate.ShouldBe(expectedDownstreamUrlTemplate);
|
_result.DownstreamUrlTemplate.ShouldBe(expectedDownstreamUrlTemplate);
|
||||||
}
|
}
|
||||||
private void GivenIHaveADownstreamPath(string downstreamPath)
|
private void GivenIHaveAUpstreamPath(string downstreamPath)
|
||||||
{
|
{
|
||||||
_downstreamUrlPath = downstreamPath;
|
_downstreamUrlPath = downstreamPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenIHaveAnDownstreamUrlTemplate(string downstreamUrlTemplate)
|
private void GivenIHaveAnUpstreamUrlTemplate(string downstreamUrlTemplate)
|
||||||
{
|
{
|
||||||
_downstreamPathTemplate = downstreamUrlTemplate;
|
_downstreamPathTemplate = downstreamUrlTemplate;
|
||||||
}
|
}
|
||||||
@ -218,5 +199,10 @@ namespace Ocelot.UnitTests.UrlMatcher
|
|||||||
{
|
{
|
||||||
_result.Match.ShouldBeTrue();
|
_result.Match.ShouldBeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ThenTheResultIsFalse()
|
||||||
|
{
|
||||||
|
_result.Match.ShouldBeFalse();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user