mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-26 14:32:51 +08:00

* feat: update to asp.net core 3.0 preview 9 * fix : AspDotNetLogger unittest * feat: update generic host and useMvc 1、Using 'UseMvc' to configure MVC is not supported while using Endpoint Routing https://github.com/aspnet/AspNetCore/issues/9542 2、 use IHost and IHostBuilder * feat : update .net core 3.0 rc1 * eureka extension * fixed logger formatter error * fixed synchronous operations are disallowed of ReadToEnd method * fix log tests * Flush method of FakeStream should do nothing * Update ContentTests.cs * Fixed ws tests * feat: delelte comment code * feat: update .net core 3.0 RTM * Update OcelotBuilderTests.cs * Update .travis.yml mono 6.0.0 and dotnet 3.0.100 * Update Ocelot.IntegrationTests.csproj update Microsoft.Data.SQLite 3.0.0 * Update .travis.yml * feat: remove FrameworkReference 1、 remove FrameworkReference 2、 update package * add appveyor configuration to use version of VS2019 with dotnet core 3 sdk support * update obsoleted SetCollectionValidator method * Swap out OpenCover for Coverlet * Bump Cake to 0.35.0 * Downgrade coveralls.net to 0.7.0 Fix disposing of PollConsul instance * Remove environment specific path separator * Do not return ReportGenerator on Mac/Linux * Remove direct dependency on IInternalConfiguration * Fix ordering of variable assignment * Fix broken tests * Fix acceptance tests for Consul
442 lines
17 KiB
C#
442 lines
17 KiB
C#
namespace Ocelot.UnitTests.Request.Mapper
|
|
{
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.Primitives;
|
|
using Ocelot.Request.Mapper;
|
|
using Ocelot.Responses;
|
|
using Shouldly;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net.Http;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using TestStack.BDDfy;
|
|
using Xunit;
|
|
|
|
public class RequestMapperTests
|
|
{
|
|
private readonly HttpContext _httpContext;
|
|
private readonly HttpRequest _inputRequest;
|
|
|
|
private readonly RequestMapper _requestMapper;
|
|
|
|
private Response<HttpRequestMessage> _mappedRequest;
|
|
|
|
private List<KeyValuePair<string, StringValues>> _inputHeaders = null;
|
|
|
|
public RequestMapperTests()
|
|
{
|
|
_httpContext = new DefaultHttpContext();
|
|
_inputRequest = _httpContext.Request;
|
|
_requestMapper = new RequestMapper();
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("https", "my.url:123", "/abc/DEF", "?a=1&b=2", "https://my.url:123/abc/DEF?a=1&b=2")]
|
|
[InlineData("http", "blah.com", "/d ef", "?abc=123", "http://blah.com/d%20ef?abc=123")] // note! the input is encoded when building the input request
|
|
[InlineData("http", "myusername:mypassword@abc.co.uk", null, null, "http://myusername:mypassword@abc.co.uk/")]
|
|
[InlineData("http", "點看.com", null, null, "http://xn--c1yn36f.com/")]
|
|
[InlineData("http", "xn--c1yn36f.com", null, null, "http://xn--c1yn36f.com/")]
|
|
public void Should_map_valid_request_uri(string scheme, string host, string path, string queryString, string expectedUri)
|
|
{
|
|
this.Given(_ => GivenTheInputRequestHasMethod("GET"))
|
|
.And(_ => GivenTheInputRequestHasScheme(scheme))
|
|
.And(_ => GivenTheInputRequestHasHost(host))
|
|
.And(_ => GivenTheInputRequestHasPath(path))
|
|
.And(_ => GivenTheInputRequestHasQueryString(queryString))
|
|
.When(_ => WhenMapped())
|
|
.Then(_ => ThenNoErrorIsReturned())
|
|
.And(_ => ThenTheMappedRequestHasUri(expectedUri))
|
|
.BDDfy();
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("ftp", "google.com", "/abc/DEF", "?a=1&b=2")]
|
|
public void Should_error_on_unsupported_request_uri(string scheme, string host, string path, string queryString)
|
|
{
|
|
this.Given(_ => GivenTheInputRequestHasMethod("GET"))
|
|
.And(_ => GivenTheInputRequestHasScheme(scheme))
|
|
.And(_ => GivenTheInputRequestHasHost(host))
|
|
.And(_ => GivenTheInputRequestHasPath(path))
|
|
.And(_ => GivenTheInputRequestHasQueryString(queryString))
|
|
.When(_ => WhenMapped())
|
|
.Then(_ => ThenAnErrorIsReturned())
|
|
.And(_ => ThenTheMappedRequestIsNull())
|
|
.BDDfy();
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("GET")]
|
|
[InlineData("POST")]
|
|
[InlineData("WHATEVER")]
|
|
public void Should_map_method(string method)
|
|
{
|
|
this.Given(_ => GivenTheInputRequestHasMethod(method))
|
|
.And(_ => GivenTheInputRequestHasAValidUri())
|
|
.When(_ => WhenMapped())
|
|
.Then(_ => ThenNoErrorIsReturned())
|
|
.And(_ => ThenTheMappedRequestHasMethod(method))
|
|
.BDDfy();
|
|
}
|
|
|
|
[Fact]
|
|
public void Should_map_all_headers()
|
|
{
|
|
this.Given(_ => GivenTheInputRequestHasHeaders())
|
|
.And(_ => GivenTheInputRequestHasMethod("GET"))
|
|
.And(_ => GivenTheInputRequestHasAValidUri())
|
|
.When(_ => WhenMapped())
|
|
.Then(_ => ThenNoErrorIsReturned())
|
|
.And(_ => ThenTheMappedRequestHasEachHeader())
|
|
.BDDfy();
|
|
}
|
|
|
|
[Fact]
|
|
public void Should_handle_no_headers()
|
|
{
|
|
this.Given(_ => GivenTheInputRequestHasNoHeaders())
|
|
.And(_ => GivenTheInputRequestHasMethod("GET"))
|
|
.And(_ => GivenTheInputRequestHasAValidUri())
|
|
.When(_ => WhenMapped())
|
|
.Then(_ => ThenNoErrorIsReturned())
|
|
.And(_ => ThenTheMappedRequestHasNoHeaders())
|
|
.BDDfy();
|
|
}
|
|
|
|
[Fact]
|
|
public void Should_map_content()
|
|
{
|
|
this.Given(_ => GivenTheInputRequestHasContent("This is my content"))
|
|
.And(_ => GivenTheInputRequestHasMethod("GET"))
|
|
.And(_ => GivenTheInputRequestHasAValidUri())
|
|
.When(_ => WhenMapped())
|
|
.Then(_ => ThenNoErrorIsReturned())
|
|
.And(_ => ThenTheMappedRequestHasContent("This is my content"))
|
|
.BDDfy();
|
|
}
|
|
|
|
[Fact]
|
|
public void Should_handle_no_content()
|
|
{
|
|
this.Given(_ => GivenTheInputRequestHasNullContent())
|
|
.And(_ => GivenTheInputRequestHasMethod("GET"))
|
|
.And(_ => GivenTheInputRequestHasAValidUri())
|
|
.When(_ => WhenMapped())
|
|
.Then(_ => ThenNoErrorIsReturned())
|
|
.And(_ => ThenTheMappedRequestHasNoContent())
|
|
.BDDfy();
|
|
}
|
|
|
|
[Fact]
|
|
public void Should_handle_no_content_type()
|
|
{
|
|
this.Given(_ => GivenTheInputRequestHasNoContentType())
|
|
.And(_ => GivenTheInputRequestHasMethod("GET"))
|
|
.And(_ => GivenTheInputRequestHasAValidUri())
|
|
.When(_ => WhenMapped())
|
|
.Then(_ => ThenNoErrorIsReturned())
|
|
.And(_ => ThenTheMappedRequestHasNoContent())
|
|
.BDDfy();
|
|
}
|
|
|
|
[Fact]
|
|
public void Should_handle_no_content_length()
|
|
{
|
|
this.Given(_ => GivenTheInputRequestHasNoContentLength())
|
|
.And(_ => GivenTheInputRequestHasMethod("GET"))
|
|
.And(_ => GivenTheInputRequestHasAValidUri())
|
|
.When(_ => WhenMapped())
|
|
.Then(_ => ThenNoErrorIsReturned())
|
|
.And(_ => ThenTheMappedRequestHasNoContent())
|
|
.BDDfy();
|
|
}
|
|
|
|
private void GivenTheInputRequestHasNoContentLength()
|
|
{
|
|
_inputRequest.ContentLength = null;
|
|
}
|
|
|
|
private void GivenTheInputRequestHasNoContentType()
|
|
{
|
|
_inputRequest.ContentType = null;
|
|
}
|
|
|
|
[Fact]
|
|
public void Should_map_content_headers()
|
|
{
|
|
byte[] md5bytes = new byte[0];
|
|
using (var md5 = MD5.Create())
|
|
{
|
|
md5bytes = md5.ComputeHash(Encoding.UTF8.GetBytes("some md5"));
|
|
}
|
|
|
|
this.Given(_ => GivenTheInputRequestHasContent("This is my content"))
|
|
.And(_ => GivenTheContentTypeIs("application/json"))
|
|
.And(_ => GivenTheContentEncodingIs("gzip, compress"))
|
|
.And(_ => GivenTheContentLanguageIs("english"))
|
|
.And(_ => GivenTheContentLocationIs("/my-receipts/38"))
|
|
.And(_ => GivenTheContentRangeIs("bytes 1-2/*"))
|
|
.And(_ => GivenTheContentDispositionIs("inline"))
|
|
.And(_ => GivenTheContentMD5Is(md5bytes))
|
|
.And(_ => GivenTheInputRequestHasMethod("GET"))
|
|
.And(_ => GivenTheInputRequestHasAValidUri())
|
|
.When(_ => WhenMapped())
|
|
.Then(_ => ThenNoErrorIsReturned())
|
|
.And(_ => ThenTheMappedRequestHasContentTypeHeader("application/json"))
|
|
.And(_ => ThenTheMappedRequestHasContentEncodingHeader("gzip", "compress"))
|
|
.And(_ => ThenTheMappedRequestHasContentLanguageHeader("english"))
|
|
.And(_ => ThenTheMappedRequestHasContentLocationHeader("/my-receipts/38"))
|
|
.And(_ => ThenTheMappedRequestHasContentMD5Header(md5bytes))
|
|
.And(_ => ThenTheMappedRequestHasContentRangeHeader())
|
|
.And(_ => ThenTheMappedRequestHasContentDispositionHeader("inline"))
|
|
.And(_ => ThenTheMappedRequestHasContentSize("This is my content".Length))
|
|
.And(_ => ThenTheContentHeadersAreNotAddedToNonContentHeaders())
|
|
.BDDfy();
|
|
}
|
|
|
|
[Fact]
|
|
public void should_not_add_content_headers()
|
|
{
|
|
this.Given(_ => GivenTheInputRequestHasContent("This is my content"))
|
|
.And(_ => GivenTheContentTypeIs("application/json"))
|
|
.And(_ => GivenTheInputRequestHasMethod("POST"))
|
|
.And(_ => GivenTheInputRequestHasAValidUri())
|
|
.When(_ => WhenMapped())
|
|
.Then(_ => ThenNoErrorIsReturned())
|
|
.And(_ => ThenTheMappedRequestHasContentTypeHeader("application/json"))
|
|
.And(_ => ThenTheMappedRequestHasContentSize("This is my content".Length))
|
|
.And(_ => ThenTheOtherContentTypeHeadersAreNotMapped())
|
|
.BDDfy();
|
|
}
|
|
|
|
private void ThenTheContentHeadersAreNotAddedToNonContentHeaders()
|
|
{
|
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-Disposition");
|
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-ContentMD5");
|
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-ContentRange");
|
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-ContentLanguage");
|
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-ContentEncoding");
|
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-ContentLocation");
|
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-Length");
|
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-Type");
|
|
}
|
|
|
|
private void ThenTheOtherContentTypeHeadersAreNotMapped()
|
|
{
|
|
_mappedRequest.Data.Content.Headers.ContentDisposition.ShouldBeNull();
|
|
_mappedRequest.Data.Content.Headers.ContentMD5.ShouldBeNull();
|
|
_mappedRequest.Data.Content.Headers.ContentRange.ShouldBeNull();
|
|
_mappedRequest.Data.Content.Headers.ContentLanguage.ShouldBeEmpty();
|
|
_mappedRequest.Data.Content.Headers.ContentEncoding.ShouldBeEmpty();
|
|
_mappedRequest.Data.Content.Headers.ContentLocation.ShouldBeNull();
|
|
}
|
|
|
|
private void ThenTheMappedRequestHasContentDispositionHeader(string expected)
|
|
{
|
|
_mappedRequest.Data.Content.Headers.ContentDisposition.DispositionType.ShouldBe(expected);
|
|
}
|
|
|
|
private void GivenTheContentDispositionIs(string input)
|
|
{
|
|
_inputRequest.Headers.Add("Content-Disposition", input);
|
|
}
|
|
|
|
private void ThenTheMappedRequestHasContentMD5Header(byte[] expected)
|
|
{
|
|
_mappedRequest.Data.Content.Headers.ContentMD5.ShouldBe(expected);
|
|
}
|
|
|
|
private void GivenTheContentMD5Is(byte[] input)
|
|
{
|
|
var base64 = Convert.ToBase64String(input);
|
|
_inputRequest.Headers.Add("Content-MD5", base64);
|
|
}
|
|
|
|
private void ThenTheMappedRequestHasContentRangeHeader()
|
|
{
|
|
_mappedRequest.Data.Content.Headers.ContentRange.From.ShouldBe(1);
|
|
_mappedRequest.Data.Content.Headers.ContentRange.To.ShouldBe(2);
|
|
}
|
|
|
|
private void GivenTheContentRangeIs(string input)
|
|
{
|
|
_inputRequest.Headers.Add("Content-Range", input);
|
|
}
|
|
|
|
private void ThenTheMappedRequestHasContentLocationHeader(string expected)
|
|
{
|
|
_mappedRequest.Data.Content.Headers.ContentLocation.OriginalString.ShouldBe(expected);
|
|
}
|
|
|
|
private void GivenTheContentLocationIs(string input)
|
|
{
|
|
_inputRequest.Headers.Add("Content-Location", input);
|
|
}
|
|
|
|
private void ThenTheMappedRequestHasContentLanguageHeader(string expected)
|
|
{
|
|
_mappedRequest.Data.Content.Headers.ContentLanguage.First().ShouldBe(expected);
|
|
}
|
|
|
|
private void GivenTheContentLanguageIs(string input)
|
|
{
|
|
_inputRequest.Headers.Add("Content-Language", input);
|
|
}
|
|
|
|
private void ThenTheMappedRequestHasContentEncodingHeader(string expected, string expectedTwo)
|
|
{
|
|
_mappedRequest.Data.Content.Headers.ContentEncoding.ToArray()[0].ShouldBe(expected);
|
|
_mappedRequest.Data.Content.Headers.ContentEncoding.ToArray()[1].ShouldBe(expectedTwo);
|
|
}
|
|
|
|
private void GivenTheContentEncodingIs(string input)
|
|
{
|
|
_inputRequest.Headers.Add("Content-Encoding", input);
|
|
}
|
|
|
|
private void GivenTheContentTypeIs(string contentType)
|
|
{
|
|
_inputRequest.ContentType = contentType;
|
|
}
|
|
|
|
private void ThenTheMappedRequestHasContentTypeHeader(string expected)
|
|
{
|
|
_mappedRequest.Data.Content.Headers.ContentType.MediaType.ShouldBe(expected);
|
|
}
|
|
|
|
private void ThenTheMappedRequestHasContentSize(long expected)
|
|
{
|
|
_mappedRequest.Data.Content.Headers.ContentLength.ShouldBe(expected);
|
|
}
|
|
|
|
private void GivenTheInputRequestHasMethod(string method)
|
|
{
|
|
_inputRequest.Method = method;
|
|
}
|
|
|
|
private void GivenTheInputRequestHasScheme(string scheme)
|
|
{
|
|
_inputRequest.Scheme = scheme;
|
|
}
|
|
|
|
private void GivenTheInputRequestHasHost(string host)
|
|
{
|
|
_inputRequest.Host = new HostString(host);
|
|
}
|
|
|
|
private void GivenTheInputRequestHasPath(string path)
|
|
{
|
|
if (path != null)
|
|
{
|
|
_inputRequest.Path = path;
|
|
}
|
|
}
|
|
|
|
private void GivenTheInputRequestHasQueryString(string querystring)
|
|
{
|
|
if (querystring != null)
|
|
{
|
|
_inputRequest.QueryString = new QueryString(querystring);
|
|
}
|
|
}
|
|
|
|
private void GivenTheInputRequestHasAValidUri()
|
|
{
|
|
GivenTheInputRequestHasScheme("http");
|
|
GivenTheInputRequestHasHost("www.google.com");
|
|
}
|
|
|
|
private void GivenTheInputRequestHasHeaders()
|
|
{
|
|
_inputHeaders = new List<KeyValuePair<string, StringValues>>()
|
|
{
|
|
new KeyValuePair<string, StringValues>("abc", new StringValues(new string[]{"123","456" })),
|
|
new KeyValuePair<string, StringValues>("def", new StringValues(new string[]{"789","012" })),
|
|
};
|
|
|
|
foreach (var inputHeader in _inputHeaders)
|
|
{
|
|
_inputRequest.Headers.Add(inputHeader);
|
|
}
|
|
}
|
|
|
|
private void GivenTheInputRequestHasNoHeaders()
|
|
{
|
|
_inputRequest.Headers.Clear();
|
|
}
|
|
|
|
private void GivenTheInputRequestHasContent(string content)
|
|
{
|
|
_inputRequest.Body = new MemoryStream(Encoding.UTF8.GetBytes(content));
|
|
}
|
|
|
|
private void GivenTheInputRequestHasNullContent()
|
|
{
|
|
_inputRequest.Body = null;
|
|
}
|
|
|
|
private async Task WhenMapped()
|
|
{
|
|
_mappedRequest = await _requestMapper.Map(_inputRequest);
|
|
}
|
|
|
|
private void ThenNoErrorIsReturned()
|
|
{
|
|
_mappedRequest.IsError.ShouldBeFalse();
|
|
}
|
|
|
|
private void ThenAnErrorIsReturned()
|
|
{
|
|
_mappedRequest.IsError.ShouldBeTrue();
|
|
}
|
|
|
|
private void ThenTheMappedRequestHasUri(string expectedUri)
|
|
{
|
|
_mappedRequest.Data.RequestUri.OriginalString.ShouldBe(expectedUri);
|
|
}
|
|
|
|
private void ThenTheMappedRequestHasMethod(string expectedMethod)
|
|
{
|
|
_mappedRequest.Data.Method.ToString().ShouldBe(expectedMethod);
|
|
}
|
|
|
|
private void ThenTheMappedRequestHasEachHeader()
|
|
{
|
|
_mappedRequest.Data.Headers.Count().ShouldBe(_inputHeaders.Count);
|
|
foreach (var header in _mappedRequest.Data.Headers)
|
|
{
|
|
var inputHeader = _inputHeaders.First(h => h.Key == header.Key);
|
|
inputHeader.ShouldNotBeNull();
|
|
inputHeader.Value.Count().ShouldBe(header.Value.Count());
|
|
foreach (var inputHeaderValue in inputHeader.Value)
|
|
{
|
|
header.Value.Any(v => v == inputHeaderValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ThenTheMappedRequestHasNoHeaders()
|
|
{
|
|
_mappedRequest.Data.Headers.Count().ShouldBe(0);
|
|
}
|
|
|
|
private void ThenTheMappedRequestHasContent(string expectedContent)
|
|
{
|
|
_mappedRequest.Data.Content.ReadAsStringAsync().GetAwaiter().GetResult().ShouldBe(expectedContent);
|
|
}
|
|
|
|
private void ThenTheMappedRequestHasNoContent()
|
|
{
|
|
_mappedRequest.Data.Content.ShouldBeNull();
|
|
}
|
|
|
|
private void ThenTheMappedRequestIsNull()
|
|
{
|
|
_mappedRequest.Data.ShouldBeNull();
|
|
}
|
|
}
|
|
}
|