mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:22:50 +08:00
Merge branch 'pitming-feature/MethodTransformer'
This commit is contained in:
commit
689f04d011
@ -24,6 +24,7 @@ Here is an example ReRoute configuration, You don't need to set all of these thi
|
|||||||
"UpstreamHttpMethod": [
|
"UpstreamHttpMethod": [
|
||||||
"Get"
|
"Get"
|
||||||
],
|
],
|
||||||
|
"DownstreamHttpMethod": "",
|
||||||
"AddHeadersToRequest": {},
|
"AddHeadersToRequest": {},
|
||||||
"AddClaimsToRequest": {},
|
"AddClaimsToRequest": {},
|
||||||
"RouteClaimsRequirement": {},
|
"RouteClaimsRequirement": {},
|
||||||
|
28
docs/features/methodtransformation.rst
Normal file
28
docs/features/methodtransformation.rst
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
HTTP Method Transformation
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Ocelot allows the user to change the HTTP request method that will be used when making a request to a downstream service.
|
||||||
|
|
||||||
|
This achieved by setting the following ReRoute configuration:
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"DownstreamPathTemplate": "/{url}",
|
||||||
|
"UpstreamPathTemplate": "/{url}",
|
||||||
|
"UpstreamHttpMethod": [
|
||||||
|
"Get"
|
||||||
|
],
|
||||||
|
"DownstreamHttpMethod": "POST",
|
||||||
|
"DownstreamScheme": "http",
|
||||||
|
"DownstreamHostAndPorts": [
|
||||||
|
{
|
||||||
|
"Host": "localhost",
|
||||||
|
"Port": 53271
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
The key property here is DownstreamHttpMethod which is set as POST and the ReRoute will only match on GET as set by UpstreamHttpMethod.
|
||||||
|
|
||||||
|
This feature can be useful when interacting with downstream apis that only support POST and you want to present some kind of RESTful interface.
|
@ -1,6 +1,7 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
using Ocelot.DependencyInjection;
|
using Ocelot.DependencyInjection;
|
||||||
using Ocelot.Middleware;
|
using Ocelot.Middleware;
|
||||||
using Ocelot.Provider.Kubernetes;
|
using Ocelot.Provider.Kubernetes;
|
||||||
@ -18,7 +19,7 @@ namespace ApiGateway
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
{
|
{
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Hosting;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ namespace DownstreamService
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
{
|
{
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
|
@ -41,6 +41,7 @@ namespace Ocelot.Configuration.Builder
|
|||||||
private List<AddHeader> _addHeadersToUpstream;
|
private List<AddHeader> _addHeadersToUpstream;
|
||||||
private bool _dangerousAcceptAnyServerCertificateValidator;
|
private bool _dangerousAcceptAnyServerCertificateValidator;
|
||||||
private SecurityOptions _securityOptions;
|
private SecurityOptions _securityOptions;
|
||||||
|
private string _downstreamHttpMethod;
|
||||||
|
|
||||||
public DownstreamReRouteBuilder()
|
public DownstreamReRouteBuilder()
|
||||||
{
|
{
|
||||||
@ -56,6 +57,12 @@ namespace Ocelot.Configuration.Builder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DownstreamReRouteBuilder WithDownStreamHttpMethod(string method)
|
||||||
|
{
|
||||||
|
_downstreamHttpMethod = method;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public DownstreamReRouteBuilder WithLoadBalancerOptions(LoadBalancerOptions loadBalancerOptions)
|
public DownstreamReRouteBuilder WithLoadBalancerOptions(LoadBalancerOptions loadBalancerOptions)
|
||||||
{
|
{
|
||||||
_loadBalancerOptions = loadBalancerOptions;
|
_loadBalancerOptions = loadBalancerOptions;
|
||||||
@ -282,7 +289,8 @@ namespace Ocelot.Configuration.Builder
|
|||||||
_addHeadersToDownstream,
|
_addHeadersToDownstream,
|
||||||
_addHeadersToUpstream,
|
_addHeadersToUpstream,
|
||||||
_dangerousAcceptAnyServerCertificateValidator,
|
_dangerousAcceptAnyServerCertificateValidator,
|
||||||
_securityOptions);
|
_securityOptions,
|
||||||
|
_downstreamHttpMethod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,6 +138,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
.WithAddHeadersToUpstream(hAndRs.AddHeadersToUpstream)
|
.WithAddHeadersToUpstream(hAndRs.AddHeadersToUpstream)
|
||||||
.WithDangerousAcceptAnyServerCertificateValidator(fileReRoute.DangerousAcceptAnyServerCertificateValidator)
|
.WithDangerousAcceptAnyServerCertificateValidator(fileReRoute.DangerousAcceptAnyServerCertificateValidator)
|
||||||
.WithSecurityOptions(securityOptions)
|
.WithSecurityOptions(securityOptions)
|
||||||
|
.WithDownStreamHttpMethod(fileReRoute.DownstreamHttpMethod)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
return reRoute;
|
return reRoute;
|
||||||
|
@ -38,7 +38,8 @@ namespace Ocelot.Configuration
|
|||||||
List<AddHeader> addHeadersToDownstream,
|
List<AddHeader> addHeadersToDownstream,
|
||||||
List<AddHeader> addHeadersToUpstream,
|
List<AddHeader> addHeadersToUpstream,
|
||||||
bool dangerousAcceptAnyServerCertificateValidator,
|
bool dangerousAcceptAnyServerCertificateValidator,
|
||||||
SecurityOptions securityOptions)
|
SecurityOptions securityOptions,
|
||||||
|
string downstreamHttpMethod)
|
||||||
{
|
{
|
||||||
DangerousAcceptAnyServerCertificateValidator = dangerousAcceptAnyServerCertificateValidator;
|
DangerousAcceptAnyServerCertificateValidator = dangerousAcceptAnyServerCertificateValidator;
|
||||||
AddHeadersToDownstream = addHeadersToDownstream;
|
AddHeadersToDownstream = addHeadersToDownstream;
|
||||||
@ -72,6 +73,7 @@ namespace Ocelot.Configuration
|
|||||||
LoadBalancerKey = loadBalancerKey;
|
LoadBalancerKey = loadBalancerKey;
|
||||||
AddHeadersToUpstream = addHeadersToUpstream;
|
AddHeadersToUpstream = addHeadersToUpstream;
|
||||||
SecurityOptions = securityOptions;
|
SecurityOptions = securityOptions;
|
||||||
|
DownstreamHttpMethod = downstreamHttpMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Key { get; }
|
public string Key { get; }
|
||||||
@ -106,5 +108,6 @@ namespace Ocelot.Configuration
|
|||||||
public List<AddHeader> AddHeadersToUpstream { get; }
|
public List<AddHeader> AddHeadersToUpstream { get; }
|
||||||
public bool DangerousAcceptAnyServerCertificateValidator { get; }
|
public bool DangerousAcceptAnyServerCertificateValidator { get; }
|
||||||
public SecurityOptions SecurityOptions { get; }
|
public SecurityOptions SecurityOptions { get; }
|
||||||
|
public string DownstreamHttpMethod { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ namespace Ocelot.Configuration.File
|
|||||||
public string DownstreamPathTemplate { get; set; }
|
public string DownstreamPathTemplate { get; set; }
|
||||||
public string UpstreamPathTemplate { get; set; }
|
public string UpstreamPathTemplate { get; set; }
|
||||||
public List<string> UpstreamHttpMethod { get; set; }
|
public List<string> UpstreamHttpMethod { get; set; }
|
||||||
|
public string DownstreamHttpMethod { get; set; }
|
||||||
public Dictionary<string, string> AddHeadersToRequest { get; set; }
|
public Dictionary<string, string> AddHeadersToRequest { get; set; }
|
||||||
public Dictionary<string, string> UpstreamHeaderTransform { get; set; }
|
public Dictionary<string, string> UpstreamHeaderTransform { get; set; }
|
||||||
public Dictionary<string, string> DownstreamHeaderTransform { get; set; }
|
public Dictionary<string, string> DownstreamHeaderTransform { get; set; }
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
namespace Ocelot.Request.Mapper
|
namespace Ocelot.Request.Mapper
|
||||||
{
|
{
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Ocelot.Configuration;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
public interface IRequestMapper
|
public interface IRequestMapper
|
||||||
{
|
{
|
||||||
Task<Response<HttpRequestMessage>> Map(HttpRequest request);
|
Task<Response<HttpRequestMessage>> Map(HttpRequest request, DownstreamReRoute downstreamReRoute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Extensions;
|
using Microsoft.AspNetCore.Http.Extensions;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
|
using Ocelot.Configuration;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -15,14 +16,14 @@
|
|||||||
{
|
{
|
||||||
private readonly string[] _unsupportedHeaders = { "host" };
|
private readonly string[] _unsupportedHeaders = { "host" };
|
||||||
|
|
||||||
public async Task<Response<HttpRequestMessage>> Map(HttpRequest request)
|
public async Task<Response<HttpRequestMessage>> Map(HttpRequest request, DownstreamReRoute downstreamReRoute)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var requestMessage = new HttpRequestMessage()
|
var requestMessage = new HttpRequestMessage()
|
||||||
{
|
{
|
||||||
Content = await MapContent(request),
|
Content = await MapContent(request),
|
||||||
Method = MapMethod(request),
|
Method = MapMethod(request, downstreamReRoute),
|
||||||
RequestUri = MapUri(request)
|
RequestUri = MapUri(request)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -71,8 +72,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpMethod MapMethod(HttpRequest request)
|
private HttpMethod MapMethod(HttpRequest request, DownstreamReRoute downstreamReRoute)
|
||||||
{
|
{
|
||||||
|
if (!string.IsNullOrEmpty(downstreamReRoute?.DownstreamHttpMethod))
|
||||||
|
{
|
||||||
|
return new HttpMethod(downstreamReRoute.DownstreamHttpMethod);
|
||||||
|
}
|
||||||
|
|
||||||
return new HttpMethod(request.Method);
|
return new HttpMethod(request.Method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ namespace Ocelot.Request.Middleware
|
|||||||
};
|
};
|
||||||
|
|
||||||
_request.RequestUri = uriBuilder.Uri;
|
_request.RequestUri = uriBuilder.Uri;
|
||||||
|
_request.Method = new HttpMethod(Method);
|
||||||
return _request;
|
return _request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ namespace Ocelot.Request.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(DownstreamContext context)
|
public async Task Invoke(DownstreamContext context)
|
||||||
{
|
{
|
||||||
var downstreamRequest = await _requestMapper.Map(context.HttpContext.Request);
|
var downstreamRequest = await _requestMapper.Map(context.HttpContext.Request, context.DownstreamReRoute);
|
||||||
|
|
||||||
if (downstreamRequest.IsError)
|
if (downstreamRequest.IsError)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Ocelot.Middleware.Pipeline;
|
using Ocelot.Middleware.Pipeline;
|
||||||
|
|
||||||
namespace Ocelot.Request.Middleware
|
namespace Ocelot.Request.Middleware
|
||||||
|
158
test/Ocelot.AcceptanceTests/MethodTests.cs
Normal file
158
test/Ocelot.AcceptanceTests/MethodTests.cs
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
namespace Ocelot.AcceptanceTests
|
||||||
|
{
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Ocelot.Configuration.File;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
public class MethodTests : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Steps _steps;
|
||||||
|
private readonly ServiceHandler _serviceHandler;
|
||||||
|
|
||||||
|
public MethodTests()
|
||||||
|
{
|
||||||
|
_serviceHandler = new ServiceHandler();
|
||||||
|
_steps = new Steps();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_response_200_when_get_converted_to_post()
|
||||||
|
{
|
||||||
|
var configuration = new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
DownstreamPathTemplate = "/{url}",
|
||||||
|
DownstreamScheme = "http",
|
||||||
|
UpstreamPathTemplate = "/{url}",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||||
|
{
|
||||||
|
new FileHostAndPort
|
||||||
|
{
|
||||||
|
Host = "localhost",
|
||||||
|
Port = 53171,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DownstreamHttpMethod = "POST",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:53171/", "/", "POST"))
|
||||||
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
|
.And(x => _steps.GivenOcelotIsRunning())
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_response_200_when_get_converted_to_post_with_content()
|
||||||
|
{
|
||||||
|
var configuration = new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
DownstreamPathTemplate = "/{url}",
|
||||||
|
DownstreamScheme = "http",
|
||||||
|
UpstreamPathTemplate = "/{url}",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||||
|
{
|
||||||
|
new FileHostAndPort
|
||||||
|
{
|
||||||
|
Host = "localhost",
|
||||||
|
Port = 53271,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DownstreamHttpMethod = "POST",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const string expected = "here is some content";
|
||||||
|
var httpContent = new StringContent(expected);
|
||||||
|
|
||||||
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:53271/", "/", "POST"))
|
||||||
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
|
.And(x => _steps.GivenOcelotIsRunning())
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/", httpContent))
|
||||||
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
|
.And(_ => _steps.ThenTheResponseBodyShouldBe(expected))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_response_200_when_get_converted_to_get_with_content()
|
||||||
|
{
|
||||||
|
var configuration = new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
DownstreamPathTemplate = "/{url}",
|
||||||
|
DownstreamScheme = "http",
|
||||||
|
UpstreamPathTemplate = "/{url}",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Post" },
|
||||||
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||||
|
{
|
||||||
|
new FileHostAndPort
|
||||||
|
{
|
||||||
|
Host = "localhost",
|
||||||
|
Port = 53272,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DownstreamHttpMethod = "GET",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const string expected = "here is some content";
|
||||||
|
var httpContent = new StringContent(expected);
|
||||||
|
|
||||||
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:53272/", "/", "GET"))
|
||||||
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
|
.And(x => _steps.GivenOcelotIsRunning())
|
||||||
|
.When(x => _steps.WhenIPostUrlOnTheApiGateway("/", httpContent))
|
||||||
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
|
.And(_ => _steps.ThenTheResponseBodyShouldBe(expected))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, string expected)
|
||||||
|
{
|
||||||
|
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, basePath, async context =>
|
||||||
|
{
|
||||||
|
if (context.Request.Method == expected)
|
||||||
|
{
|
||||||
|
context.Response.StatusCode = 200;
|
||||||
|
var reader = new StreamReader(context.Request.Body);
|
||||||
|
var body = await reader.ReadToEndAsync();
|
||||||
|
await context.Response.WriteAsync(body);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Response.StatusCode = 500;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_serviceHandler.Dispose();
|
||||||
|
_steps.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -909,6 +909,18 @@ namespace Ocelot.AcceptanceTests
|
|||||||
_response = _ocelotClient.GetAsync(url).Result;
|
_response = _ocelotClient.GetAsync(url).Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void WhenIGetUrlOnTheApiGateway(string url, HttpContent content)
|
||||||
|
{
|
||||||
|
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, url) {Content = content};
|
||||||
|
_response = _ocelotClient.SendAsync(httpRequestMessage).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WhenIPostUrlOnTheApiGateway(string url, HttpContent content)
|
||||||
|
{
|
||||||
|
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url) { Content = content };
|
||||||
|
_response = _ocelotClient.SendAsync(httpRequestMessage).Result;
|
||||||
|
}
|
||||||
|
|
||||||
public void WhenIGetUrlOnTheApiGateway(string url, string cookie, string value)
|
public void WhenIGetUrlOnTheApiGateway(string url, string cookie, string value)
|
||||||
{
|
{
|
||||||
var request = _ocelotServer.CreateRequest(url);
|
var request = _ocelotServer.CreateRequest(url);
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
using Ocelot.Middleware;
|
namespace Ocelot.UnitTests.Request
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Request
|
|
||||||
{
|
{
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Moq;
|
using Moq;
|
||||||
@ -9,9 +7,12 @@ namespace Ocelot.UnitTests.Request
|
|||||||
using Ocelot.Request.Creator;
|
using Ocelot.Request.Creator;
|
||||||
using Ocelot.Request.Mapper;
|
using Ocelot.Request.Mapper;
|
||||||
using Ocelot.Request.Middleware;
|
using Ocelot.Request.Middleware;
|
||||||
|
using Ocelot.Configuration.Builder;
|
||||||
|
using Ocelot.Middleware;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using Ocelot.Configuration;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
@ -65,6 +66,20 @@ namespace Ocelot.UnitTests.Request
|
|||||||
.Then(_ => ThenTheContexRequestIsMappedToADownstreamRequest())
|
.Then(_ => ThenTheContexRequestIsMappedToADownstreamRequest())
|
||||||
.And(_ => ThenTheDownstreamRequestIsStored())
|
.And(_ => ThenTheDownstreamRequestIsStored())
|
||||||
.And(_ => ThenTheNextMiddlewareIsInvoked())
|
.And(_ => ThenTheNextMiddlewareIsInvoked())
|
||||||
|
.And(_ => ThenTheDownstreamRequestMethodIs("GET"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Should_map_downstream_reroute_method_to_downstream_request()
|
||||||
|
{
|
||||||
|
this.Given(_ => GivenTheHttpContextContainsARequest())
|
||||||
|
.And(_ => GivenTheMapperWillReturnAMappedRequest())
|
||||||
|
.When(_ => WhenTheMiddlewareIsInvoked())
|
||||||
|
.Then(_ => ThenTheContexRequestIsMappedToADownstreamRequest())
|
||||||
|
.And(_ => ThenTheDownstreamRequestIsStored())
|
||||||
|
.And(_ => ThenTheNextMiddlewareIsInvoked())
|
||||||
|
.And(_ => ThenTheDownstreamRequestMethodIs("GET"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +95,11 @@ namespace Ocelot.UnitTests.Request
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ThenTheDownstreamRequestMethodIs(string expected)
|
||||||
|
{
|
||||||
|
_downstreamContext.DownstreamRequest.Method.ShouldBe(expected);
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheHttpContextContainsARequest()
|
private void GivenTheHttpContextContainsARequest()
|
||||||
{
|
{
|
||||||
_httpContext
|
_httpContext
|
||||||
@ -92,7 +112,7 @@ namespace Ocelot.UnitTests.Request
|
|||||||
_mappedRequest = new OkResponse<HttpRequestMessage>(new HttpRequestMessage(HttpMethod.Get, "http://www.bbc.co.uk"));
|
_mappedRequest = new OkResponse<HttpRequestMessage>(new HttpRequestMessage(HttpMethod.Get, "http://www.bbc.co.uk"));
|
||||||
|
|
||||||
_requestMapper
|
_requestMapper
|
||||||
.Setup(rm => rm.Map(It.IsAny<HttpRequest>()))
|
.Setup(rm => rm.Map(It.IsAny<HttpRequest>(), It.IsAny<DownstreamReRoute>()))
|
||||||
.ReturnsAsync(_mappedRequest);
|
.ReturnsAsync(_mappedRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +121,7 @@ namespace Ocelot.UnitTests.Request
|
|||||||
_mappedRequest = new ErrorResponse<HttpRequestMessage>(new UnmappableRequestError(new System.Exception("boooom!")));
|
_mappedRequest = new ErrorResponse<HttpRequestMessage>(new UnmappableRequestError(new System.Exception("boooom!")));
|
||||||
|
|
||||||
_requestMapper
|
_requestMapper
|
||||||
.Setup(rm => rm.Map(It.IsAny<HttpRequest>()))
|
.Setup(rm => rm.Map(It.IsAny<HttpRequest>(), It.IsAny<DownstreamReRoute>()))
|
||||||
.ReturnsAsync(_mappedRequest);
|
.ReturnsAsync(_mappedRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +132,7 @@ namespace Ocelot.UnitTests.Request
|
|||||||
|
|
||||||
private void ThenTheContexRequestIsMappedToADownstreamRequest()
|
private void ThenTheContexRequestIsMappedToADownstreamRequest()
|
||||||
{
|
{
|
||||||
_requestMapper.Verify(rm => rm.Map(_httpRequest.Object), Times.Once);
|
_requestMapper.Verify(rm => rm.Map(_httpRequest.Object, _downstreamContext.DownstreamReRoute), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheDownstreamRequestIsStored()
|
private void ThenTheDownstreamRequestIsStored()
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Ocelot.Configuration;
|
||||||
|
using Ocelot.Configuration.Builder;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
@ -27,6 +29,8 @@
|
|||||||
|
|
||||||
private List<KeyValuePair<string, StringValues>> _inputHeaders = null;
|
private List<KeyValuePair<string, StringValues>> _inputHeaders = null;
|
||||||
|
|
||||||
|
private DownstreamReRoute _downstreamReRoute;
|
||||||
|
|
||||||
public RequestMapperTests()
|
public RequestMapperTests()
|
||||||
{
|
{
|
||||||
_httpContext = new DefaultHttpContext();
|
_httpContext = new DefaultHttpContext();
|
||||||
@ -82,6 +86,21 @@
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("", "GET")]
|
||||||
|
[InlineData(null, "GET")]
|
||||||
|
[InlineData("POST", "POST")]
|
||||||
|
public void Should_use_downstream_reroute_method_if_set(string input, string expected)
|
||||||
|
{
|
||||||
|
this.Given(_ => GivenTheInputRequestHasMethod("GET"))
|
||||||
|
.And(_ => GivenTheDownstreamReRouteMethodIs(input))
|
||||||
|
.And(_ => GivenTheInputRequestHasAValidUri())
|
||||||
|
.When(_ => WhenMapped())
|
||||||
|
.Then(_ => ThenNoErrorIsReturned())
|
||||||
|
.And(_ => ThenTheMappedRequestHasMethod(expected))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Should_map_all_headers()
|
public void Should_map_all_headers()
|
||||||
{
|
{
|
||||||
@ -154,16 +173,6 @@
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheInputRequestHasNoContentLength()
|
|
||||||
{
|
|
||||||
_inputRequest.ContentLength = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenTheInputRequestHasNoContentType()
|
|
||||||
{
|
|
||||||
_inputRequest.ContentType = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Should_map_content_headers()
|
public void Should_map_content_headers()
|
||||||
{
|
{
|
||||||
@ -212,6 +221,22 @@
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GivenTheDownstreamReRouteMethodIs(string input)
|
||||||
|
{
|
||||||
|
_downstreamReRoute = new DownstreamReRouteBuilder().WithDownStreamHttpMethod(input).Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheInputRequestHasNoContentLength()
|
||||||
|
{
|
||||||
|
_inputRequest.ContentLength = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheInputRequestHasNoContentType()
|
||||||
|
{
|
||||||
|
_inputRequest.ContentType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void ThenTheContentHeadersAreNotAddedToNonContentHeaders()
|
private void ThenTheContentHeadersAreNotAddedToNonContentHeaders()
|
||||||
{
|
{
|
||||||
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-Disposition");
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-Disposition");
|
||||||
@ -380,7 +405,7 @@
|
|||||||
|
|
||||||
private async Task WhenMapped()
|
private async Task WhenMapped()
|
||||||
{
|
{
|
||||||
_mappedRequest = await _requestMapper.Map(_inputRequest);
|
_mappedRequest = await _requestMapper.Map(_inputRequest, _downstreamReRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenNoErrorIsReturned()
|
private void ThenNoErrorIsReturned()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user