mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 14:02:49 +08:00
* #451 started implementing querystring support in templates * #451 ocelot.json back to normal and specified in docs query string wont work in upstream template * Revert "#451 ocelot.json back to normal and specified in docs query string wont work in upstream template" This reverts commit 563193f7b2f78bad6109484fe77f3c87de831005. * #451 ocelot.json back to normal and specified in docs query string wont work in upstream template
This commit is contained in:
parent
89c3887d36
commit
75f9a8f9be
@ -185,3 +185,34 @@ Dynamic Routing
|
||||
This feature was requested in `issue 340 <https://github.com/TomPallister/Ocelot/issue/340>`_. The idea is to enable dynamic routing
|
||||
when using a service discovery provider so you don't have to provide the ReRoute config. See the docs :ref:`service-discovery` if
|
||||
this sounds interesting to you.
|
||||
|
||||
Query Strings
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
Ocelot allow's you to specify a querystring as part of the DownstreamPathTemplate like the example below.
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"ReRoutes": [
|
||||
{
|
||||
"DownstreamPathTemplate": "/api/subscriptions/{subscriptionId}/updates?unitId={unitId}",
|
||||
"UpstreamPathTemplate": "/api/units/{subscriptionId}/{unitId}/updates",
|
||||
"UpstreamHttpMethod": [
|
||||
"Get"
|
||||
],
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "localhost",
|
||||
"Port": 50110
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"GlobalConfiguration": {
|
||||
"UseServiceDiscovery": false
|
||||
}
|
||||
}
|
||||
|
||||
In this example Ocelot will use the value from the {unitId} in the upstream path template and add it to the downstream request as a query string parameter called unitId! Please note you cannot use query string parameters to match routes in the UpstreamPathTemplate.
|
||||
|
@ -28,14 +28,14 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
||||
|
||||
public async Task Invoke(DownstreamContext context)
|
||||
{
|
||||
var dsPath = _replacer
|
||||
var response = _replacer
|
||||
.Replace(context.DownstreamReRoute.DownstreamPathTemplate, context.TemplatePlaceholderNameAndValues);
|
||||
|
||||
if (dsPath.IsError)
|
||||
if (response.IsError)
|
||||
{
|
||||
Logger.LogDebug("IDownstreamPathPlaceholderReplacer returned an error, setting pipeline error");
|
||||
|
||||
SetPipelineError(context, dsPath.Errors);
|
||||
SetPipelineError(context, response.Errors);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -43,13 +43,26 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
||||
|
||||
if (ServiceFabricRequest(context))
|
||||
{
|
||||
var pathAndQuery = CreateServiceFabricUri(context, dsPath);
|
||||
var pathAndQuery = CreateServiceFabricUri(context, response);
|
||||
context.DownstreamRequest.AbsolutePath = pathAndQuery.path;
|
||||
context.DownstreamRequest.Query = pathAndQuery.query;
|
||||
}
|
||||
else
|
||||
{
|
||||
context.DownstreamRequest.AbsolutePath = dsPath.Data.Value;
|
||||
var dsPath = response.Data;
|
||||
|
||||
if(ContainsQueryString(dsPath))
|
||||
{
|
||||
context.DownstreamRequest.AbsolutePath = GetPath(dsPath);
|
||||
context.DownstreamRequest.Query = GetQueryString(dsPath);
|
||||
|
||||
// todo - do we need to add anything from the request query string onto the query from the
|
||||
// templae?
|
||||
}
|
||||
else
|
||||
{
|
||||
context.DownstreamRequest.AbsolutePath = dsPath.Value;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.LogDebug($"Downstream url is {context.DownstreamRequest}");
|
||||
@ -57,6 +70,21 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
||||
await _next.Invoke(context);
|
||||
}
|
||||
|
||||
private string GetPath(DownstreamPath dsPath)
|
||||
{
|
||||
return dsPath.Value.Substring(0, dsPath.Value.IndexOf("?"));
|
||||
}
|
||||
|
||||
private string GetQueryString(DownstreamPath dsPath)
|
||||
{
|
||||
return dsPath.Value.Substring(dsPath.Value.IndexOf("?"));
|
||||
}
|
||||
|
||||
private bool ContainsQueryString(DownstreamPath dsPath)
|
||||
{
|
||||
return dsPath.Value.Contains("?");
|
||||
}
|
||||
|
||||
private (string path, string query) CreateServiceFabricUri(DownstreamContext context, Response<DownstreamPath> dsPath)
|
||||
{
|
||||
var query = context.DownstreamRequest.Query;
|
||||
|
104
test/Ocelot.AcceptanceTests/RoutingWithQueryStringTests.cs
Normal file
104
test/Ocelot.AcceptanceTests/RoutingWithQueryStringTests.cs
Normal file
@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Configuration.File;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
public class RoutingWithQueryStringTests : IDisposable
|
||||
{
|
||||
private IWebHost _builder;
|
||||
private readonly Steps _steps;
|
||||
private string _downstreamPath;
|
||||
|
||||
public RoutingWithQueryStringTests()
|
||||
{
|
||||
_steps = new Steps();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_200_with_query_string_template()
|
||||
{
|
||||
var subscriptionId = Guid.NewGuid().ToString();
|
||||
var unitId = Guid.NewGuid().ToString();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/api/subscriptions/{subscriptionId}/updates?unitId={unitId}",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 61879,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/api/units/{subscriptionId}/{unitId}/updates",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:61879", $"/api/subscriptions/{subscriptionId}/updates", $"?unitId={unitId}", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway($"/api/units/{subscriptionId}/{unitId}/updates"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, string queryString, int statusCode, string responseBody)
|
||||
{
|
||||
_builder = new WebHostBuilder()
|
||||
.UseUrls(baseUrl)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UsePathBase(basePath);
|
||||
app.Run(async context =>
|
||||
{
|
||||
|
||||
if(context.Request.PathBase.Value != basePath || context.Request.QueryString.Value != queryString)
|
||||
{
|
||||
context.Response.StatusCode = 404;
|
||||
await context.Response.WriteAsync("downstream path didnt match base path");
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
}
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
_builder.Start();
|
||||
}
|
||||
|
||||
internal void ThenTheDownstreamUrlPathShouldBe(string expectedDownstreamPath)
|
||||
{
|
||||
_downstreamPath.ShouldBe(expectedDownstreamPath);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_builder?.Dispose();
|
||||
_steps.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,345 +1,345 @@
|
||||
{
|
||||
"ReRoutes": [
|
||||
{
|
||||
"DownstreamPathTemplate": "/profile",
|
||||
"DownstreamScheme": "http",
|
||||
"UpstreamPathTemplate": "/profile",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "localhost",
|
||||
"Port": 3000
|
||||
"ReRoutes": [
|
||||
{
|
||||
"DownstreamPathTemplate": "/profile",
|
||||
"DownstreamScheme": "http",
|
||||
"UpstreamPathTemplate": "/profile",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "localhost",
|
||||
"Port": 3000
|
||||
}
|
||||
],
|
||||
"QoSOptions": {
|
||||
"TimeoutValue": 360000
|
||||
}
|
||||
],
|
||||
"QoSOptions": {
|
||||
"TimeoutValue": 360000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/api/v1/todo/",
|
||||
"DownstreamScheme": "http",
|
||||
"UpstreamPathTemplate": "/api/v1/todo/",
|
||||
"UpstreamHttpMethod": [ "Get", "Post" ],
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "lxtodo.azurewebsites.net",
|
||||
"Port": 80
|
||||
}
|
||||
|
||||
],
|
||||
"DownstreamHeaderTransform": {
|
||||
"Location": "{DownstreamBaseUrl}, {BaseUrl}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/api/values",
|
||||
"DownstreamScheme": "https",
|
||||
"UpstreamPathTemplate": "/api/values",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "testapivalues.azurewebsites.net",
|
||||
"Port": 443
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "localhost",
|
||||
"Port": 52876
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/identityserverexample",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
},
|
||||
"AuthenticationOptions": {
|
||||
"AuthenticationProviderKey": "TestKey",
|
||||
"AllowedScopes": [
|
||||
"openid",
|
||||
"offline_access"
|
||||
{
|
||||
"DownstreamPathTemplate": "/api/v1/todo/",
|
||||
"DownstreamScheme": "http",
|
||||
"UpstreamPathTemplate": "/api/v1/todo/",
|
||||
"UpstreamHttpMethod": [ "Get", "Post" ],
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "lxtodo.azurewebsites.net",
|
||||
"Port": 80
|
||||
}
|
||||
|
||||
],
|
||||
"DownstreamHeaderTransform": {
|
||||
"Location": "{DownstreamBaseUrl}, {BaseUrl}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/api/values",
|
||||
"DownstreamScheme": "https",
|
||||
"UpstreamPathTemplate": "/api/values",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "testapivalues.azurewebsites.net",
|
||||
"Port": 443
|
||||
}
|
||||
]
|
||||
},
|
||||
"AddHeadersToRequest": {
|
||||
"CustomerId": "Claims[CustomerId] > value",
|
||||
"LocationId": "Claims[LocationId] > value",
|
||||
"UserType": "Claims[sub] > value[0] > |",
|
||||
"UserId": "Claims[sub] > value[1] > |"
|
||||
{
|
||||
"DownstreamPathTemplate": "/",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "localhost",
|
||||
"Port": 52876
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/identityserverexample",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
},
|
||||
"AuthenticationOptions": {
|
||||
"AuthenticationProviderKey": "TestKey",
|
||||
"AllowedScopes": [
|
||||
"openid",
|
||||
"offline_access"
|
||||
]
|
||||
},
|
||||
"AddHeadersToRequest": {
|
||||
"CustomerId": "Claims[CustomerId] > value",
|
||||
"LocationId": "Claims[LocationId] > value",
|
||||
"UserType": "Claims[sub] > value[0] > |",
|
||||
"UserId": "Claims[sub] > value[1] > |"
|
||||
},
|
||||
"AddClaimsToRequest": {
|
||||
"CustomerId": "Claims[CustomerId] > value",
|
||||
"LocationId": "Claims[LocationId] > value",
|
||||
"UserType": "Claims[sub] > value[0] > |",
|
||||
"UserId": "Claims[sub] > value[1] > |"
|
||||
},
|
||||
"AddQueriesToRequest": {
|
||||
"CustomerId": "Claims[CustomerId] > value",
|
||||
"LocationId": "Claims[LocationId] > value",
|
||||
"UserType": "Claims[sub] > value[0] > |",
|
||||
"UserId": "Claims[sub] > value[1] > |"
|
||||
},
|
||||
"RouteClaimsRequirement": {
|
||||
"UserType": "registered"
|
||||
},
|
||||
"RequestIdKey": "OcRequestId"
|
||||
},
|
||||
"AddClaimsToRequest": {
|
||||
"CustomerId": "Claims[CustomerId] > value",
|
||||
"LocationId": "Claims[LocationId] > value",
|
||||
"UserType": "Claims[sub] > value[0] > |",
|
||||
"UserId": "Claims[sub] > value[1] > |"
|
||||
},
|
||||
"AddQueriesToRequest": {
|
||||
"CustomerId": "Claims[CustomerId] > value",
|
||||
"LocationId": "Claims[LocationId] > value",
|
||||
"UserType": "Claims[sub] > value[0] > |",
|
||||
"UserId": "Claims[sub] > value[1] > |"
|
||||
},
|
||||
"RouteClaimsRequirement": {
|
||||
"UserType": "registered"
|
||||
},
|
||||
"RequestIdKey": "OcRequestId"
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts",
|
||||
"DownstreamScheme": "https",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 443
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts",
|
||||
"DownstreamScheme": "https",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 443
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"HttpHandlerOptions": {
|
||||
"AllowAutoRedirect": true,
|
||||
"UseCookieContainer": true
|
||||
},
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"HttpHandlerOptions": {
|
||||
"AllowAutoRedirect": true,
|
||||
"UseCookieContainer": true
|
||||
},
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts/{postId}",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts/{postId}",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"RequestIdKey": "ReRouteRequestId",
|
||||
"HttpHandlerOptions": {
|
||||
"AllowAutoRedirect": true,
|
||||
"UseCookieContainer": true,
|
||||
"UseTracing": true,
|
||||
"UseProxy": true
|
||||
},
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts/{postId}/comments",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts/{postId}/comments",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"HttpHandlerOptions": {
|
||||
"AllowAutoRedirect": true,
|
||||
"UseCookieContainer": true,
|
||||
"UseTracing": false
|
||||
},
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/comments",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/comments",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts",
|
||||
"UpstreamHttpMethod": [ "Post" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts/{postId}",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts/{postId}",
|
||||
"UpstreamHttpMethod": [ "Put" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts/{postId}",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts/{postId}",
|
||||
"UpstreamHttpMethod": [ "Patch" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts/{postId}",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts/{postId}",
|
||||
"UpstreamHttpMethod": [ "Delete" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/api/products",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/products",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
},
|
||||
"FileCacheOptions": { "TtlSeconds": 15 }
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/api/products/{productId}",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/products/{productId}",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"FileCacheOptions": { "TtlSeconds": 15 }
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/api/products",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/products",
|
||||
"UpstreamHttpMethod": [ "Post" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/api/products/{productId}",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/products/{productId}",
|
||||
"UpstreamHttpMethod": [ "Put" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
},
|
||||
"FileCacheOptions": { "TtlSeconds": 15 }
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts/",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
},
|
||||
"FileCacheOptions": { "TtlSeconds": 15 }
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "www.bbc.co.uk",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/bbc/",
|
||||
"UpstreamHttpMethod": [ "Get" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts/{postId}",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts/{postId}",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"RequestIdKey": "ReRouteRequestId",
|
||||
"HttpHandlerOptions": {
|
||||
"AllowAutoRedirect": true,
|
||||
"UseCookieContainer": true,
|
||||
"UseTracing": true,
|
||||
"UseProxy": true
|
||||
},
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts/{postId}/comments",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts/{postId}/comments",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"HttpHandlerOptions": {
|
||||
"AllowAutoRedirect": true,
|
||||
"UseCookieContainer": true,
|
||||
"UseTracing": false
|
||||
},
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/comments",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/comments",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts",
|
||||
"UpstreamHttpMethod": [ "Post" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts/{postId}",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts/{postId}",
|
||||
"UpstreamHttpMethod": [ "Put" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts/{postId}",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts/{postId}",
|
||||
"UpstreamHttpMethod": [ "Patch" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts/{postId}",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts/{postId}",
|
||||
"UpstreamHttpMethod": [ "Delete" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/api/products",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/products",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
},
|
||||
"FileCacheOptions": { "TtlSeconds": 15 }
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/api/products/{productId}",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/products/{productId}",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"FileCacheOptions": { "TtlSeconds": 15 }
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/api/products",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/products",
|
||||
"UpstreamHttpMethod": [ "Post" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/api/products/{productId}",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/products/{productId}",
|
||||
"UpstreamHttpMethod": [ "Put" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
},
|
||||
"FileCacheOptions": { "TtlSeconds": 15 }
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/posts",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "jsonplaceholder.typicode.com",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/posts/",
|
||||
"UpstreamHttpMethod": [ "Get" ],
|
||||
"QoSOptions": {
|
||||
"ExceptionsAllowedBeforeBreaking": 3,
|
||||
"DurationOfBreak": 10,
|
||||
"TimeoutValue": 5000
|
||||
},
|
||||
"FileCacheOptions": { "TtlSeconds": 15 }
|
||||
},
|
||||
{
|
||||
"DownstreamPathTemplate": "/",
|
||||
"DownstreamScheme": "http",
|
||||
"DownstreamHostAndPorts": [
|
||||
{
|
||||
"Host": "www.bbc.co.uk",
|
||||
"Port": 80
|
||||
}
|
||||
],
|
||||
"UpstreamPathTemplate": "/bbc/",
|
||||
"UpstreamHttpMethod": [ "Get" ]
|
||||
}
|
||||
],
|
||||
],
|
||||
|
||||
"GlobalConfiguration": {
|
||||
"RequestIdKey": "ot-traceid"
|
||||
"GlobalConfiguration": {
|
||||
"RequestIdKey": "ot-traceid"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,6 +68,7 @@
|
||||
.And(x => x.GivenTheUrlReplacerWillReturn("/api/products/1"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("https://my.url:80/api/products/1?q=123"))
|
||||
.And(x => ThenTheQueryStringIs("?q=123"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
@ -227,5 +228,10 @@
|
||||
{
|
||||
_downstreamContext.DownstreamRequest.ToHttpRequestMessage().RequestUri.OriginalString.ShouldBe(expectedUri);
|
||||
}
|
||||
|
||||
private void ThenTheQueryStringIs(string queryString)
|
||||
{
|
||||
_downstreamContext.DownstreamRequest.Query.ShouldBe(queryString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user