mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 14:02:49 +08:00
check which version of .net framework before creating http handler (#412)
* #405 needto check which version of .net we are using but cannot use compiler directives * #405 started puttig abstraction around static method to get frameworks so we can test this logic * #405 added test for all methods and tidied up tests * #405 made contains as ms docs are wrong, thanks to davidni for the heads up
This commit is contained in:
parent
b5a827cf70
commit
e636cefdb1
@ -48,6 +48,7 @@ namespace Ocelot.DependencyInjection
|
||||
using ServiceDiscovery.Providers;
|
||||
using Steeltoe.Common.Discovery;
|
||||
using Pivotal.Discovery.Client;
|
||||
using Ocelot.Request.Creator;
|
||||
|
||||
public class OcelotBuilder : IOcelotBuilder
|
||||
{
|
||||
@ -161,6 +162,8 @@ namespace Ocelot.DependencyInjection
|
||||
_services.TryAddSingleton<IConsulClientFactory, ConsulClientFactory>();
|
||||
_services.TryAddSingleton<IResponseAggregatorFactory, InMemoryResponseAggregatorFactory>();
|
||||
_services.TryAddSingleton<IDefinedAggregatorProvider, ServiceLocatorDefinedAggregatorProvider>();
|
||||
_services.TryAddSingleton<IDownstreamRequestCreator, DownstreamRequestCreator>();
|
||||
_services.TryAddSingleton<IFrameworkDescription, FrameworkDescription>();
|
||||
}
|
||||
|
||||
public IOcelotAdministrationBuilder AddAdministration(string path, string secret)
|
||||
|
12
src/Ocelot/Infrastructure/FrameworkDescription.cs
Normal file
12
src/Ocelot/Infrastructure/FrameworkDescription.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ocelot.Infrastructure
|
||||
{
|
||||
public class FrameworkDescription : IFrameworkDescription
|
||||
{
|
||||
public string Get()
|
||||
{
|
||||
return RuntimeInformation.FrameworkDescription;
|
||||
}
|
||||
}
|
||||
}
|
7
src/Ocelot/Infrastructure/IFrameworkDescription.cs
Normal file
7
src/Ocelot/Infrastructure/IFrameworkDescription.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Ocelot.Infrastructure
|
||||
{
|
||||
public interface IFrameworkDescription
|
||||
{
|
||||
string Get();
|
||||
}
|
||||
}
|
42
src/Ocelot/Request/Creator/DownstreamRequestCreator.cs
Normal file
42
src/Ocelot/Request/Creator/DownstreamRequestCreator.cs
Normal file
@ -0,0 +1,42 @@
|
||||
namespace Ocelot.Request.Creator
|
||||
{
|
||||
using System.Net.Http;
|
||||
using Ocelot.Request.Middleware;
|
||||
using System.Runtime.InteropServices;
|
||||
using Ocelot.Infrastructure;
|
||||
|
||||
public class DownstreamRequestCreator : IDownstreamRequestCreator
|
||||
{
|
||||
private readonly IFrameworkDescription _framework;
|
||||
private const string dotNetFramework = ".NET Framework";
|
||||
|
||||
public DownstreamRequestCreator(IFrameworkDescription framework)
|
||||
{
|
||||
_framework = framework;
|
||||
}
|
||||
|
||||
public DownstreamRequest Create(HttpRequestMessage request)
|
||||
{
|
||||
/**
|
||||
* According to https://tools.ietf.org/html/rfc7231
|
||||
* GET,HEAD,DELETE,CONNECT,TRACE
|
||||
* Can have body but server can reject the request.
|
||||
* And MS HttpClient in Full Framework actually rejects it.
|
||||
* see #366 issue
|
||||
**/
|
||||
|
||||
if(_framework.Get().Contains(dotNetFramework))
|
||||
{
|
||||
if (request.Method == HttpMethod.Get ||
|
||||
request.Method == HttpMethod.Head ||
|
||||
request.Method == HttpMethod.Delete ||
|
||||
request.Method == HttpMethod.Trace)
|
||||
{
|
||||
request.Content = null;
|
||||
}
|
||||
}
|
||||
|
||||
return new DownstreamRequest(request);
|
||||
}
|
||||
}
|
||||
}
|
10
src/Ocelot/Request/Creator/IDownstreamRequestCreator.cs
Normal file
10
src/Ocelot/Request/Creator/IDownstreamRequestCreator.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace Ocelot.Request.Creator
|
||||
{
|
||||
using System.Net.Http;
|
||||
using Ocelot.Request.Middleware;
|
||||
|
||||
public interface IDownstreamRequestCreator
|
||||
{
|
||||
DownstreamRequest Create(HttpRequestMessage request);
|
||||
}
|
||||
}
|
@ -48,22 +48,6 @@ namespace Ocelot.Request.Middleware
|
||||
Scheme = Scheme
|
||||
};
|
||||
|
||||
/**
|
||||
* According to https://tools.ietf.org/html/rfc7231
|
||||
* GET,HEAD,DELETE,CONNECT,TRACE
|
||||
* Can have body but server can reject the request.
|
||||
* And MS HttpClient in Full Framework actually rejects it.
|
||||
* see #366 issue
|
||||
**/
|
||||
#if NET461 || NET462 || NET47 || NET471 || NET472
|
||||
if (_request.Method == HttpMethod.Get ||
|
||||
_request.Method == HttpMethod.Head ||
|
||||
_request.Method == HttpMethod.Delete ||
|
||||
_request.Method == HttpMethod.Trace)
|
||||
{
|
||||
_request.Content = null;
|
||||
}
|
||||
#endif
|
||||
_request.RequestUri = uriBuilder.Uri;
|
||||
return _request;
|
||||
}
|
||||
|
@ -1,25 +1,28 @@
|
||||
namespace Ocelot.Request.Middleware
|
||||
{
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Creator;
|
||||
|
||||
public class DownstreamRequestInitialiserMiddleware : OcelotMiddleware
|
||||
{
|
||||
private readonly OcelotRequestDelegate _next;
|
||||
private readonly Mapper.IRequestMapper _requestMapper;
|
||||
private readonly IDownstreamRequestCreator _creator;
|
||||
|
||||
public DownstreamRequestInitialiserMiddleware(OcelotRequestDelegate next,
|
||||
IOcelotLoggerFactory loggerFactory,
|
||||
Mapper.IRequestMapper requestMapper)
|
||||
Mapper.IRequestMapper requestMapper,
|
||||
IDownstreamRequestCreator creator)
|
||||
:base(loggerFactory.CreateLogger<DownstreamRequestInitialiserMiddleware>())
|
||||
{
|
||||
_next = next;
|
||||
_requestMapper = requestMapper;
|
||||
_creator = creator;
|
||||
}
|
||||
|
||||
public async Task Invoke(DownstreamContext context)
|
||||
@ -31,7 +34,7 @@ namespace Ocelot.Request.Middleware
|
||||
return;
|
||||
}
|
||||
|
||||
context.DownstreamRequest = new DownstreamRequest(downstreamRequest.Data);
|
||||
context.DownstreamRequest = _creator.Create(downstreamRequest.Data);
|
||||
|
||||
await _next.Invoke(context);
|
||||
}
|
||||
|
@ -114,7 +114,8 @@
|
||||
"HttpHandlerOptions": {
|
||||
"AllowAutoRedirect": true,
|
||||
"UseCookieContainer": true,
|
||||
"UseTracing": true
|
||||
"UseTracing": true,
|
||||
"UseProxy": true
|
||||
},
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
|
@ -28,6 +28,15 @@
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="idsrv3test.pfx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.3" />
|
||||
|
@ -0,0 +1,93 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using Ocelot.Infrastructure;
|
||||
using Ocelot.Request.Creator;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Request.Creator
|
||||
{
|
||||
public class DownstreamRequestCreatorTests
|
||||
{
|
||||
private Mock<IFrameworkDescription> _framework;
|
||||
private DownstreamRequestCreator _downstreamRequestCreator;
|
||||
private HttpRequestMessage _request;
|
||||
private DownstreamRequest _result;
|
||||
|
||||
public DownstreamRequestCreatorTests()
|
||||
{
|
||||
_framework = new Mock<IFrameworkDescription>();
|
||||
_downstreamRequestCreator = new DownstreamRequestCreator(_framework.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_downstream_request()
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "http://www.test.com");
|
||||
var content = new StringContent("test");
|
||||
request.Content = content;
|
||||
|
||||
this.Given(_ => GivenTheFrameworkIs(""))
|
||||
.And(_ => GivenTheRequestIs(request))
|
||||
.When(_ => WhenICreate())
|
||||
.Then(_ => ThenTheDownstreamRequestHasABody())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_remove_body_for_http_methods()
|
||||
{
|
||||
var methods = new List<HttpMethod> { HttpMethod.Get, HttpMethod.Head, HttpMethod.Delete, HttpMethod.Trace };
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "http://www.test.com");
|
||||
var content = new StringContent("test");
|
||||
request.Content = content;
|
||||
|
||||
methods.ForEach(m => {
|
||||
this.Given(_ => GivenTheFrameworkIs(".NET Framework"))
|
||||
.And(_ => GivenTheRequestIs(request))
|
||||
.When(_ => WhenICreate())
|
||||
.Then(_ => ThenTheDownstreamRequestDoesNotHaveABody())
|
||||
.BDDfy();
|
||||
});
|
||||
}
|
||||
|
||||
private void GivenTheFrameworkIs(string framework)
|
||||
{
|
||||
_framework.Setup(x => x.Get()).Returns(framework);
|
||||
}
|
||||
|
||||
private void GivenTheRequestIs(HttpRequestMessage request)
|
||||
{
|
||||
_request = request;
|
||||
}
|
||||
|
||||
private void WhenICreate()
|
||||
{
|
||||
_result = _downstreamRequestCreator.Create(_request);
|
||||
}
|
||||
|
||||
private async Task ThenTheDownstreamRequestHasABody()
|
||||
{
|
||||
_result.ShouldNotBeNull();
|
||||
_result.Method.ToLower().ShouldBe("get");
|
||||
_result.Scheme.ToLower().ShouldBe("http");
|
||||
_result.Host.ToLower().ShouldBe("www.test.com");
|
||||
var resultContent = await _result.ToHttpRequestMessage().Content.ReadAsStringAsync();
|
||||
resultContent.ShouldBe("test");
|
||||
}
|
||||
|
||||
private void ThenTheDownstreamRequestDoesNotHaveABody()
|
||||
{
|
||||
_result.ShouldNotBeNull();
|
||||
_result.Method.ToLower().ShouldBe("get");
|
||||
_result.Scheme.ToLower().ShouldBe("http");
|
||||
_result.Host.ToLower().ShouldBe("www.test.com");
|
||||
_result.ToHttpRequestMessage().Content.ShouldBeNull();
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,8 @@ namespace Ocelot.UnitTests.Request
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Shouldly;
|
||||
using Ocelot.Request.Creator;
|
||||
using Ocelot.Infrastructure;
|
||||
|
||||
public class DownstreamRequestInitialiserMiddlewareTests
|
||||
{
|
||||
@ -50,7 +52,8 @@ namespace Ocelot.UnitTests.Request
|
||||
_middleware = new DownstreamRequestInitialiserMiddleware(
|
||||
_next.Object,
|
||||
_loggerFactory.Object,
|
||||
_requestMapper.Object);
|
||||
_requestMapper.Object,
|
||||
new DownstreamRequestCreator(new FrameworkDescription()));
|
||||
|
||||
_downstreamContext = new DownstreamContext(_httpContext.Object);
|
||||
}
|
||||
|
BIN
test/Ocelot.UnitTests/idsrv3test.pfx
Normal file
BIN
test/Ocelot.UnitTests/idsrv3test.pfx
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user