mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:22:50 +08:00
commit
2fded67de8
@ -13,7 +13,7 @@ osx_image: xcode9.2
|
|||||||
mono:
|
mono:
|
||||||
- 4.4.2
|
- 4.4.2
|
||||||
|
|
||||||
dotnet: 2.1.4
|
dotnet: 2.1.301
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- git fetch --unshallow # Travis always does a shallow clone, but GitVersion needs the full history including branches and tags
|
- git fetch --unshallow # Travis always does a shallow clone, but GitVersion needs the full history including branches and tags
|
||||||
|
@ -55,7 +55,7 @@ A quick list of Ocelot's capabilities for more information see the [documentatio
|
|||||||
|
|
||||||
## How to install
|
## How to install
|
||||||
|
|
||||||
Ocelot is designed to work with ASP.NET Core only and it targets `netstandard2.0`. This means it can be used anywhere `.NET Standard 2.0` is supported, including `.NET Core 2.0` and `.NET Framework 4.6.1` and up. [This](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) documentation may prove helpful when working out if Ocelot would be suitable for you.
|
Ocelot is designed to work with ASP.NET Core only and it targets `netstandard2.0`. This means it can be used anywhere `.NET Standard 2.0` is supported, including `.NET Core 2.1` and `.NET Framework 4.7.2` and up. [This](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) documentation may prove helpful when working out if Ocelot would be suitable for you.
|
||||||
|
|
||||||
Install Ocelot and it's dependencies using NuGet.
|
Install Ocelot and it's dependencies using NuGet.
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ In order to use IdentityServer bearer tokens register your IdentityServer servic
|
|||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
var authenticationProviderKey = "TestKey";
|
var authenticationProviderKey = "TestKey";
|
||||||
var options = o =>
|
Action<IdentityServerAuthenticationOptions> options = o =>
|
||||||
{
|
{
|
||||||
o.Authority = "https://whereyouridentityserverlives.com";
|
o.Authority = "https://whereyouridentityserverlives.com";
|
||||||
o.ApiName = "api";
|
o.ApiName = "api";
|
||||||
@ -136,6 +136,11 @@ Then map the authentication provider key to a ReRoute in your configuration e.g.
|
|||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
|
|
||||||
|
Okta
|
||||||
|
^^^^
|
||||||
|
|
||||||
|
I have not had time to write this up but we have `Issue 446 <https://github.com/ThreeMammals/Ocelot/issues/446>`_ that contains some code and examples that might help with Okta integration.
|
||||||
|
|
||||||
Allowed Scopes
|
Allowed Scopes
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@ -2,15 +2,19 @@ Caching
|
|||||||
=======
|
=======
|
||||||
|
|
||||||
Ocelot supports some very rudimentary caching at the moment provider by
|
Ocelot supports some very rudimentary caching at the moment provider by
|
||||||
the `CacheManager <http://cachemanager.net/>`_ project. This is an amazing project
|
the `CacheManager <https://github.com/MichaCo/CacheManager>`_ project. This is an amazing project
|
||||||
that is solving a lot of caching problems. I would reccomend using this package to
|
that is solving a lot of caching problems. I would reccomend using this package to
|
||||||
cache with Ocelot. If you look at the example `here <https://github.com/TomPallister/Ocelot/blob/develop/test/Ocelot.ManualTest/Startup.cs>`_ you can see how the cache manager is setup and then passed into the Ocelot
|
cache with Ocelot.
|
||||||
AddOcelotOutputCaching configuration method. You can use any settings supported by
|
|
||||||
the CacheManager package and just pass them in.
|
|
||||||
|
|
||||||
Anyway Ocelot currently supports caching on the URL of the downstream service
|
The following example shows how to add CacheManager to Ocelot so that you can do output caching. The first thing you need to do is add the following to your ConfigureServices..
|
||||||
and setting a TTL in seconds to expire the cache. You can also clear the cache for a region
|
|
||||||
by calling Ocelot's administration API.
|
.. code-block:: csharp
|
||||||
|
|
||||||
|
s.AddOcelot()
|
||||||
|
.AddCacheManager(x =>
|
||||||
|
{
|
||||||
|
x.WithDictionaryHandle();
|
||||||
|
})
|
||||||
|
|
||||||
In order to use caching on a route in your ReRoute configuration add this setting.
|
In order to use caching on a route in your ReRoute configuration add this setting.
|
||||||
|
|
||||||
@ -19,3 +23,12 @@ In order to use caching on a route in your ReRoute configuration add this settin
|
|||||||
"FileCacheOptions": { "TtlSeconds": 15, "Region": "somename" }
|
"FileCacheOptions": { "TtlSeconds": 15, "Region": "somename" }
|
||||||
|
|
||||||
In this example ttl seconds is set to 15 which means the cache will expire after 15 seconds.
|
In this example ttl seconds is set to 15 which means the cache will expire after 15 seconds.
|
||||||
|
|
||||||
|
If you look at the example `here <https://github.com/TomPallister/Ocelot/blob/develop/test/Ocelot.ManualTest/Program.cs>`_ you can see how the cache manager is setup and then passed into the Ocelot
|
||||||
|
AddOcelotOutputCaching configuration method. You can use any settings supported by
|
||||||
|
the CacheManager package and just pass them in.
|
||||||
|
|
||||||
|
Anyway Ocelot currently supports caching on the URL of the downstream service
|
||||||
|
and setting a TTL in seconds to expire the cache. You can also clear the cache for a region
|
||||||
|
by calling Ocelot's administration API.
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Delegating Handers
|
Delegating Handlers
|
||||||
==================
|
===================
|
||||||
|
|
||||||
Ocelot allows the user to add delegating handlers to the HttpClient transport. This feature was requested `GitHub #208 <https://github.com/TomPallister/Ocelot/issues/208>`_
|
Ocelot allows the user to add delegating handlers to the HttpClient transport. This feature was requested `GitHub #208 <https://github.com/TomPallister/Ocelot/issues/208>`_
|
||||||
and I decided that it was going to be useful in various ways. Since then we extended it in `GitHub #264 <https://github.com/TomPallister/Ocelot/issues/264>`_.
|
and I decided that it was going to be useful in various ways. Since then we extended it in `GitHub #264 <https://github.com/TomPallister/Ocelot/issues/264>`_.
|
||||||
@ -23,21 +23,13 @@ asp.net core container so you can inject any other services you have registered
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Next you must add the handlers to Ocelot's container either as singleton like follows..
|
Next you must add the handlers to Ocelot's container like below...
|
||||||
|
|
||||||
.. code-block:: csharp
|
.. code-block:: csharp
|
||||||
|
|
||||||
services.AddOcelot()
|
services.AddOcelot()
|
||||||
.AddSingletonDelegatingHandler<FakeHandler>()
|
.AddDelegatingHandler<FakeHandler>()
|
||||||
.AddSingletonDelegatingHandler<FakeHandlerTwo>()
|
.AddDelegatingHandler<FakeHandlerTwo>()
|
||||||
|
|
||||||
Or transient as below...
|
|
||||||
|
|
||||||
.. code-block:: csharp
|
|
||||||
|
|
||||||
services.AddOcelot()
|
|
||||||
.AddTransientDelegatingHandler<FakeHandler>()
|
|
||||||
.AddTransientDelegatingHandler<FakeHandlerTwo>()
|
|
||||||
|
|
||||||
Both of these Add methods have a default parameter called global which is set to false. If it is false then the intent of
|
Both of these Add methods have a default parameter called global which is set to false. If it is false then the intent of
|
||||||
the DelegatingHandler is to be applied to specific ReRoutes via ocelot.json (more on that later). If it is set to true
|
the DelegatingHandler is to be applied to specific ReRoutes via ocelot.json (more on that later). If it is set to true
|
||||||
@ -45,17 +37,12 @@ then it becomes a global handler and will be applied to all ReRoutes.
|
|||||||
|
|
||||||
e.g.
|
e.g.
|
||||||
|
|
||||||
.. code-block:: csharp
|
As below...
|
||||||
|
|
||||||
services.AddOcelot()
|
|
||||||
.AddSingletonDelegatingHandler<FakeHandler>(true)
|
|
||||||
|
|
||||||
Or transient as below...
|
|
||||||
|
|
||||||
.. code-block:: csharp
|
.. code-block:: csharp
|
||||||
|
|
||||||
services.AddOcelot()
|
services.AddOcelot()
|
||||||
.AddTransientDelegatingHandler<FakeHandler>(true)
|
.AddDelegatingHandler<FakeHandler>(true)
|
||||||
|
|
||||||
Finally if you want ReRoute specific DelegatingHandlers or to order your specific and / or global (more on this later) DelegatingHandlers
|
Finally if you want ReRoute specific DelegatingHandlers or to order your specific and / or global (more on this later) DelegatingHandlers
|
||||||
then you must add the following json to the specific ReRoute in ocelot.json. The names in the array must match the class names of your
|
then you must add the following json to the specific ReRoute in ocelot.json. The names in the array must match the class names of your
|
||||||
|
@ -185,3 +185,63 @@ Dynamic Routing
|
|||||||
This feature was requested in `issue 340 <https://github.com/TomPallister/Ocelot/issue/340>`_. The idea is to enable 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
|
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.
|
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!
|
||||||
|
|
||||||
|
Ocelot will also allow you to put query string parametrs in the UpstreamPathTemplate so you can match certain queries to certain services.
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"ReRoutes": [
|
||||||
|
{
|
||||||
|
"DownstreamPathTemplate": "/api/units/{subscriptionId}/{unitId}/updates",
|
||||||
|
"UpstreamPathTemplate": "/api/subscriptions/{subscriptionId}/updates?unitId={unitId}",
|
||||||
|
"UpstreamHttpMethod": [
|
||||||
|
"Get"
|
||||||
|
],
|
||||||
|
"DownstreamScheme": "http",
|
||||||
|
"DownstreamHostAndPorts": [
|
||||||
|
{
|
||||||
|
"Host": "localhost",
|
||||||
|
"Port": 50110
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"GlobalConfiguration": {
|
||||||
|
"UseServiceDiscovery": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
In this example Ocelot will only match requests that have a matching url path and the querystring starts with unitId=something. You can have other queries after this
|
||||||
|
but you must start with the matching parameter. Also in this example Ocelot will swap the unitId param from the query string and use it in the downstream request path.
|
@ -18,7 +18,8 @@ will be used.
|
|||||||
|
|
||||||
"ServiceDiscoveryProvider": {
|
"ServiceDiscoveryProvider": {
|
||||||
"Host": "localhost",
|
"Host": "localhost",
|
||||||
"Port": 8500
|
"Port": 8500,
|
||||||
|
"Type": "Consul"
|
||||||
}
|
}
|
||||||
|
|
||||||
In the future we can add a feature that allows ReRoute specfic configuration.
|
In the future we can add a feature that allows ReRoute specfic configuration.
|
||||||
@ -136,8 +137,8 @@ The config might look something like
|
|||||||
"RequestIdKey": null,
|
"RequestIdKey": null,
|
||||||
"ServiceDiscoveryProvider": {
|
"ServiceDiscoveryProvider": {
|
||||||
"Host": "localhost",
|
"Host": "localhost",
|
||||||
"Port": 8510,
|
"Port": 8500,
|
||||||
"Type": null,
|
"Type": "Consul",
|
||||||
"Token": null,
|
"Token": null,
|
||||||
"ConfigurationKey": null
|
"ConfigurationKey": null
|
||||||
},
|
},
|
||||||
|
@ -4,7 +4,7 @@ Getting Started
|
|||||||
Ocelot is designed to work with .NET Core only and is currently
|
Ocelot is designed to work with .NET Core only and is currently
|
||||||
built to netstandard2.0 `this <https://docs.microsoft.com/en-us/dotnet/articles/standard/library>`_ documentation may prove helpful when working out if Ocelot would be suitable for you.
|
built to netstandard2.0 `this <https://docs.microsoft.com/en-us/dotnet/articles/standard/library>`_ documentation may prove helpful when working out if Ocelot would be suitable for you.
|
||||||
|
|
||||||
.NET Core 2.0
|
.NET Core 2.1
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
**Install NuGet package**
|
**Install NuGet package**
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"projects": [ "src", "test" ],
|
"projects": [ "src", "test" ],
|
||||||
"sdk": {
|
"sdk": {
|
||||||
"version": "2.1.4"
|
"version": "2.1.301"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,13 +8,16 @@ namespace Ocelot.Configuration.Creator
|
|||||||
public ServiceProviderConfiguration Create(FileGlobalConfiguration globalConfiguration)
|
public ServiceProviderConfiguration Create(FileGlobalConfiguration globalConfiguration)
|
||||||
{
|
{
|
||||||
var port = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
|
var port = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
|
||||||
var host = globalConfiguration?.ServiceDiscoveryProvider?.Host ?? "consul";
|
var host = globalConfiguration?.ServiceDiscoveryProvider?.Host ?? "localhost";
|
||||||
|
var type = !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Type)
|
||||||
|
? globalConfiguration?.ServiceDiscoveryProvider?.Type
|
||||||
|
: "consul";
|
||||||
var pollingInterval = globalConfiguration?.ServiceDiscoveryProvider?.PollingInterval ?? 0;
|
var pollingInterval = globalConfiguration?.ServiceDiscoveryProvider?.PollingInterval ?? 0;
|
||||||
|
|
||||||
return new ServiceProviderConfigurationBuilder()
|
return new ServiceProviderConfigurationBuilder()
|
||||||
.WithHost(host)
|
.WithHost(host)
|
||||||
.WithPort(port)
|
.WithPort(port)
|
||||||
.WithType(globalConfiguration?.ServiceDiscoveryProvider?.Type)
|
.WithType(type)
|
||||||
.WithToken(globalConfiguration?.ServiceDiscoveryProvider?.Token)
|
.WithToken(globalConfiguration?.ServiceDiscoveryProvider?.Token)
|
||||||
.WithConfigurationKey(globalConfiguration?.ServiceDiscoveryProvider?.ConfigurationKey)
|
.WithConfigurationKey(globalConfiguration?.ServiceDiscoveryProvider?.ConfigurationKey)
|
||||||
.WithPollingInterval(pollingInterval)
|
.WithPollingInterval(pollingInterval)
|
||||||
|
@ -16,6 +16,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
{
|
{
|
||||||
var upstreamTemplate = reRoute.UpstreamPathTemplate;
|
var upstreamTemplate = reRoute.UpstreamPathTemplate;
|
||||||
|
|
||||||
|
|
||||||
var placeholders = new List<string>();
|
var placeholders = new List<string>();
|
||||||
|
|
||||||
for (var i = 0; i < upstreamTemplate.Length; i++)
|
for (var i = 0; i < upstreamTemplate.Length; i++)
|
||||||
@ -30,11 +31,19 @@ namespace Ocelot.Configuration.Creator
|
|||||||
//hack to handle /{url} case
|
//hack to handle /{url} case
|
||||||
if(ForwardSlashAndOnePlaceHolder(upstreamTemplate, placeholders, postitionOfPlaceHolderClosingBracket))
|
if(ForwardSlashAndOnePlaceHolder(upstreamTemplate, placeholders, postitionOfPlaceHolderClosingBracket))
|
||||||
{
|
{
|
||||||
return new UpstreamPathTemplate(RegExForwardSlashAndOnePlaceHolder, 0);
|
return new UpstreamPathTemplate(RegExForwardSlashAndOnePlaceHolder, 0, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var containsQueryString = false;
|
||||||
|
|
||||||
|
if (upstreamTemplate.Contains("?"))
|
||||||
|
{
|
||||||
|
containsQueryString = true;
|
||||||
|
upstreamTemplate = upstreamTemplate.Replace("?", "\\?");
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var placeholder in placeholders)
|
foreach (var placeholder in placeholders)
|
||||||
{
|
{
|
||||||
upstreamTemplate = upstreamTemplate.Replace(placeholder, RegExMatchOneOrMoreOfEverything);
|
upstreamTemplate = upstreamTemplate.Replace(placeholder, RegExMatchOneOrMoreOfEverything);
|
||||||
@ -42,7 +51,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
|
|
||||||
if (upstreamTemplate == "/")
|
if (upstreamTemplate == "/")
|
||||||
{
|
{
|
||||||
return new UpstreamPathTemplate(RegExForwardSlashOnly, reRoute.Priority);
|
return new UpstreamPathTemplate(RegExForwardSlashOnly, reRoute.Priority, containsQueryString);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(upstreamTemplate.EndsWith("/"))
|
if(upstreamTemplate.EndsWith("/"))
|
||||||
@ -54,7 +63,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
? $"^{upstreamTemplate}{RegExMatchEndString}"
|
? $"^{upstreamTemplate}{RegExMatchEndString}"
|
||||||
: $"^{RegExIgnoreCase}{upstreamTemplate}{RegExMatchEndString}";
|
: $"^{RegExIgnoreCase}{upstreamTemplate}{RegExMatchEndString}";
|
||||||
|
|
||||||
return new UpstreamPathTemplate(route, reRoute.Priority);
|
return new UpstreamPathTemplate(route, reRoute.Priority, containsQueryString);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ForwardSlashAndOnePlaceHolder(string upstreamTemplate, List<string> placeholders, int postitionOfPlaceHolderClosingBracket)
|
private bool ForwardSlashAndOnePlaceHolder(string upstreamTemplate, List<string> placeholders, int postitionOfPlaceHolderClosingBracket)
|
||||||
|
@ -29,12 +29,17 @@ namespace Ocelot.DependencyInjection
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static IConfigurationBuilder AddOcelot(this IConfigurationBuilder builder)
|
public static IConfigurationBuilder AddOcelot(this IConfigurationBuilder builder)
|
||||||
|
{
|
||||||
|
return builder.AddOcelot(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IConfigurationBuilder AddOcelot(this IConfigurationBuilder builder, string folder)
|
||||||
{
|
{
|
||||||
const string pattern = "(?i)ocelot\\.([a-zA-Z0-9]*)(\\.json)$";
|
const string pattern = "(?i)ocelot\\.([a-zA-Z0-9]*)(\\.json)$";
|
||||||
|
|
||||||
var reg = new Regex(pattern);
|
var reg = new Regex(pattern);
|
||||||
|
|
||||||
var files = Directory.GetFiles(".")
|
var files = Directory.GetFiles(folder)
|
||||||
.Where(path => reg.IsMatch(path))
|
.Where(path => reg.IsMatch(path))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
@ -43,7 +48,7 @@ namespace Ocelot.DependencyInjection
|
|||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
// windows and unix sigh...
|
// windows and unix sigh...
|
||||||
if(files.Count > 1 && (file == "./ocelot.json" || file == ".\\ocelot.json"))
|
if(files.Count > 1 && (Path.GetFileName(file) == "ocelot.json"))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -53,7 +58,7 @@ namespace Ocelot.DependencyInjection
|
|||||||
var config = JsonConvert.DeserializeObject<FileConfiguration>(lines);
|
var config = JsonConvert.DeserializeObject<FileConfiguration>(lines);
|
||||||
|
|
||||||
// windows and unix sigh...
|
// windows and unix sigh...
|
||||||
if (file == "./ocelot.global.json" || file == ".\\ocelot.global.json")
|
if (Path.GetFileName(file) == "ocelot.global.json")
|
||||||
{
|
{
|
||||||
fileConfiguration.GlobalConfiguration = config.GlobalConfiguration;
|
fileConfiguration.GlobalConfiguration = config.GlobalConfiguration;
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,15 @@ using System;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using IdentityServer4.AccessTokenValidation;
|
using IdentityServer4.AccessTokenValidation;
|
||||||
using Ocelot.Middleware.Multiplexer;
|
using Ocelot.Middleware.Multiplexer;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
namespace Ocelot.DependencyInjection
|
namespace Ocelot.DependencyInjection
|
||||||
{
|
{
|
||||||
public interface IOcelotBuilder
|
public interface IOcelotBuilder
|
||||||
{
|
{
|
||||||
|
IServiceCollection Services { get; }
|
||||||
|
IConfiguration Configuration { get; }
|
||||||
IOcelotBuilder AddStoreOcelotConfigurationInConsul();
|
IOcelotBuilder AddStoreOcelotConfigurationInConsul();
|
||||||
|
|
||||||
IOcelotBuilder AddCacheManager(Action<ConfigurationBuilderCachePart> settings);
|
IOcelotBuilder AddCacheManager(Action<ConfigurationBuilderCachePart> settings);
|
||||||
@ -19,10 +23,7 @@ namespace Ocelot.DependencyInjection
|
|||||||
|
|
||||||
IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configOptions);
|
IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configOptions);
|
||||||
|
|
||||||
IOcelotBuilder AddSingletonDelegatingHandler<T>(bool global = false)
|
IOcelotBuilder AddDelegatingHandler<T>(bool global = false)
|
||||||
where T : DelegatingHandler;
|
|
||||||
|
|
||||||
IOcelotBuilder AddTransientDelegatingHandler<T>(bool global = false)
|
|
||||||
where T : DelegatingHandler;
|
where T : DelegatingHandler;
|
||||||
|
|
||||||
IOcelotBuilder AddSingletonDefinedAggregator<T>()
|
IOcelotBuilder AddSingletonDefinedAggregator<T>()
|
||||||
|
@ -55,6 +55,10 @@ namespace Ocelot.DependencyInjection
|
|||||||
private readonly IServiceCollection _services;
|
private readonly IServiceCollection _services;
|
||||||
private readonly IConfiguration _configurationRoot;
|
private readonly IConfiguration _configurationRoot;
|
||||||
|
|
||||||
|
public IServiceCollection Services => _services;
|
||||||
|
|
||||||
|
public IConfiguration Configuration => _configurationRoot;
|
||||||
|
|
||||||
public OcelotBuilder(IServiceCollection services, IConfiguration configurationRoot)
|
public OcelotBuilder(IServiceCollection services, IConfiguration configurationRoot)
|
||||||
{
|
{
|
||||||
_configurationRoot = configurationRoot;
|
_configurationRoot = configurationRoot;
|
||||||
@ -212,26 +216,7 @@ namespace Ocelot.DependencyInjection
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IOcelotBuilder AddSingletonDelegatingHandler<THandler>(bool global = false)
|
public IOcelotBuilder AddDelegatingHandler<THandler>(bool global = false)
|
||||||
where THandler : DelegatingHandler
|
|
||||||
{
|
|
||||||
if(global)
|
|
||||||
{
|
|
||||||
_services.AddSingleton<THandler>();
|
|
||||||
_services.AddSingleton<GlobalDelegatingHandler>(s => {
|
|
||||||
var service = s.GetService<THandler>();
|
|
||||||
return new GlobalDelegatingHandler(service);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_services.AddSingleton<DelegatingHandler, THandler>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IOcelotBuilder AddTransientDelegatingHandler<THandler>(bool global = false)
|
|
||||||
where THandler : DelegatingHandler
|
where THandler : DelegatingHandler
|
||||||
{
|
{
|
||||||
if(global)
|
if(global)
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
_cache = new ConcurrentDictionary<string, OkResponse<DownstreamRoute>>();
|
_cache = new ConcurrentDictionary<string, OkResponse<DownstreamRoute>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Response<DownstreamRoute> Get(string upstreamUrlPath, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost)
|
public Response<DownstreamRoute> Get(string upstreamUrlPath, string upstreamQueryString, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost)
|
||||||
{
|
{
|
||||||
var serviceName = GetServiceName(upstreamUrlPath);
|
var serviceName = GetServiceName(upstreamUrlPath);
|
||||||
|
|
||||||
@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
downstreamRoute = new OkResponse<DownstreamRoute>(new DownstreamRoute(new List<PlaceholderNameAndValue>(), reRoute));
|
downstreamRoute = new OkResponse<DownstreamRoute>(new DownstreamRoute(new List<PlaceholderNameAndValue>(), reRoute));
|
||||||
|
|
||||||
_cache.AddOrUpdate(loadBalancerKey, downstreamRoute, (x, y) => downstreamRoute);
|
_cache.AddOrUpdate(loadBalancerKey, downstreamRoute, (x, y) => downstreamRoute);
|
||||||
|
|
||||||
return downstreamRoute;
|
return downstreamRoute;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ namespace Ocelot.DownstreamRouteFinder.Finder
|
|||||||
_placeholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder;
|
_placeholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Response<DownstreamRoute> Get(string path, string httpMethod, IInternalConfiguration configuration, string upstreamHost)
|
public Response<DownstreamRoute> Get(string upstreamUrlPath, string upstreamQueryString, string httpMethod, IInternalConfiguration configuration, string upstreamHost)
|
||||||
{
|
{
|
||||||
var downstreamRoutes = new List<DownstreamRoute>();
|
var downstreamRoutes = new List<DownstreamRoute>();
|
||||||
|
|
||||||
@ -28,11 +28,11 @@ namespace Ocelot.DownstreamRouteFinder.Finder
|
|||||||
|
|
||||||
foreach (var reRoute in applicableReRoutes)
|
foreach (var reRoute in applicableReRoutes)
|
||||||
{
|
{
|
||||||
var urlMatch = _urlMatcher.Match(path, reRoute.UpstreamTemplatePattern.Template);
|
var urlMatch = _urlMatcher.Match(upstreamUrlPath, upstreamQueryString, reRoute.UpstreamTemplatePattern.Template, reRoute.UpstreamTemplatePattern.ContainsQueryString);
|
||||||
|
|
||||||
if (urlMatch.Data.Match)
|
if (urlMatch.Data.Match)
|
||||||
{
|
{
|
||||||
downstreamRoutes.Add(GetPlaceholderNamesAndValues(path, reRoute));
|
downstreamRoutes.Add(GetPlaceholderNamesAndValues(upstreamUrlPath, upstreamQueryString, reRoute));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ namespace Ocelot.DownstreamRouteFinder.Finder
|
|||||||
return notNullOption != null ? new OkResponse<DownstreamRoute>(notNullOption) : new OkResponse<DownstreamRoute>(nullOption);
|
return notNullOption != null ? new OkResponse<DownstreamRoute>(notNullOption) : new OkResponse<DownstreamRoute>(nullOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ErrorResponse<DownstreamRoute>(new UnableToFindDownstreamRouteError(path, httpMethod));
|
return new ErrorResponse<DownstreamRoute>(new UnableToFindDownstreamRouteError(upstreamUrlPath, httpMethod));
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool RouteIsApplicableToThisRequest(ReRoute reRoute, string httpMethod, string upstreamHost)
|
private bool RouteIsApplicableToThisRequest(ReRoute reRoute, string httpMethod, string upstreamHost)
|
||||||
@ -53,9 +53,9 @@ namespace Ocelot.DownstreamRouteFinder.Finder
|
|||||||
(string.IsNullOrEmpty(reRoute.UpstreamHost) || reRoute.UpstreamHost == upstreamHost);
|
(string.IsNullOrEmpty(reRoute.UpstreamHost) || reRoute.UpstreamHost == upstreamHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DownstreamRoute GetPlaceholderNamesAndValues(string path, ReRoute reRoute)
|
private DownstreamRoute GetPlaceholderNamesAndValues(string path, string query, ReRoute reRoute)
|
||||||
{
|
{
|
||||||
var templatePlaceholderNameAndValues = _placeholderNameAndValueFinder.Find(path, reRoute.UpstreamPathTemplate.Value);
|
var templatePlaceholderNameAndValues = _placeholderNameAndValueFinder.Find(path, query, reRoute.UpstreamPathTemplate.Value);
|
||||||
|
|
||||||
return new DownstreamRoute(templatePlaceholderNameAndValues.Data, reRoute);
|
return new DownstreamRoute(templatePlaceholderNameAndValues.Data, reRoute);
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,16 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Configuration;
|
using Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Ocelot.Logging;
|
||||||
|
|
||||||
public class DownstreamRouteProviderFactory : IDownstreamRouteProviderFactory
|
public class DownstreamRouteProviderFactory : IDownstreamRouteProviderFactory
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, IDownstreamRouteProvider> _providers;
|
private readonly Dictionary<string, IDownstreamRouteProvider> _providers;
|
||||||
|
private IOcelotLogger _logger;
|
||||||
|
|
||||||
public DownstreamRouteProviderFactory(IServiceProvider provider)
|
public DownstreamRouteProviderFactory(IServiceProvider provider, IOcelotLoggerFactory factory)
|
||||||
{
|
{
|
||||||
|
_logger = factory.CreateLogger<DownstreamRouteProviderFactory>();
|
||||||
_providers = provider.GetServices<IDownstreamRouteProvider>().ToDictionary(x => x.GetType().Name);
|
_providers = provider.GetServices<IDownstreamRouteProvider>().ToDictionary(x => x.GetType().Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,6 +22,7 @@
|
|||||||
{
|
{
|
||||||
if(!config.ReRoutes.Any() && IsServiceDiscovery(config.ServiceProviderConfiguration))
|
if(!config.ReRoutes.Any() && IsServiceDiscovery(config.ServiceProviderConfiguration))
|
||||||
{
|
{
|
||||||
|
_logger.LogInformation($"Selected {nameof(DownstreamRouteCreator)} as DownstreamRouteProvider for this request");
|
||||||
return _providers[nameof(DownstreamRouteCreator)];
|
return _providers[nameof(DownstreamRouteCreator)];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +31,7 @@
|
|||||||
|
|
||||||
private bool IsServiceDiscovery(ServiceProviderConfiguration config)
|
private bool IsServiceDiscovery(ServiceProviderConfiguration config)
|
||||||
{
|
{
|
||||||
if(!string.IsNullOrEmpty(config?.Host) || config?.Port > 0)
|
if(!string.IsNullOrEmpty(config?.Host) && config?.Port > 0 && !string.IsNullOrEmpty(config.Type))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,6 @@ namespace Ocelot.DownstreamRouteFinder.Finder
|
|||||||
{
|
{
|
||||||
public interface IDownstreamRouteProvider
|
public interface IDownstreamRouteProvider
|
||||||
{
|
{
|
||||||
Response<DownstreamRoute> Get(string upstreamUrlPath, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost);
|
Response<DownstreamRoute> Get(string upstreamUrlPath, string upstreamQueryString, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,13 +33,15 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
|
|||||||
{
|
{
|
||||||
var upstreamUrlPath = context.HttpContext.Request.Path.ToString();
|
var upstreamUrlPath = context.HttpContext.Request.Path.ToString();
|
||||||
|
|
||||||
|
var upstreamQueryString = context.HttpContext.Request.QueryString.ToString();
|
||||||
|
|
||||||
var upstreamHost = context.HttpContext.Request.Headers["Host"];
|
var upstreamHost = context.HttpContext.Request.Headers["Host"];
|
||||||
|
|
||||||
Logger.LogDebug($"Upstream url path is {upstreamUrlPath}");
|
Logger.LogDebug($"Upstream url path is {upstreamUrlPath}");
|
||||||
|
|
||||||
var provider = _factory.Get(context.Configuration);
|
var provider = _factory.Get(context.Configuration);
|
||||||
|
|
||||||
var downstreamRoute = provider.Get(upstreamUrlPath, context.HttpContext.Request.Method, context.Configuration, upstreamHost);
|
var downstreamRoute = provider.Get(upstreamUrlPath, upstreamQueryString, context.HttpContext.Request.Method, context.Configuration, upstreamHost);
|
||||||
|
|
||||||
if (downstreamRoute.IsError)
|
if (downstreamRoute.IsError)
|
||||||
{
|
{
|
||||||
|
@ -5,6 +5,6 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher
|
|||||||
{
|
{
|
||||||
public interface IPlaceholderNameAndValueFinder
|
public interface IPlaceholderNameAndValueFinder
|
||||||
{
|
{
|
||||||
Response<List<PlaceholderNameAndValue>> Find(string path, string pathTemplate);
|
Response<List<PlaceholderNameAndValue>> Find(string path, string query, string pathTemplate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,6 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher
|
|||||||
{
|
{
|
||||||
public interface IUrlPathToUrlTemplateMatcher
|
public interface IUrlPathToUrlTemplateMatcher
|
||||||
{
|
{
|
||||||
Response<UrlMatch> Match(string upstreamUrlPath, string upstreamUrlPathTemplate);
|
Response<UrlMatch> Match(string upstreamUrlPath, string upstreamQueryString, string upstreamUrlPathTemplate, bool containsQueryString);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,11 +5,18 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher
|
|||||||
{
|
{
|
||||||
public class RegExUrlMatcher : IUrlPathToUrlTemplateMatcher
|
public class RegExUrlMatcher : IUrlPathToUrlTemplateMatcher
|
||||||
{
|
{
|
||||||
public Response<UrlMatch> Match(string upstreamUrlPath, string upstreamUrlPathTemplate)
|
public Response<UrlMatch> Match(string upstreamUrlPath, string upstreamQueryString, string upstreamUrlPathTemplate, bool containsQueryString)
|
||||||
{
|
{
|
||||||
var regex = new Regex(upstreamUrlPathTemplate);
|
var regex = new Regex(upstreamUrlPathTemplate);
|
||||||
|
|
||||||
return regex.IsMatch(upstreamUrlPath)
|
if (!containsQueryString)
|
||||||
|
{
|
||||||
|
return regex.IsMatch(upstreamUrlPath)
|
||||||
|
? new OkResponse<UrlMatch>(new UrlMatch(true))
|
||||||
|
: new OkResponse<UrlMatch>(new UrlMatch(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
return regex.IsMatch($"{upstreamUrlPath}{upstreamQueryString}")
|
||||||
? new OkResponse<UrlMatch>(new UrlMatch(true))
|
? new OkResponse<UrlMatch>(new UrlMatch(true))
|
||||||
: new OkResponse<UrlMatch>(new UrlMatch(false));
|
: new OkResponse<UrlMatch>(new UrlMatch(false));
|
||||||
}
|
}
|
||||||
|
@ -5,27 +5,46 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher
|
|||||||
{
|
{
|
||||||
public class UrlPathPlaceholderNameAndValueFinder : IPlaceholderNameAndValueFinder
|
public class UrlPathPlaceholderNameAndValueFinder : IPlaceholderNameAndValueFinder
|
||||||
{
|
{
|
||||||
public Response<List<PlaceholderNameAndValue>> Find(string path, string pathTemplate)
|
public Response<List<PlaceholderNameAndValue>> Find(string path, string query, string pathTemplate)
|
||||||
{
|
{
|
||||||
var placeHolderNameAndValues = new List<PlaceholderNameAndValue>();
|
var placeHolderNameAndValues = new List<PlaceholderNameAndValue>();
|
||||||
|
|
||||||
|
path = $"{path}{query}";
|
||||||
|
|
||||||
int counterForPath = 0;
|
int counterForPath = 0;
|
||||||
|
|
||||||
|
var delimiter = '/';
|
||||||
|
var nextDelimiter = '/';
|
||||||
|
|
||||||
for (int counterForTemplate = 0; counterForTemplate < pathTemplate.Length; counterForTemplate++)
|
for (int counterForTemplate = 0; counterForTemplate < pathTemplate.Length; counterForTemplate++)
|
||||||
{
|
{
|
||||||
if ((path.Length > counterForPath) && CharactersDontMatch(pathTemplate[counterForTemplate], path[counterForPath]) && ContinueScanningUrl(counterForPath,path.Length))
|
if ((path.Length > counterForPath) && CharactersDontMatch(pathTemplate[counterForTemplate], path[counterForPath]) && ContinueScanningUrl(counterForPath,path.Length))
|
||||||
{
|
{
|
||||||
if (IsPlaceholder(pathTemplate[counterForTemplate]))
|
if (IsPlaceholder(pathTemplate[counterForTemplate]))
|
||||||
{
|
{
|
||||||
|
//should_find_multiple_query_string make test pass
|
||||||
|
if (PassedQueryString(pathTemplate, counterForTemplate))
|
||||||
|
{
|
||||||
|
delimiter = '&';
|
||||||
|
nextDelimiter = '&';
|
||||||
|
}
|
||||||
|
|
||||||
|
//should_find_multiple_query_string_and_path makes test pass
|
||||||
|
if (NotPassedQueryString(pathTemplate, counterForTemplate) && NoMoreForwardSlash(pathTemplate, counterForTemplate))
|
||||||
|
{
|
||||||
|
delimiter = '?';
|
||||||
|
nextDelimiter = '?';
|
||||||
|
}
|
||||||
|
|
||||||
var placeholderName = GetPlaceholderName(pathTemplate, counterForTemplate);
|
var placeholderName = GetPlaceholderName(pathTemplate, counterForTemplate);
|
||||||
|
|
||||||
var placeholderValue = GetPlaceholderValue(pathTemplate, placeholderName, path, counterForPath);
|
var placeholderValue = GetPlaceholderValue(pathTemplate, query, placeholderName, path, counterForPath, delimiter);
|
||||||
|
|
||||||
placeHolderNameAndValues.Add(new PlaceholderNameAndValue(placeholderName, placeholderValue));
|
placeHolderNameAndValues.Add(new PlaceholderNameAndValue(placeholderName, placeholderValue));
|
||||||
|
|
||||||
counterForTemplate = GetNextCounterPosition(pathTemplate, counterForTemplate, '}');
|
counterForTemplate = GetNextCounterPosition(pathTemplate, counterForTemplate, '}');
|
||||||
|
|
||||||
counterForPath = GetNextCounterPosition(path, counterForPath, '/');
|
counterForPath = GetNextCounterPosition(path, counterForPath, nextDelimiter);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -44,7 +63,7 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var placeholderValue = GetPlaceholderValue(pathTemplate, placeholderName, path, counterForPath + 1);
|
var placeholderValue = GetPlaceholderValue(pathTemplate, query, placeholderName, path, counterForPath + 1, '/');
|
||||||
placeHolderNameAndValues.Add(new PlaceholderNameAndValue(placeholderName, placeholderValue));
|
placeHolderNameAndValues.Add(new PlaceholderNameAndValue(placeholderName, placeholderValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +76,21 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher
|
|||||||
return new OkResponse<List<PlaceholderNameAndValue>>(placeHolderNameAndValues);
|
return new OkResponse<List<PlaceholderNameAndValue>>(placeHolderNameAndValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool NoMoreForwardSlash(string pathTemplate, int counterForTemplate)
|
||||||
|
{
|
||||||
|
return !pathTemplate.Substring(counterForTemplate).Contains("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool NotPassedQueryString(string pathTemplate, int counterForTemplate)
|
||||||
|
{
|
||||||
|
return !pathTemplate.Substring(0, counterForTemplate).Contains("?");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool PassedQueryString(string pathTemplate, int counterForTemplate)
|
||||||
|
{
|
||||||
|
return pathTemplate.Substring(0, counterForTemplate).Contains("?");
|
||||||
|
}
|
||||||
|
|
||||||
private bool IsCatchAll(string path, int counterForPath, string pathTemplate)
|
private bool IsCatchAll(string path, int counterForPath, string pathTemplate)
|
||||||
{
|
{
|
||||||
return string.IsNullOrEmpty(path) || (path.Length > counterForPath && path[counterForPath] == '/') && pathTemplate.Length > 1
|
return string.IsNullOrEmpty(path) || (path.Length > counterForPath && path[counterForPath] == '/') && pathTemplate.Length > 1
|
||||||
@ -69,11 +103,11 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher
|
|||||||
return path.Length == 1 || path.Length == 0;
|
return path.Length == 1 || path.Length == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetPlaceholderValue(string urlPathTemplate, string variableName, string urlPath, int counterForUrl)
|
private string GetPlaceholderValue(string urlPathTemplate, string query, string variableName, string urlPath, int counterForUrl, char delimiter)
|
||||||
{
|
{
|
||||||
var positionOfNextSlash = urlPath.IndexOf('/', counterForUrl);
|
var positionOfNextSlash = urlPath.IndexOf(delimiter, counterForUrl);
|
||||||
|
|
||||||
if (positionOfNextSlash == -1 || urlPathTemplate.Trim('/').EndsWith(variableName))
|
if (positionOfNextSlash == -1 || (urlPathTemplate.Trim(delimiter).EndsWith(variableName) && string.IsNullOrEmpty(query)))
|
||||||
{
|
{
|
||||||
positionOfNextSlash = urlPath.Length;
|
positionOfNextSlash = urlPath.Length;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer;
|
using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer;
|
||||||
using Ocelot.Infrastructure.RequestData;
|
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.Middleware;
|
using Ocelot.Middleware;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using Ocelot.Values;
|
using Ocelot.Values;
|
||||||
|
|
||||||
namespace Ocelot.DownstreamUrlCreator.Middleware
|
namespace Ocelot.DownstreamUrlCreator.Middleware
|
||||||
{
|
{
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
public class DownstreamUrlCreatorMiddleware : OcelotMiddleware
|
public class DownstreamUrlCreatorMiddleware : OcelotMiddleware
|
||||||
{
|
{
|
||||||
private readonly OcelotRequestDelegate _next;
|
private readonly OcelotRequestDelegate _next;
|
||||||
@ -28,14 +26,14 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(DownstreamContext context)
|
public async Task Invoke(DownstreamContext context)
|
||||||
{
|
{
|
||||||
var dsPath = _replacer
|
var response = _replacer
|
||||||
.Replace(context.DownstreamReRoute.DownstreamPathTemplate, context.TemplatePlaceholderNameAndValues);
|
.Replace(context.DownstreamReRoute.DownstreamPathTemplate, context.TemplatePlaceholderNameAndValues);
|
||||||
|
|
||||||
if (dsPath.IsError)
|
if (response.IsError)
|
||||||
{
|
{
|
||||||
Logger.LogDebug("IDownstreamPathPlaceholderReplacer returned an error, setting pipeline error");
|
Logger.LogDebug("IDownstreamPathPlaceholderReplacer returned an error, setting pipeline error");
|
||||||
|
|
||||||
SetPipelineError(context, dsPath.Errors);
|
SetPipelineError(context, response.Errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,13 +41,25 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
|||||||
|
|
||||||
if (ServiceFabricRequest(context))
|
if (ServiceFabricRequest(context))
|
||||||
{
|
{
|
||||||
var pathAndQuery = CreateServiceFabricUri(context, dsPath);
|
var pathAndQuery = CreateServiceFabricUri(context, response);
|
||||||
context.DownstreamRequest.AbsolutePath = pathAndQuery.path;
|
context.DownstreamRequest.AbsolutePath = pathAndQuery.path;
|
||||||
context.DownstreamRequest.Query = pathAndQuery.query;
|
context.DownstreamRequest.Query = pathAndQuery.query;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context.DownstreamRequest.AbsolutePath = dsPath.Data.Value;
|
var dsPath = response.Data;
|
||||||
|
|
||||||
|
if(ContainsQueryString(dsPath))
|
||||||
|
{
|
||||||
|
context.DownstreamRequest.AbsolutePath = GetPath(dsPath);
|
||||||
|
context.DownstreamRequest.Query = GetQueryString(dsPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RemoveQueryStringParametersThatHaveBeenUsedInTemplate(context);
|
||||||
|
|
||||||
|
context.DownstreamRequest.AbsolutePath = dsPath.Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.LogDebug($"Downstream url is {context.DownstreamRequest}");
|
Logger.LogDebug($"Downstream url is {context.DownstreamRequest}");
|
||||||
@ -57,6 +67,44 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
|||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void RemoveQueryStringParametersThatHaveBeenUsedInTemplate(DownstreamContext context)
|
||||||
|
{
|
||||||
|
foreach (var nAndV in context.TemplatePlaceholderNameAndValues)
|
||||||
|
{
|
||||||
|
var name = nAndV.Name.Replace("{", "").Replace("}", "");
|
||||||
|
|
||||||
|
if (context.DownstreamRequest.Query.Contains(name) &&
|
||||||
|
context.DownstreamRequest.Query.Contains(nAndV.Value))
|
||||||
|
{
|
||||||
|
var questionMarkOrAmpersand = context.DownstreamRequest.Query.IndexOf(name, StringComparison.Ordinal);
|
||||||
|
context.DownstreamRequest.Query = context.DownstreamRequest.Query.Remove(questionMarkOrAmpersand - 1, 1);
|
||||||
|
|
||||||
|
var rgx = new Regex($@"\b{name}={nAndV.Value}\b");
|
||||||
|
context.DownstreamRequest.Query = rgx.Replace(context.DownstreamRequest.Query, "");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(context.DownstreamRequest.Query))
|
||||||
|
{
|
||||||
|
context.DownstreamRequest.Query = '?' + context.DownstreamRequest.Query.Substring(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetPath(DownstreamPath dsPath)
|
||||||
|
{
|
||||||
|
return dsPath.Value.Substring(0, dsPath.Value.IndexOf("?", StringComparison.Ordinal));
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetQueryString(DownstreamPath dsPath)
|
||||||
|
{
|
||||||
|
return dsPath.Value.Substring(dsPath.Value.IndexOf("?", StringComparison.Ordinal));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ContainsQueryString(DownstreamPath dsPath)
|
||||||
|
{
|
||||||
|
return dsPath.Value.Contains("?");
|
||||||
|
}
|
||||||
|
|
||||||
private (string path, string query) CreateServiceFabricUri(DownstreamContext context, Response<DownstreamPath> dsPath)
|
private (string path, string query) CreateServiceFabricUri(DownstreamContext context, Response<DownstreamPath> dsPath)
|
||||||
{
|
{
|
||||||
var query = context.DownstreamRequest.Query;
|
var query = context.DownstreamRequest.Query;
|
||||||
|
@ -38,6 +38,11 @@ namespace Ocelot.Headers.Middleware
|
|||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
|
if(context.IsError)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var postFAndRs = context.DownstreamReRoute.DownstreamHeadersFindAndReplace;
|
var postFAndRs = context.DownstreamReRoute.DownstreamHeadersFindAndReplace;
|
||||||
|
|
||||||
_postReplacer.Replace(context.DownstreamResponse, postFAndRs, context.DownstreamRequest);
|
_postReplacer.Replace(context.DownstreamResponse, postFAndRs, context.DownstreamRequest);
|
||||||
|
@ -20,7 +20,7 @@ namespace Ocelot.LoadBalancer.LoadBalancers
|
|||||||
public async Task<Response<ServiceHostAndPort>> Lease(DownstreamContext downstreamContext)
|
public async Task<Response<ServiceHostAndPort>> Lease(DownstreamContext downstreamContext)
|
||||||
{
|
{
|
||||||
var services = await _services();
|
var services = await _services();
|
||||||
//todo first or default could be null..
|
|
||||||
if (services == null || services.Count == 0)
|
if (services == null || services.Count == 0)
|
||||||
{
|
{
|
||||||
return new ErrorResponse<ServiceHostAndPort>(new ServicesAreEmptyError("There were no services in NoLoadBalancer"));
|
return new ErrorResponse<ServiceHostAndPort>(new ServicesAreEmptyError("There were no services in NoLoadBalancer"));
|
||||||
|
@ -29,13 +29,19 @@
|
|||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder builder, Action<OcelotPipelineConfiguration> pipelineConfiguration)
|
||||||
|
{
|
||||||
|
var config = new OcelotPipelineConfiguration();
|
||||||
|
pipelineConfiguration?.Invoke(config);
|
||||||
|
return await builder.UseOcelot(config);
|
||||||
|
}
|
||||||
public static async Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder builder, OcelotPipelineConfiguration pipelineConfiguration)
|
public static async Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder builder, OcelotPipelineConfiguration pipelineConfiguration)
|
||||||
{
|
{
|
||||||
var configuration = await CreateConfiguration(builder);
|
var configuration = await CreateConfiguration(builder);
|
||||||
|
|
||||||
CreateAdministrationArea(builder, configuration);
|
CreateAdministrationArea(builder, configuration);
|
||||||
|
|
||||||
if(UsingRafty(builder))
|
if (UsingRafty(builder))
|
||||||
{
|
{
|
||||||
SetUpRafty(builder);
|
SetUpRafty(builder);
|
||||||
}
|
}
|
||||||
@ -78,7 +84,7 @@
|
|||||||
private static bool UsingRafty(IApplicationBuilder builder)
|
private static bool UsingRafty(IApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
var possible = builder.ApplicationServices.GetService(typeof(INode)) as INode;
|
var possible = builder.ApplicationServices.GetService(typeof(INode)) as INode;
|
||||||
if(possible != null)
|
if (possible != null)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -196,7 +202,7 @@
|
|||||||
{
|
{
|
||||||
var ocelotConfiguration = provider.Get();
|
var ocelotConfiguration = provider.Get();
|
||||||
|
|
||||||
if(ocelotConfiguration?.Data == null || ocelotConfiguration.IsError)
|
if (ocelotConfiguration?.Data == null || ocelotConfiguration.IsError)
|
||||||
{
|
{
|
||||||
ThrowToStopOcelotStarting(ocelotConfiguration);
|
ThrowToStopOcelotStarting(ocelotConfiguration);
|
||||||
}
|
}
|
||||||
@ -216,7 +222,7 @@
|
|||||||
|
|
||||||
private static void CreateAdministrationArea(IApplicationBuilder builder, IInternalConfiguration configuration)
|
private static void CreateAdministrationArea(IApplicationBuilder builder, IInternalConfiguration configuration)
|
||||||
{
|
{
|
||||||
if(!string.IsNullOrEmpty(configuration.AdministrationPath))
|
if (!string.IsNullOrEmpty(configuration.AdministrationPath))
|
||||||
{
|
{
|
||||||
builder.Map(configuration.AdministrationPath, app =>
|
builder.Map(configuration.AdministrationPath, app =>
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
namespace Ocelot.Middleware
|
namespace Ocelot.Middleware
|
||||||
{
|
{
|
||||||
|
using Ocelot.Middleware.Pipeline;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
public class OcelotPipelineConfiguration
|
public class OcelotPipelineConfiguration
|
||||||
@ -38,5 +40,9 @@
|
|||||||
/// This allows the user to implement there own query string manipulation logic
|
/// This allows the user to implement there own query string manipulation logic
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Func<DownstreamContext, Func<Task>, Task> PreQueryStringBuilderMiddleware { get; set; }
|
public Func<DownstreamContext, Func<Task>, Task> PreQueryStringBuilderMiddleware { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// This is an extension that will branch to different pipes
|
||||||
|
/// </summary>
|
||||||
|
public List<Func<IOcelotPipelineBuilder, Func<DownstreamContext, bool>>> MapWhenOcelotPipeline { get; } = new List<Func<IOcelotPipelineBuilder, Func<DownstreamContext, bool>>>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,13 +80,14 @@ namespace Ocelot.Middleware.Pipeline
|
|||||||
var diagnosticListener = (DiagnosticListener)app.ApplicationServices.GetService(typeof(DiagnosticListener));
|
var diagnosticListener = (DiagnosticListener)app.ApplicationServices.GetService(typeof(DiagnosticListener));
|
||||||
var middlewareName = ocelotDelegate.Target.GetType().Name;
|
var middlewareName = ocelotDelegate.Target.GetType().Name;
|
||||||
|
|
||||||
OcelotRequestDelegate wrapped = context => {
|
OcelotRequestDelegate wrapped = context =>
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Write(diagnosticListener, "Ocelot.MiddlewareStarted", middlewareName, context);
|
Write(diagnosticListener, "Ocelot.MiddlewareStarted", middlewareName, context);
|
||||||
return ocelotDelegate(context);
|
return ocelotDelegate(context);
|
||||||
}
|
}
|
||||||
catch(Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
WriteException(diagnosticListener, ex, "Ocelot.MiddlewareException", middlewareName, context);
|
WriteException(diagnosticListener, ex, "Ocelot.MiddlewareException", middlewareName, context);
|
||||||
throw ex;
|
throw ex;
|
||||||
@ -117,7 +118,7 @@ namespace Ocelot.Middleware.Pipeline
|
|||||||
|
|
||||||
private static void Write(DiagnosticListener diagnosticListener, string message, string middlewareName, DownstreamContext context)
|
private static void Write(DiagnosticListener diagnosticListener, string message, string middlewareName, DownstreamContext context)
|
||||||
{
|
{
|
||||||
if(diagnosticListener != null)
|
if (diagnosticListener != null)
|
||||||
{
|
{
|
||||||
diagnosticListener.Write(message, new { name = middlewareName, context = context });
|
diagnosticListener.Write(message, new { name = middlewareName, context = context });
|
||||||
}
|
}
|
||||||
@ -125,7 +126,7 @@ namespace Ocelot.Middleware.Pipeline
|
|||||||
|
|
||||||
private static void WriteException(DiagnosticListener diagnosticListener, Exception exception, string message, string middlewareName, DownstreamContext context)
|
private static void WriteException(DiagnosticListener diagnosticListener, Exception exception, string message, string middlewareName, DownstreamContext context)
|
||||||
{
|
{
|
||||||
if(diagnosticListener != null)
|
if (diagnosticListener != null)
|
||||||
{
|
{
|
||||||
diagnosticListener.Write(message, new { name = middlewareName, context = context, exception = exception });
|
diagnosticListener.Write(message, new { name = middlewareName, context = context, exception = exception });
|
||||||
}
|
}
|
||||||
@ -160,6 +161,28 @@ namespace Ocelot.Middleware.Pipeline
|
|||||||
return app.Use(next => new MapWhenMiddleware(next, options).Invoke);
|
return app.Use(next => new MapWhenMiddleware(next, options).Invoke);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IOcelotPipelineBuilder MapWhen(this IOcelotPipelineBuilder app, Func<IOcelotPipelineBuilder, Predicate> pipelineBuilderFunc)
|
||||||
|
{
|
||||||
|
if (app == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(app));
|
||||||
|
}
|
||||||
|
if (pipelineBuilderFunc == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(pipelineBuilderFunc));
|
||||||
|
}
|
||||||
|
var branchBuilder = app.New();
|
||||||
|
var predicate = pipelineBuilderFunc.Invoke(app);
|
||||||
|
var branch = branchBuilder.Build();
|
||||||
|
|
||||||
|
var options = new MapWhenOptions
|
||||||
|
{
|
||||||
|
Predicate = predicate,
|
||||||
|
Branch = branch
|
||||||
|
};
|
||||||
|
return app.Use(next => new MapWhenMiddleware(next, options).Invoke);
|
||||||
|
}
|
||||||
|
|
||||||
private static Func<T, DownstreamContext, IServiceProvider, Task> Compile<T>(MethodInfo methodinfo, ParameterInfo[] parameters)
|
private static Func<T, DownstreamContext, IServiceProvider, Task> Compile<T>(MethodInfo methodinfo, ParameterInfo[] parameters)
|
||||||
{
|
{
|
||||||
var middleware = typeof(T);
|
var middleware = typeof(T);
|
||||||
|
@ -28,6 +28,15 @@ namespace Ocelot.Middleware.Pipeline
|
|||||||
// It also sets the Request Id if anything is set globally
|
// It also sets the Request Id if anything is set globally
|
||||||
builder.UseExceptionHandlerMiddleware();
|
builder.UseExceptionHandlerMiddleware();
|
||||||
|
|
||||||
|
//Expand other branch pipes
|
||||||
|
if (pipelineConfiguration.MapWhenOcelotPipeline != null)
|
||||||
|
{
|
||||||
|
foreach (var pipeline in pipelineConfiguration.MapWhenOcelotPipeline)
|
||||||
|
{
|
||||||
|
builder.MapWhen(pipeline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the request is for websockets upgrade we fork into a different pipeline
|
// If the request is for websockets upgrade we fork into a different pipeline
|
||||||
builder.MapWhen(context => context.HttpContext.WebSockets.IsWebSocketRequest,
|
builder.MapWhen(context => context.HttpContext.WebSockets.IsWebSocketRequest,
|
||||||
app =>
|
app =>
|
||||||
|
@ -25,37 +25,37 @@
|
|||||||
<DebugSymbols>True</DebugSymbols>
|
<DebugSymbols>True</DebugSymbols>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Butterfly.Client" Version="0.0.8"/>
|
<PackageReference Include="Butterfly.Client" Version="0.0.8" />
|
||||||
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8">
|
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8">
|
||||||
<NoWarn>NU1701</NoWarn>
|
<NoWarn>NU1701</NoWarn>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="FluentValidation" Version="7.5.2"/>
|
<PackageReference Include="FluentValidation" Version="7.6.104" />
|
||||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.6.0"/>
|
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.6.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.3"/>
|
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.4"/>
|
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.MiddlewareAnalysis" Version="2.0.3"/>
|
<PackageReference Include="Microsoft.AspNetCore.MiddlewareAnalysis" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Data.SQLite" Version="2.0.1"/>
|
<PackageReference Include="Microsoft.Data.SQLite" Version="2.1.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.2"/>
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.2"/>
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.2"/>
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" Version="2.0.1">
|
<PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" Version="2.1.0">
|
||||||
<NoWarn>NU1701</NoWarn>
|
<NoWarn>NU1701</NoWarn>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.2"/>
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.2"/>
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.2"/>
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.2"/>
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.1.1" />
|
||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
|
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.0"/>
|
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.0" />
|
||||||
<PackageReference Include="CacheManager.Core" Version="1.1.2"/>
|
<PackageReference Include="CacheManager.Core" Version="1.1.2" />
|
||||||
<PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="1.1.2"/>
|
<PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="1.1.2" />
|
||||||
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="1.1.2"/>
|
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="1.1.2" />
|
||||||
<PackageReference Include="Consul" Version="0.7.2.4"/>
|
<PackageReference Include="Consul" Version="0.7.2.5" />
|
||||||
<PackageReference Include="Polly" Version="6.0.1"/>
|
<PackageReference Include="Polly" Version="6.0.1" />
|
||||||
<PackageReference Include="IdentityServer4" Version="2.2.0"/>
|
<PackageReference Include="IdentityServer4" Version="2.2.0" />
|
||||||
<PackageReference Include="Pivotal.Discovery.ClientCore" Version="2.0.1"/>
|
<PackageReference Include="Pivotal.Discovery.ClientCore" Version="2.0.1" />
|
||||||
<PackageReference Include="Rafty" Version="0.4.4"/>
|
<PackageReference Include="Rafty" Version="0.4.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -99,6 +99,7 @@ namespace Ocelot.Raft
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_sempaphore.Release();
|
_sempaphore.Release();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -120,6 +121,7 @@ namespace Ocelot.Raft
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_sempaphore.Release();
|
_sempaphore.Release();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -135,6 +137,7 @@ namespace Ocelot.Raft
|
|||||||
TypeNameHandling = TypeNameHandling.All
|
TypeNameHandling = TypeNameHandling.All
|
||||||
};
|
};
|
||||||
var data = JsonConvert.SerializeObject(log, jsonSerializerSettings);
|
var data = JsonConvert.SerializeObject(log, jsonSerializerSettings);
|
||||||
|
|
||||||
//todo - sql injection dont copy this..
|
//todo - sql injection dont copy this..
|
||||||
var sql = $"insert into logs (data) values ('{data}')";
|
var sql = $"insert into logs (data) values ('{data}')";
|
||||||
_logger.LogInformation($"id: {_nodeId.Id}, sql: {sql}");
|
_logger.LogInformation($"id: {_nodeId.Id}, sql: {sql}");
|
||||||
@ -162,6 +165,7 @@ namespace Ocelot.Raft
|
|||||||
using (var connection = new SqliteConnection($"Data Source={_path};"))
|
using (var connection = new SqliteConnection($"Data Source={_path};"))
|
||||||
{
|
{
|
||||||
connection.Open();
|
connection.Open();
|
||||||
|
|
||||||
//todo - sql injection dont copy this..
|
//todo - sql injection dont copy this..
|
||||||
var sql = $"select data from logs where id = {index};";
|
var sql = $"select data from logs where id = {index};";
|
||||||
_logger.LogInformation($"id: {_nodeId.Id} sql: {sql}");
|
_logger.LogInformation($"id: {_nodeId.Id} sql: {sql}");
|
||||||
@ -188,6 +192,7 @@ namespace Ocelot.Raft
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_sempaphore.Release();
|
_sempaphore.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,6 +202,7 @@ namespace Ocelot.Raft
|
|||||||
using (var connection = new SqliteConnection($"Data Source={_path};"))
|
using (var connection = new SqliteConnection($"Data Source={_path};"))
|
||||||
{
|
{
|
||||||
connection.Open();
|
connection.Open();
|
||||||
|
|
||||||
//todo - sql injection dont copy this..
|
//todo - sql injection dont copy this..
|
||||||
var sql = $"select data from logs where id = {index};";
|
var sql = $"select data from logs where id = {index};";
|
||||||
using (var command = new SqliteCommand(sql, connection))
|
using (var command = new SqliteCommand(sql, connection))
|
||||||
@ -227,6 +233,7 @@ namespace Ocelot.Raft
|
|||||||
using (var connection = new SqliteConnection($"Data Source={_path};"))
|
using (var connection = new SqliteConnection($"Data Source={_path};"))
|
||||||
{
|
{
|
||||||
connection.Open();
|
connection.Open();
|
||||||
|
|
||||||
//todo - sql injection dont copy this..
|
//todo - sql injection dont copy this..
|
||||||
var sql = $"select data from logs where id = {index}";
|
var sql = $"select data from logs where id = {index}";
|
||||||
using (var command = new SqliteCommand(sql, connection))
|
using (var command = new SqliteCommand(sql, connection))
|
||||||
@ -251,6 +258,7 @@ namespace Ocelot.Raft
|
|||||||
using (var connection = new SqliteConnection($"Data Source={_path};"))
|
using (var connection = new SqliteConnection($"Data Source={_path};"))
|
||||||
{
|
{
|
||||||
connection.Open();
|
connection.Open();
|
||||||
|
|
||||||
//todo - sql injection dont copy this..
|
//todo - sql injection dont copy this..
|
||||||
var sql = $"select id, data from logs where id >= {index}";
|
var sql = $"select id, data from logs where id >= {index}";
|
||||||
using (var command = new SqliteCommand(sql, connection))
|
using (var command = new SqliteCommand(sql, connection))
|
||||||
@ -267,10 +275,10 @@ namespace Ocelot.Raft
|
|||||||
};
|
};
|
||||||
var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings);
|
var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings);
|
||||||
logsToReturn.Add((id, log));
|
logsToReturn.Add((id, log));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_sempaphore.Release();
|
_sempaphore.Release();
|
||||||
return logsToReturn;
|
return logsToReturn;
|
||||||
}
|
}
|
||||||
@ -283,6 +291,7 @@ namespace Ocelot.Raft
|
|||||||
using (var connection = new SqliteConnection($"Data Source={_path};"))
|
using (var connection = new SqliteConnection($"Data Source={_path};"))
|
||||||
{
|
{
|
||||||
connection.Open();
|
connection.Open();
|
||||||
|
|
||||||
//todo - sql injection dont copy this..
|
//todo - sql injection dont copy this..
|
||||||
var sql = $"select data from logs where id = {index}";
|
var sql = $"select data from logs where id = {index}";
|
||||||
using (var command = new SqliteCommand(sql, connection))
|
using (var command = new SqliteCommand(sql, connection))
|
||||||
@ -299,15 +308,18 @@ namespace Ocelot.Raft
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_sempaphore.Release();
|
_sempaphore.Release();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Remove(int indexOfCommand)
|
public async Task Remove(int indexOfCommand)
|
||||||
{
|
{
|
||||||
_sempaphore.Wait();
|
_sempaphore.Wait();
|
||||||
using (var connection = new SqliteConnection($"Data Source={_path};"))
|
using (var connection = new SqliteConnection($"Data Source={_path};"))
|
||||||
{
|
{
|
||||||
connection.Open();
|
connection.Open();
|
||||||
|
|
||||||
//todo - sql injection dont copy this..
|
//todo - sql injection dont copy this..
|
||||||
var deleteSql = $"delete from logs where id >= {indexOfCommand};";
|
var deleteSql = $"delete from logs where id >= {indexOfCommand};";
|
||||||
_logger.LogInformation($"id: {_nodeId.Id} Remove {deleteSql}");
|
_logger.LogInformation($"id: {_nodeId.Id} Remove {deleteSql}");
|
||||||
@ -316,6 +328,7 @@ namespace Ocelot.Raft
|
|||||||
var result = await deleteCommand.ExecuteNonQueryAsync();
|
var result = await deleteCommand.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_sempaphore.Release();
|
_sempaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,12 @@ namespace Ocelot.Request.Creator
|
|||||||
{
|
{
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Ocelot.Request.Middleware;
|
using Ocelot.Request.Middleware;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using Ocelot.Infrastructure;
|
using Ocelot.Infrastructure;
|
||||||
|
|
||||||
public class DownstreamRequestCreator : IDownstreamRequestCreator
|
public class DownstreamRequestCreator : IDownstreamRequestCreator
|
||||||
{
|
{
|
||||||
private readonly IFrameworkDescription _framework;
|
private readonly IFrameworkDescription _framework;
|
||||||
private const string dotNetFramework = ".NET Framework";
|
private const string DotNetFramework = ".NET Framework";
|
||||||
|
|
||||||
public DownstreamRequestCreator(IFrameworkDescription framework)
|
public DownstreamRequestCreator(IFrameworkDescription framework)
|
||||||
{
|
{
|
||||||
@ -24,8 +23,7 @@ namespace Ocelot.Request.Creator
|
|||||||
* And MS HttpClient in Full Framework actually rejects it.
|
* And MS HttpClient in Full Framework actually rejects it.
|
||||||
* see #366 issue
|
* see #366 issue
|
||||||
**/
|
**/
|
||||||
|
if(_framework.Get().Contains(DotNetFramework))
|
||||||
if(_framework.Get().Contains(dotNetFramework))
|
|
||||||
{
|
{
|
||||||
if (request.Method == HttpMethod.Get ||
|
if (request.Method == HttpMethod.Get ||
|
||||||
request.Method == HttpMethod.Head ||
|
request.Method == HttpMethod.Head ||
|
||||||
|
@ -28,6 +28,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);
|
||||||
|
|
||||||
if (downstreamRequest.IsError)
|
if (downstreamRequest.IsError)
|
||||||
{
|
{
|
||||||
SetPipelineError(context, downstreamRequest.Errors);
|
SetPipelineError(context, downstreamRequest.Errors);
|
||||||
|
@ -40,6 +40,7 @@ namespace Ocelot.Requester
|
|||||||
|
|
||||||
if (httpClient != null)
|
if (httpClient != null)
|
||||||
{
|
{
|
||||||
|
_client = httpClient;
|
||||||
return httpClient;
|
return httpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,10 @@
|
|||||||
using System;
|
namespace Ocelot.Requester
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Ocelot.Requester
|
|
||||||
{
|
{
|
||||||
|
using System;
|
||||||
|
|
||||||
public interface IHttpClientCache
|
public interface IHttpClientCache
|
||||||
{
|
{
|
||||||
bool Exists(string id);
|
IHttpClient Get(string key);
|
||||||
IHttpClient Get(string id);
|
void Set(string key, IHttpClient handler, TimeSpan expirationTime);
|
||||||
void Remove(string id);
|
|
||||||
void Set(string id, IHttpClient handler, TimeSpan expirationTime);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,54 +1,26 @@
|
|||||||
using Microsoft.Extensions.Caching.Memory;
|
namespace Ocelot.Requester
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Ocelot.Requester
|
|
||||||
{
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
public class MemoryHttpClientCache : IHttpClientCache
|
public class MemoryHttpClientCache : IHttpClientCache
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<string, ConcurrentQueue<IHttpClient>> _httpClientsCache = new ConcurrentDictionary<string, ConcurrentQueue<IHttpClient>>();
|
private readonly ConcurrentDictionary<string, IHttpClient> _httpClientsCache;
|
||||||
|
|
||||||
public void Set(string id, IHttpClient client, TimeSpan expirationTime)
|
public MemoryHttpClientCache()
|
||||||
{
|
{
|
||||||
ConcurrentQueue<IHttpClient> connectionQueue;
|
_httpClientsCache = new ConcurrentDictionary<string, IHttpClient>();
|
||||||
if (_httpClientsCache.TryGetValue(id, out connectionQueue))
|
|
||||||
{
|
|
||||||
connectionQueue.Enqueue(client);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
connectionQueue = new ConcurrentQueue<IHttpClient>();
|
|
||||||
connectionQueue.Enqueue(client);
|
|
||||||
_httpClientsCache.TryAdd(id, connectionQueue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Exists(string id)
|
public void Set(string key, IHttpClient client, TimeSpan expirationTime)
|
||||||
{
|
{
|
||||||
ConcurrentQueue<IHttpClient> connectionQueue;
|
_httpClientsCache.AddOrUpdate(key, client, (k, oldValue) => client);
|
||||||
return _httpClientsCache.TryGetValue(id, out connectionQueue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IHttpClient Get(string id)
|
public IHttpClient Get(string key)
|
||||||
{
|
{
|
||||||
IHttpClient client= null;
|
//todo handle error?
|
||||||
ConcurrentQueue<IHttpClient> connectionQueue;
|
return _httpClientsCache.TryGetValue(key, out var client) ? client : null;
|
||||||
if (_httpClientsCache.TryGetValue(id, out connectionQueue))
|
|
||||||
{
|
|
||||||
connectionQueue.TryDequeue(out client);
|
|
||||||
}
|
|
||||||
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Remove(string id)
|
|
||||||
{
|
|
||||||
ConcurrentQueue<IHttpClient> connectionQueue;
|
|
||||||
_httpClientsCache.TryRemove(id, out connectionQueue);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,16 @@ namespace Ocelot.Values
|
|||||||
{
|
{
|
||||||
public class UpstreamPathTemplate
|
public class UpstreamPathTemplate
|
||||||
{
|
{
|
||||||
public UpstreamPathTemplate(string template, int priority)
|
public UpstreamPathTemplate(string template, int priority, bool containsQueryString)
|
||||||
{
|
{
|
||||||
Template = template;
|
Template = template;
|
||||||
Priority = priority;
|
Priority = priority;
|
||||||
|
ContainsQueryString = containsQueryString;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Template { get; }
|
public string Template { get; }
|
||||||
|
|
||||||
public int Priority { get; }
|
public int Priority { get; }
|
||||||
|
public bool ContainsQueryString { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,57 @@ namespace Ocelot.AcceptanceTests
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_call_global_di_handlers_multiple_times()
|
||||||
|
{
|
||||||
|
var configuration = new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
DownstreamPathTemplate = "/",
|
||||||
|
DownstreamScheme = "http",
|
||||||
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||||
|
{
|
||||||
|
new FileHostAndPort
|
||||||
|
{
|
||||||
|
Host = "localhost",
|
||||||
|
Port = 9187,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UpstreamPathTemplate = "/",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:9187", "/", 200, "Hello from Laura"))
|
||||||
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
|
.And(x => _steps.GivenOcelotIsRunningWithGlobalHandlerRegisteredInDi<FakeHandlerAgain>())
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
|
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_call_global_di_handlers_with_dependency()
|
public void should_call_global_di_handlers_with_dependency()
|
||||||
{
|
{
|
||||||
@ -198,6 +249,17 @@ namespace Ocelot.AcceptanceTests
|
|||||||
return base.SendAsync(request, cancellationToken);
|
return base.SendAsync(request, cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ReSharper disable once ClassNeverInstantiated.Local
|
||||||
|
private class FakeHandlerAgain : DelegatingHandler
|
||||||
|
{
|
||||||
|
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Console.WriteLine(request.RequestUri);
|
||||||
|
|
||||||
|
//do stuff and optionally call the base handler..
|
||||||
|
return await base.SendAsync(request, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode, string responseBody)
|
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode, string responseBody)
|
||||||
{
|
{
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||||
<RuntimeFrameworkVersion>2.0.0</RuntimeFrameworkVersion>
|
|
||||||
<AssemblyName>Ocelot.AcceptanceTests</AssemblyName>
|
<AssemblyName>Ocelot.AcceptanceTests</AssemblyName>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<PackageId>Ocelot.AcceptanceTests</PackageId>
|
<PackageId>Ocelot.AcceptanceTests</PackageId>
|
||||||
@ -34,25 +33,25 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CacheManager.Serialization.Json" Version="1.1.2" />
|
<PackageReference Include="CacheManager.Serialization.Json" Version="1.1.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.3" />
|
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
|
||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
|
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
||||||
<PackageReference Include="Shouldly" Version="3.0.0" />
|
<PackageReference Include="Shouldly" Version="3.0.0" />
|
||||||
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
||||||
<PackageReference Include="Consul" Version="0.7.2.4" />
|
<PackageReference Include="Consul" Version="0.7.2.5" />
|
||||||
<PackageReference Include="xunit" Version="2.3.1" />
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
|
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
|
||||||
<PackageReference Include="Rafty" Version="0.4.4" />
|
<PackageReference Include="Rafty" Version="0.4.4" />
|
||||||
|
84
test/Ocelot.AcceptanceTests/ResponseCodeTests.cs
Normal file
84
test/Ocelot.AcceptanceTests/ResponseCodeTests.cs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
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 ResponseCodeTests : IDisposable
|
||||||
|
{
|
||||||
|
private IWebHost _builder;
|
||||||
|
private readonly Steps _steps;
|
||||||
|
private string _downstreamPath;
|
||||||
|
|
||||||
|
public ResponseCodeTests()
|
||||||
|
{
|
||||||
|
_steps = new Steps();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_response_304_when_service_returns_304()
|
||||||
|
{
|
||||||
|
var configuration = new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
DownstreamPathTemplate = "/{everything}",
|
||||||
|
DownstreamScheme = "http",
|
||||||
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||||
|
{
|
||||||
|
new FileHostAndPort
|
||||||
|
{
|
||||||
|
Host = "localhost",
|
||||||
|
Port = 51879,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UpstreamPathTemplate = "/{everything}",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/inline.132.bundle.js", 304))
|
||||||
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
|
.And(x => _steps.GivenOcelotIsRunning())
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/inline.132.bundle.js"))
|
||||||
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.NotModified))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode)
|
||||||
|
{
|
||||||
|
_builder = new WebHostBuilder()
|
||||||
|
.UseUrls(baseUrl)
|
||||||
|
.UseKestrel()
|
||||||
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
|
.UseIISIntegration()
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UsePathBase(basePath);
|
||||||
|
app.Run(async context =>
|
||||||
|
{
|
||||||
|
context.Response.StatusCode = statusCode;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
_builder.Start();
|
||||||
|
}
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_builder?.Dispose();
|
||||||
|
_steps.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
249
test/Ocelot.AcceptanceTests/RoutingWithQueryStringTests.cs
Normal file
249
test/Ocelot.AcceptanceTests/RoutingWithQueryStringTests.cs
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_response_200_with_query_string_upstream_template()
|
||||||
|
{
|
||||||
|
var subscriptionId = Guid.NewGuid().ToString();
|
||||||
|
var unitId = Guid.NewGuid().ToString();
|
||||||
|
|
||||||
|
var configuration = new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
DownstreamPathTemplate = "/api/units/{subscriptionId}/{unitId}/updates",
|
||||||
|
DownstreamScheme = "http",
|
||||||
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||||
|
{
|
||||||
|
new FileHostAndPort
|
||||||
|
{
|
||||||
|
Host = "localhost",
|
||||||
|
Port = 64879,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UpstreamPathTemplate = "/api/subscriptions/{subscriptionId}/updates?unitId={unitId}",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:64879", $"/api/units/{subscriptionId}/{unitId}/updates", "", 200, "Hello from Laura"))
|
||||||
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
|
.And(x => _steps.GivenOcelotIsRunning())
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway($"/api/subscriptions/{subscriptionId}/updates?unitId={unitId}"))
|
||||||
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
|
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_response_404_with_query_string_upstream_template_no_query_string()
|
||||||
|
{
|
||||||
|
var subscriptionId = Guid.NewGuid().ToString();
|
||||||
|
var unitId = Guid.NewGuid().ToString();
|
||||||
|
|
||||||
|
var configuration = new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
DownstreamPathTemplate = "/api/units/{subscriptionId}/{unitId}/updates",
|
||||||
|
DownstreamScheme = "http",
|
||||||
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||||
|
{
|
||||||
|
new FileHostAndPort
|
||||||
|
{
|
||||||
|
Host = "localhost",
|
||||||
|
Port = 64879,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UpstreamPathTemplate = "/api/subscriptions/{subscriptionId}/updates?unitId={unitId}",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:64879", $"/api/units/{subscriptionId}/{unitId}/updates", "", 200, "Hello from Laura"))
|
||||||
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
|
.And(x => _steps.GivenOcelotIsRunning())
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway($"/api/subscriptions/{subscriptionId}/updates"))
|
||||||
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.NotFound))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_response_404_with_query_string_upstream_template_different_query_string()
|
||||||
|
{
|
||||||
|
var subscriptionId = Guid.NewGuid().ToString();
|
||||||
|
var unitId = Guid.NewGuid().ToString();
|
||||||
|
|
||||||
|
var configuration = new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
DownstreamPathTemplate = "/api/units/{subscriptionId}/{unitId}/updates",
|
||||||
|
DownstreamScheme = "http",
|
||||||
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||||
|
{
|
||||||
|
new FileHostAndPort
|
||||||
|
{
|
||||||
|
Host = "localhost",
|
||||||
|
Port = 64879,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UpstreamPathTemplate = "/api/subscriptions/{subscriptionId}/updates?unitId={unitId}",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:64879", $"/api/units/{subscriptionId}/{unitId}/updates", "", 200, "Hello from Laura"))
|
||||||
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
|
.And(x => _steps.GivenOcelotIsRunning())
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway($"/api/subscriptions/{subscriptionId}/updates?test=1"))
|
||||||
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.NotFound))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_response_200_with_query_string_upstream_template_multiple_params()
|
||||||
|
{
|
||||||
|
var subscriptionId = Guid.NewGuid().ToString();
|
||||||
|
var unitId = Guid.NewGuid().ToString();
|
||||||
|
|
||||||
|
var configuration = new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
DownstreamPathTemplate = "/api/units/{subscriptionId}/{unitId}/updates",
|
||||||
|
DownstreamScheme = "http",
|
||||||
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||||
|
{
|
||||||
|
new FileHostAndPort
|
||||||
|
{
|
||||||
|
Host = "localhost",
|
||||||
|
Port = 64879,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UpstreamPathTemplate = "/api/subscriptions/{subscriptionId}/updates?unitId={unitId}",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:64879", $"/api/units/{subscriptionId}/{unitId}/updates", "?productId=1", 200, "Hello from Laura"))
|
||||||
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
|
.And(x => _steps.GivenOcelotIsRunning())
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway($"/api/subscriptions/{subscriptionId}/updates?unitId={unitId}&productId=1"))
|
||||||
|
.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 = 500;
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -237,8 +237,8 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
s.AddSingleton(_webHostBuilder);
|
s.AddSingleton(_webHostBuilder);
|
||||||
s.AddOcelot()
|
s.AddOcelot()
|
||||||
.AddSingletonDelegatingHandler<TOne>()
|
.AddDelegatingHandler<TOne>()
|
||||||
.AddSingletonDelegatingHandler<TWo>();
|
.AddDelegatingHandler<TWo>();
|
||||||
})
|
})
|
||||||
.Configure(a =>
|
.Configure(a =>
|
||||||
{
|
{
|
||||||
@ -303,8 +303,39 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
s.AddSingleton(_webHostBuilder);
|
s.AddSingleton(_webHostBuilder);
|
||||||
s.AddOcelot()
|
s.AddOcelot()
|
||||||
.AddSingletonDelegatingHandler<TOne>(true)
|
.AddDelegatingHandler<TOne>(true)
|
||||||
.AddSingletonDelegatingHandler<TWo>(true);
|
.AddDelegatingHandler<TWo>(true);
|
||||||
|
})
|
||||||
|
.Configure(a =>
|
||||||
|
{
|
||||||
|
a.UseOcelot().Wait();
|
||||||
|
});
|
||||||
|
|
||||||
|
_ocelotServer = new TestServer(_webHostBuilder);
|
||||||
|
|
||||||
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenOcelotIsRunningWithGlobalHandlerRegisteredInDi<TOne>()
|
||||||
|
where TOne : DelegatingHandler
|
||||||
|
{
|
||||||
|
_webHostBuilder = new WebHostBuilder();
|
||||||
|
|
||||||
|
_webHostBuilder
|
||||||
|
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||||
|
{
|
||||||
|
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
|
||||||
|
var env = hostingContext.HostingEnvironment;
|
||||||
|
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||||
|
config.AddJsonFile("ocelot.json");
|
||||||
|
config.AddEnvironmentVariables();
|
||||||
|
})
|
||||||
|
.ConfigureServices(s =>
|
||||||
|
{
|
||||||
|
s.AddSingleton(_webHostBuilder);
|
||||||
|
s.AddOcelot()
|
||||||
|
.AddDelegatingHandler<TOne>(true);
|
||||||
})
|
})
|
||||||
.Configure(a =>
|
.Configure(a =>
|
||||||
{
|
{
|
||||||
@ -336,7 +367,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
s.AddSingleton(_webHostBuilder);
|
s.AddSingleton(_webHostBuilder);
|
||||||
s.AddSingleton<FakeDependency>(dependency);
|
s.AddSingleton<FakeDependency>(dependency);
|
||||||
s.AddOcelot()
|
s.AddOcelot()
|
||||||
.AddSingletonDelegatingHandler<TOne>(true);
|
.AddDelegatingHandler<TOne>(true);
|
||||||
})
|
})
|
||||||
.Configure(a =>
|
.Configure(a =>
|
||||||
{
|
{
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||||
<RuntimeFrameworkVersion>2.0.0</RuntimeFrameworkVersion>
|
|
||||||
<AssemblyName>Ocelot.Benchmarks</AssemblyName>
|
<AssemblyName>Ocelot.Benchmarks</AssemblyName>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<PackageId>Ocelot.Benchmarks</PackageId>
|
<PackageId>Ocelot.Benchmarks</PackageId>
|
||||||
|
@ -14,6 +14,7 @@ namespace Ocelot.Benchmarks
|
|||||||
private RegExUrlMatcher _urlPathMatcher;
|
private RegExUrlMatcher _urlPathMatcher;
|
||||||
private string _downstreamUrlPath;
|
private string _downstreamUrlPath;
|
||||||
private string _downstreamUrlPathTemplate;
|
private string _downstreamUrlPathTemplate;
|
||||||
|
private string _upstreamQuery;
|
||||||
|
|
||||||
public UrlPathToUrlPathTemplateMatcherBenchmarks()
|
public UrlPathToUrlPathTemplateMatcherBenchmarks()
|
||||||
{
|
{
|
||||||
@ -33,7 +34,7 @@ namespace Ocelot.Benchmarks
|
|||||||
[Benchmark(Baseline = true)]
|
[Benchmark(Baseline = true)]
|
||||||
public void Baseline()
|
public void Baseline()
|
||||||
{
|
{
|
||||||
_urlPathMatcher.Match(_downstreamUrlPath, _downstreamUrlPathTemplate);
|
_urlPathMatcher.Match(_downstreamUrlPath, _upstreamQuery, _downstreamUrlPathTemplate, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// * Summary *
|
// * Summary *
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||||
<RuntimeFrameworkVersion>2.0.0</RuntimeFrameworkVersion>
|
|
||||||
<AssemblyName>Ocelot.IntegrationTests</AssemblyName>
|
<AssemblyName>Ocelot.IntegrationTests</AssemblyName>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<PackageId>Ocelot.IntegrationTests</PackageId>
|
<PackageId>Ocelot.IntegrationTests</PackageId>
|
||||||
@ -25,26 +24,26 @@
|
|||||||
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
|
||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
|
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
||||||
<PackageReference Include="xunit" Version="2.3.1" />
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
<PackageReference Include="IdentityServer4" Version="2.2.0" />
|
<PackageReference Include="IdentityServer4" Version="2.2.0" />
|
||||||
<PackageReference Include="Shouldly" Version="3.0.0" />
|
<PackageReference Include="Shouldly" Version="3.0.0" />
|
||||||
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
||||||
<PackageReference Include="Consul" Version="0.7.2.4" />
|
<PackageReference Include="Consul" Version="0.7.2.5" />
|
||||||
<PackageReference Include="Rafty" Version="0.4.4" />
|
<PackageReference Include="Rafty" Version="0.4.4" />
|
||||||
<PackageReference Include="Microsoft.Data.SQLite" Version="2.0.1" />
|
<PackageReference Include="Microsoft.Data.SQLite" Version="2.1.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||||
<RuntimeFrameworkVersion>2.0.0</RuntimeFrameworkVersion>
|
|
||||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||||
<AssemblyName>Ocelot.ManualTest</AssemblyName>
|
<AssemblyName>Ocelot.ManualTest</AssemblyName>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
@ -15,6 +14,11 @@
|
|||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="ocelot.json">
|
||||||
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="ocelot.json;appsettings.json;idsrv3test.pfx">
|
<None Update="ocelot.json;appsettings.json;idsrv3test.pfx">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
@ -24,15 +28,15 @@
|
|||||||
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.1.1" />
|
||||||
<PackageReference Include="Consul" Version="0.7.2.4" />
|
<PackageReference Include="Consul" Version="0.7.2.5" />
|
||||||
<PackageReference Include="Polly" Version="6.0.1" />
|
<PackageReference Include="Polly" Version="6.0.1" />
|
||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
|
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
@ -7,6 +7,11 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Ocelot.DependencyInjection;
|
using Ocelot.DependencyInjection;
|
||||||
using Ocelot.Middleware;
|
using Ocelot.Middleware;
|
||||||
|
using System;
|
||||||
|
using IdentityServer4.AccessTokenValidation;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
@ -33,10 +38,11 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
s.AddOcelot()
|
s.AddOcelot()
|
||||||
.AddCacheManager(x =>
|
.AddDelegatingHandler<FakeHandler>(true)
|
||||||
{
|
// .AddCacheManager(x =>
|
||||||
x.WithDictionaryHandle();
|
// {
|
||||||
})
|
// x.WithDictionaryHandle();
|
||||||
|
// })
|
||||||
/*.AddOpenTracing(option =>
|
/*.AddOpenTracing(option =>
|
||||||
{
|
{
|
||||||
option.CollectorUrl = "http://localhost:9618";
|
option.CollectorUrl = "http://localhost:9618";
|
||||||
@ -58,4 +64,15 @@
|
|||||||
.Run();
|
.Run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class FakeHandler : DelegatingHandler
|
||||||
|
{
|
||||||
|
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Console.WriteLine(request.RequestUri);
|
||||||
|
|
||||||
|
//do stuff and optionally call the base handler..
|
||||||
|
return await base.SendAsync(request, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,334 +1,345 @@
|
|||||||
{
|
{
|
||||||
"ReRoutes": [
|
"ReRoutes": [
|
||||||
{
|
{
|
||||||
"DownstreamPathTemplate": "/profile",
|
"DownstreamPathTemplate": "/profile",
|
||||||
"DownstreamScheme": "http",
|
"DownstreamScheme": "http",
|
||||||
"UpstreamPathTemplate": "/profile",
|
"UpstreamPathTemplate": "/profile",
|
||||||
"UpstreamHttpMethod": [ "Get" ],
|
"UpstreamHttpMethod": [ "Get" ],
|
||||||
"DownstreamHostAndPorts": [
|
"DownstreamHostAndPorts": [
|
||||||
{
|
{
|
||||||
"Host": "localhost",
|
"Host": "localhost",
|
||||||
"Port": 3000
|
"Port": 3000
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"QoSOptions": {
|
||||||
|
"TimeoutValue": 360000
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"QoSOptions": {
|
|
||||||
"TimeoutValue": 360000
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"DownstreamPathTemplate": "/api/values",
|
|
||||||
"DownstreamScheme": "http",
|
|
||||||
"UpstreamPathTemplate": "/api/values",
|
|
||||||
"UpstreamHttpMethod": [ "Get" ],
|
|
||||||
"DownstreamHostAndPorts": [
|
|
||||||
{
|
|
||||||
"Host": "localhost",
|
|
||||||
"Port": 5007
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"HttpHandlerOptions": {
|
|
||||||
"AllowAutoRedirect": true,
|
|
||||||
"UseCookieContainer": true,
|
|
||||||
"UseTracing": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"DownstreamPathTemplate": "/",
|
|
||||||
"DownstreamScheme": "http",
|
|
||||||
"DownstreamHostAndPorts": [
|
|
||||||
{
|
|
||||||
"Host": "localhost",
|
|
||||||
"Port": 52876
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"UpstreamPathTemplate": "/identityserverexample",
|
|
||||||
"UpstreamHttpMethod": [ "Get" ],
|
|
||||||
"QoSOptions": {
|
|
||||||
"ExceptionsAllowedBeforeBreaking": 3,
|
|
||||||
"DurationOfBreak": 10,
|
|
||||||
"TimeoutValue": 5000
|
|
||||||
},
|
},
|
||||||
"AuthenticationOptions": {
|
{
|
||||||
"AuthenticationProviderKey": "TestKey",
|
"DownstreamPathTemplate": "/api/v1/todo/",
|
||||||
"AllowedScopes": [
|
"DownstreamScheme": "http",
|
||||||
"openid",
|
"UpstreamPathTemplate": "/api/v1/todo/",
|
||||||
"offline_access"
|
"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",
|
"DownstreamPathTemplate": "/",
|
||||||
"LocationId": "Claims[LocationId] > value",
|
"DownstreamScheme": "http",
|
||||||
"UserType": "Claims[sub] > value[0] > |",
|
"DownstreamHostAndPorts": [
|
||||||
"UserId": "Claims[sub] > value[1] > |"
|
{
|
||||||
|
"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",
|
"DownstreamPathTemplate": "/posts",
|
||||||
"LocationId": "Claims[LocationId] > value",
|
"DownstreamScheme": "https",
|
||||||
"UserType": "Claims[sub] > value[0] > |",
|
"DownstreamHostAndPorts": [
|
||||||
"UserId": "Claims[sub] > value[1] > |"
|
{
|
||||||
},
|
"Host": "jsonplaceholder.typicode.com",
|
||||||
"AddQueriesToRequest": {
|
"Port": 443
|
||||||
"CustomerId": "Claims[CustomerId] > value",
|
}
|
||||||
"LocationId": "Claims[LocationId] > value",
|
],
|
||||||
"UserType": "Claims[sub] > value[0] > |",
|
"UpstreamPathTemplate": "/posts",
|
||||||
"UserId": "Claims[sub] > value[1] > |"
|
"UpstreamHttpMethod": [ "Get" ],
|
||||||
},
|
"HttpHandlerOptions": {
|
||||||
"RouteClaimsRequirement": {
|
"AllowAutoRedirect": true,
|
||||||
"UserType": "registered"
|
"UseCookieContainer": true
|
||||||
},
|
},
|
||||||
"RequestIdKey": "OcRequestId"
|
"QoSOptions": {
|
||||||
},
|
"ExceptionsAllowedBeforeBreaking": 3,
|
||||||
{
|
"DurationOfBreak": 10,
|
||||||
"DownstreamPathTemplate": "/posts",
|
"TimeoutValue": 5000
|
||||||
"DownstreamScheme": "https",
|
|
||||||
"DownstreamHostAndPorts": [
|
|
||||||
{
|
|
||||||
"Host": "jsonplaceholder.typicode.com",
|
|
||||||
"Port": 443
|
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"UpstreamPathTemplate": "/posts",
|
|
||||||
"UpstreamHttpMethod": [ "Get" ],
|
|
||||||
"HttpHandlerOptions": {
|
|
||||||
"AllowAutoRedirect": true,
|
|
||||||
"UseCookieContainer": true
|
|
||||||
},
|
},
|
||||||
"QoSOptions": {
|
{
|
||||||
"ExceptionsAllowedBeforeBreaking": 3,
|
"DownstreamPathTemplate": "/posts/{postId}",
|
||||||
"DurationOfBreak": 10,
|
"DownstreamScheme": "http",
|
||||||
"TimeoutValue": 5000
|
"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": {
|
"GlobalConfiguration": {
|
||||||
"RequestIdKey": "ot-traceid"
|
"RequestIdKey": "ot-traceid"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -599,7 +599,7 @@
|
|||||||
.WithDownstreamPathTemplate("/products/{productId}")
|
.WithDownstreamPathTemplate("/products/{productId}")
|
||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("(?i)/api/products/.*/$", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("(?i)/api/products/.*/$", 1, false))
|
||||||
.WithLoadBalancerKey("/api/products/{productId}|Get|")
|
.WithLoadBalancerKey("/api/products/{productId}|Get|")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
@ -628,7 +628,7 @@
|
|||||||
.WithDownstreamReRoute(downstreamReRoute)
|
.WithDownstreamReRoute(downstreamReRoute)
|
||||||
.WithUpstreamPathTemplate("/api/products/{productId}")
|
.WithUpstreamPathTemplate("/api/products/{productId}")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("(?i)/api/products/.*/$", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("(?i)/api/products/.*/$", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
}))
|
}))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -922,7 +922,7 @@
|
|||||||
{
|
{
|
||||||
_upstreamTemplatePatternCreator
|
_upstreamTemplatePatternCreator
|
||||||
.Setup(x => x.Create(It.IsAny<FileReRoute>()))
|
.Setup(x => x.Create(It.IsAny<FileReRoute>()))
|
||||||
.Returns(new UpstreamPathTemplate(pattern, 1));
|
.Returns(new UpstreamPathTemplate(pattern, 1, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheRequestIdKeyCreatorIsCalledCorrectly()
|
private void ThenTheRequestIdKeyCreatorIsCalledCorrectly()
|
||||||
|
@ -10,7 +10,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
public class UpstreamTemplatePatternCreatorTests
|
public class UpstreamTemplatePatternCreatorTests
|
||||||
{
|
{
|
||||||
private FileReRoute _fileReRoute;
|
private FileReRoute _fileReRoute;
|
||||||
private UpstreamTemplatePatternCreator _creator;
|
private readonly UpstreamTemplatePatternCreator _creator;
|
||||||
private UpstreamPathTemplate _result;
|
private UpstreamPathTemplate _result;
|
||||||
|
|
||||||
public UpstreamTemplatePatternCreatorTests()
|
public UpstreamTemplatePatternCreatorTests()
|
||||||
@ -191,6 +191,36 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_create_template_pattern_that_matches_query_string()
|
||||||
|
{
|
||||||
|
var fileReRoute = new FileReRoute
|
||||||
|
{
|
||||||
|
UpstreamPathTemplate = "/api/subscriptions/{subscriptionId}/updates?unitId={unitId}"
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
|
||||||
|
.When(x => x.WhenICreateTheTemplatePattern())
|
||||||
|
.Then(x => x.ThenTheFollowingIsReturned("^(?i)/api/subscriptions/.+/updates\\?unitId=.+$"))
|
||||||
|
.And(x => ThenThePriorityIs(1))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_create_template_pattern_that_matches_query_string_with_multiple_params()
|
||||||
|
{
|
||||||
|
var fileReRoute = new FileReRoute
|
||||||
|
{
|
||||||
|
UpstreamPathTemplate = "/api/subscriptions/{subscriptionId}/updates?unitId={unitId}&productId={productId}"
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => x.GivenTheFollowingFileReRoute(fileReRoute))
|
||||||
|
.When(x => x.WhenICreateTheTemplatePattern())
|
||||||
|
.Then(x => x.ThenTheFollowingIsReturned("^(?i)/api/subscriptions/.+/updates\\?unitId=.+&productId=.+$"))
|
||||||
|
.And(x => ThenThePriorityIs(1))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheFollowingFileReRoute(FileReRoute fileReRoute)
|
private void GivenTheFollowingFileReRoute(FileReRoute fileReRoute)
|
||||||
{
|
{
|
||||||
_fileReRoute = fileReRoute;
|
_fileReRoute = fileReRoute;
|
||||||
|
@ -32,14 +32,29 @@
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_merge_files()
|
public void should_merge_files()
|
||||||
{
|
{
|
||||||
this.Given(_ => GivenMultipleConfigurationFiles())
|
this.Given(_ => GivenMultipleConfigurationFiles(""))
|
||||||
.When(_ => WhenIAddOcelotConfiguration())
|
.When(_ => WhenIAddOcelotConfiguration())
|
||||||
.Then(_ => ThenTheConfigsAreMerged())
|
.Then(_ => ThenTheConfigsAreMerged())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenMultipleConfigurationFiles()
|
[Fact]
|
||||||
|
public void should_merge_files_in_specific_folder()
|
||||||
{
|
{
|
||||||
|
string configFolder = "ConfigFiles";
|
||||||
|
this.Given(_ => GivenMultipleConfigurationFiles(configFolder))
|
||||||
|
.When(_ => WhenIAddOcelotConfigurationWithSpecificFolder(configFolder))
|
||||||
|
.Then(_ => ThenTheConfigsAreMerged())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenMultipleConfigurationFiles(string folder)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(folder))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(folder);
|
||||||
|
}
|
||||||
|
|
||||||
_globalConfig = new FileConfiguration
|
_globalConfig = new FileConfiguration
|
||||||
{
|
{
|
||||||
GlobalConfiguration = new FileGlobalConfiguration
|
GlobalConfiguration = new FileGlobalConfiguration
|
||||||
@ -159,10 +174,15 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
File.WriteAllText("ocelot.global.json", JsonConvert.SerializeObject(_globalConfig));
|
string globalFilename = Path.Combine(folder, "ocelot.global.json");
|
||||||
File.WriteAllText("ocelot.reRoutesA.json", JsonConvert.SerializeObject(_reRouteA));
|
string reroutesAFilename = Path.Combine(folder, "ocelot.reRoutesA.json");
|
||||||
File.WriteAllText("ocelot.reRoutesB.json", JsonConvert.SerializeObject(_reRouteB));
|
string reroutesBFilename = Path.Combine(folder, "ocelot.reRoutesB.json");
|
||||||
File.WriteAllText("ocelot.aggregates.json", JsonConvert.SerializeObject(_aggregate));
|
string aggregatesFilename = Path.Combine(folder, "ocelot.aggregates.json");
|
||||||
|
|
||||||
|
File.WriteAllText(globalFilename, JsonConvert.SerializeObject(_globalConfig));
|
||||||
|
File.WriteAllText(reroutesAFilename, JsonConvert.SerializeObject(_reRouteA));
|
||||||
|
File.WriteAllText(reroutesBFilename, JsonConvert.SerializeObject(_reRouteB));
|
||||||
|
File.WriteAllText(aggregatesFilename, JsonConvert.SerializeObject(_aggregate));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenIAddOcelotConfiguration()
|
private void WhenIAddOcelotConfiguration()
|
||||||
@ -172,6 +192,13 @@
|
|||||||
_configRoot = builder.Build();
|
_configRoot = builder.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WhenIAddOcelotConfigurationWithSpecificFolder(string folder)
|
||||||
|
{
|
||||||
|
IConfigurationBuilder builder = new ConfigurationBuilder();
|
||||||
|
builder.AddOcelot(folder);
|
||||||
|
_configRoot = builder.Build();
|
||||||
|
}
|
||||||
|
|
||||||
private void ThenTheConfigsAreMerged()
|
private void ThenTheConfigsAreMerged()
|
||||||
{
|
{
|
||||||
var fc = (FileConfiguration)_configRoot.Get(typeof(FileConfiguration));
|
var fc = (FileConfiguration)_configRoot.Get(typeof(FileConfiguration));
|
||||||
|
@ -52,17 +52,6 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void should_add_specific_delegating_handler_singleton()
|
|
||||||
{
|
|
||||||
this.Given(x => WhenISetUpOcelotServices())
|
|
||||||
.When(x => AddSpecificDelegatingHandler<FakeDelegatingHandler>())
|
|
||||||
.And(x => AddSpecificDelegatingHandler<FakeDelegatingHandlerTwo>())
|
|
||||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
|
||||||
.And(x => ThenTheSpecificHandlersAreSingleton())
|
|
||||||
.BDDfy();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_add_global_delegating_handlers_transient()
|
public void should_add_global_delegating_handlers_transient()
|
||||||
{
|
{
|
||||||
@ -74,17 +63,6 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void should_add_global_delegating_handlers_singleton()
|
|
||||||
{
|
|
||||||
this.Given(x => WhenISetUpOcelotServices())
|
|
||||||
.When(x => AddGlobalDelegatingHandler<FakeDelegatingHandler>())
|
|
||||||
.And(x => AddGlobalDelegatingHandler<FakeDelegatingHandlerTwo>())
|
|
||||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
|
||||||
.And(x => ThenTheGlobalHandlersAreSingleton())
|
|
||||||
.BDDfy();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_set_up_services()
|
public void should_set_up_services()
|
||||||
{
|
{
|
||||||
@ -231,15 +209,6 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
first.ShouldNotBe(second);
|
first.ShouldNotBe(second);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheGlobalHandlersAreSingleton()
|
|
||||||
{
|
|
||||||
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
|
||||||
var first = handlers[0].DelegatingHandler;
|
|
||||||
handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
|
||||||
var second = handlers[0].DelegatingHandler;
|
|
||||||
first.ShouldBe(second);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThenTheGlobalHandlersAreTransient()
|
private void ThenTheGlobalHandlersAreTransient()
|
||||||
{
|
{
|
||||||
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||||
@ -262,13 +231,13 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
private void AddTransientGlobalDelegatingHandler<T>()
|
private void AddTransientGlobalDelegatingHandler<T>()
|
||||||
where T : DelegatingHandler
|
where T : DelegatingHandler
|
||||||
{
|
{
|
||||||
_ocelotBuilder.AddTransientDelegatingHandler<T>(true);
|
_ocelotBuilder.AddDelegatingHandler<T>(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddSpecificTransientDelegatingHandler<T>()
|
private void AddSpecificTransientDelegatingHandler<T>()
|
||||||
where T : DelegatingHandler
|
where T : DelegatingHandler
|
||||||
{
|
{
|
||||||
_ocelotBuilder.AddTransientDelegatingHandler<T>();
|
_ocelotBuilder.AddDelegatingHandler<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheCorrectAdminPathIsRegitered()
|
private void ThenTheCorrectAdminPathIsRegitered()
|
||||||
@ -365,13 +334,13 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
private void AddGlobalDelegatingHandler<T>()
|
private void AddGlobalDelegatingHandler<T>()
|
||||||
where T : DelegatingHandler
|
where T : DelegatingHandler
|
||||||
{
|
{
|
||||||
_ocelotBuilder.AddSingletonDelegatingHandler<T>(true);
|
_ocelotBuilder.AddDelegatingHandler<T>(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddSpecificDelegatingHandler<T>()
|
private void AddSpecificDelegatingHandler<T>()
|
||||||
where T : DelegatingHandler
|
where T : DelegatingHandler
|
||||||
{
|
{
|
||||||
_ocelotBuilder.AddSingletonDelegatingHandler<T>();
|
_ocelotBuilder.AddDelegatingHandler<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenAnOcelotBuilderIsReturned()
|
private void ThenAnOcelotBuilderIsReturned()
|
||||||
|
@ -28,6 +28,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
private IInternalConfiguration _configuration;
|
private IInternalConfiguration _configuration;
|
||||||
private Mock<IQoSOptionsCreator> _qosOptionsCreator;
|
private Mock<IQoSOptionsCreator> _qosOptionsCreator;
|
||||||
private Response<DownstreamRoute> _resultTwo;
|
private Response<DownstreamRoute> _resultTwo;
|
||||||
|
private string _upstreamQuery;
|
||||||
|
|
||||||
public DownstreamRouteCreatorTests()
|
public DownstreamRouteCreatorTests()
|
||||||
{
|
{
|
||||||
@ -247,12 +248,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
|
|
||||||
private void WhenICreate()
|
private void WhenICreate()
|
||||||
{
|
{
|
||||||
_result = _creator.Get(_upstreamUrlPath, _upstreamHttpMethod, _configuration, _upstreamHost);
|
_result = _creator.Get(_upstreamUrlPath, _upstreamQuery, _upstreamHttpMethod, _configuration, _upstreamHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenICreateAgain()
|
private void WhenICreateAgain()
|
||||||
{
|
{
|
||||||
_resultTwo = _creator.Get(_upstreamUrlPath, _upstreamHttpMethod, _configuration, _upstreamHost);
|
_resultTwo = _creator.Get(_upstreamUrlPath, _upstreamQuery, _upstreamHttpMethod, _configuration, _upstreamHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheDownstreamRoutesAreTheSameReference()
|
private void ThenTheDownstreamRoutesAreTheSameReference()
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
{
|
{
|
||||||
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||||
_finder
|
_finder
|
||||||
.Setup(x => x.Get(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IInternalConfiguration>(), It.IsAny<string>()))
|
.Setup(x => x.Get(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IInternalConfiguration>(), It.IsAny<string>()))
|
||||||
.Returns(_downstreamRoute);
|
.Returns(_downstreamRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
private Response<UrlMatch> _match;
|
private Response<UrlMatch> _match;
|
||||||
private string _upstreamHttpMethod;
|
private string _upstreamHttpMethod;
|
||||||
private string _upstreamHost;
|
private string _upstreamHost;
|
||||||
|
private string _upstreamQuery;
|
||||||
|
|
||||||
public DownstreamRouteFinderTests()
|
public DownstreamRouteFinderTests()
|
||||||
{
|
{
|
||||||
@ -48,22 +49,22 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1, false))
|
||||||
.Build(),
|
.Build(),
|
||||||
new ReRouteBuilder()
|
new ReRouteBuilder()
|
||||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 0))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 0, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 0))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 0, false))
|
||||||
.Build()
|
.Build()
|
||||||
}, string.Empty, serviceProviderConfig))
|
}, string.Empty, serviceProviderConfig))
|
||||||
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
|
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
|
||||||
@ -73,13 +74,13 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
new ReRouteBuilder()
|
new ReRouteBuilder()
|
||||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1, false))
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1, false))
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
)))
|
)))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -100,22 +101,22 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 0))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 0, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 0))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 0, false))
|
||||||
.Build(),
|
.Build(),
|
||||||
new ReRouteBuilder()
|
new ReRouteBuilder()
|
||||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
}, string.Empty, serviceProviderConfig))
|
}, string.Empty, serviceProviderConfig))
|
||||||
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
|
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
|
||||||
@ -125,10 +126,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
new ReRouteBuilder()
|
new ReRouteBuilder()
|
||||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1, false))
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1, false))
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.Build()
|
.Build()
|
||||||
)))
|
)))
|
||||||
@ -151,11 +152,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
}, string.Empty, serviceProviderConfig
|
}, string.Empty, serviceProviderConfig
|
||||||
))
|
))
|
||||||
@ -169,10 +170,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
)))
|
)))
|
||||||
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly())
|
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly())
|
||||||
@ -195,11 +196,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
}, string.Empty, serviceProviderConfig
|
}, string.Empty, serviceProviderConfig
|
||||||
))
|
))
|
||||||
@ -213,10 +214,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
)))
|
)))
|
||||||
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly("matchInUrlMatcher"))
|
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly("matchInUrlMatcher"))
|
||||||
@ -240,11 +241,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
}, string.Empty, serviceProviderConfig
|
}, string.Empty, serviceProviderConfig
|
||||||
))
|
))
|
||||||
@ -257,10 +258,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
)))
|
)))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -283,22 +284,22 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build(),
|
.Build(),
|
||||||
new ReRouteBuilder()
|
new ReRouteBuilder()
|
||||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("someDownstreamPathForAPost")
|
.WithDownstreamPathTemplate("someDownstreamPathForAPost")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
}, string.Empty, serviceProviderConfig
|
}, string.Empty, serviceProviderConfig
|
||||||
))
|
))
|
||||||
@ -311,10 +312,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("someDownstreamPathForAPost")
|
.WithDownstreamPathTemplate("someDownstreamPathForAPost")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
)))
|
)))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -333,11 +334,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("somPath")
|
.WithDownstreamPathTemplate("somPath")
|
||||||
.WithUpstreamPathTemplate("somePath")
|
.WithUpstreamPathTemplate("somePath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("somePath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("somePath", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("somePath")
|
.WithUpstreamPathTemplate("somePath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("somePath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("somePath", 1, false))
|
||||||
.Build(),
|
.Build(),
|
||||||
}, string.Empty, serviceProviderConfig
|
}, string.Empty, serviceProviderConfig
|
||||||
))
|
))
|
||||||
@ -367,11 +368,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get", "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Get", "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get", "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Get", "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
}, string.Empty, serviceProviderConfig
|
}, string.Empty, serviceProviderConfig
|
||||||
))
|
))
|
||||||
@ -384,10 +385,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
)))
|
)))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -410,11 +411,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string>())
|
.WithUpstreamHttpMethod(new List<string>())
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string>())
|
.WithUpstreamHttpMethod(new List<string>())
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
}, string.Empty, serviceProviderConfig
|
}, string.Empty, serviceProviderConfig
|
||||||
))
|
))
|
||||||
@ -427,10 +428,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
.WithUpstreamHttpMethod(new List<string> { "Post" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
)))
|
)))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -453,11 +454,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get", "Patch", "Delete" })
|
.WithUpstreamHttpMethod(new List<string> { "Get", "Patch", "Delete" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get", "Patch", "Delete" })
|
.WithUpstreamHttpMethod(new List<string> { "Get", "Patch", "Delete" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
}, string.Empty, serviceProviderConfig
|
}, string.Empty, serviceProviderConfig
|
||||||
))
|
))
|
||||||
@ -486,12 +487,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.WithUpstreamHost("MATCH")
|
.WithUpstreamHost("MATCH")
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.WithUpstreamHost("MATCH")
|
.WithUpstreamHost("MATCH")
|
||||||
.Build()
|
.Build()
|
||||||
}, string.Empty, serviceProviderConfig
|
}, string.Empty, serviceProviderConfig
|
||||||
@ -506,10 +507,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
)))
|
)))
|
||||||
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly())
|
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly())
|
||||||
@ -533,11 +534,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
}, string.Empty, serviceProviderConfig
|
}, string.Empty, serviceProviderConfig
|
||||||
))
|
))
|
||||||
@ -551,10 +552,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
)))
|
)))
|
||||||
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly())
|
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly())
|
||||||
@ -576,12 +577,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.WithUpstreamHost("MATCH")
|
.WithUpstreamHost("MATCH")
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.WithUpstreamHost("MATCH")
|
.WithUpstreamHost("MATCH")
|
||||||
.Build(),
|
.Build(),
|
||||||
new ReRouteBuilder()
|
new ReRouteBuilder()
|
||||||
@ -589,12 +590,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { }) // empty list of methods
|
.WithUpstreamHttpMethod(new List<string> { }) // empty list of methods
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.WithUpstreamHost("MATCH")
|
.WithUpstreamHost("MATCH")
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { }) // empty list of methods
|
.WithUpstreamHttpMethod(new List<string> { }) // empty list of methods
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.WithUpstreamHost("MATCH")
|
.WithUpstreamHost("MATCH")
|
||||||
.Build()
|
.Build()
|
||||||
}, string.Empty, serviceProviderConfig
|
}, string.Empty, serviceProviderConfig
|
||||||
@ -622,12 +623,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string>())
|
.WithUpstreamHttpMethod(new List<string>())
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.WithUpstreamHost("MATCH")
|
.WithUpstreamHost("MATCH")
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string>())
|
.WithUpstreamHttpMethod(new List<string>())
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.WithUpstreamHost("MATCH")
|
.WithUpstreamHost("MATCH")
|
||||||
.Build()
|
.Build()
|
||||||
}, string.Empty, serviceProviderConfig
|
}, string.Empty, serviceProviderConfig
|
||||||
@ -655,12 +656,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string>())
|
.WithUpstreamHttpMethod(new List<string>())
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.WithUpstreamHost("MATCH")
|
.WithUpstreamHost("MATCH")
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string>())
|
.WithUpstreamHttpMethod(new List<string>())
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.WithUpstreamHost("MATCH")
|
.WithUpstreamHost("MATCH")
|
||||||
.Build()
|
.Build()
|
||||||
}, string.Empty, serviceProviderConfig
|
}, string.Empty, serviceProviderConfig
|
||||||
@ -689,23 +690,23 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamPathTemplate("THENULLPATH")
|
.WithDownstreamPathTemplate("THENULLPATH")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build(),
|
.Build(),
|
||||||
new ReRouteBuilder()
|
new ReRouteBuilder()
|
||||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.WithUpstreamHost("MATCH")
|
.WithUpstreamHost("MATCH")
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamPathTemplate("someUpstreamPath")
|
.WithUpstreamPathTemplate("someUpstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.WithUpstreamHost("MATCH")
|
.WithUpstreamHost("MATCH")
|
||||||
.Build()
|
.Build()
|
||||||
}, string.Empty, serviceProviderConfig
|
}, string.Empty, serviceProviderConfig
|
||||||
@ -720,10 +721,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate("someDownstreamPath")
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build())
|
.Build())
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
|
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1, false))
|
||||||
.Build()
|
.Build()
|
||||||
)))
|
)))
|
||||||
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly(2))
|
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly(2))
|
||||||
@ -738,7 +739,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
private void GivenTheTemplateVariableAndNameFinderReturns(Response<List<PlaceholderNameAndValue>> response)
|
private void GivenTheTemplateVariableAndNameFinderReturns(Response<List<PlaceholderNameAndValue>> response)
|
||||||
{
|
{
|
||||||
_finder
|
_finder
|
||||||
.Setup(x => x.Find(It.IsAny<string>(), It.IsAny<string>()))
|
.Setup(x => x.Find(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Returns(response);
|
.Returns(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -755,32 +756,32 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
private void ThenTheUrlMatcherIsCalledCorrectly()
|
private void ThenTheUrlMatcherIsCalledCorrectly()
|
||||||
{
|
{
|
||||||
_mockMatcher
|
_mockMatcher
|
||||||
.Verify(x => x.Match(_upstreamUrlPath, _reRoutesConfig[0].UpstreamPathTemplate.Value), Times.Once);
|
.Verify(x => x.Match(_upstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamPathTemplate.Value, _reRoutesConfig[0].UpstreamTemplatePattern.ContainsQueryString), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheUrlMatcherIsCalledCorrectly(int times)
|
private void ThenTheUrlMatcherIsCalledCorrectly(int times)
|
||||||
{
|
{
|
||||||
_mockMatcher
|
_mockMatcher
|
||||||
.Verify(x => x.Match(_upstreamUrlPath, _reRoutesConfig[0].UpstreamPathTemplate.Value), Times.Exactly(times));
|
.Verify(x => x.Match(_upstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamPathTemplate.Value, _reRoutesConfig[0].UpstreamTemplatePattern.ContainsQueryString), Times.Exactly(times));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheUrlMatcherIsCalledCorrectly(string expectedUpstreamUrlPath)
|
private void ThenTheUrlMatcherIsCalledCorrectly(string expectedUpstreamUrlPath)
|
||||||
{
|
{
|
||||||
_mockMatcher
|
_mockMatcher
|
||||||
.Verify(x => x.Match(expectedUpstreamUrlPath, _reRoutesConfig[0].UpstreamPathTemplate.Value), Times.Once);
|
.Verify(x => x.Match(expectedUpstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamPathTemplate.Value, _reRoutesConfig[0].UpstreamTemplatePattern.ContainsQueryString), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheUrlMatcherIsNotCalled()
|
private void ThenTheUrlMatcherIsNotCalled()
|
||||||
{
|
{
|
||||||
_mockMatcher
|
_mockMatcher
|
||||||
.Verify(x => x.Match(_upstreamUrlPath, _reRoutesConfig[0].UpstreamPathTemplate.Value), Times.Never);
|
.Verify(x => x.Match(_upstreamUrlPath, _upstreamQuery, _reRoutesConfig[0].UpstreamPathTemplate.Value, _reRoutesConfig[0].UpstreamTemplatePattern.ContainsQueryString), Times.Never);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheUrlMatcherReturns(Response<UrlMatch> match)
|
private void GivenTheUrlMatcherReturns(Response<UrlMatch> match)
|
||||||
{
|
{
|
||||||
_match = match;
|
_match = match;
|
||||||
_mockMatcher
|
_mockMatcher
|
||||||
.Setup(x => x.Match(It.IsAny<string>(), It.IsAny<string>()))
|
.Setup(x => x.Match(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()))
|
||||||
.Returns(_match);
|
.Returns(_match);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -797,7 +798,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
|
|
||||||
private void WhenICallTheFinder()
|
private void WhenICallTheFinder()
|
||||||
{
|
{
|
||||||
_result = _downstreamRouteFinder.Get(_upstreamUrlPath, _upstreamHttpMethod, _config, _upstreamHost);
|
_result = _downstreamRouteFinder.Get(_upstreamUrlPath, _upstreamQuery, _upstreamHttpMethod, _config, _upstreamHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheFollowingIsReturned(DownstreamRoute expected)
|
private void ThenTheFollowingIsReturned(DownstreamRoute expected)
|
||||||
|
@ -1,26 +1,28 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Moq;
|
|
||||||
using Ocelot.Configuration;
|
|
||||||
using Ocelot.Configuration.Builder;
|
|
||||||
using Ocelot.DownstreamRouteFinder;
|
|
||||||
using Ocelot.DownstreamRouteFinder.Finder;
|
|
||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
|
||||||
using Ocelot.Responses;
|
|
||||||
using Ocelot.Values;
|
|
||||||
using Shouldly;
|
|
||||||
using TestStack.BDDfy;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.DownstreamRouteFinder
|
namespace Ocelot.UnitTests.DownstreamRouteFinder
|
||||||
{
|
{
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Moq;
|
||||||
|
using Ocelot.Configuration;
|
||||||
|
using Ocelot.Configuration.Builder;
|
||||||
|
using Ocelot.DownstreamRouteFinder;
|
||||||
|
using Ocelot.DownstreamRouteFinder.Finder;
|
||||||
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
|
using Ocelot.Responses;
|
||||||
|
using Ocelot.Values;
|
||||||
|
using Shouldly;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Xunit;
|
||||||
using Ocelot.Configuration.Creator;
|
using Ocelot.Configuration.Creator;
|
||||||
|
using Ocelot.Logging;
|
||||||
|
|
||||||
public class DownstreamRouteProviderFactoryTests
|
public class DownstreamRouteProviderFactoryTests
|
||||||
{
|
{
|
||||||
private readonly DownstreamRouteProviderFactory _factory;
|
private readonly DownstreamRouteProviderFactory _factory;
|
||||||
private IInternalConfiguration _config;
|
private IInternalConfiguration _config;
|
||||||
private IDownstreamRouteProvider _result;
|
private IDownstreamRouteProvider _result;
|
||||||
|
private Mock<IOcelotLogger> _logger;
|
||||||
|
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||||
|
|
||||||
public DownstreamRouteProviderFactoryTests()
|
public DownstreamRouteProviderFactoryTests()
|
||||||
{
|
{
|
||||||
@ -31,7 +33,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
services.AddSingleton<IDownstreamRouteProvider, Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteFinder>();
|
services.AddSingleton<IDownstreamRouteProvider, Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteFinder>();
|
||||||
services.AddSingleton<IDownstreamRouteProvider, Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteCreator>();
|
services.AddSingleton<IDownstreamRouteProvider, Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteCreator>();
|
||||||
var provider = services.BuildServiceProvider();
|
var provider = services.BuildServiceProvider();
|
||||||
_factory = new DownstreamRouteProviderFactory(provider);
|
_logger = new Mock<IOcelotLogger>();
|
||||||
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
|
_loggerFactory.Setup(x => x.CreateLogger<DownstreamRouteProviderFactory>()).Returns(_logger.Object);
|
||||||
|
_factory = new DownstreamRouteProviderFactory(provider, _loggerFactory.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -49,12 +54,34 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_downstream_route_finder_as_no_service_discovery()
|
public void should_return_downstream_route_finder_as_no_service_discovery_given_no_host()
|
||||||
{
|
{
|
||||||
var spConfig = new ServiceProviderConfigurationBuilder().Build();
|
var spConfig = new ServiceProviderConfigurationBuilder().WithHost("").WithPort(50).Build();
|
||||||
var reRoutes = new List<ReRoute>
|
var reRoutes = new List<ReRoute>();
|
||||||
{
|
|
||||||
};
|
this.Given(_ => GivenTheReRoutes(reRoutes, spConfig))
|
||||||
|
.When(_ => WhenIGet())
|
||||||
|
.Then(_ => ThenTheResultShouldBe<Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteFinder>())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_downstream_route_finder_given_no_service_discovery_port()
|
||||||
|
{
|
||||||
|
var spConfig = new ServiceProviderConfigurationBuilder().WithHost("localhost").WithPort(0).Build();
|
||||||
|
var reRoutes = new List<ReRoute>();
|
||||||
|
|
||||||
|
this.Given(_ => GivenTheReRoutes(reRoutes, spConfig))
|
||||||
|
.When(_ => WhenIGet())
|
||||||
|
.Then(_ => ThenTheResultShouldBe<Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteFinder>())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_downstream_route_finder_given_no_service_discovery_type()
|
||||||
|
{
|
||||||
|
var spConfig = new ServiceProviderConfigurationBuilder().WithHost("localhost").WithPort(50).WithType("").Build();
|
||||||
|
var reRoutes = new List<ReRoute>();
|
||||||
|
|
||||||
this.Given(_ => GivenTheReRoutes(reRoutes, spConfig))
|
this.Given(_ => GivenTheReRoutes(reRoutes, spConfig))
|
||||||
.When(_ => WhenIGet())
|
.When(_ => WhenIGet())
|
||||||
@ -65,10 +92,9 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_downstream_route_creator()
|
public void should_return_downstream_route_creator()
|
||||||
{
|
{
|
||||||
var spConfig = new ServiceProviderConfigurationBuilder().WithHost("test").WithPort(50).Build();
|
var spConfig = new ServiceProviderConfigurationBuilder().WithHost("test").WithPort(50).WithType("test").Build();
|
||||||
var reRoutes = new List<ReRoute>
|
var reRoutes = new List<ReRoute>();
|
||||||
{
|
|
||||||
};
|
|
||||||
this.Given(_ => GivenTheReRoutes(reRoutes, spConfig))
|
this.Given(_ => GivenTheReRoutes(reRoutes, spConfig))
|
||||||
.When(_ => WhenIGet())
|
.When(_ => WhenIGet())
|
||||||
.Then(_ => ThenTheResultShouldBe<Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteCreator>())
|
.Then(_ => ThenTheResultShouldBe<Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteCreator>())
|
||||||
|
@ -9,22 +9,65 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
public class RegExUrlMatcherTests
|
public class RegExUrlMatcherTests
|
||||||
{
|
{
|
||||||
private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
|
private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
|
||||||
private string _downstreamUrlPath;
|
private string _path;
|
||||||
private string _downstreamPathTemplate;
|
private string _downstreamPathTemplate;
|
||||||
private Response<UrlMatch> _result;
|
private Response<UrlMatch> _result;
|
||||||
|
private string _queryString;
|
||||||
|
private bool _containsQueryString;
|
||||||
|
|
||||||
public RegExUrlMatcherTests()
|
public RegExUrlMatcherTests()
|
||||||
{
|
{
|
||||||
_urlMatcher = new RegExUrlMatcher();
|
_urlMatcher = new RegExUrlMatcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_match_path_with_no_query_string()
|
||||||
|
{
|
||||||
|
const string regExForwardSlashAndOnePlaceHolder = "^(?i)/newThing$";
|
||||||
|
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("/newThing"))
|
||||||
|
.And(_ => GivenIHaveAQueryString("?DeviceType=IphoneApp&Browser=moonpigIphone&BrowserString=-&CountryCode=123&DeviceName=iPhone 5 (GSM+CDMA)&OperatingSystem=iPhone OS 7.1.2&BrowserVersion=3708AdHoc&ipAddress=-"))
|
||||||
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern(regExForwardSlashAndOnePlaceHolder))
|
||||||
|
.When(x => x.WhenIMatchThePaths())
|
||||||
|
.And(x => x.ThenTheResultIsTrue())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_match_query_string()
|
||||||
|
{
|
||||||
|
const string regExForwardSlashAndOnePlaceHolder = "^(?i)/api/subscriptions/.+/updates\\?unitId=.+$";
|
||||||
|
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("/api/subscriptions/1/updates"))
|
||||||
|
.And(_ => GivenIHaveAQueryString("?unitId=2"))
|
||||||
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern(regExForwardSlashAndOnePlaceHolder))
|
||||||
|
.And(_ => GivenThereIsAQueryInTemplate())
|
||||||
|
.When(x => x.WhenIMatchThePaths())
|
||||||
|
.And(x => x.ThenTheResultIsTrue())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_match_query_string_with_multiple_params()
|
||||||
|
{
|
||||||
|
const string regExForwardSlashAndOnePlaceHolder = "^(?i)/api/subscriptions/.+/updates\\?unitId=.+&productId=.+$";
|
||||||
|
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("/api/subscriptions/1/updates?unitId=2"))
|
||||||
|
.And(_ => GivenIHaveAQueryString("?unitId=2&productId=2"))
|
||||||
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern(regExForwardSlashAndOnePlaceHolder))
|
||||||
|
.And(_ => GivenThereIsAQueryInTemplate())
|
||||||
|
.When(x => x.WhenIMatchThePaths())
|
||||||
|
.And(x => x.ThenTheResultIsTrue())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_not_match_slash_becaue_we_need_to_match_something_after_it()
|
public void should_not_match_slash_becaue_we_need_to_match_something_after_it()
|
||||||
{
|
{
|
||||||
const string RegExForwardSlashAndOnePlaceHolder = "^/[0-9a-zA-Z].*";
|
const string regExForwardSlashAndOnePlaceHolder = "^/[0-9a-zA-Z].+";
|
||||||
|
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("/"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("/"))
|
||||||
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern(RegExForwardSlashAndOnePlaceHolder))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern(regExForwardSlashAndOnePlaceHolder))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.And(x => x.ThenTheResultIsFalse())
|
.And(x => x.ThenTheResultIsFalse())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -44,7 +87,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
public void should_not_match_issue_134()
|
public void should_not_match_issue_134()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("/api/vacancy/1/"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("/api/vacancy/1/"))
|
||||||
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^(?i)/vacancy/.*/$"))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^(?i)/vacancy/.+/$"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.And(x => x.ThenTheResultIsFalse())
|
.And(x => x.ThenTheResultIsFalse())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -64,7 +107,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
public void should_find_match_when_template_smaller_than_valid_path()
|
public void should_find_match_when_template_smaller_than_valid_path()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("/api/products/2354325435624623464235"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("/api/products/2354325435624623464235"))
|
||||||
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^/api/products/.*$"))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^/api/products/.+$"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.And(x => x.ThenTheResultIsTrue())
|
.And(x => x.ThenTheResultIsTrue())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -124,7 +167,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
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()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1"))
|
||||||
.Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.*$"))
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+$"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -134,7 +177,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
public void can_match_down_stream_url_with_downstream_template_with_two_place_holders()
|
public void can_match_down_stream_url_with_downstream_template_with_two_place_holders()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2"))
|
||||||
.Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.*/.*$"))
|
.Given(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+/.+$"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -144,7 +187,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
public void can_match_down_stream_url_with_downstream_template_with_two_place_holders_seperated_by_something()
|
public void can_match_down_stream_url_with_downstream_template_with_two_place_holders_seperated_by_something()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2"))
|
||||||
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.*/categories/.*$"))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+/categories/.+$"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -154,7 +197,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
public void can_match_down_stream_url_with_downstream_template_with_three_place_holders_seperated_by_something()
|
public void can_match_down_stream_url_with_downstream_template_with_three_place_holders_seperated_by_something()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/123"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/123"))
|
||||||
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.*/categories/.*/variant/.*$"))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+/categories/.+/variant/.+$"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -164,7 +207,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
public void can_match_down_stream_url_with_downstream_template_with_three_place_holders()
|
public void can_match_down_stream_url_with_downstream_template_with_three_place_holders()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/"))
|
||||||
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.*/categories/.*/variant/$"))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+/categories/.+/variant/$"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -174,7 +217,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
public void should_ignore_case_sensitivity()
|
public void should_ignore_case_sensitivity()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("API/product/products/1/categories/2/variant/"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("API/product/products/1/categories/2/variant/"))
|
||||||
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^(?i)api/product/products/.*/categories/.*/variant/$"))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^(?i)api/product/products/.+/categories/.+/variant/$"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.Then(x => x.ThenTheResultIsTrue())
|
.Then(x => x.ThenTheResultIsTrue())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -184,15 +227,20 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
public void should_respect_case_sensitivity()
|
public void should_respect_case_sensitivity()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenIHaveAUpstreamPath("API/product/products/1/categories/2/variant/"))
|
this.Given(x => x.GivenIHaveAUpstreamPath("API/product/products/1/categories/2/variant/"))
|
||||||
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.*/categories/.*/variant/$"))
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplatePattern("^api/product/products/.+/categories/.+/variant/$"))
|
||||||
.When(x => x.WhenIMatchThePaths())
|
.When(x => x.WhenIMatchThePaths())
|
||||||
.Then(x => x.ThenTheResultIsFalse())
|
.Then(x => x.ThenTheResultIsFalse())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenIHaveAUpstreamPath(string downstreamPath)
|
private void GivenIHaveAUpstreamPath(string path)
|
||||||
{
|
{
|
||||||
_downstreamUrlPath = downstreamPath;
|
_path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenIHaveAQueryString(string queryString)
|
||||||
|
{
|
||||||
|
_queryString = queryString;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenIHaveAnUpstreamUrlTemplatePattern(string downstreamUrlTemplate)
|
private void GivenIHaveAnUpstreamUrlTemplatePattern(string downstreamUrlTemplate)
|
||||||
@ -202,7 +250,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
|
|
||||||
private void WhenIMatchThePaths()
|
private void WhenIMatchThePaths()
|
||||||
{
|
{
|
||||||
_result = _urlMatcher.Match(_downstreamUrlPath, _downstreamPathTemplate);
|
_result = _urlMatcher.Match(_path, _queryString, _downstreamPathTemplate, _containsQueryString);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheResultIsTrue()
|
private void ThenTheResultIsTrue()
|
||||||
@ -214,5 +262,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
{
|
{
|
||||||
_result.Data.Match.ShouldBeFalse();
|
_result.Data.Match.ShouldBeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GivenThereIsAQueryInTemplate()
|
||||||
|
{
|
||||||
|
_containsQueryString = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,6 +14,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
private string _downstreamUrlPath;
|
private string _downstreamUrlPath;
|
||||||
private string _downstreamPathTemplate;
|
private string _downstreamPathTemplate;
|
||||||
private Response<List<PlaceholderNameAndValue>> _result;
|
private Response<List<PlaceholderNameAndValue>> _result;
|
||||||
|
private string _query;
|
||||||
|
|
||||||
public UrlPathPlaceholderNameAndValueFinderTests()
|
public UrlPathPlaceholderNameAndValueFinderTests()
|
||||||
{
|
{
|
||||||
@ -114,6 +115,91 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_find_query_string()
|
||||||
|
{
|
||||||
|
var expectedTemplates = new List<PlaceholderNameAndValue>
|
||||||
|
{
|
||||||
|
new PlaceholderNameAndValue("{productId}", "1")
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("/products"))
|
||||||
|
.And(x => x.GivenIHaveAQuery("?productId=1"))
|
||||||
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("/products?productId={productId}"))
|
||||||
|
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
|
||||||
|
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_find_query_string_dont_include_hardcoded()
|
||||||
|
{
|
||||||
|
var expectedTemplates = new List<PlaceholderNameAndValue>
|
||||||
|
{
|
||||||
|
new PlaceholderNameAndValue("{productId}", "1")
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("/products"))
|
||||||
|
.And(x => x.GivenIHaveAQuery("?productId=1&categoryId=2"))
|
||||||
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("/products?productId={productId}"))
|
||||||
|
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
|
||||||
|
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_find_multiple_query_string()
|
||||||
|
{
|
||||||
|
var expectedTemplates = new List<PlaceholderNameAndValue>
|
||||||
|
{
|
||||||
|
new PlaceholderNameAndValue("{productId}", "1"),
|
||||||
|
new PlaceholderNameAndValue("{categoryId}", "2")
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("/products"))
|
||||||
|
.And(x => x.GivenIHaveAQuery("?productId=1&categoryId=2"))
|
||||||
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("/products?productId={productId}&categoryId={categoryId}"))
|
||||||
|
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
|
||||||
|
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_find_multiple_query_string_and_path()
|
||||||
|
{
|
||||||
|
var expectedTemplates = new List<PlaceholderNameAndValue>
|
||||||
|
{
|
||||||
|
new PlaceholderNameAndValue("{productId}", "1"),
|
||||||
|
new PlaceholderNameAndValue("{categoryId}", "2"),
|
||||||
|
new PlaceholderNameAndValue("{account}", "3")
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("/products/3"))
|
||||||
|
.And(x => x.GivenIHaveAQuery("?productId=1&categoryId=2"))
|
||||||
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("/products/{account}?productId={productId}&categoryId={categoryId}"))
|
||||||
|
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
|
||||||
|
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_find_multiple_query_string_and_path_that_ends_with_slash()
|
||||||
|
{
|
||||||
|
var expectedTemplates = new List<PlaceholderNameAndValue>
|
||||||
|
{
|
||||||
|
new PlaceholderNameAndValue("{productId}", "1"),
|
||||||
|
new PlaceholderNameAndValue("{categoryId}", "2"),
|
||||||
|
new PlaceholderNameAndValue("{account}", "3")
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => x.GivenIHaveAUpstreamPath("/products/3/"))
|
||||||
|
.And(x => x.GivenIHaveAQuery("?productId=1&categoryId=2"))
|
||||||
|
.And(x => x.GivenIHaveAnUpstreamUrlTemplate("/products/{account}/?productId={productId}&categoryId={categoryId}"))
|
||||||
|
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
|
||||||
|
.And(x => x.ThenTheTemplatesVariablesAre(expectedTemplates))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void can_match_down_stream_url_with_no_slash()
|
public void can_match_down_stream_url_with_no_slash()
|
||||||
{
|
{
|
||||||
@ -260,7 +346,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
|
|||||||
|
|
||||||
private void WhenIFindTheUrlVariableNamesAndValues()
|
private void WhenIFindTheUrlVariableNamesAndValues()
|
||||||
{
|
{
|
||||||
_result = _finder.Find(_downstreamUrlPath, _downstreamPathTemplate);
|
_result = _finder.Find(_downstreamUrlPath, _query, _downstreamPathTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenIHaveAQuery(string query)
|
||||||
|
{
|
||||||
|
_query = query;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,104 @@
|
|||||||
.And(x => x.GivenTheUrlReplacerWillReturn("/api/products/1"))
|
.And(x => x.GivenTheUrlReplacerWillReturn("/api/products/1"))
|
||||||
.When(x => x.WhenICallTheMiddleware())
|
.When(x => x.WhenICallTheMiddleware())
|
||||||
.Then(x => x.ThenTheDownstreamRequestUriIs("https://my.url:80/api/products/1?q=123"))
|
.Then(x => x.ThenTheDownstreamRequestUriIs("https://my.url:80/api/products/1?q=123"))
|
||||||
|
.And(x => ThenTheQueryStringIs("?q=123"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_replace_query_string()
|
||||||
|
{
|
||||||
|
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||||
|
.WithDownstreamPathTemplate("/api/units/{subscriptionId}/{unitId}/updates")
|
||||||
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
|
.WithDownstreamScheme("https")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var config = new ServiceProviderConfigurationBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||||
|
new DownstreamRoute(
|
||||||
|
new List<PlaceholderNameAndValue>
|
||||||
|
{
|
||||||
|
new PlaceholderNameAndValue("{subscriptionId}", "1"),
|
||||||
|
new PlaceholderNameAndValue("{unitId}", "2")
|
||||||
|
},
|
||||||
|
new ReRouteBuilder()
|
||||||
|
.WithDownstreamReRoute(downstreamReRoute)
|
||||||
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
|
.Build())))
|
||||||
|
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:5000/api/subscriptions/1/updates?unitId=2"))
|
||||||
|
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||||
|
.And(x => x.GivenTheUrlReplacerWillReturn("api/units/1/2/updates"))
|
||||||
|
.When(x => x.WhenICallTheMiddleware())
|
||||||
|
.Then(x => x.ThenTheDownstreamRequestUriIs("https://localhost:5000/api/units/1/2/updates"))
|
||||||
|
.And(x => ThenTheQueryStringIs(""))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_replace_query_string_but_leave_non_placeholder_queries()
|
||||||
|
{
|
||||||
|
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||||
|
.WithDownstreamPathTemplate("/api/units/{subscriptionId}/{unitId}/updates")
|
||||||
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
|
.WithDownstreamScheme("https")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var config = new ServiceProviderConfigurationBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||||
|
new DownstreamRoute(
|
||||||
|
new List<PlaceholderNameAndValue>
|
||||||
|
{
|
||||||
|
new PlaceholderNameAndValue("{subscriptionId}", "1"),
|
||||||
|
new PlaceholderNameAndValue("{unitId}", "2")
|
||||||
|
},
|
||||||
|
new ReRouteBuilder()
|
||||||
|
.WithDownstreamReRoute(downstreamReRoute)
|
||||||
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
|
.Build())))
|
||||||
|
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:5000/api/subscriptions/1/updates?unitId=2&productId=2"))
|
||||||
|
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||||
|
.And(x => x.GivenTheUrlReplacerWillReturn("api/units/1/2/updates"))
|
||||||
|
.When(x => x.WhenICallTheMiddleware())
|
||||||
|
.Then(x => x.ThenTheDownstreamRequestUriIs("https://localhost:5000/api/units/1/2/updates?productId=2"))
|
||||||
|
.And(x => ThenTheQueryStringIs("?productId=2"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_replace_query_string_exact_match()
|
||||||
|
{
|
||||||
|
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||||
|
.WithDownstreamPathTemplate("/api/units/{subscriptionId}/{unitId}/updates/{unitIdIty}")
|
||||||
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
|
.WithDownstreamScheme("https")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var config = new ServiceProviderConfigurationBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||||
|
new DownstreamRoute(
|
||||||
|
new List<PlaceholderNameAndValue>
|
||||||
|
{
|
||||||
|
new PlaceholderNameAndValue("{subscriptionId}", "1"),
|
||||||
|
new PlaceholderNameAndValue("{unitId}", "2"),
|
||||||
|
new PlaceholderNameAndValue("{unitIdIty}", "3")
|
||||||
|
},
|
||||||
|
new ReRouteBuilder()
|
||||||
|
.WithDownstreamReRoute(downstreamReRoute)
|
||||||
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
|
.Build())))
|
||||||
|
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:5000/api/subscriptions/1/updates?unitId=2?unitIdIty=3"))
|
||||||
|
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||||
|
.And(x => x.GivenTheUrlReplacerWillReturn("api/units/1/2/updates/3"))
|
||||||
|
.When(x => x.WhenICallTheMiddleware())
|
||||||
|
.Then(x => x.ThenTheDownstreamRequestUriIs("https://localhost:5000/api/units/1/2/updates/3"))
|
||||||
|
.And(x => ThenTheQueryStringIs(""))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,5 +325,10 @@
|
|||||||
{
|
{
|
||||||
_downstreamContext.DownstreamRequest.ToHttpRequestMessage().RequestUri.OriginalString.ShouldBe(expectedUri);
|
_downstreamContext.DownstreamRequest.ToHttpRequestMessage().RequestUri.OriginalString.ShouldBe(expectedUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ThenTheQueryStringIs(string queryString)
|
||||||
|
{
|
||||||
|
_downstreamContext.DownstreamRequest.Query.ShouldBe(queryString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,13 @@ namespace Ocelot.UnitTests.Middleware
|
|||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Ocelot.DependencyInjection;
|
using Ocelot.DependencyInjection;
|
||||||
|
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||||
|
using Ocelot.DownstreamUrlCreator.Middleware;
|
||||||
|
using Ocelot.LoadBalancer.Middleware;
|
||||||
using Ocelot.Middleware;
|
using Ocelot.Middleware;
|
||||||
using Ocelot.Middleware.Pipeline;
|
using Ocelot.Middleware.Pipeline;
|
||||||
|
using Ocelot.Request.Middleware;
|
||||||
|
using Ocelot.WebSockets.Middleware;
|
||||||
using Pivotal.Discovery.Client;
|
using Pivotal.Discovery.Client;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using Steeltoe.Common.Discovery;
|
using Steeltoe.Common.Discovery;
|
||||||
@ -26,6 +31,16 @@ namespace Ocelot.UnitTests.Middleware
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_expand_pipeline()
|
||||||
|
{
|
||||||
|
this.Given(_ => GivenTheDepedenciesAreSetUp())
|
||||||
|
.When(_ => WhenIExpandBuild())
|
||||||
|
.Then(_ => ThenThePipelineIsBuilt())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void ThenThePipelineIsBuilt()
|
private void ThenThePipelineIsBuilt()
|
||||||
{
|
{
|
||||||
_handlers.ShouldNotBeNull();
|
_handlers.ShouldNotBeNull();
|
||||||
@ -36,6 +51,23 @@ namespace Ocelot.UnitTests.Middleware
|
|||||||
_handlers = _builder.BuildOcelotPipeline(new OcelotPipelineConfiguration());
|
_handlers = _builder.BuildOcelotPipeline(new OcelotPipelineConfiguration());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WhenIExpandBuild()
|
||||||
|
{
|
||||||
|
OcelotPipelineConfiguration configuration = new OcelotPipelineConfiguration();
|
||||||
|
configuration.MapWhenOcelotPipeline.Add((app) =>
|
||||||
|
{
|
||||||
|
app.UseDownstreamRouteFinderMiddleware();
|
||||||
|
app.UseDownstreamRequestInitialiser();
|
||||||
|
app.UseLoadBalancingMiddleware();
|
||||||
|
app.UseDownstreamUrlCreatorMiddleware();
|
||||||
|
app.UseWebSocketsProxyMiddleware();
|
||||||
|
|
||||||
|
return context => context.HttpContext.WebSockets.IsWebSocketRequest;
|
||||||
|
});
|
||||||
|
_handlers = _builder.BuildOcelotPipeline(new OcelotPipelineConfiguration());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void GivenTheDepedenciesAreSetUp()
|
private void GivenTheDepedenciesAreSetUp()
|
||||||
{
|
{
|
||||||
IConfigurationBuilder test = new ConfigurationBuilder();
|
IConfigurationBuilder test = new ConfigurationBuilder();
|
||||||
@ -45,7 +77,6 @@ namespace Ocelot.UnitTests.Middleware
|
|||||||
services.AddDiscoveryClient(new DiscoveryOptions
|
services.AddDiscoveryClient(new DiscoveryOptions
|
||||||
{
|
{
|
||||||
ClientType = DiscoveryClientType.EUREKA,
|
ClientType = DiscoveryClientType.EUREKA,
|
||||||
//options can not be null
|
|
||||||
ClientOptions = new EurekaClientOptions()
|
ClientOptions = new EurekaClientOptions()
|
||||||
{
|
{
|
||||||
ShouldFetchRegistry = false,
|
ShouldFetchRegistry = false,
|
||||||
|
@ -79,6 +79,8 @@ namespace Ocelot.UnitTests.Middleware
|
|||||||
del.Invoke(_downstreamContext);
|
del.Invoke(_downstreamContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void ThenTheFuncIsInThePipeline()
|
private void ThenTheFuncIsInThePipeline()
|
||||||
{
|
{
|
||||||
_counter.ShouldBe(1);
|
_counter.ShouldBe(1);
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||||
<RuntimeFrameworkVersion>2.0.0</RuntimeFrameworkVersion>
|
|
||||||
<AssemblyName>Ocelot.UnitTests</AssemblyName>
|
<AssemblyName>Ocelot.UnitTests</AssemblyName>
|
||||||
<PackageId>Ocelot.UnitTests</PackageId>
|
<PackageId>Ocelot.UnitTests</PackageId>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
@ -38,22 +37,22 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.3" />
|
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
|
||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
|
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.1.1" />
|
||||||
<PackageReference Include="Moq" Version="4.8.2" />
|
<PackageReference Include="Moq" Version="4.8.3" />
|
||||||
<PackageReference Include="Shouldly" Version="3.0.0" />
|
<PackageReference Include="Shouldly" Version="3.0.0" />
|
||||||
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
||||||
<PackageReference Include="xunit" Version="2.3.1" />
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
|
@ -23,15 +23,18 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
{
|
{
|
||||||
public class HttpClientBuilderTests : IDisposable
|
public class HttpClientBuilderTests : IDisposable
|
||||||
{
|
{
|
||||||
private readonly HttpClientBuilder _builder;
|
private HttpClientBuilder _builder;
|
||||||
private readonly Mock<IDelegatingHandlerHandlerFactory> _factory;
|
private readonly Mock<IDelegatingHandlerHandlerFactory> _factory;
|
||||||
private IHttpClient _httpClient;
|
private IHttpClient _httpClient;
|
||||||
private HttpResponseMessage _response;
|
private HttpResponseMessage _response;
|
||||||
private DownstreamContext _context;
|
private DownstreamContext _context;
|
||||||
private readonly Mock<IHttpClientCache> _cacheHandlers;
|
private readonly Mock<IHttpClientCache> _cacheHandlers;
|
||||||
private Mock<IOcelotLogger> _logger;
|
private readonly Mock<IOcelotLogger> _logger;
|
||||||
private int _count;
|
private int _count;
|
||||||
private IWebHost _host;
|
private IWebHost _host;
|
||||||
|
private IHttpClient _againHttpClient;
|
||||||
|
private IHttpClient _firstHttpClient;
|
||||||
|
private MemoryHttpClientCache _realCache;
|
||||||
|
|
||||||
public HttpClientBuilderTests()
|
public HttpClientBuilderTests()
|
||||||
{
|
{
|
||||||
@ -61,6 +64,47 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_get_from_cache()
|
||||||
|
{
|
||||||
|
var qosOptions = new QoSOptionsBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var reRoute = new DownstreamReRouteBuilder()
|
||||||
|
.WithQosOptions(qosOptions)
|
||||||
|
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true))
|
||||||
|
.WithLoadBalancerKey("")
|
||||||
|
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
this.Given(x => GivenARealCache())
|
||||||
|
.And(x => GivenTheFactoryReturns())
|
||||||
|
.And(x => GivenARequest(reRoute))
|
||||||
|
.And(x => WhenIBuildTheFirstTime())
|
||||||
|
.And(x => WhenISave())
|
||||||
|
.And(x => WhenIBuildAgain())
|
||||||
|
.And(x => WhenISave())
|
||||||
|
.When(x => WhenIBuildAgain())
|
||||||
|
.Then(x => ThenTheHttpClientIsFromTheCache())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenARealCache()
|
||||||
|
{
|
||||||
|
_realCache = new MemoryHttpClientCache();
|
||||||
|
_builder = new HttpClientBuilder(_factory.Object, _realCache, _logger.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheHttpClientIsFromTheCache()
|
||||||
|
{
|
||||||
|
_againHttpClient.ShouldBe(_firstHttpClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenISave()
|
||||||
|
{
|
||||||
|
_builder.Save();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_log_if_ignoring_ssl_errors()
|
public void should_log_if_ignoring_ssl_errors()
|
||||||
{
|
{
|
||||||
@ -302,6 +346,17 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
_httpClient = _builder.Create(_context);
|
_httpClient = _builder.Create(_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WhenIBuildTheFirstTime()
|
||||||
|
{
|
||||||
|
_firstHttpClient = _builder.Create(_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenIBuildAgain()
|
||||||
|
{
|
||||||
|
_builder = new HttpClientBuilder(_factory.Object, _realCache, _logger.Object);
|
||||||
|
_againHttpClient = _builder.Create(_context);
|
||||||
|
}
|
||||||
|
|
||||||
private void ThenTheHttpClientShouldNotBeNull()
|
private void ThenTheHttpClientShouldNotBeNull()
|
||||||
{
|
{
|
||||||
_httpClient.ShouldNotBeNull();
|
_httpClient.ShouldNotBeNull();
|
||||||
|
@ -1,33 +1,24 @@
|
|||||||
using System;
|
namespace Ocelot.UnitTests.ServiceDiscovery
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using Consul;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Moq;
|
|
||||||
using Ocelot.Infrastructure.Consul;
|
|
||||||
using Ocelot.Logging;
|
|
||||||
using Ocelot.ServiceDiscovery.Configuration;
|
|
||||||
using Ocelot.ServiceDiscovery.Providers;
|
|
||||||
using Ocelot.Values;
|
|
||||||
using Xunit;
|
|
||||||
using TestStack.BDDfy;
|
|
||||||
using Shouldly;
|
|
||||||
using static Ocelot.Infrastructure.Wait;
|
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.ServiceDiscovery
|
|
||||||
{
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Moq;
|
||||||
|
using Ocelot.Logging;
|
||||||
|
using Ocelot.ServiceDiscovery.Providers;
|
||||||
|
using Ocelot.Values;
|
||||||
|
using Xunit;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Shouldly;
|
||||||
|
using static Ocelot.Infrastructure.Wait;
|
||||||
|
|
||||||
public class PollingConsulServiceDiscoveryProviderTests
|
public class PollingConsulServiceDiscoveryProviderTests
|
||||||
{
|
{
|
||||||
private readonly int _delay;
|
private readonly int _delay;
|
||||||
private PollingConsulServiceDiscoveryProvider _provider;
|
private PollingConsulServiceDiscoveryProvider _provider;
|
||||||
private readonly string _serviceName;
|
private readonly List<Service> _services;
|
||||||
private List<Service> _services;
|
|
||||||
private readonly Mock<IOcelotLoggerFactory> _factory;
|
private readonly Mock<IOcelotLoggerFactory> _factory;
|
||||||
private readonly Mock<IOcelotLogger> _logger;
|
private readonly Mock<IOcelotLogger> _logger;
|
||||||
private Mock<IServiceDiscoveryProvider> _consulServiceDiscoveryProvider;
|
private readonly Mock<IServiceDiscoveryProvider> _consulServiceDiscoveryProvider;
|
||||||
private List<Service> _result;
|
private List<Service> _result;
|
||||||
|
|
||||||
public PollingConsulServiceDiscoveryProviderTests()
|
public PollingConsulServiceDiscoveryProviderTests()
|
||||||
@ -64,7 +55,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery
|
|||||||
|
|
||||||
private void WhenIGetTheServices(int expected)
|
private void WhenIGetTheServices(int expected)
|
||||||
{
|
{
|
||||||
_provider = new PollingConsulServiceDiscoveryProvider(_delay, _serviceName, _factory.Object, _consulServiceDiscoveryProvider.Object);
|
_provider = new PollingConsulServiceDiscoveryProvider(_delay, "", _factory.Object, _consulServiceDiscoveryProvider.Object);
|
||||||
|
|
||||||
var result = WaitFor(3000).Until(() => {
|
var result = WaitFor(3000).Until(() => {
|
||||||
try
|
try
|
||||||
|
Loading…
x
Reference in New Issue
Block a user