Feature/merge configuration files (#316)

* #296 renamed configuration.json to ocelot.json in preparation

* removed things we dont need for tests

* another file we dont need

* removed some async we dont need

* refactoring to consolidate configuration code

* removed another pointless abstraction

* #296 started writing merge code

* #296 coming up with ideas for this config merging

* #296 still hacking this idea around

* #296 will now do a crappy merge on the configuration

* #296 change so tests pass on windows
This commit is contained in:
Tom Pallister 2018-04-17 22:06:41 +01:00 committed by GitHub
parent 3607c0867e
commit aa55fe34cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
84 changed files with 883 additions and 1050 deletions

2
.gitignore vendored
View File

@ -243,7 +243,7 @@ tools/
.DS_Store .DS_Store
# Ocelot acceptance test config # Ocelot acceptance test config
test/Ocelot.AcceptanceTests/configuration.json test/Ocelot.AcceptanceTests/ocelot.json
# Read the docstates # Read the docstates
_build/ _build/

View File

@ -1,7 +1,7 @@
Configuration Configuration
============ ============
An example configuration can be found `here <https://github.com/TomPallister/Ocelot/blob/develop/test/Ocelot.ManualTest/configuration.json>`_. An example configuration can be found `here <https://github.com/TomPallister/Ocelot/blob/develop/test/Ocelot.ManualTest/ocelot.json>`_.
There are two sections to the configuration. An array of ReRoutes and a GlobalConfiguration. There are two sections to the configuration. An array of ReRoutes and a GlobalConfiguration.
The ReRoutes are the objects that tell Ocelot how to treat an upstream request. The Global The ReRoutes are the objects that tell Ocelot how to treat an upstream request. The Global
configuration is a bit hacky and allows overrides of ReRoute specific settings. It's useful configuration is a bit hacky and allows overrides of ReRoute specific settings. It's useful
@ -69,22 +69,6 @@ Here is an example ReRoute configuration, You don't need to set all of these thi
More information on how to use these options is below.. More information on how to use these options is below..
Follow Redirects / Use CookieContainer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use HttpHandlerOptions in ReRoute configuration to set up HttpHandler behavior:
1. AllowAutoRedirect is a value that indicates whether the request should follow redirection responses. Set it true if the request should automatically
follow redirection responses from the Downstream resource; otherwise false. The default value is false.
2. UseCookieContainer is a value that indicates whether the handler uses the CookieContainer
property to store server cookies and uses these cookies when sending requests. The default value is false. Please note
that if you are using the CookieContainer Ocelot caches the HttpClient for each downstream service. This means that all requests
to that DownstreamService will share the same cookies. `Issue 274 <https://github.com/ThreeMammals/Ocelot/issues/274>`_ was created because a user
noticed that the cookies were being shared. I tried to think of a nice way to handle this but I think it is impossible. If you don't cache the clients
that means each request gets a new client and therefore a new cookie container. If you clear the cookies from the cached client container you get race conditions due to inflight
requests. This would also mean that subsequent requests dont use the cookies from the previous response! All in all not a great situation. I would avoid setting
UseCookieContainer to true unless you have a really really good reason. Just look at your response headers and forward the cookies back with your next request!
Multiple environments Multiple environments
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
@ -99,15 +83,40 @@ to you
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true) .AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
.AddJsonFile("configuration.json") .AddJsonFile("ocelot.json")
.AddJsonFile($"configuration.{hostingContext.HostingEnvironment.EnvironmentName}.json") .AddJsonFile($"configuration.{hostingContext.HostingEnvironment.EnvironmentName}.json")
.AddEnvironmentVariables(); .AddEnvironmentVariables();
}) })
Ocelot should now use the environment specific configuration and fall back to configuration.json if there isnt one. Ocelot will now use the environment specific configuration and fall back to ocelot.json if there isnt one.
You also need to set the corresponding environment variable which is ASPNETCORE_ENVIRONMENT. More info on this can be found in the `asp.net core docs <https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments>`_. You also need to set the corresponding environment variable which is ASPNETCORE_ENVIRONMENT. More info on this can be found in the `asp.net core docs <https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments>`_.
Merging configuration files
^^^^^^^^^^^^^^^^^^^^^^^^^^^
This feature was requested in `Issue 296 <https://github.com/ThreeMammals/Ocelot/issues/296>`_ and allows users to have multiple configuration files to make managing large configurations easier.
Instead of adding the configuration directly e.g. AddJsonFile("ocelot.json") you can call AddOcelot() like below.
.. code-block:: csharp
.ConfigureAppConfiguration((hostingContext, config) =>
{
config
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
.AddOcelot()
.AddEnvironmentVariables();
})
In this scenario Ocelot will look for any files that match the pattern ocleot.*.json and then merge these together. If you want to set the GlobalConfiguration property you must have a file called ocelot.global.json.
The way Ocelot merges the files is basically load them, loop over them, add any ReRoutes, add any AggregateReRoutes and if the file is called ocelot.global.json add the GlobalConfiguration aswell as any ReRoutes or AggregateReRoutes. Ocelot will then save the merged configuration to a file called ocelot.json and this will be used as the source of truth while ocelot is running.
At the moment there is no validation at this stage it only happens when Ocelot validates the final merged configuration. This is something to be aware of when you are investigating problems. I would advise always checking what is in ocelot.json if you have any problems.
Store configuration in consul Store configuration in consul
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -119,7 +128,7 @@ If you add the following when you register your services Ocelot will attempt to
.AddOcelot() .AddOcelot()
.AddStoreOcelotConfigurationInConsul(); .AddStoreOcelotConfigurationInConsul();
You also need to add the following to your configuration.json. This is how Ocelot You also need to add the following to your ocelot.json. This is how Ocelot
finds your Consul agent and interacts to load and store the configuration from Consul. finds your Consul agent and interacts to load and store the configuration from Consul.
.. code-block:: json .. code-block:: json
@ -135,3 +144,19 @@ I decided to create this feature after working on the raft consensus algorithm a
I guess it means if you want to use Ocelot to its fullest you take on Consul as a dependency for now. I guess it means if you want to use Ocelot to its fullest you take on Consul as a dependency for now.
This feature has a 3 second ttl cache before making a new request to your local consul agent. This feature has a 3 second ttl cache before making a new request to your local consul agent.
Follow Redirects / Use CookieContainer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use HttpHandlerOptions in ReRoute configuration to set up HttpHandler behavior:
1. AllowAutoRedirect is a value that indicates whether the request should follow redirection responses. Set it true if the request should automatically
follow redirection responses from the Downstream resource; otherwise false. The default value is false.
2. UseCookieContainer is a value that indicates whether the handler uses the CookieContainer
property to store server cookies and uses these cookies when sending requests. The default value is false. Please note
that if you are using the CookieContainer Ocelot caches the HttpClient for each downstream service. This means that all requests
to that DownstreamService will share the same cookies. `Issue 274 <https://github.com/ThreeMammals/Ocelot/issues/274>`_ was created because a user
noticed that the cookies were being shared. I tried to think of a nice way to handle this but I think it is impossible. If you don't cache the clients
that means each request gets a new client and therefore a new cookie container. If you clear the cookies from the cached client container you get race conditions due to inflight
requests. This would also mean that subsequent requests dont use the cookies from the previous response! All in all not a great situation. I would avoid setting
UseCookieContainer to true unless you have a really really good reason. Just look at your response headers and forward the cookies back with your next request!

View File

@ -40,7 +40,7 @@ Or transient as below...
.AddTransientDelegatingHandler<FakeHandlerTwo>() .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 configuration.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
then it becomes a global handler and will be applied to all ReRoutes. then it becomes a global handler and will be applied to all ReRoutes.
e.g. e.g.
@ -58,7 +58,7 @@ Or transient as below...
.AddTransientDelegatingHandler<FakeHandler>(true) .AddTransientDelegatingHandler<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 configuration.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
DelegatingHandlers for Ocelot to match them together. DelegatingHandlers for Ocelot to match them together.
.. code-block:: json .. code-block:: json
@ -70,8 +70,8 @@ DelegatingHandlers for Ocelot to match them together.
You can have as many DelegatingHandlers as you want and they are run in the following order: You can have as many DelegatingHandlers as you want and they are run in the following order:
1. Any globals that are left in the order they were added to services and are not in the DelegatingHandlers array from configuration.json. 1. Any globals that are left in the order they were added to services and are not in the DelegatingHandlers array from ocelot.json.
2. Any non global DelegatingHandlers plus any globals that were in the DelegatingHandlers array from configuration.json ordered as they are in the DelegatingHandlers array. 2. Any non global DelegatingHandlers plus any globals that were in the DelegatingHandlers array from ocelot.json ordered as they are in the DelegatingHandlers array.
3. Tracing DelegatingHandler if enabled (see tracing docs). 3. Tracing DelegatingHandler if enabled (see tracing docs).
4. QoS DelegatingHandler if enabled (see QoS docs). 4. QoS DelegatingHandler if enabled (see QoS docs).
5. The HttpClient sends the HttpRequestMessage. 5. The HttpClient sends the HttpRequestMessage.

View File

@ -8,7 +8,7 @@ Add to Request
This feature was requestes in `GitHub #313 <https://github.com/ThreeMammals/Ocelot/issues/313>`_. This feature was requestes in `GitHub #313 <https://github.com/ThreeMammals/Ocelot/issues/313>`_.
If you want to add a header to your upstream request please add the following to a ReRoute in your configuration.json: If you want to add a header to your upstream request please add the following to a ReRoute in your ocelot.json:
.. code-block:: json .. code-block:: json
@ -25,7 +25,7 @@ Add to Response
This feature was requested in `GitHub #280 <https://github.com/TomPallister/Ocelot/issues/280>`_. This feature was requested in `GitHub #280 <https://github.com/TomPallister/Ocelot/issues/280>`_.
If you want to add a header to your downstream response please add the following to a ReRoute in configuration.json. If you want to add a header to your downstream response please add the following to a ReRoute in ocelot.json..
.. code-block:: json .. code-block:: json
@ -57,7 +57,7 @@ The key is "Test" and the value is "http://www.bbc.co.uk/, http://ocelot.com/".
Pre Downstream Request Pre Downstream Request
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^
Add the following to a ReRoute in configuration.json in order to replace http://www.bbc.co.uk/ with http://ocelot.com/. This header will be changed before the request downstream and will be sent to the downstream server. Add the following to a ReRoute in ocelot.json in order to replace http://www.bbc.co.uk/ with http://ocelot.com/. This header will be changed before the request downstream and will be sent to the downstream server.
.. code-block:: json .. code-block:: json
@ -68,7 +68,7 @@ Add the following to a ReRoute in configuration.json in order to replace http://
Post Downstream Request Post Downstream Request
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
Add the following to a ReRoute in configuration.json in order to replace http://www.bbc.co.uk/ with http://ocelot.com/. This transformation will take place after Ocelot has received the response from the downstream service. Add the following to a ReRoute in ocelot.json in order to replace http://www.bbc.co.uk/ with http://ocelot.com/. This transformation will take place after Ocelot has received the response from the downstream service.
.. code-block:: json .. code-block:: json

View File

@ -16,7 +16,7 @@ You must choose in your configuration which load balancer to use.
Configuration Configuration
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
The following shows how to set up multiple downstream services for a ReRoute using configuration.json and then select the LeadConnection load balancer. This is the simplest way to get load balancing set up. The following shows how to set up multiple downstream services for a ReRoute using ocelot.json and then select the LeadConnection load balancer. This is the simplest way to get load balancing set up.
.. code-block:: json .. code-block:: json

View File

@ -23,7 +23,7 @@ Period - This value specifies the period, such as 1s, 5m, 1h,1d and so on.
PeriodTimespan - This value specifies that we can retry after a certain number of seconds. PeriodTimespan - This value specifies that we can retry after a certain number of seconds.
Limit - This value specifies the maximum number of requests that a client can make in a defined period. Limit - This value specifies the maximum number of requests that a client can make in a defined period.
You can also set the following in the GlobalConfiguration part of configuration.json You can also set the following in the GlobalConfiguration part of ocelot.json
.. code-block:: json .. code-block:: json

View File

@ -7,7 +7,7 @@ architecture with Ocelot.
This feature was requested as part of `Issue 79 <https://github.com/TomPallister/Ocelot/pull/79>`_ and further improvements were made as part of `Issue 298 <https://github.com/TomPallister/Ocelot/issue/298>`_. This feature was requested as part of `Issue 79 <https://github.com/TomPallister/Ocelot/pull/79>`_ and further improvements were made as part of `Issue 298 <https://github.com/TomPallister/Ocelot/issue/298>`_.
In order to set this up you must do something like the following in your configuration.json. Here we have specified two normal ReRoutes and each one has a Key property. In order to set this up you must do something like the following in your ocelot.json. Here we have specified two normal ReRoutes and each one has a Key property.
We then specify an Aggregate that composes the two ReRoutes using their keys in the ReRouteKeys list and says then we have the UpstreamPathTemplate which works like a normal ReRoute. We then specify an Aggregate that composes the two ReRoutes using their keys in the ReRouteKeys list and says then we have the UpstreamPathTemplate which works like a normal ReRoute.
Obviously you cannot have duplicate UpstreamPathTemplates between ReRoutes and Aggregates. You can use all of Ocelot's normal ReRoute options apart from RequestIdKey (explained in gotchas below). Obviously you cannot have duplicate UpstreamPathTemplates between ReRoutes and Aggregates. You can use all of Ocelot's normal ReRoute options apart from RequestIdKey (explained in gotchas below).
@ -17,7 +17,7 @@ Advanced register your own Aggregators
Ocelot started with just the basic request aggregation and since then we have added a more advanced method that let's the user take in the responses from the Ocelot started with just the basic request aggregation and since then we have added a more advanced method that let's the user take in the responses from the
downstream services and then aggregate them into a response object. downstream services and then aggregate them into a response object.
The configuration.json setup is pretty much the same as the basic aggregation approach apart from you need to add an Aggregator property like below. The ocelot.json setup is pretty much the same as the basic aggregation approach apart from you need to add an Aggregator property like below.
.. code-block:: json .. code-block:: json

View File

@ -12,7 +12,7 @@ In order to use the reques tid feature you have two options.
*Global* *Global*
In your configuration.json set the following in the GlobalConfiguration section. This will be used for all requests into Ocelot. In your ocelot.json set the following in the GlobalConfiguration section. This will be used for all requests into Ocelot.
.. code-block:: json .. code-block:: json
@ -24,7 +24,7 @@ I reccomend using the GlobalConfiguration unless you really need it to be ReRout
*ReRoute* *ReRoute*
If you want to override this for a specific ReRoute add the following to configuration.json for the specific ReRoute. If you want to override this for a specific ReRoute add the following to ocelot.json for the specific ReRoute.
.. code-block:: json .. code-block:: json

View File

@ -145,9 +145,9 @@ Priority
^^^^^^^^ ^^^^^^^^
In `Issue 270 <https://github.com/TomPallister/Ocelot/pull/270>`_ I finally decided to expose the ReRoute priority in In `Issue 270 <https://github.com/TomPallister/Ocelot/pull/270>`_ I finally decided to expose the ReRoute priority in
configuration.json. This means you can decide in what order you want your ReRoutes to match the Upstream HttpRequest. ocelot.json. This means you can decide in what order you want your ReRoutes to match the Upstream HttpRequest.
In order to get this working add the following to a ReRoute in configuration.json, 0 is just an example value here but will explain below. In order to get this working add the following to a ReRoute in ocelot.json, 0 is just an example value here but will explain below.
.. code-block:: json .. code-block:: json

View File

@ -20,7 +20,7 @@ In your ConfigureServices method
option.Service = "Ocelot"; option.Service = "Ocelot";
}); });
Then in your configuration.json add the following to the ReRoute you want to trace.. Then in your ocelot.json add the following to the ReRoute you want to trace..
.. code-block:: json .. code-block:: json

View File

@ -15,7 +15,7 @@ In your Configure method you need to tell your application to use WebSockets.
app.UseOcelot().Wait(); app.UseOcelot().Wait();
}) })
Then in your configuration.json add the following to proxy a ReRoute using websockets. Then in your ocelot.json add the following to proxy a ReRoute using websockets.
.. code-block:: json .. code-block:: json

View File

@ -18,7 +18,7 @@ All versions can be found `here <https://www.nuget.org/packages/Ocelot/>`_.
**Configuration** **Configuration**
The following is a very basic configuration.json. It won't do anything but should get Ocelot starting. The following is a very basic ocelot.json. It won't do anything but should get Ocelot starting.
.. code-block:: json .. code-block:: json
@ -55,7 +55,7 @@ AddOcelot() (adds ocelot services), UseOcelot().Wait() (sets up all the Ocelot m
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true) .AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
.AddJsonFile("configuration.json") .AddJsonFile("ocelot.json")
.AddEnvironmentVariables(); .AddEnvironmentVariables();
}) })
.ConfigureServices(s => { .ConfigureServices(s => {
@ -87,7 +87,7 @@ All versions can be found `here <https://www.nuget.org/packages/Ocelot/>`_.
**Configuration** **Configuration**
The following is a very basic configuration.json. It won't do anything but should get Ocelot starting. The following is a very basic ocelot.json. It won't do anything but should get Ocelot starting.
.. code-block:: json .. code-block:: json
@ -135,7 +135,7 @@ An example startup using a json file for configuration can be seen below.
.SetBasePath(env.ContentRootPath) .SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddJsonFile("configuration.json") .AddJsonFile("ocelot.json")
.AddEnvironmentVariables(); .AddEnvironmentVariables();
Configuration = builder.Build(); Configuration = builder.Build();

View File

@ -7,7 +7,7 @@ Ocelot does not support...
* Fowarding a host header - The host header that you send to Ocelot will not be forwarded to the downstream service. Obviously this would break everything :( * Fowarding a host header - The host header that you send to Ocelot will not be forwarded to the downstream service. Obviously this would break everything :(
* Swagger - I have looked multiple times at building swagger.json out of the Ocelot configuration.json but it doesnt fit into the vision * Swagger - I have looked multiple times at building swagger.json out of the Ocelot ocelot.json but it doesnt fit into the vision
I have for Ocelot. If you would like to have Swagger in Ocelot then you must roll your own swagger.json and do the following in your I have for Ocelot. If you would like to have Swagger in Ocelot then you must roll your own swagger.json and do the following in your
Startup.cs or Program.cs. The code sample below registers a piece of middleware that loads your hand rolled swagger.json and returns Startup.cs or Program.cs. The code sample below registers a piece of middleware that loads your hand rolled swagger.json and returns
it on /swagger/v1/swagger.json. It then registers the SwaggerUI middleware from Swashbuckle.AspNetCore it on /swagger/v1/swagger.json. It then registers the SwaggerUI middleware from Swashbuckle.AspNetCore
@ -28,8 +28,8 @@ it on /swagger/v1/swagger.json. It then registers the SwaggerUI middleware from
app.UseOcelot().Wait(); app.UseOcelot().Wait();
The main reasons why I don't think Swagger makes sense is we already hand roll our definition in configuration.json. The main reasons why I don't think Swagger makes sense is we already hand roll our definition in ocelot.json.
If we want people developing against Ocelot to be able to see what routes are available then either share the configuration.json If we want people developing against Ocelot to be able to see what routes are available then either share the ocelot.json
with them (This should be as easy as granting access to a repo etc) or use the Ocelot administration API so that they can query Ocelot for the configuration. with them (This should be as easy as granting access to a repo etc) or use the Ocelot administration API so that they can query Ocelot for the configuration.
In addition to this many people will configure Ocelot to proxy all traffic like /products/{everything} to there product service In addition to this many people will configure Ocelot to proxy all traffic like /products/{everything} to there product service
@ -40,4 +40,4 @@ package doesnt reload swagger.json if it changes during runtime. Ocelot's config
information would not match. Unless I rolled my own Swagger implementation. information would not match. Unless I rolled my own Swagger implementation.
If the user wants something to easily test against the Ocelot API then I suggest using Postman as a simple way to do this. It might If the user wants something to easily test against the Ocelot API then I suggest using Postman as a simple way to do this. It might
even be possible to write something that maps configuration.json to the postman json spec. However I don't intend to do this. even be possible to write something that maps ocelot.json to the postman json spec. However I don't intend to do this.

View File

@ -3,7 +3,7 @@
<TargetFramework>netcoreapp2.0</TargetFramework> <TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Update="configuration.json;appsettings.json"> <None Update="ocelot.json;appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>

View File

@ -106,7 +106,7 @@ namespace OcelotGraphQL
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true) .AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
.AddJsonFile("configuration.json") .AddJsonFile("ocelot.json")
.AddEnvironmentVariables(); .AddEnvironmentVariables();
}) })
.ConfigureServices(s => { .ConfigureServices(s => {

View File

@ -47,7 +47,7 @@ RESPONSE
## Notes ## Notes
Please note this project never goes out to another service, it just gets the data for GraphQL in memory. You would need to add the details of your GraphQL server in configuration.json e.g. Please note this project never goes out to another service, it just gets the data for GraphQL in memory. You would need to add the details of your GraphQL server in ocelot.json e.g.
```json ```json
{ {

View File

@ -13,7 +13,7 @@
# Service fabric # Service fabric
OcelotApplicationApiGatewayPkg/Code OcelotApplicationApiGatewayPkg/Code
OcelotApplication/OcelotApplicationApiGatewayPkg/Code/appsettings.json OcelotApplication/OcelotApplicationApiGatewayPkg/Code/appsettings.json
OcelotApplication/OcelotApplicationApiGatewayPkg/Code/configuration.json OcelotApplication/OcelotApplicationApiGatewayPkg/Code/ocelot.json
OcelotApplication/OcelotApplicationApiGatewayPkg/Code/runtimes/ OcelotApplication/OcelotApplicationApiGatewayPkg/Code/runtimes/
OcelotApplicationServicePkg/Code OcelotApplicationServicePkg/Code
OcelotApplication/OcelotApplicationApiGatewayPkg/Code/web.config OcelotApplication/OcelotApplicationApiGatewayPkg/Code/web.config

View File

@ -8,7 +8,7 @@
<PackageId>OcelotApplicationApiGateway</PackageId> <PackageId>OcelotApplicationApiGateway</PackageId>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Update="configuration.json;appsettings.json;"> <None Update="ocelot.json;appsettings.json;">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>

View File

@ -67,7 +67,7 @@ namespace OcelotApplicationApiGateway
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true) .AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
.AddJsonFile("configuration.json") .AddJsonFile("ocelot.json")
.AddEnvironmentVariables(); .AddEnvironmentVariables();
}) })
.ConfigureLogging((hostingContext, logging) => .ConfigureLogging((hostingContext, logging) =>

View File

@ -1,9 +1,5 @@
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Ocelot.Cache;
using Ocelot.Configuration.Provider;
namespace Ocelot.Cache namespace Ocelot.Cache
{ {
@ -11,7 +7,7 @@ namespace Ocelot.Cache
[Route("outputcache")] [Route("outputcache")]
public class OutputCacheController : Controller public class OutputCacheController : Controller
{ {
private IOcelotCache<CachedResponse> _cache; private readonly IOcelotCache<CachedResponse> _cache;
public OutputCacheController(IOcelotCache<CachedResponse> cache) public OutputCacheController(IOcelotCache<CachedResponse> cache)
{ {

View File

@ -1,22 +0,0 @@
using System;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
namespace Ocelot.Configuration.Authentication
{
public class HashMatcher : IHashMatcher
{
public bool Match(string password, string salt, string hash)
{
byte[] s = Convert.FromBase64String(salt);
string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: s,
prf: KeyDerivationPrf.HMACSHA256,
iterationCount: 10000,
numBytesRequested: 256 / 8));
return hashed == hash;
}
}
}

View File

@ -1,7 +0,0 @@
namespace Ocelot.Configuration.Authentication
{
public interface IHashMatcher
{
bool Match(string password, string salt, string hash);
}
}

View File

@ -16,9 +16,8 @@ namespace Ocelot.Configuration.Creator
/// <summary> /// <summary>
/// Register as singleton /// Register as singleton
/// </summary> /// </summary>
public class FileOcelotConfigurationCreator : IOcelotConfigurationCreator public class FileInternalConfigurationCreator : IInternalConfigurationCreator
{ {
private readonly IOptions<FileConfiguration> _options;
private readonly IConfigurationValidator _configurationValidator; private readonly IConfigurationValidator _configurationValidator;
private readonly IOcelotLogger _logger; private readonly IOcelotLogger _logger;
private readonly IClaimsToThingCreator _claimsToThingCreator; private readonly IClaimsToThingCreator _claimsToThingCreator;
@ -35,8 +34,7 @@ namespace Ocelot.Configuration.Creator
private readonly IHeaderFindAndReplaceCreator _headerFAndRCreator; private readonly IHeaderFindAndReplaceCreator _headerFAndRCreator;
private readonly IDownstreamAddressesCreator _downstreamAddressesCreator; private readonly IDownstreamAddressesCreator _downstreamAddressesCreator;
public FileOcelotConfigurationCreator( public FileInternalConfigurationCreator(
IOptions<FileConfiguration> options,
IConfigurationValidator configurationValidator, IConfigurationValidator configurationValidator,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IClaimsToThingCreator claimsToThingCreator, IClaimsToThingCreator claimsToThingCreator,
@ -62,9 +60,8 @@ namespace Ocelot.Configuration.Creator
_requestIdKeyCreator = requestIdKeyCreator; _requestIdKeyCreator = requestIdKeyCreator;
_upstreamTemplatePatternCreator = upstreamTemplatePatternCreator; _upstreamTemplatePatternCreator = upstreamTemplatePatternCreator;
_authOptionsCreator = authOptionsCreator; _authOptionsCreator = authOptionsCreator;
_options = options;
_configurationValidator = configurationValidator; _configurationValidator = configurationValidator;
_logger = loggerFactory.CreateLogger<FileOcelotConfigurationCreator>(); _logger = loggerFactory.CreateLogger<FileInternalConfigurationCreator>();
_claimsToThingCreator = claimsToThingCreator; _claimsToThingCreator = claimsToThingCreator;
_serviceProviderConfigCreator = serviceProviderConfigCreator; _serviceProviderConfigCreator = serviceProviderConfigCreator;
_qosOptionsCreator = qosOptionsCreator; _qosOptionsCreator = qosOptionsCreator;
@ -72,19 +69,19 @@ namespace Ocelot.Configuration.Creator
_httpHandlerOptionsCreator = httpHandlerOptionsCreator; _httpHandlerOptionsCreator = httpHandlerOptionsCreator;
} }
public async Task<Response<IOcelotConfiguration>> Create(FileConfiguration fileConfiguration) public async Task<Response<IInternalConfiguration>> Create(FileConfiguration fileConfiguration)
{ {
var config = await SetUpConfiguration(fileConfiguration); var config = await SetUpConfiguration(fileConfiguration);
return config; return config;
} }
private async Task<Response<IOcelotConfiguration>> SetUpConfiguration(FileConfiguration fileConfiguration) private async Task<Response<IInternalConfiguration>> SetUpConfiguration(FileConfiguration fileConfiguration)
{ {
var response = await _configurationValidator.IsValid(fileConfiguration); var response = await _configurationValidator.IsValid(fileConfiguration);
if (response.Data.IsError) if (response.Data.IsError)
{ {
return new ErrorResponse<IOcelotConfiguration>(response.Data.Errors); return new ErrorResponse<IInternalConfiguration>(response.Data.Errors);
} }
var reRoutes = new List<ReRoute>(); var reRoutes = new List<ReRoute>();
@ -106,9 +103,9 @@ namespace Ocelot.Configuration.Creator
var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration); var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration);
var config = new OcelotConfiguration(reRoutes, _adminPath.Path, serviceProviderConfiguration, fileConfiguration.GlobalConfiguration.RequestIdKey); var config = new InternalConfiguration(reRoutes, _adminPath.Path, serviceProviderConfiguration, fileConfiguration.GlobalConfiguration.RequestIdKey);
return new OkResponse<IOcelotConfiguration>(config); return new OkResponse<IInternalConfiguration>(config);
} }
public ReRoute SetUpAggregateReRoute(List<ReRoute> reRoutes, FileAggregateReRoute aggregateReRoute, FileGlobalConfiguration globalConfiguration) public ReRoute SetUpAggregateReRoute(List<ReRoute> reRoutes, FileAggregateReRoute aggregateReRoute, FileGlobalConfiguration globalConfiguration)

View File

@ -0,0 +1,11 @@
using System.Threading.Tasks;
using Ocelot.Configuration.File;
using Ocelot.Responses;
namespace Ocelot.Configuration.Creator
{
public interface IInternalConfigurationCreator
{
Task<Response<IInternalConfiguration>> Create(FileConfiguration fileConfiguration);
}
}

View File

@ -1,11 +0,0 @@
using System.Threading.Tasks;
using Ocelot.Configuration.File;
using Ocelot.Responses;
namespace Ocelot.Configuration.Creator
{
public interface IOcelotConfigurationCreator
{
Task<Response<IOcelotConfiguration>> Create(FileConfiguration fileConfiguration);
}
}

View File

@ -1,8 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using IdentityServer4.AccessTokenValidation;
using IdentityServer4.Models;
using Ocelot.Configuration.Provider;
namespace Ocelot.Configuration.Creator namespace Ocelot.Configuration.Creator
{ {

View File

@ -2,34 +2,34 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.Configuration.File; using Ocelot.Configuration.File;
using Ocelot.Configuration.Provider;
using Ocelot.Configuration.Setter; using Ocelot.Configuration.Setter;
using Ocelot.Raft; using Ocelot.Raft;
using Rafty.Concensus; using Rafty.Concensus;
namespace Ocelot.Configuration namespace Ocelot.Configuration
{ {
using Repository;
[Authorize] [Authorize]
[Route("configuration")] [Route("configuration")]
public class FileConfigurationController : Controller public class FileConfigurationController : Controller
{ {
private readonly IFileConfigurationProvider _configGetter; private readonly IFileConfigurationRepository _repo;
private readonly IFileConfigurationSetter _configSetter; private readonly IFileConfigurationSetter _setter;
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _provider;
public FileConfigurationController(IFileConfigurationProvider getFileConfig, IFileConfigurationSetter configSetter, IServiceProvider serviceProvider) public FileConfigurationController(IFileConfigurationRepository repo, IFileConfigurationSetter setter, IServiceProvider provider)
{ {
_configGetter = getFileConfig; _repo = repo;
_configSetter = configSetter; _setter = setter;
_serviceProvider = serviceProvider; _provider = provider;
} }
[HttpGet] [HttpGet]
public async Task<IActionResult> Get() public async Task<IActionResult> Get()
{ {
var response = await _configGetter.Get(); var response = await _repo.Get();
if(response.IsError) if(response.IsError)
{ {
@ -43,7 +43,7 @@ namespace Ocelot.Configuration
public async Task<IActionResult> Post([FromBody]FileConfiguration fileConfiguration) public async Task<IActionResult> Post([FromBody]FileConfiguration fileConfiguration)
{ {
//todo - this code is a bit shit sort it out.. //todo - this code is a bit shit sort it out..
var test = _serviceProvider.GetService(typeof(INode)); var test = _provider.GetService(typeof(INode));
if (test != null) if (test != null)
{ {
var node = (INode)test; var node = (INode)test;
@ -56,7 +56,7 @@ namespace Ocelot.Configuration
return new OkObjectResult(result.Command.Configuration); return new OkObjectResult(result.Command.Configuration);
} }
var response = await _configSetter.Set(fileConfiguration); var response = await _setter.Set(fileConfiguration);
if (response.IsError) if (response.IsError)
{ {

View File

@ -1,9 +1,7 @@
using System.Collections.Generic; namespace Ocelot.Configuration
using IdentityServer4.AccessTokenValidation;
using IdentityServer4.Models;
namespace Ocelot.Configuration.Provider
{ {
using System.Collections.Generic;
public interface IIdentityServerConfiguration public interface IIdentityServerConfiguration
{ {
string ApiName { get; } string ApiName { get; }

View File

@ -2,7 +2,7 @@ using System.Collections.Generic;
namespace Ocelot.Configuration namespace Ocelot.Configuration
{ {
public interface IOcelotConfiguration public interface IInternalConfiguration
{ {
List<ReRoute> ReRoutes { get; } List<ReRoute> ReRoutes { get; }
string AdministrationPath {get;} string AdministrationPath {get;}

View File

@ -1,9 +1,7 @@
using System.Collections.Generic; namespace Ocelot.Configuration
using IdentityServer4.AccessTokenValidation;
using IdentityServer4.Models;
namespace Ocelot.Configuration.Provider
{ {
using System.Collections.Generic;
public class IdentityServerConfiguration : IIdentityServerConfiguration public class IdentityServerConfiguration : IIdentityServerConfiguration
{ {
public IdentityServerConfiguration( public IdentityServerConfiguration(
@ -22,11 +20,11 @@ namespace Ocelot.Configuration.Provider
CredentialsSigningCertificatePassword = credentialsSigningCertificatePassword; CredentialsSigningCertificatePassword = credentialsSigningCertificatePassword;
} }
public string ApiName { get; private set; } public string ApiName { get; }
public bool RequireHttps { get; private set; } public bool RequireHttps { get; }
public List<string> AllowedScopes { get; private set; } public List<string> AllowedScopes { get; }
public string ApiSecret { get; private set; } public string ApiSecret { get; }
public string CredentialsSigningCertificateLocation { get; private set; } public string CredentialsSigningCertificateLocation { get; }
public string CredentialsSigningCertificatePassword { get; private set; } public string CredentialsSigningCertificatePassword { get; }
} }
} }

View File

@ -2,9 +2,9 @@ using System.Collections.Generic;
namespace Ocelot.Configuration namespace Ocelot.Configuration
{ {
public class OcelotConfiguration : IOcelotConfiguration public class InternalConfiguration : IInternalConfiguration
{ {
public OcelotConfiguration(List<ReRoute> reRoutes, string administrationPath, ServiceProviderConfiguration serviceProviderConfiguration, string requestId) public InternalConfiguration(List<ReRoute> reRoutes, string administrationPath, ServiceProviderConfiguration serviceProviderConfiguration, string requestId)
{ {
ReRoutes = reRoutes; ReRoutes = reRoutes;
AdministrationPath = administrationPath; AdministrationPath = administrationPath;

View File

@ -1,26 +0,0 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Ocelot.Configuration.File;
using Ocelot.Configuration.Repository;
using Ocelot.Responses;
namespace Ocelot.Configuration.Provider
{
public class FileConfigurationProvider : IFileConfigurationProvider
{
private IFileConfigurationRepository _repo;
public FileConfigurationProvider(IFileConfigurationRepository repo)
{
_repo = repo;
}
public async Task<Response<FileConfiguration>> Get()
{
var fileConfig = await _repo.Get();
return new OkResponse<FileConfiguration>(fileConfig.Data);
}
}
}

View File

@ -1,11 +0,0 @@
using System.Threading.Tasks;
using Ocelot.Configuration.File;
using Ocelot.Responses;
namespace Ocelot.Configuration.Provider
{
public interface IFileConfigurationProvider
{
Task<Response<FileConfiguration>> Get();
}
}

View File

@ -1,11 +0,0 @@
using System.Threading.Tasks;
using Ocelot.Configuration.File;
using Ocelot.Responses;
namespace Ocelot.Configuration.Provider
{
public interface IOcelotConfigurationProvider
{
Task<Response<IOcelotConfiguration>> Get();
}
}

View File

@ -1,32 +0,0 @@
using System.Threading.Tasks;
using Ocelot.Configuration.File;
using Ocelot.Configuration.Repository;
using Ocelot.Responses;
namespace Ocelot.Configuration.Provider
{
/// <summary>
/// Register as singleton
/// </summary>
public class OcelotConfigurationProvider : IOcelotConfigurationProvider
{
private readonly IOcelotConfigurationRepository _config;
public OcelotConfigurationProvider(IOcelotConfigurationRepository repo)
{
_config = repo;
}
public async Task<Response<IOcelotConfiguration>> Get()
{
var repoConfig = await _config.Get();
if (repoConfig.IsError)
{
return new ErrorResponse<IOcelotConfiguration>(repoConfig.Errors);
}
return new OkResponse<IOcelotConfiguration>(repoConfig.Data);
}
}
}

View File

@ -1,3 +1,5 @@
namespace Ocelot.Configuration.Repository
{
using System; using System;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -5,26 +7,41 @@ using Consul;
using Newtonsoft.Json; using Newtonsoft.Json;
using Ocelot.Configuration.File; using Ocelot.Configuration.File;
using Ocelot.Infrastructure.Consul; using Ocelot.Infrastructure.Consul;
using Ocelot.Logging;
using Ocelot.Responses; using Ocelot.Responses;
using Ocelot.ServiceDiscovery.Configuration; using Ocelot.ServiceDiscovery.Configuration;
namespace Ocelot.Configuration.Repository
{
public class ConsulFileConfigurationRepository : IFileConfigurationRepository public class ConsulFileConfigurationRepository : IFileConfigurationRepository
{ {
private readonly ConsulClient _consul; private readonly ConsulClient _consul;
private const string OcelotConfiguration = "OcelotConfiguration"; private const string OcelotConfiguration = "InternalConfiguration";
private readonly Cache.IOcelotCache<FileConfiguration> _cache; private readonly Cache.IOcelotCache<FileConfiguration> _cache;
private readonly IOcelotLogger _logger;
public ConsulFileConfigurationRepository( public ConsulFileConfigurationRepository(
Cache.IOcelotCache<FileConfiguration> cache, Cache.IOcelotCache<FileConfiguration> cache,
ServiceProviderConfiguration serviceProviderConfig, IInternalConfigurationRepository repo,
IConsulClientFactory factory) IConsulClientFactory factory,
IOcelotLoggerFactory loggerFactory)
{ {
var consulHost = string.IsNullOrEmpty(serviceProviderConfig?.Host) ? "localhost" : serviceProviderConfig?.Host; _logger = loggerFactory.CreateLogger<ConsulFileConfigurationRepository>();
var consulPort = serviceProviderConfig?.Port ?? 8500;
var config = new ConsulRegistryConfiguration(consulHost, consulPort, OcelotConfiguration, serviceProviderConfig?.Token);
_cache = cache; _cache = cache;
var internalConfig = repo.Get();
var consulHost = "localhost";
var consulPort = 8500;
string token = null;
if (!internalConfig.IsError)
{
consulHost = string.IsNullOrEmpty(internalConfig.Data.ServiceProviderConfiguration?.Host) ? consulHost : internalConfig.Data.ServiceProviderConfiguration?.Host;
consulPort = internalConfig.Data.ServiceProviderConfiguration?.Port ?? consulPort;
token = internalConfig.Data.ServiceProviderConfiguration?.Token;
}
var config = new ConsulRegistryConfiguration(consulHost, consulPort, OcelotConfiguration, token);
_consul = factory.Get(config); _consul = factory.Get(config);
} }

View File

@ -7,15 +7,17 @@ using Ocelot.Responses;
namespace Ocelot.Configuration.Repository namespace Ocelot.Configuration.Repository
{ {
public class FileConfigurationRepository : IFileConfigurationRepository public class DiskFileConfigurationRepository : IFileConfigurationRepository
{ {
private readonly string _configFilePath; private readonly string _configFilePath;
private static readonly object _lock = new object(); private static readonly object _lock = new object();
public FileConfigurationRepository(IHostingEnvironment hostingEnvironment) private const string ConfigurationFileName = "ocelot";
public DiskFileConfigurationRepository(IHostingEnvironment hostingEnvironment)
{ {
_configFilePath = $"{AppContext.BaseDirectory}/configuration{(string.IsNullOrEmpty(hostingEnvironment.EnvironmentName) ? string.Empty : ".")}{hostingEnvironment.EnvironmentName}.json"; _configFilePath = $"{AppContext.BaseDirectory}/{ConfigurationFileName}{(string.IsNullOrEmpty(hostingEnvironment.EnvironmentName) ? string.Empty : ".")}{hostingEnvironment.EnvironmentName}.json";
} }
public Task<Response<FileConfiguration>> Get() public Task<Response<FileConfiguration>> Get()

View File

@ -0,0 +1,10 @@
using Ocelot.Responses;
namespace Ocelot.Configuration.Repository
{
public interface IInternalConfigurationRepository
{
Response<IInternalConfiguration> Get();
Response AddOrReplace(IInternalConfiguration internalConfiguration);
}
}

View File

@ -1,12 +0,0 @@
using System.Threading.Tasks;
using Ocelot.Configuration.File;
using Ocelot.Responses;
namespace Ocelot.Configuration.Repository
{
public interface IOcelotConfigurationRepository
{
Task<Response<IOcelotConfiguration>> Get();
Task<Response> AddOrReplace(IOcelotConfiguration ocelotConfiguration);
}
}

View File

@ -0,0 +1,29 @@
using Ocelot.Responses;
namespace Ocelot.Configuration.Repository
{
/// <summary>
/// Register as singleton
/// </summary>
public class InMemoryInternalConfigurationRepository : IInternalConfigurationRepository
{
private static readonly object LockObject = new object();
private IInternalConfiguration _internalConfiguration;
public Response<IInternalConfiguration> Get()
{
return new OkResponse<IInternalConfiguration>(_internalConfiguration);
}
public Response AddOrReplace(IInternalConfiguration internalConfiguration)
{
lock (LockObject)
{
_internalConfiguration = internalConfiguration;
}
return new OkResponse();
}
}
}

View File

@ -1,30 +0,0 @@
using System.Threading.Tasks;
using Ocelot.Responses;
namespace Ocelot.Configuration.Repository
{
/// <summary>
/// Register as singleton
/// </summary>
public class InMemoryOcelotConfigurationRepository : IOcelotConfigurationRepository
{
private static readonly object LockObject = new object();
private IOcelotConfiguration _ocelotConfiguration;
public Task<Response<IOcelotConfiguration>> Get()
{
return Task.FromResult<Response<IOcelotConfiguration>>(new OkResponse<IOcelotConfiguration>(_ocelotConfiguration));
}
public Task<Response> AddOrReplace(IOcelotConfiguration ocelotConfiguration)
{
lock (LockObject)
{
_ocelotConfiguration = ocelotConfiguration;
}
return Task.FromResult<Response>(new OkResponse());
}
}
}

View File

@ -6,14 +6,16 @@ using Ocelot.Responses;
namespace Ocelot.Configuration.Setter namespace Ocelot.Configuration.Setter
{ {
public class FileConfigurationSetter : IFileConfigurationSetter public class FileAndInternalConfigurationSetter : IFileConfigurationSetter
{ {
private readonly IOcelotConfigurationRepository _configRepo; private readonly IInternalConfigurationRepository _configRepo;
private readonly IOcelotConfigurationCreator _configCreator; private readonly IInternalConfigurationCreator _configCreator;
private readonly IFileConfigurationRepository _repo; private readonly IFileConfigurationRepository _repo;
public FileConfigurationSetter(IOcelotConfigurationRepository configRepo, public FileAndInternalConfigurationSetter(
IOcelotConfigurationCreator configCreator, IFileConfigurationRepository repo) IInternalConfigurationRepository configRepo,
IInternalConfigurationCreator configCreator,
IFileConfigurationRepository repo)
{ {
_configRepo = configRepo; _configRepo = configRepo;
_configCreator = configCreator; _configCreator = configCreator;
@ -33,7 +35,7 @@ namespace Ocelot.Configuration.Setter
if(!config.IsError) if(!config.IsError)
{ {
await _configRepo.AddOrReplace(config.Data); _configRepo.AddOrReplace(config.Data);
} }
return new ErrorResponse(config.Errors); return new ErrorResponse(config.Errors);

View File

@ -1,21 +1,73 @@
namespace Ocelot.DependencyInjection
{
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Memory; using Microsoft.Extensions.Configuration.Memory;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Configuration.File;
using Newtonsoft.Json;
namespace Ocelot.DependencyInjection
{
public static class ConfigurationBuilderExtensions public static class ConfigurationBuilderExtensions
{ {
[Obsolete("Please set BaseUrl in configuration.json GlobalConfiguration.BaseUrl")] [Obsolete("Please set BaseUrl in ocelot.json GlobalConfiguration.BaseUrl")]
public static IConfigurationBuilder AddOcelotBaseUrl(this IConfigurationBuilder builder, string baseUrl) public static IConfigurationBuilder AddOcelotBaseUrl(this IConfigurationBuilder builder, string baseUrl)
{ {
var memorySource = new MemoryConfigurationSource(); var memorySource = new MemoryConfigurationSource
memorySource.InitialData = new List<KeyValuePair<string, string>> {
InitialData = new List<KeyValuePair<string, string>>
{ {
new KeyValuePair<string, string>("BaseUrl", baseUrl) new KeyValuePair<string, string>("BaseUrl", baseUrl)
}
}; };
builder.Add(memorySource); builder.Add(memorySource);
return builder;
}
public static IConfigurationBuilder AddOcelot(this IConfigurationBuilder builder)
{
const string pattern = "(?i)ocelot(.*).json$";
var reg = new Regex(pattern);
var files = Directory.GetFiles(".")
.Where(path => reg.IsMatch(path)).Where(x => x.Count(s => s == '.') == 3)
.ToList();
var fileConfiguration = new FileConfiguration();
foreach (var file in files)
{
// windows and unix sigh...
if(files.Count > 1 && (file == "./ocelot.json" || file == ".\\ocelot.json"))
{
continue;
}
var lines = File.ReadAllText(file);
var config = JsonConvert.DeserializeObject<FileConfiguration>(lines);
// windows and unix sigh...
if (file == "./ocelot.global.json" || file == ".\\ocelot.global.json")
{
fileConfiguration.GlobalConfiguration = config.GlobalConfiguration;
}
fileConfiguration.Aggregates.AddRange(config.Aggregates);
fileConfiguration.ReRoutes.AddRange(config.ReRoutes);
}
var json = JsonConvert.SerializeObject(fileConfiguration);
File.WriteAllText("ocelot.json", json);
builder.AddJsonFile("ocelot.json");
return builder; return builder;
} }
} }

View File

@ -1,7 +1,3 @@
using Butterfly.Client.Tracing;
using Microsoft.Extensions.Options;
using Ocelot.Middleware.Multiplexer;
namespace Ocelot.DependencyInjection namespace Ocelot.DependencyInjection
{ {
using CacheManager.Core; using CacheManager.Core;
@ -12,17 +8,14 @@ namespace Ocelot.DependencyInjection
using Ocelot.Authorisation; using Ocelot.Authorisation;
using Ocelot.Cache; using Ocelot.Cache;
using Ocelot.Claims; using Ocelot.Claims;
using Ocelot.Configuration.Authentication;
using Ocelot.Configuration.Creator; using Ocelot.Configuration.Creator;
using Ocelot.Configuration.File; using Ocelot.Configuration.File;
using Ocelot.Configuration.Parser; using Ocelot.Configuration.Parser;
using Ocelot.Configuration.Provider;
using Ocelot.Configuration.Repository; using Ocelot.Configuration.Repository;
using Ocelot.Configuration.Setter; using Ocelot.Configuration.Setter;
using Ocelot.Configuration.Validator; using Ocelot.Configuration.Validator;
using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.DownstreamRouteFinder.Finder;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.DownstreamUrlCreator;
using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer;
using Ocelot.Headers; using Ocelot.Headers;
using Ocelot.Infrastructure.Claims.Parser; using Ocelot.Infrastructure.Claims.Parser;
@ -44,16 +37,14 @@ namespace Ocelot.DependencyInjection
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using IdentityServer4.AccessTokenValidation; using IdentityServer4.AccessTokenValidation;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using FileConfigurationProvider = Ocelot.Configuration.Provider.FileConfigurationProvider;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Linq;
using System.Net.Http; using System.Net.Http;
using Butterfly.Client.AspNetCore; using Butterfly.Client.AspNetCore;
using Ocelot.Infrastructure; using Ocelot.Infrastructure;
using Ocelot.Infrastructure.Consul; using Ocelot.Infrastructure.Consul;
using Butterfly.Client.Tracing;
using Ocelot.Middleware.Multiplexer;
public class OcelotBuilder : IOcelotBuilder public class OcelotBuilder : IOcelotBuilder
{ {
@ -78,8 +69,8 @@ namespace Ocelot.DependencyInjection
_services.TryAddSingleton<IHttpResponseHeaderReplacer, HttpResponseHeaderReplacer>(); _services.TryAddSingleton<IHttpResponseHeaderReplacer, HttpResponseHeaderReplacer>();
_services.TryAddSingleton<IHttpContextRequestHeaderReplacer, HttpContextRequestHeaderReplacer>(); _services.TryAddSingleton<IHttpContextRequestHeaderReplacer, HttpContextRequestHeaderReplacer>();
_services.TryAddSingleton<IHeaderFindAndReplaceCreator, HeaderFindAndReplaceCreator>(); _services.TryAddSingleton<IHeaderFindAndReplaceCreator, HeaderFindAndReplaceCreator>();
_services.TryAddSingleton<IOcelotConfigurationCreator, FileOcelotConfigurationCreator>(); _services.TryAddSingleton<IInternalConfigurationCreator, FileInternalConfigurationCreator>();
_services.TryAddSingleton<IOcelotConfigurationRepository, InMemoryOcelotConfigurationRepository>(); _services.TryAddSingleton<IInternalConfigurationRepository, InMemoryInternalConfigurationRepository>();
_services.TryAddSingleton<IConfigurationValidator, FileConfigurationFluentValidator>(); _services.TryAddSingleton<IConfigurationValidator, FileConfigurationFluentValidator>();
_services.TryAddSingleton<IClaimsToThingCreator, ClaimsToThingCreator>(); _services.TryAddSingleton<IClaimsToThingCreator, ClaimsToThingCreator>();
_services.TryAddSingleton<IAuthenticationOptionsCreator, AuthenticationOptionsCreator>(); _services.TryAddSingleton<IAuthenticationOptionsCreator, AuthenticationOptionsCreator>();
@ -91,9 +82,8 @@ namespace Ocelot.DependencyInjection
_services.TryAddSingleton<IRateLimitOptionsCreator, RateLimitOptionsCreator>(); _services.TryAddSingleton<IRateLimitOptionsCreator, RateLimitOptionsCreator>();
_services.TryAddSingleton<IBaseUrlFinder, BaseUrlFinder>(); _services.TryAddSingleton<IBaseUrlFinder, BaseUrlFinder>();
_services.TryAddSingleton<IRegionCreator, RegionCreator>(); _services.TryAddSingleton<IRegionCreator, RegionCreator>();
_services.TryAddSingleton<IFileConfigurationRepository, FileConfigurationRepository>(); _services.TryAddSingleton<IFileConfigurationRepository, DiskFileConfigurationRepository>();
_services.TryAddSingleton<IFileConfigurationSetter, FileConfigurationSetter>(); _services.TryAddSingleton<IFileConfigurationSetter, FileAndInternalConfigurationSetter>();
_services.TryAddSingleton<IFileConfigurationProvider, FileConfigurationProvider>();
_services.TryAddSingleton<IQosProviderHouse, QosProviderHouse>(); _services.TryAddSingleton<IQosProviderHouse, QosProviderHouse>();
_services.TryAddSingleton<IQoSProviderFactory, QoSProviderFactory>(); _services.TryAddSingleton<IQoSProviderFactory, QoSProviderFactory>();
_services.TryAddSingleton<IServiceDiscoveryProviderFactory, ServiceDiscoveryProviderFactory>(); _services.TryAddSingleton<IServiceDiscoveryProviderFactory, ServiceDiscoveryProviderFactory>();
@ -101,7 +91,6 @@ namespace Ocelot.DependencyInjection
_services.TryAddSingleton<ILoadBalancerHouse, LoadBalancerHouse>(); _services.TryAddSingleton<ILoadBalancerHouse, LoadBalancerHouse>();
_services.TryAddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>(); _services.TryAddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
_services.TryAddSingleton<IRemoveOutputHeaders, RemoveOutputHeaders>(); _services.TryAddSingleton<IRemoveOutputHeaders, RemoveOutputHeaders>();
_services.TryAddSingleton<IOcelotConfigurationProvider, OcelotConfigurationProvider>();
_services.TryAddSingleton<IClaimToThingConfigurationParser, ClaimToThingConfigurationParser>(); _services.TryAddSingleton<IClaimToThingConfigurationParser, ClaimToThingConfigurationParser>();
_services.TryAddSingleton<IClaimsAuthoriser, ClaimsAuthoriser>(); _services.TryAddSingleton<IClaimsAuthoriser, ClaimsAuthoriser>();
_services.TryAddSingleton<IScopesAuthoriser, ScopesAuthoriser>(); _services.TryAddSingleton<IScopesAuthoriser, ScopesAuthoriser>();
@ -252,17 +241,6 @@ namespace Ocelot.DependencyInjection
public IOcelotBuilder AddStoreOcelotConfigurationInConsul() public IOcelotBuilder AddStoreOcelotConfigurationInConsul()
{ {
var serviceDiscoveryPort = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Port", 0);
var serviceDiscoveryHost = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Host", string.Empty);
var serviceDiscoveryToken = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Token", string.Empty);
var config = new ServiceProviderConfigurationBuilder()
.WithPort(serviceDiscoveryPort)
.WithHost(serviceDiscoveryHost)
.WithToken(serviceDiscoveryToken)
.Build();
_services.AddSingleton<ServiceProviderConfiguration>(config);
_services.AddSingleton<ConsulFileConfigurationPoller>(); _services.AddSingleton<ConsulFileConfigurationPoller>();
_services.AddSingleton<IFileConfigurationRepository, ConsulFileConfigurationRepository>(); _services.AddSingleton<IFileConfigurationRepository, ConsulFileConfigurationRepository>();
return this; return this;
@ -278,12 +256,12 @@ namespace Ocelot.DependencyInjection
_services.AddSingleton<ICacheManager<CachedResponse>>(cacheManagerOutputCache); _services.AddSingleton<ICacheManager<CachedResponse>>(cacheManagerOutputCache);
_services.AddSingleton<IOcelotCache<CachedResponse>>(ocelotOutputCacheManager); _services.AddSingleton<IOcelotCache<CachedResponse>>(ocelotOutputCacheManager);
var ocelotConfigCacheManagerOutputCache = CacheFactory.Build<IOcelotConfiguration>("OcelotConfigurationCache", settings); var ocelotConfigCacheManagerOutputCache = CacheFactory.Build<IInternalConfiguration>("OcelotConfigurationCache", settings);
var ocelotConfigCacheManager = new OcelotCacheManagerCache<IOcelotConfiguration>(ocelotConfigCacheManagerOutputCache); var ocelotConfigCacheManager = new OcelotCacheManagerCache<IInternalConfiguration>(ocelotConfigCacheManagerOutputCache);
_services.RemoveAll(typeof(ICacheManager<IOcelotConfiguration>)); _services.RemoveAll(typeof(ICacheManager<IInternalConfiguration>));
_services.RemoveAll(typeof(IOcelotCache<IOcelotConfiguration>)); _services.RemoveAll(typeof(IOcelotCache<IInternalConfiguration>));
_services.AddSingleton<ICacheManager<IOcelotConfiguration>>(ocelotConfigCacheManagerOutputCache); _services.AddSingleton<ICacheManager<IInternalConfiguration>>(ocelotConfigCacheManagerOutputCache);
_services.AddSingleton<IOcelotCache<IOcelotConfiguration>>(ocelotConfigCacheManager); _services.AddSingleton<IOcelotCache<IInternalConfiguration>>(ocelotConfigCacheManager);
var fileConfigCacheManagerOutputCache = CacheFactory.Build<FileConfiguration>("FileConfigurationCache", settings); var fileConfigCacheManagerOutputCache = CacheFactory.Build<FileConfiguration>("FileConfigurationCache", settings);
var fileConfigCacheManager = new OcelotCacheManagerCache<FileConfiguration>(fileConfigCacheManagerOutputCache); var fileConfigCacheManager = new OcelotCacheManagerCache<FileConfiguration>(fileConfigCacheManagerOutputCache);
@ -304,7 +282,6 @@ namespace Ocelot.DependencyInjection
private void AddIdentityServer(IIdentityServerConfiguration identityServerConfiguration, IAdministrationPath adminPath) private void AddIdentityServer(IIdentityServerConfiguration identityServerConfiguration, IAdministrationPath adminPath)
{ {
_services.TryAddSingleton<IIdentityServerConfiguration>(identityServerConfiguration); _services.TryAddSingleton<IIdentityServerConfiguration>(identityServerConfiguration);
_services.TryAddSingleton<IHashMatcher, HashMatcher>();
var identityServerBuilder = _services var identityServerBuilder = _services
.AddIdentityServer(o => { .AddIdentityServer(o => {
o.IssuerUri = "Ocelot"; o.IssuerUri = "Ocelot";

View File

@ -18,7 +18,7 @@ namespace Ocelot.DownstreamRouteFinder.Finder
_placeholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder; _placeholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder;
} }
public Response<DownstreamRoute> FindDownstreamRoute(string path, string httpMethod, IOcelotConfiguration configuration, string upstreamHost) public Response<DownstreamRoute> FindDownstreamRoute(string path, string httpMethod, IInternalConfiguration configuration, string upstreamHost)
{ {
var downstreamRoutes = new List<DownstreamRoute>(); var downstreamRoutes = new List<DownstreamRoute>();

View File

@ -6,6 +6,6 @@ namespace Ocelot.DownstreamRouteFinder.Finder
{ {
public interface IDownstreamRouteFinder public interface IDownstreamRouteFinder
{ {
Response<DownstreamRoute> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod, IOcelotConfiguration configuration, string upstreamHost); Response<DownstreamRoute> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost);
} }
} }

View File

@ -1,7 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Linq; using System.Linq;
using Ocelot.Configuration; using Ocelot.Configuration.Repository;
using Ocelot.Configuration.Provider;
using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.DownstreamRouteFinder.Finder;
using Ocelot.Infrastructure.Extensions; using Ocelot.Infrastructure.Extensions;
using Ocelot.Logging; using Ocelot.Logging;
@ -14,17 +13,17 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IDownstreamRouteFinder _downstreamRouteFinder; private readonly IDownstreamRouteFinder _downstreamRouteFinder;
private readonly IOcelotConfigurationProvider _configProvider; private readonly IInternalConfigurationRepository _repo;
private readonly IMultiplexer _multiplexer; private readonly IMultiplexer _multiplexer;
public DownstreamRouteFinderMiddleware(OcelotRequestDelegate next, public DownstreamRouteFinderMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IDownstreamRouteFinder downstreamRouteFinder, IDownstreamRouteFinder downstreamRouteFinder,
IOcelotConfigurationProvider configProvider, IInternalConfigurationRepository repo,
IMultiplexer multiplexer) IMultiplexer multiplexer)
:base(loggerFactory.CreateLogger<DownstreamRouteFinderMiddleware>()) :base(loggerFactory.CreateLogger<DownstreamRouteFinderMiddleware>())
{ {
_configProvider = configProvider; _repo = repo;
_multiplexer = multiplexer; _multiplexer = multiplexer;
_next = next; _next = next;
_downstreamRouteFinder = downstreamRouteFinder; _downstreamRouteFinder = downstreamRouteFinder;
@ -36,7 +35,7 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
var upstreamHost = context.HttpContext.Request.Headers["Host"]; var upstreamHost = context.HttpContext.Request.Headers["Host"];
var configuration = await _configProvider.Get(); var configuration = _repo.Get();
if (configuration.IsError) if (configuration.IsError)
{ {

View File

@ -1,10 +1,7 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Ocelot.Configuration.Repository;
using Microsoft.Extensions.Primitives;
using Ocelot.Configuration.Provider;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Infrastructure.Extensions; using Ocelot.Infrastructure.Extensions;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging; using Ocelot.Logging;
@ -18,16 +15,16 @@ namespace Ocelot.Errors.Middleware
public class ExceptionHandlerMiddleware : OcelotMiddleware public class ExceptionHandlerMiddleware : OcelotMiddleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IOcelotConfigurationProvider _provider; private readonly IInternalConfigurationRepository _configRepo;
private readonly IRequestScopedDataRepository _repo; private readonly IRequestScopedDataRepository _repo;
public ExceptionHandlerMiddleware(OcelotRequestDelegate next, public ExceptionHandlerMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IOcelotConfigurationProvider provider, IInternalConfigurationRepository configRepo,
IRequestScopedDataRepository repo) IRequestScopedDataRepository repo)
: base(loggerFactory.CreateLogger<ExceptionHandlerMiddleware>()) : base(loggerFactory.CreateLogger<ExceptionHandlerMiddleware>())
{ {
_provider = provider; _configRepo = configRepo;
_repo = repo; _repo = repo;
_next = next; _next = next;
} }
@ -36,7 +33,7 @@ namespace Ocelot.Errors.Middleware
{ {
try try
{ {
await TrySetGlobalRequestId(context); TrySetGlobalRequestId(context);
Logger.LogDebug("ocelot pipeline started"); Logger.LogDebug("ocelot pipeline started");
@ -56,12 +53,12 @@ namespace Ocelot.Errors.Middleware
Logger.LogDebug("ocelot pipeline finished"); Logger.LogDebug("ocelot pipeline finished");
} }
private async Task TrySetGlobalRequestId(DownstreamContext context) private void TrySetGlobalRequestId(DownstreamContext context)
{ {
//try and get the global request id and set it for logs... //try and get the global request id and set it for logs...
//should this basically be immutable per request...i guess it should! //should this basically be immutable per request...i guess it should!
//first thing is get config //first thing is get config
var configuration = await _provider.Get(); var configuration = _configRepo.Get();
if(configuration.IsError) if(configuration.IsError)
{ {

View File

@ -4,14 +4,12 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System.Diagnostics; using System.Diagnostics;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Creator; using Ocelot.Configuration.Creator;
using Ocelot.Configuration.File; using Ocelot.Configuration.File;
using Ocelot.Configuration.Provider;
using Ocelot.Configuration.Repository; using Ocelot.Configuration.Repository;
using Ocelot.Configuration.Setter; using Ocelot.Configuration.Setter;
using Ocelot.Responses; using Ocelot.Responses;
@ -85,63 +83,108 @@
node.Start(nodeId.Id); node.Start(nodeId.Id);
} }
private static async Task<IOcelotConfiguration> CreateConfiguration(IApplicationBuilder builder) private static async Task<IInternalConfiguration> CreateConfiguration(IApplicationBuilder builder)
{ {
var deps = GetDependencies(builder); // make configuration from file system?
// earlier user needed to add ocelot files in startup configuration stuff, asp.net will map it to this
var fileConfig = (IOptions<FileConfiguration>)builder.ApplicationServices.GetService(typeof(IOptions<FileConfiguration>));
var ocelotConfiguration = await deps.provider.Get(); // now create the config
var internalConfigCreator = (IInternalConfigurationCreator)builder.ApplicationServices.GetService(typeof(IInternalConfigurationCreator));
var internalConfig = await internalConfigCreator.Create(fileConfig.Value);
if (ConfigurationNotSetUp(ocelotConfiguration)) // now save it in memory
var internalConfigRepo = (IInternalConfigurationRepository)builder.ApplicationServices.GetService(typeof(IInternalConfigurationRepository));
internalConfigRepo.AddOrReplace(internalConfig.Data);
var fileConfigSetter = (IFileConfigurationSetter)builder.ApplicationServices.GetService(typeof(IFileConfigurationSetter));
var fileConfigRepo = (IFileConfigurationRepository)builder.ApplicationServices.GetService(typeof(IFileConfigurationRepository));
if (UsingConsul(fileConfigRepo))
{ {
var response = await SetConfig(builder, deps.fileConfiguration, deps.setter, deps.provider, deps.repo); await SetFileConfigInConsul(builder, fileConfigRepo, fileConfig, internalConfigCreator, internalConfigRepo);
}
else
{
await SetFileConfig(fileConfigSetter, fileConfig);
}
if (UnableToSetConfig(response)) return GetOcelotConfigAndReturn(internalConfigRepo);
}
private static async Task SetFileConfigInConsul(IApplicationBuilder builder,
IFileConfigurationRepository fileConfigRepo, IOptions<FileConfiguration> fileConfig,
IInternalConfigurationCreator internalConfigCreator, IInternalConfigurationRepository internalConfigRepo)
{
// get the config from consul.
var fileConfigFromConsul = await fileConfigRepo.Get();
if (IsError(fileConfigFromConsul))
{
ThrowToStopOcelotStarting(fileConfigFromConsul);
}
else if (ConfigNotStoredInConsul(fileConfigFromConsul))
{
//there was no config in consul set the file in config in consul
await fileConfigRepo.Set(fileConfig.Value);
}
else
{
// create the internal config from consul data
var internalConfig = await internalConfigCreator.Create(fileConfigFromConsul.Data);
if (IsError(internalConfig))
{
ThrowToStopOcelotStarting(internalConfig);
}
else
{
// add the internal config to the internal repo
var response = internalConfigRepo.AddOrReplace(internalConfig.Data);
if (IsError(response))
{ {
ThrowToStopOcelotStarting(response); ThrowToStopOcelotStarting(response);
} }
} }
return await GetOcelotConfigAndReturn(deps.provider); if (IsError(internalConfig))
}
private static async Task<Response> SetConfig(IApplicationBuilder builder, IOptions<FileConfiguration> fileConfiguration, IFileConfigurationSetter setter, IOcelotConfigurationProvider provider, IFileConfigurationRepository repo)
{ {
if (UsingConsul(repo)) ThrowToStopOcelotStarting(internalConfig);
}
}
//todo - this starts the poller if it has been registered...please this is so bad.
var hack = builder.ApplicationServices.GetService(typeof(ConsulFileConfigurationPoller));
}
private static async Task SetFileConfig(IFileConfigurationSetter fileConfigSetter, IOptions<FileConfiguration> fileConfig)
{ {
return await SetUpConfigFromConsul(builder, repo, setter, fileConfiguration); Response response;
response = await fileConfigSetter.Set(fileConfig.Value);
if (IsError(response))
{
ThrowToStopOcelotStarting(response);
}
} }
return await setter.Set(fileConfiguration.Value); private static bool ConfigNotStoredInConsul(Responses.Response<FileConfiguration> fileConfigFromConsul)
{
return fileConfigFromConsul.Data == null;
} }
private static bool UnableToSetConfig(Response response) private static bool IsError(Response response)
{ {
return response == null || response.IsError; return response == null || response.IsError;
} }
private static bool ConfigurationNotSetUp(Ocelot.Responses.Response<IOcelotConfiguration> ocelotConfiguration) private static IInternalConfiguration GetOcelotConfigAndReturn(IInternalConfigurationRepository provider)
{ {
return ocelotConfiguration == null || ocelotConfiguration.Data == null || ocelotConfiguration.IsError; var ocelotConfiguration = provider.Get();
}
private static (IOptions<FileConfiguration> fileConfiguration, IFileConfigurationSetter setter, IOcelotConfigurationProvider provider, IFileConfigurationRepository repo) GetDependencies(IApplicationBuilder builder) if(ocelotConfiguration?.Data == null || ocelotConfiguration.IsError)
{
var fileConfiguration = (IOptions<FileConfiguration>)builder.ApplicationServices.GetService(typeof(IOptions<FileConfiguration>));
var setter = (IFileConfigurationSetter)builder.ApplicationServices.GetService(typeof(IFileConfigurationSetter));
var provider = (IOcelotConfigurationProvider)builder.ApplicationServices.GetService(typeof(IOcelotConfigurationProvider));
var repo = (IFileConfigurationRepository)builder.ApplicationServices.GetService(typeof(IFileConfigurationRepository));
return (fileConfiguration, setter, provider, repo);
}
private static async Task<IOcelotConfiguration> GetOcelotConfigAndReturn(IOcelotConfigurationProvider provider)
{
var ocelotConfiguration = await provider.Get();
if(ocelotConfiguration == null || ocelotConfiguration.Data == null || ocelotConfiguration.IsError)
{ {
ThrowToStopOcelotStarting(ocelotConfiguration); ThrowToStopOcelotStarting(ocelotConfiguration);
} }
@ -159,49 +202,7 @@
return fileConfigRepo.GetType() == typeof(ConsulFileConfigurationRepository); return fileConfigRepo.GetType() == typeof(ConsulFileConfigurationRepository);
} }
private static async Task<Response> SetUpConfigFromConsul(IApplicationBuilder builder, IFileConfigurationRepository consulFileConfigRepo, IFileConfigurationSetter setter, IOptions<FileConfiguration> fileConfig) private static void CreateAdministrationArea(IApplicationBuilder builder, IInternalConfiguration configuration)
{
Response config = null;
var ocelotConfigurationRepository =
(IOcelotConfigurationRepository) builder.ApplicationServices.GetService(
typeof(IOcelotConfigurationRepository));
var ocelotConfigurationCreator =
(IOcelotConfigurationCreator) builder.ApplicationServices.GetService(
typeof(IOcelotConfigurationCreator));
var fileConfigFromConsul = await consulFileConfigRepo.Get();
if (fileConfigFromConsul.Data == null)
{
config = await setter.Set(fileConfig.Value);
var hack = builder.ApplicationServices.GetService(typeof(ConsulFileConfigurationPoller));
}
else
{
var ocelotConfig = await ocelotConfigurationCreator.Create(fileConfigFromConsul.Data);
if(ocelotConfig.IsError)
{
return new ErrorResponse(ocelotConfig.Errors);
}
config = await ocelotConfigurationRepository.AddOrReplace(ocelotConfig.Data);
if (config.IsError)
{
return new ErrorResponse(config.Errors);
}
//todo - this starts the poller if it has been registered...please this is so bad.
var hack = builder.ApplicationServices.GetService(typeof(ConsulFileConfigurationPoller));
}
return new OkResponse();
}
private static void CreateAdministrationArea(IApplicationBuilder builder, IOcelotConfiguration configuration)
{ {
if(!string.IsNullOrEmpty(configuration.AdministrationPath)) if(!string.IsNullOrEmpty(configuration.AdministrationPath))
{ {

View File

@ -1,10 +1,8 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Provider; using Ocelot.Configuration.Repository;
using Ocelot.Middleware; using Ocelot.Middleware;
using Rafty.Concensus; using Rafty.Concensus;
using Rafty.Infrastructure; using Rafty.Infrastructure;
@ -15,21 +13,20 @@ namespace Ocelot.Raft
public class FilePeersProvider : IPeersProvider public class FilePeersProvider : IPeersProvider
{ {
private readonly IOptions<FilePeers> _options; private readonly IOptions<FilePeers> _options;
private List<IPeer> _peers; private readonly List<IPeer> _peers;
private IBaseUrlFinder _finder; private IBaseUrlFinder _finder;
private IOcelotConfigurationProvider _provider; private IInternalConfigurationRepository _repo;
private IIdentityServerConfiguration _identityServerConfig; private IIdentityServerConfiguration _identityServerConfig;
public FilePeersProvider(IOptions<FilePeers> options, IBaseUrlFinder finder, IOcelotConfigurationProvider provider, IIdentityServerConfiguration identityServerConfig) public FilePeersProvider(IOptions<FilePeers> options, IBaseUrlFinder finder, IInternalConfigurationRepository repo, IIdentityServerConfiguration identityServerConfig)
{ {
_identityServerConfig = identityServerConfig; _identityServerConfig = identityServerConfig;
_provider = provider; _repo = repo;
_finder = finder; _finder = finder;
_options = options; _options = options;
_peers = new List<IPeer>(); _peers = new List<IPeer>();
//todo - sort out async nonsense.. var config = _repo.Get();
var config = _provider.Get().GetAwaiter().GetResult();
foreach (var item in _options.Value.Peers) foreach (var item in _options.Value.Peers)
{ {
var httpClient = new HttpClient(); var httpClient = new HttpClient();

View File

@ -1,12 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Newtonsoft.Json; using Newtonsoft.Json;
using Ocelot.Authentication;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Provider;
using Ocelot.Middleware; using Ocelot.Middleware;
using Rafty.Concensus; using Rafty.Concensus;
using Rafty.FiniteStateMachine; using Rafty.FiniteStateMachine;
@ -16,15 +12,15 @@ namespace Ocelot.Raft
[ExcludeFromCoverage] [ExcludeFromCoverage]
public class HttpPeer : IPeer public class HttpPeer : IPeer
{ {
private string _hostAndPort; private readonly string _hostAndPort;
private HttpClient _httpClient; private readonly HttpClient _httpClient;
private JsonSerializerSettings _jsonSerializerSettings; private readonly JsonSerializerSettings _jsonSerializerSettings;
private string _baseSchemeUrlAndPort; private readonly string _baseSchemeUrlAndPort;
private BearerToken _token; private BearerToken _token;
private IOcelotConfiguration _config; private readonly IInternalConfiguration _config;
private IIdentityServerConfiguration _identityServerConfiguration; private readonly IIdentityServerConfiguration _identityServerConfiguration;
public HttpPeer(string hostAndPort, HttpClient httpClient, IBaseUrlFinder finder, IOcelotConfiguration config, IIdentityServerConfiguration identityServerConfiguration) public HttpPeer(string hostAndPort, HttpClient httpClient, IBaseUrlFinder finder, IInternalConfiguration config, IIdentityServerConfiguration identityServerConfiguration)
{ {
_identityServerConfiguration = identityServerConfiguration; _identityServerConfiguration = identityServerConfiguration;
_config = config; _config = config;

View File

@ -303,7 +303,7 @@ namespace Ocelot.AcceptanceTests
{ {
app.Run(async context => app.Run(async context =>
{ {
if (context.Request.Method.ToLower() == "get" && context.Request.Path.Value == "/v1/kv/OcelotConfiguration") if (context.Request.Method.ToLower() == "get" && context.Request.Path.Value == "/v1/kv/InternalConfiguration")
{ {
var json = JsonConvert.SerializeObject(_config); var json = JsonConvert.SerializeObject(_config);
@ -315,7 +315,7 @@ namespace Ocelot.AcceptanceTests
await context.Response.WriteJsonAsync(new FakeConsulGetResponse[] { kvp }); await context.Response.WriteJsonAsync(new FakeConsulGetResponse[] { kvp });
} }
else if (context.Request.Method.ToLower() == "put" && context.Request.Path.Value == "/v1/kv/OcelotConfiguration") else if (context.Request.Method.ToLower() == "put" && context.Request.Path.Value == "/v1/kv/InternalConfiguration")
{ {
try try
{ {
@ -352,7 +352,7 @@ namespace Ocelot.AcceptanceTests
public int CreateIndex => 100; public int CreateIndex => 100;
public int ModifyIndex => 200; public int ModifyIndex => 200;
public int LockIndex => 200; public int LockIndex => 200;
public string Key => "OcelotConfiguration"; public string Key => "InternalConfiguration";
public int Flags => 0; public int Flags => 0;
public string Value { get; private set; } public string Value { get; private set; }
public string Session => "adf4238a-882b-9ddc-4a9d-5b6758e4159e"; public string Session => "adf4238a-882b-9ddc-4a9d-5b6758e4159e";

View File

@ -26,7 +26,7 @@ namespace Ocelot.AcceptanceTests
{ {
_counter = 0; _counter = 0;
_steps = new Steps(); _steps = new Steps();
_configurationPath = "configuration.json"; _configurationPath = "ocelot.json";
} }
[Fact] [Fact]

View File

@ -15,7 +15,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Update="configuration.json;appsettings.json"> <None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>

View File

@ -66,7 +66,7 @@ namespace Ocelot.AcceptanceTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureLogging((hostingContext, logging) => .ConfigureLogging((hostingContext, logging) =>
@ -124,7 +124,7 @@ namespace Ocelot.AcceptanceTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(s => .ConfigureServices(s =>
@ -152,7 +152,7 @@ namespace Ocelot.AcceptanceTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(s => .ConfigureServices(s =>
@ -190,7 +190,7 @@ namespace Ocelot.AcceptanceTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(s => .ConfigureServices(s =>
@ -221,7 +221,7 @@ namespace Ocelot.AcceptanceTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(s => .ConfigureServices(s =>
@ -254,7 +254,7 @@ namespace Ocelot.AcceptanceTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(s => .ConfigureServices(s =>
@ -287,7 +287,7 @@ namespace Ocelot.AcceptanceTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(s => .ConfigureServices(s =>
@ -319,7 +319,7 @@ namespace Ocelot.AcceptanceTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(s => .ConfigureServices(s =>
@ -358,7 +358,7 @@ namespace Ocelot.AcceptanceTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(s => .ConfigureServices(s =>
@ -400,7 +400,7 @@ namespace Ocelot.AcceptanceTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(s => .ConfigureServices(s =>
@ -437,7 +437,7 @@ namespace Ocelot.AcceptanceTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(s => .ConfigureServices(s =>
@ -465,7 +465,7 @@ namespace Ocelot.AcceptanceTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(s => .ConfigureServices(s =>
@ -525,7 +525,7 @@ namespace Ocelot.AcceptanceTests
var builder = new ConfigurationBuilder() var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory()) .SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile("configuration.json") .AddJsonFile("ocelot.json")
.AddEnvironmentVariables(); .AddEnvironmentVariables();
var configuration = builder.Build(); var configuration = builder.Build();

View File

@ -5,6 +5,6 @@ namespace Ocelot.AcceptanceTests
{ {
public static class TestConfiguration public static class TestConfiguration
{ {
public static string ConfigurationPath => Path.Combine(AppContext.BaseDirectory, "configuration.json"); public static string ConfigurationPath => Path.Combine(AppContext.BaseDirectory, "ocelot.json");
} }
} }

View File

@ -1,59 +0,0 @@
{
"ReRoutes": [
{
"DownstreamPathTemplate": "41879/",
"UpstreamPathTemplate": "/",
"UpstreamHttpMethod": "Get",
"AuthenticationOptions": {
"Provider": null,
"ProviderRootUrl": null,
"ApiName": null,
"RequireHttps": false,
"AllowedScopes": [],
"ApiSecret": null
},
"AddHeadersToRequest": {},
"AddClaimsToRequest": {},
"RouteClaimsRequirement": {},
"AddQueriesToRequest": {},
"RequestIdKey": null,
"FileCacheOptions": {
"TtlSeconds": 0
},
"ReRouteIsCaseSensitive": false,
"ServiceName": null,
"DownstreamScheme": "http",
"DownstreamHost": "localhost",
"DownstreamPort": 41879,
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 0,
"DurationOfBreak": 0,
"TimeoutValue": 0
},
"LoadBalancer": null,
"RateLimitOptions": {
"ClientWhitelist": [],
"EnableRateLimiting": false,
"Period": null,
"PeriodTimespan": 0,
"Limit": 0
}
}
],
"GlobalConfiguration": {
"RequestIdKey": null,
"ServiceDiscoveryProvider": {
"Provider": null,
"Host": null,
"Port": 0
},
"AdministrationPath": null,
"RateLimitOptions": {
"ClientIdHeader": "ClientId",
"QuotaExceededMessage": null,
"RateLimitCounterPrefix": "ocelot",
"DisableRateLimitHeaders": false,
"HttpStatusCode": 429
}
}
}

View File

@ -461,7 +461,7 @@ namespace Ocelot.IntegrationTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(x => .ConfigureServices(x =>
@ -579,7 +579,7 @@ namespace Ocelot.IntegrationTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(x => { .ConfigureServices(x => {
@ -612,7 +612,7 @@ namespace Ocelot.IntegrationTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(x => .ConfigureServices(x =>
@ -652,7 +652,7 @@ namespace Ocelot.IntegrationTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(x => { .ConfigureServices(x => {
@ -675,7 +675,7 @@ namespace Ocelot.IntegrationTests
private void GivenThereIsAConfiguration(FileConfiguration fileConfiguration) private void GivenThereIsAConfiguration(FileConfiguration fileConfiguration)
{ {
var configurationPath = $"{Directory.GetCurrentDirectory()}/configuration.json"; var configurationPath = $"{Directory.GetCurrentDirectory()}/ocelot.json";
var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration); var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
@ -688,7 +688,7 @@ namespace Ocelot.IntegrationTests
var text = File.ReadAllText(configurationPath); var text = File.ReadAllText(configurationPath);
configurationPath = $"{AppContext.BaseDirectory}/configuration.json"; configurationPath = $"{AppContext.BaseDirectory}/ocelot.json";
if (File.Exists(configurationPath)) if (File.Exists(configurationPath))
{ {

View File

@ -14,7 +14,7 @@
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Update="peers.json;configuration.json;appsettings.json;idsrv3test.pfx"> <None Update="peers.json;appsettings.json;idsrv3test.pfx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>

View File

@ -301,7 +301,7 @@ namespace Ocelot.IntegrationTests
private void GivenThereIsAConfiguration(FileConfiguration fileConfiguration) private void GivenThereIsAConfiguration(FileConfiguration fileConfiguration)
{ {
var configurationPath = $"{Directory.GetCurrentDirectory()}/configuration.json"; var configurationPath = $"{Directory.GetCurrentDirectory()}/ocelot.json";
var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration); var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
@ -314,7 +314,7 @@ namespace Ocelot.IntegrationTests
var text = File.ReadAllText(configurationPath); var text = File.ReadAllText(configurationPath);
configurationPath = $"{AppContext.BaseDirectory}/configuration.json"; configurationPath = $"{AppContext.BaseDirectory}/ocelot.json";
if (File.Exists(configurationPath)) if (File.Exists(configurationPath))
{ {
@ -340,7 +340,7 @@ namespace Ocelot.IntegrationTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddJsonFile("peers.json", optional: true, reloadOnChange: true); config.AddJsonFile("peers.json", optional: true, reloadOnChange: true);
#pragma warning disable CS0618 #pragma warning disable CS0618
config.AddOcelotBaseUrl(url); config.AddOcelotBaseUrl(url);

View File

@ -108,7 +108,7 @@ namespace Ocelot.IntegrationTests
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json"); config.AddJsonFile("ocelot.json");
config.AddEnvironmentVariables(); config.AddEnvironmentVariables();
}) })
.ConfigureServices(x => .ConfigureServices(x =>
@ -138,7 +138,7 @@ namespace Ocelot.IntegrationTests
private void GivenThereIsAConfiguration(FileConfiguration fileConfiguration) private void GivenThereIsAConfiguration(FileConfiguration fileConfiguration)
{ {
var configurationPath = $"{Directory.GetCurrentDirectory()}/configuration.json"; var configurationPath = $"{Directory.GetCurrentDirectory()}/ocelot.json";
var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration); var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
@ -151,7 +151,7 @@ namespace Ocelot.IntegrationTests
var text = File.ReadAllText(configurationPath); var text = File.ReadAllText(configurationPath);
configurationPath = $"{AppContext.BaseDirectory}/configuration.json"; configurationPath = $"{AppContext.BaseDirectory}/ocelot.json";
if (File.Exists(configurationPath)) if (File.Exists(configurationPath))
{ {

View File

@ -16,7 +16,7 @@
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Update="configuration.json;appsettings.json;idsrv3test.pfx"> <None Update="ocelot.json;appsettings.json;idsrv3test.pfx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>

View File

@ -21,7 +21,7 @@ namespace Ocelot.ManualTest
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true) .AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
.AddJsonFile("configuration.json") .AddJsonFile("ocelot.json")
.AddEnvironmentVariables(); .AddEnvironmentVariables();
}) })
.ConfigureServices(s => { .ConfigureServices(s => {

View File

@ -1,6 +1,6 @@
using System.Collections.Generic; namespace Ocelot.UnitTests.Configuration
using Castle.Components.DictionaryAdapter; {
using Microsoft.Extensions.Options; using System.Collections.Generic;
using Moq; using Moq;
using Ocelot.Cache; using Ocelot.Cache;
using Ocelot.Configuration; using Ocelot.Configuration;
@ -13,10 +13,6 @@ using Ocelot.Responses;
using Shouldly; using Shouldly;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
namespace Ocelot.UnitTests.Configuration
{
using System;
using Ocelot.DependencyInjection; using Ocelot.DependencyInjection;
using Ocelot.Errors; using Ocelot.Errors;
using Ocelot.UnitTests.TestData; using Ocelot.UnitTests.TestData;
@ -24,23 +20,22 @@ namespace Ocelot.UnitTests.Configuration
public class FileConfigurationCreatorTests public class FileConfigurationCreatorTests
{ {
private readonly Mock<IOptions<FileConfiguration>> _fileConfig;
private readonly Mock<IConfigurationValidator> _validator; private readonly Mock<IConfigurationValidator> _validator;
private Response<IOcelotConfiguration> _config; private Response<IInternalConfiguration> _config;
private FileConfiguration _fileConfiguration; private FileConfiguration _fileConfiguration;
private readonly Mock<IOcelotLoggerFactory> _logger; private readonly Mock<IOcelotLoggerFactory> _logger;
private readonly FileOcelotConfigurationCreator _ocelotConfigurationCreator; private readonly FileInternalConfigurationCreator _internalConfigurationCreator;
private Mock<IClaimsToThingCreator> _claimsToThingCreator; private readonly Mock<IClaimsToThingCreator> _claimsToThingCreator;
private Mock<IAuthenticationOptionsCreator> _authOptionsCreator; private readonly Mock<IAuthenticationOptionsCreator> _authOptionsCreator;
private Mock<IUpstreamTemplatePatternCreator> _upstreamTemplatePatternCreator; private readonly Mock<IUpstreamTemplatePatternCreator> _upstreamTemplatePatternCreator;
private Mock<IRequestIdKeyCreator> _requestIdKeyCreator; private readonly Mock<IRequestIdKeyCreator> _requestIdKeyCreator;
private Mock<IServiceProviderConfigurationCreator> _serviceProviderConfigCreator; private readonly Mock<IServiceProviderConfigurationCreator> _serviceProviderConfigCreator;
private Mock<IQoSOptionsCreator> _qosOptionsCreator; private readonly Mock<IQoSOptionsCreator> _qosOptionsCreator;
private Mock<IReRouteOptionsCreator> _fileReRouteOptionsCreator; private readonly Mock<IReRouteOptionsCreator> _fileReRouteOptionsCreator;
private Mock<IRateLimitOptionsCreator> _rateLimitOptions; private readonly Mock<IRateLimitOptionsCreator> _rateLimitOptions;
private Mock<IRegionCreator> _regionCreator; private readonly Mock<IRegionCreator> _regionCreator;
private Mock<IHttpHandlerOptionsCreator> _httpHandlerOptionsCreator; private readonly Mock<IHttpHandlerOptionsCreator> _httpHandlerOptionsCreator;
private Mock<IAdministrationPath> _adminPath; private readonly Mock<IAdministrationPath> _adminPath;
private readonly Mock<IHeaderFindAndReplaceCreator> _headerFindAndReplaceCreator; private readonly Mock<IHeaderFindAndReplaceCreator> _headerFindAndReplaceCreator;
private readonly Mock<IDownstreamAddressesCreator> _downstreamAddressesCreator; private readonly Mock<IDownstreamAddressesCreator> _downstreamAddressesCreator;
@ -48,7 +43,6 @@ namespace Ocelot.UnitTests.Configuration
{ {
_logger = new Mock<IOcelotLoggerFactory>(); _logger = new Mock<IOcelotLoggerFactory>();
_validator = new Mock<IConfigurationValidator>(); _validator = new Mock<IConfigurationValidator>();
_fileConfig = new Mock<IOptions<FileConfiguration>>();
_claimsToThingCreator = new Mock<IClaimsToThingCreator>(); _claimsToThingCreator = new Mock<IClaimsToThingCreator>();
_authOptionsCreator = new Mock<IAuthenticationOptionsCreator>(); _authOptionsCreator = new Mock<IAuthenticationOptionsCreator>();
_upstreamTemplatePatternCreator = new Mock<IUpstreamTemplatePatternCreator>(); _upstreamTemplatePatternCreator = new Mock<IUpstreamTemplatePatternCreator>();
@ -63,8 +57,7 @@ namespace Ocelot.UnitTests.Configuration
_headerFindAndReplaceCreator = new Mock<IHeaderFindAndReplaceCreator>(); _headerFindAndReplaceCreator = new Mock<IHeaderFindAndReplaceCreator>();
_downstreamAddressesCreator = new Mock<IDownstreamAddressesCreator>(); _downstreamAddressesCreator = new Mock<IDownstreamAddressesCreator>();
_ocelotConfigurationCreator = new FileOcelotConfigurationCreator( _internalConfigurationCreator = new FileInternalConfigurationCreator(
_fileConfig.Object,
_validator.Object, _validator.Object,
_logger.Object, _logger.Object,
_claimsToThingCreator.Object, _claimsToThingCreator.Object,
@ -262,7 +255,7 @@ namespace Ocelot.UnitTests.Configuration
.And(x => x.GivenTheConfigIsValid()) .And(x => x.GivenTheConfigIsValid())
.And(x => x.GivenTheFollowingRegionIsReturned("region")) .And(x => x.GivenTheFollowingRegionIsReturned("region"))
.When(x => x.WhenICreateTheConfig()) .When(x => x.WhenICreateTheConfig())
.Then(x => x.ThenTheRegionCreatorIsCalledCorrectly("region")) .Then(x => x.ThenTheRegionCreatorIsCalledCorrectly())
.And(x => x.ThenTheHeaderFindAndReplaceCreatorIsCalledCorrectly()) .And(x => x.ThenTheHeaderFindAndReplaceCreatorIsCalledCorrectly())
.BDDfy(); .BDDfy();
} }
@ -800,14 +793,11 @@ namespace Ocelot.UnitTests.Configuration
private void GivenTheConfigIs(FileConfiguration fileConfiguration) private void GivenTheConfigIs(FileConfiguration fileConfiguration)
{ {
_fileConfiguration = fileConfiguration; _fileConfiguration = fileConfiguration;
_fileConfig
.Setup(x => x.Value)
.Returns(_fileConfiguration);
} }
private void WhenICreateTheConfig() private void WhenICreateTheConfig()
{ {
_config = _ocelotConfigurationCreator.Create(_fileConfiguration).Result; _config = _internalConfigurationCreator.Create(_fileConfiguration).Result;
} }
private void ThenTheReRoutesAre(List<ReRoute> expectedReRoutes) private void ThenTheReRoutesAre(List<ReRoute> expectedReRoutes)
@ -928,7 +918,7 @@ namespace Ocelot.UnitTests.Configuration
.Returns(region); .Returns(region);
} }
private void ThenTheRegionCreatorIsCalledCorrectly(string expected) private void ThenTheRegionCreatorIsCalledCorrectly()
{ {
_regionCreator _regionCreator
.Verify(x => x.Create(_fileConfiguration.ReRoutes[0]), Times.Once); .Verify(x => x.Create(_fileConfiguration.ReRoutes[0]), Times.Once);

View File

@ -1,60 +0,0 @@
using System;
using System.Collections.Generic;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.File;
using Ocelot.Responses;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
using Newtonsoft.Json;
using System.IO;
using Ocelot.Configuration.Provider;
using Ocelot.Configuration.Repository;
namespace Ocelot.UnitTests.Configuration
{
public class FileConfigurationProviderTests
{
private readonly IFileConfigurationProvider _provider;
private Mock<IFileConfigurationRepository> _repo;
private FileConfiguration _result;
private FileConfiguration _fileConfiguration;
public FileConfigurationProviderTests()
{
_repo = new Mock<IFileConfigurationRepository>();
_provider = new FileConfigurationProvider(_repo.Object);
}
[Fact]
public void should_return_file_configuration()
{
var config = new FileConfiguration();
this.Given(x => x.GivenTheConfigurationIs(config))
.When(x => x.WhenIGetTheReRoutes())
.Then(x => x.ThenTheRepoIsCalledCorrectly())
.BDDfy();
}
private void GivenTheConfigurationIs(FileConfiguration fileConfiguration)
{
_fileConfiguration = fileConfiguration;
_repo
.Setup(x => x.Get())
.ReturnsAsync(new OkResponse<FileConfiguration>(fileConfiguration));
}
private void WhenIGetTheReRoutes()
{
_result = _provider.Get().Result.Data;
}
private void ThenTheRepoIsCalledCorrectly()
{
_repo
.Verify(x => x.Get(), Times.Once);
}
}
}

View File

@ -18,12 +18,16 @@ namespace Ocelot.UnitTests.Configuration
private IFileConfigurationRepository _repo; private IFileConfigurationRepository _repo;
private FileConfiguration _result; private FileConfiguration _result;
private FileConfiguration _fileConfiguration; private FileConfiguration _fileConfiguration;
private string _environmentName = "DEV";
// This is a bit dirty and it is dev.dev so that the ConfigurationBuilderExtensionsTests
// cant pick it up if they run in parralel..sigh these are not really unit
// tests but whatever...
private string _environmentName = "DEV.DEV";
public FileConfigurationRepositoryTests() public FileConfigurationRepositoryTests()
{ {
_hostingEnvironment.Setup(he => he.EnvironmentName).Returns(_environmentName); _hostingEnvironment.Setup(he => he.EnvironmentName).Returns(_environmentName);
_repo = new FileConfigurationRepository(_hostingEnvironment.Object); _repo = new DiskFileConfigurationRepository(_hostingEnvironment.Object);
} }
[Fact] [Fact]
@ -75,7 +79,7 @@ namespace Ocelot.UnitTests.Configuration
{ {
_environmentName = null; _environmentName = null;
_hostingEnvironment.Setup(he => he.EnvironmentName).Returns(_environmentName); _hostingEnvironment.Setup(he => he.EnvironmentName).Returns(_environmentName);
_repo = new FileConfigurationRepository(_hostingEnvironment.Object); _repo = new DiskFileConfigurationRepository(_hostingEnvironment.Object);
} }
private void GivenIHaveAConfiguration(FileConfiguration fileConfiguration) private void GivenIHaveAConfiguration(FileConfiguration fileConfiguration)
@ -113,7 +117,7 @@ namespace Ocelot.UnitTests.Configuration
private void GivenTheConfigurationIs(FileConfiguration fileConfiguration) private void GivenTheConfigurationIs(FileConfiguration fileConfiguration)
{ {
var configurationPath = $"{AppContext.BaseDirectory}/configuration{(string.IsNullOrEmpty(_environmentName) ? string.Empty : ".")}{_environmentName}.json"; var configurationPath = $"{AppContext.BaseDirectory}/ocelot{(string.IsNullOrEmpty(_environmentName) ? string.Empty : ".")}{_environmentName}.json";
var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration); var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);

View File

@ -18,19 +18,19 @@ namespace Ocelot.UnitTests.Configuration
public class FileConfigurationSetterTests public class FileConfigurationSetterTests
{ {
private FileConfiguration _fileConfiguration; private FileConfiguration _fileConfiguration;
private FileConfigurationSetter _configSetter; private FileAndInternalConfigurationSetter _configSetter;
private Mock<IOcelotConfigurationRepository> _configRepo; private Mock<IInternalConfigurationRepository> _configRepo;
private Mock<IOcelotConfigurationCreator> _configCreator; private Mock<IInternalConfigurationCreator> _configCreator;
private Response<IOcelotConfiguration> _configuration; private Response<IInternalConfiguration> _configuration;
private object _result; private object _result;
private Mock<IFileConfigurationRepository> _repo; private Mock<IFileConfigurationRepository> _repo;
public FileConfigurationSetterTests() public FileConfigurationSetterTests()
{ {
_repo = new Mock<IFileConfigurationRepository>(); _repo = new Mock<IFileConfigurationRepository>();
_configRepo = new Mock<IOcelotConfigurationRepository>(); _configRepo = new Mock<IInternalConfigurationRepository>();
_configCreator = new Mock<IOcelotConfigurationCreator>(); _configCreator = new Mock<IInternalConfigurationCreator>();
_configSetter = new FileConfigurationSetter(_configRepo.Object, _configCreator.Object, _repo.Object); _configSetter = new FileAndInternalConfigurationSetter(_configRepo.Object, _configCreator.Object, _repo.Object);
} }
[Fact] [Fact]
@ -38,11 +38,11 @@ namespace Ocelot.UnitTests.Configuration
{ {
var fileConfig = new FileConfiguration(); var fileConfig = new FileConfiguration();
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build(); var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
var config = new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig, "asdf"); var config = new InternalConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig, "asdf");
this.Given(x => GivenTheFollowingConfiguration(fileConfig)) this.Given(x => GivenTheFollowingConfiguration(fileConfig))
.And(x => GivenTheRepoReturns(new OkResponse())) .And(x => GivenTheRepoReturns(new OkResponse()))
.And(x => GivenTheCreatorReturns(new OkResponse<IOcelotConfiguration>(config))) .And(x => GivenTheCreatorReturns(new OkResponse<IInternalConfiguration>(config)))
.When(x => WhenISetTheConfiguration()) .When(x => WhenISetTheConfiguration())
.Then(x => ThenTheConfigurationRepositoryIsCalledCorrectly()) .Then(x => ThenTheConfigurationRepositoryIsCalledCorrectly())
.BDDfy(); .BDDfy();
@ -67,7 +67,7 @@ namespace Ocelot.UnitTests.Configuration
this.Given(x => GivenTheFollowingConfiguration(fileConfig)) this.Given(x => GivenTheFollowingConfiguration(fileConfig))
.And(x => GivenTheRepoReturns(new OkResponse())) .And(x => GivenTheRepoReturns(new OkResponse()))
.And(x => GivenTheCreatorReturns(new ErrorResponse<IOcelotConfiguration>(It.IsAny<Error>()))) .And(x => GivenTheCreatorReturns(new ErrorResponse<IInternalConfiguration>(It.IsAny<Error>())))
.When(x => WhenISetTheConfiguration()) .When(x => WhenISetTheConfiguration())
.And(x => ThenAnErrorResponseIsReturned()) .And(x => ThenAnErrorResponseIsReturned())
.BDDfy(); .BDDfy();
@ -85,7 +85,7 @@ namespace Ocelot.UnitTests.Configuration
_result.ShouldBeOfType<ErrorResponse>(); _result.ShouldBeOfType<ErrorResponse>();
} }
private void GivenTheCreatorReturns(Response<IOcelotConfiguration> configuration) private void GivenTheCreatorReturns(Response<IInternalConfiguration> configuration)
{ {
_configuration = configuration; _configuration = configuration;
_configCreator _configCreator

View File

@ -1,76 +0,0 @@
using Ocelot.Configuration.Authentication;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
namespace Ocelot.UnitTests.Configuration
{
public class HashMatcherTests
{
private string _password;
private string _hash;
private string _salt;
private bool _result;
private HashMatcher _hashMatcher;
public HashMatcherTests()
{
_hashMatcher = new HashMatcher();
}
[Fact]
public void should_match_hash()
{
var hash = "kE/mxd1hO9h9Sl2VhGhwJUd9xZEv4NP6qXoN39nIqM4=";
var salt = "zzWITpnDximUNKYLiUam/w==";
var password = "secret";
this.Given(x => GivenThePassword(password))
.And(x => GivenTheHash(hash))
.And(x => GivenTheSalt(salt))
.When(x => WhenIMatch())
.Then(x => ThenTheResultIs(true))
.BDDfy();
}
[Fact]
public void should_not_match_hash()
{
var hash = "kE/mxd1hO9h9Sl2VhGhwJUd9xZEv4NP6qXoN39nIqM4=";
var salt = "zzWITpnDximUNKYLiUam/w==";
var password = "secret1";
this.Given(x => GivenThePassword(password))
.And(x => GivenTheHash(hash))
.And(x => GivenTheSalt(salt))
.When(x => WhenIMatch())
.Then(x => ThenTheResultIs(false))
.BDDfy();
}
private void GivenThePassword(string password)
{
_password = password;
}
private void GivenTheHash(string hash)
{
_hash = hash;
}
private void GivenTheSalt(string salt)
{
_salt = salt;
}
private void WhenIMatch()
{
_result = _hashMatcher.Match(_password, _salt, _hash);
}
private void ThenTheResultIs(bool expected)
{
_result.ShouldBe(expected);
}
}
}

View File

@ -149,6 +149,7 @@ namespace Ocelot.UnitTests.Configuration
.Then(x => ThenTheFollowingDownstreamIsReturned(downstream)) .Then(x => ThenTheFollowingDownstreamIsReturned(downstream))
.BDDfy(); .BDDfy();
} }
[Fact] [Fact]
public void should_add_trace_id_header() public void should_add_trace_id_header()
{ {

View File

@ -1,7 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Repository; using Ocelot.Configuration.Repository;
@ -14,14 +12,14 @@ namespace Ocelot.UnitTests.Configuration
{ {
public class InMemoryConfigurationRepositoryTests public class InMemoryConfigurationRepositoryTests
{ {
private readonly InMemoryOcelotConfigurationRepository _repo; private readonly InMemoryInternalConfigurationRepository _repo;
private IOcelotConfiguration _config; private IInternalConfiguration _config;
private Response _result; private Response _result;
private Response<IOcelotConfiguration> _getResult; private Response<IInternalConfiguration> _getResult;
public InMemoryConfigurationRepositoryTests() public InMemoryConfigurationRepositoryTests()
{ {
_repo = new InMemoryOcelotConfigurationRepository(); _repo = new InMemoryInternalConfigurationRepository();
} }
[Fact] [Fact]
@ -49,7 +47,7 @@ namespace Ocelot.UnitTests.Configuration
private void WhenIGetTheConfiguration() private void WhenIGetTheConfiguration()
{ {
_getResult = _repo.Get().Result; _getResult = _repo.Get();
} }
private void GivenThereIsASavedConfiguration() private void GivenThereIsASavedConfiguration()
@ -58,14 +56,14 @@ namespace Ocelot.UnitTests.Configuration
WhenIAddOrReplaceTheConfig(); WhenIAddOrReplaceTheConfig();
} }
private void GivenTheConfigurationIs(IOcelotConfiguration config) private void GivenTheConfigurationIs(IInternalConfiguration config)
{ {
_config = config; _config = config;
} }
private void WhenIAddOrReplaceTheConfig() private void WhenIAddOrReplaceTheConfig()
{ {
_result = _repo.AddOrReplace(_config).Result; _result = _repo.AddOrReplace(_config);
} }
private void ThenNoErrorsAreReturned() private void ThenNoErrorsAreReturned()
@ -73,7 +71,7 @@ namespace Ocelot.UnitTests.Configuration
_result.IsError.ShouldBeFalse(); _result.IsError.ShouldBeFalse();
} }
class FakeConfig : IOcelotConfiguration class FakeConfig : IInternalConfiguration
{ {
private readonly string _downstreamTemplatePath; private readonly string _downstreamTemplatePath;

View File

@ -1,80 +0,0 @@
using System.Collections.Generic;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Creator;
using Ocelot.Configuration.Provider;
using Ocelot.Configuration.Repository;
using Ocelot.Errors;
using Ocelot.Responses;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
namespace Ocelot.UnitTests.Configuration
{
public class OcelotConfigurationProviderTests
{
private readonly IOcelotConfigurationProvider _ocelotConfigurationProvider;
private readonly Mock<IOcelotConfigurationRepository> _configurationRepository;
private Response<IOcelotConfiguration> _result;
public OcelotConfigurationProviderTests()
{
_configurationRepository = new Mock<IOcelotConfigurationRepository>();
_ocelotConfigurationProvider = new OcelotConfigurationProvider(_configurationRepository.Object);
}
[Fact]
public void should_get_config()
{
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
this.Given(x => x.GivenTheRepoReturns(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig, ""))))
.When(x => x.WhenIGetTheConfig())
.Then(x => x.TheFollowingIsReturned(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig, ""))))
.BDDfy();
}
[Fact]
public void should_return_error()
{
this.Given(x => x.GivenTheRepoReturns(new ErrorResponse<IOcelotConfiguration>(new List<Error>
{
new AnyError()
})))
.When(x => x.WhenIGetTheConfig())
.Then(x => x.TheFollowingIsReturned(
new ErrorResponse<IOcelotConfiguration>(new List<Error>
{
new AnyError()
})))
.BDDfy();
}
private void GivenTheRepoReturns(Response<IOcelotConfiguration> config)
{
_configurationRepository
.Setup(x => x.Get())
.ReturnsAsync(config);
}
private void WhenIGetTheConfig()
{
_result = _ocelotConfigurationProvider.Get().Result;
}
private void TheFollowingIsReturned(Response<IOcelotConfiguration> expected)
{
_result.IsError.ShouldBe(expected.IsError);
}
class AnyError : Error
{
public AnyError()
: base("blamo", OcelotErrorCode.UnknownError)
{
}
}
}
}

View File

@ -8,32 +8,30 @@ using Ocelot.Responses;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
using Shouldly; using Shouldly;
using Ocelot.Configuration.Provider;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.Raft; using Ocelot.Raft;
using Rafty.Concensus; using Rafty.Concensus;
using Newtonsoft.Json;
using Rafty.FiniteStateMachine;
using Ocelot.Configuration; using Ocelot.Configuration;
namespace Ocelot.UnitTests.Controllers namespace Ocelot.UnitTests.Controllers
{ {
using Ocelot.Configuration.Repository;
public class FileConfigurationControllerTests public class FileConfigurationControllerTests
{ {
private FileConfigurationController _controller; private readonly FileConfigurationController _controller;
private Mock<IFileConfigurationProvider> _configGetter; private readonly Mock<IFileConfigurationRepository> _repo;
private Mock<IFileConfigurationSetter> _configSetter; private readonly Mock<IFileConfigurationSetter> _setter;
private IActionResult _result; private IActionResult _result;
private FileConfiguration _fileConfiguration; private FileConfiguration _fileConfiguration;
private Mock<IServiceProvider> _provider; private readonly Mock<IServiceProvider> _provider;
private Mock<INode> _node; private Mock<INode> _node;
public FileConfigurationControllerTests() public FileConfigurationControllerTests()
{ {
_provider = new Mock<IServiceProvider>(); _provider = new Mock<IServiceProvider>();
_configGetter = new Mock<IFileConfigurationProvider>(); _repo = new Mock<IFileConfigurationRepository>();
_configSetter = new Mock<IFileConfigurationSetter>(); _setter = new Mock<IFileConfigurationSetter>();
_controller = new FileConfigurationController(_configGetter.Object, _configSetter.Object, _provider.Object); _controller = new FileConfigurationController(_repo.Object, _setter.Object, _provider.Object);
} }
[Fact] [Fact]
@ -140,14 +138,14 @@ namespace Ocelot.UnitTests.Controllers
private void GivenTheConfigSetterReturns(Response response) private void GivenTheConfigSetterReturns(Response response)
{ {
_configSetter _setter
.Setup(x => x.Set(It.IsAny<FileConfiguration>())) .Setup(x => x.Set(It.IsAny<FileConfiguration>()))
.ReturnsAsync(response); .ReturnsAsync(response);
} }
private void ThenTheConfigrationSetterIsCalledCorrectly() private void ThenTheConfigrationSetterIsCalledCorrectly()
{ {
_configSetter _setter
.Verify(x => x.Set(_fileConfiguration), Times.Once); .Verify(x => x.Set(_fileConfiguration), Times.Once);
} }
@ -168,7 +166,7 @@ namespace Ocelot.UnitTests.Controllers
private void GivenTheGetConfigurationReturns(Ocelot.Responses.Response<FileConfiguration> fileConfiguration) private void GivenTheGetConfigurationReturns(Ocelot.Responses.Response<FileConfiguration> fileConfiguration)
{ {
_configGetter _repo
.Setup(x => x.Get()) .Setup(x => x.Get())
.ReturnsAsync(fileConfiguration); .ReturnsAsync(fileConfiguration);
} }
@ -180,7 +178,7 @@ namespace Ocelot.UnitTests.Controllers
private void TheTheGetFileConfigurationIsCalledCorrectly() private void TheTheGetFileConfigurationIsCalledCorrectly()
{ {
_configGetter _repo
.Verify(x => x.Get(), Times.Once); .Verify(x => x.Get(), Times.Once);
} }

View File

@ -1,25 +1,213 @@
using Microsoft.Extensions.Configuration; namespace Ocelot.UnitTests.DependencyInjection
{
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using Ocelot.Configuration.File;
using Microsoft.Extensions.Configuration;
using Ocelot.DependencyInjection; using Ocelot.DependencyInjection;
using Shouldly; using Shouldly;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
namespace Ocelot.UnitTests.DependencyInjection
{
public class ConfigurationBuilderExtensionsTests public class ConfigurationBuilderExtensionsTests
{ {
private IConfigurationRoot _configuration; private IConfigurationRoot _configuration;
private string _result; private string _result;
private IConfigurationRoot _configRoot;
private FileConfiguration _globalConfig;
private FileConfiguration _reRouteA;
private FileConfiguration _reRouteB;
private FileConfiguration _aggregate;
[Fact] [Fact]
public void should_add_base_url_to_config() public void should_add_base_url_to_config()
{ {
this.Given(x => GivenTheBaseUrl("test")) this.Given(_ => GivenTheBaseUrl("test"))
.When(x => WhenIGet("BaseUrl")) .When(_ => WhenIGet("BaseUrl"))
.Then(x => ThenTheResultIs("test")) .Then(_ => ThenTheResultIs("test"))
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_merge_files()
{
this.Given(_ => GivenMultipleConfigurationFiles())
.When(_ => WhenIAddOcelotConfiguration())
.Then(_ => ThenTheConfigsAreMerged())
.BDDfy();
}
private void GivenMultipleConfigurationFiles()
{
_globalConfig = new FileConfiguration
{
GlobalConfiguration = new FileGlobalConfiguration
{
BaseUrl = "BaseUrl",
RateLimitOptions = new FileRateLimitOptions
{
HttpStatusCode = 500,
ClientIdHeader = "ClientIdHeader",
DisableRateLimitHeaders = true,
QuotaExceededMessage = "QuotaExceededMessage",
RateLimitCounterPrefix = "RateLimitCounterPrefix"
},
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider
{
Host = "Host",
Port = 80,
Type = "Type"
},
RequestIdKey = "RequestIdKey"
}
};
_reRouteA = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamScheme = "DownstreamScheme",
DownstreamPathTemplate = "DownstreamPathTemplate",
Key = "Key",
UpstreamHost = "UpstreamHost",
UpstreamHttpMethod = new List<string>
{
"UpstreamHttpMethod"
},
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "Host",
Port = 80
}
}
}
}
};
_reRouteB = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamScheme = "DownstreamSchemeB",
DownstreamPathTemplate = "DownstreamPathTemplateB",
Key = "KeyB",
UpstreamHost = "UpstreamHostB",
UpstreamHttpMethod = new List<string>
{
"UpstreamHttpMethodB"
},
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "HostB",
Port = 80
}
}
},
new FileReRoute
{
DownstreamScheme = "DownstreamSchemeBB",
DownstreamPathTemplate = "DownstreamPathTemplateBB",
Key = "KeyBB",
UpstreamHost = "UpstreamHostBB",
UpstreamHttpMethod = new List<string>
{
"UpstreamHttpMethodBB"
},
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "HostBB",
Port = 80
}
}
}
}
};
_aggregate = new FileConfiguration
{
Aggregates = new List<FileAggregateReRoute>
{
new FileAggregateReRoute
{
ReRouteKeys = new List<string>
{
"KeyB",
"KeyBB"
},
UpstreamPathTemplate = "UpstreamPathTemplate",
},
new FileAggregateReRoute
{
ReRouteKeys = new List<string>
{
"KeyB",
"KeyBB"
},
UpstreamPathTemplate = "UpstreamPathTemplate",
}
}
};
File.WriteAllText("ocelot.global.json", JsonConvert.SerializeObject(_globalConfig));
File.WriteAllText("ocelot.reRoutesA.json", JsonConvert.SerializeObject(_reRouteA));
File.WriteAllText("ocelot.reRoutesB.json", JsonConvert.SerializeObject(_reRouteB));
File.WriteAllText("ocelot.aggregates.json", JsonConvert.SerializeObject(_aggregate));
}
private void WhenIAddOcelotConfiguration()
{
IConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddOcelot();
_configRoot = builder.Build();
}
private void ThenTheConfigsAreMerged()
{
var fc = (FileConfiguration)_configRoot.Get(typeof(FileConfiguration));
fc.GlobalConfiguration.BaseUrl.ShouldBe(_globalConfig.GlobalConfiguration.BaseUrl);
fc.GlobalConfiguration.RateLimitOptions.ClientIdHeader.ShouldBe(_globalConfig.GlobalConfiguration.RateLimitOptions.ClientIdHeader);
fc.GlobalConfiguration.RateLimitOptions.DisableRateLimitHeaders.ShouldBe(_globalConfig.GlobalConfiguration.RateLimitOptions.DisableRateLimitHeaders);
fc.GlobalConfiguration.RateLimitOptions.HttpStatusCode.ShouldBe(_globalConfig.GlobalConfiguration.RateLimitOptions.HttpStatusCode);
fc.GlobalConfiguration.RateLimitOptions.QuotaExceededMessage.ShouldBe(_globalConfig.GlobalConfiguration.RateLimitOptions.QuotaExceededMessage);
fc.GlobalConfiguration.RateLimitOptions.RateLimitCounterPrefix.ShouldBe(_globalConfig.GlobalConfiguration.RateLimitOptions.RateLimitCounterPrefix);
fc.GlobalConfiguration.RequestIdKey.ShouldBe(_globalConfig.GlobalConfiguration.RequestIdKey);
fc.GlobalConfiguration.ServiceDiscoveryProvider.Host.ShouldBe(_globalConfig.GlobalConfiguration.ServiceDiscoveryProvider.Host);
fc.GlobalConfiguration.ServiceDiscoveryProvider.Port.ShouldBe(_globalConfig.GlobalConfiguration.ServiceDiscoveryProvider.Port);
fc.GlobalConfiguration.ServiceDiscoveryProvider.Type.ShouldBe(_globalConfig.GlobalConfiguration.ServiceDiscoveryProvider.Type);
fc.ReRoutes.Count.ShouldBe(_reRouteA.ReRoutes.Count + _reRouteB.ReRoutes.Count);
fc.ReRoutes.ShouldContain(x => x.DownstreamPathTemplate == _reRouteA.ReRoutes[0].DownstreamPathTemplate);
fc.ReRoutes.ShouldContain(x => x.DownstreamPathTemplate == _reRouteB.ReRoutes[0].DownstreamPathTemplate);
fc.ReRoutes.ShouldContain(x => x.DownstreamPathTemplate == _reRouteB.ReRoutes[1].DownstreamPathTemplate);
fc.ReRoutes.ShouldContain(x => x.DownstreamScheme == _reRouteA.ReRoutes[0].DownstreamScheme);
fc.ReRoutes.ShouldContain(x => x.DownstreamScheme == _reRouteB.ReRoutes[0].DownstreamScheme);
fc.ReRoutes.ShouldContain(x => x.DownstreamScheme == _reRouteB.ReRoutes[1].DownstreamScheme);
fc.ReRoutes.ShouldContain(x => x.Key == _reRouteA.ReRoutes[0].Key);
fc.ReRoutes.ShouldContain(x => x.Key == _reRouteB.ReRoutes[0].Key);
fc.ReRoutes.ShouldContain(x => x.Key == _reRouteB.ReRoutes[1].Key);
fc.ReRoutes.ShouldContain(x => x.UpstreamHost == _reRouteA.ReRoutes[0].UpstreamHost);
fc.ReRoutes.ShouldContain(x => x.UpstreamHost == _reRouteB.ReRoutes[0].UpstreamHost);
fc.ReRoutes.ShouldContain(x => x.UpstreamHost == _reRouteB.ReRoutes[1].UpstreamHost);
fc.Aggregates.Count.ShouldBe(_aggregate.Aggregates.Count);
}
private void GivenTheBaseUrl(string baseUrl) private void GivenTheBaseUrl(string baseUrl)
{ {
#pragma warning disable CS0618 #pragma warning disable CS0618

View File

@ -325,8 +325,8 @@ namespace Ocelot.UnitTests.DependencyInjection
var outputCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<CachedResponse>)); var outputCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<CachedResponse>));
var outputCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<CachedResponse>)); var outputCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<CachedResponse>));
var instance = (ICacheManager<CachedResponse>)outputCacheManager.ImplementationInstance; var instance = (ICacheManager<CachedResponse>)outputCacheManager.ImplementationInstance;
var ocelotConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<IOcelotConfiguration>)); var ocelotConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<IInternalConfiguration>));
var ocelotConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<IOcelotConfiguration>)); var ocelotConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<IInternalConfiguration>));
var fileConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<FileConfiguration>)); var fileConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache<FileConfiguration>));
var fileConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<FileConfiguration>)); var fileConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager<FileConfiguration>));

View File

@ -1,7 +1,4 @@
using Ocelot.Middleware; namespace Ocelot.UnitTests.DownstreamRouteFinder
using Ocelot.Middleware.Multiplexer;
namespace Ocelot.UnitTests.DownstreamRouteFinder
{ {
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -9,7 +6,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
using Moq; using Moq;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Provider;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.DownstreamRouteFinder.Finder;
using Ocelot.DownstreamRouteFinder.Middleware; using Ocelot.DownstreamRouteFinder.Middleware;
@ -19,23 +15,26 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
using Shouldly; using Shouldly;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
using Ocelot.Configuration.Repository;
using Ocelot.Middleware;
using Ocelot.Middleware.Multiplexer;
public class DownstreamRouteFinderMiddlewareTests public class DownstreamRouteFinderMiddlewareTests
{ {
private readonly Mock<IDownstreamRouteFinder> _finder; private readonly Mock<IDownstreamRouteFinder> _finder;
private readonly Mock<IOcelotConfigurationProvider> _provider; private readonly Mock<IInternalConfigurationRepository> _repo;
private Response<DownstreamRoute> _downstreamRoute; private Response<DownstreamRoute> _downstreamRoute;
private IOcelotConfiguration _config; private IInternalConfiguration _config;
private Mock<IOcelotLoggerFactory> _loggerFactory; private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger; private Mock<IOcelotLogger> _logger;
private DownstreamRouteFinderMiddleware _middleware; private readonly DownstreamRouteFinderMiddleware _middleware;
private DownstreamContext _downstreamContext; private readonly DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next; private OcelotRequestDelegate _next;
private readonly Mock<IMultiplexer> _multiplexer; private readonly Mock<IMultiplexer> _multiplexer;
public DownstreamRouteFinderMiddlewareTests() public DownstreamRouteFinderMiddlewareTests()
{ {
_provider = new Mock<IOcelotConfigurationProvider>(); _repo = new Mock<IInternalConfigurationRepository>();
_finder = new Mock<IDownstreamRouteFinder>(); _finder = new Mock<IDownstreamRouteFinder>();
_downstreamContext = new DownstreamContext(new DefaultHttpContext()); _downstreamContext = new DownstreamContext(new DefaultHttpContext());
_loggerFactory = new Mock<IOcelotLoggerFactory>(); _loggerFactory = new Mock<IOcelotLoggerFactory>();
@ -43,13 +42,13 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
_loggerFactory.Setup(x => x.CreateLogger<DownstreamRouteFinderMiddleware>()).Returns(_logger.Object); _loggerFactory.Setup(x => x.CreateLogger<DownstreamRouteFinderMiddleware>()).Returns(_logger.Object);
_next = context => Task.CompletedTask; _next = context => Task.CompletedTask;
_multiplexer = new Mock<IMultiplexer>(); _multiplexer = new Mock<IMultiplexer>();
_middleware = new DownstreamRouteFinderMiddleware(_next, _loggerFactory.Object, _finder.Object, _provider.Object, _multiplexer.Object); _middleware = new DownstreamRouteFinderMiddleware(_next, _loggerFactory.Object, _finder.Object, _repo.Object, _multiplexer.Object);
} }
[Fact] [Fact]
public void should_call_scoped_data_repository_correctly() public void should_call_scoped_data_repository_correctly()
{ {
var config = new OcelotConfiguration(null, null, new ServiceProviderConfigurationBuilder().Build(), ""); var config = new InternalConfiguration(null, null, new ServiceProviderConfigurationBuilder().Build(), "");
var downstreamReRoute = new DownstreamReRouteBuilder() var downstreamReRoute = new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("any old string") .WithDownstreamPathTemplate("any old string")
@ -74,19 +73,19 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
_middleware.Invoke(_downstreamContext).GetAwaiter().GetType(); _middleware.Invoke(_downstreamContext).GetAwaiter().GetType();
} }
private void GivenTheFollowingConfig(IOcelotConfiguration config) private void GivenTheFollowingConfig(IInternalConfiguration config)
{ {
_config = config; _config = config;
_provider _repo
.Setup(x => x.Get()) .Setup(x => x.Get())
.ReturnsAsync(new OkResponse<IOcelotConfiguration>(_config)); .Returns(new OkResponse<IInternalConfiguration>(_config));
} }
private void GivenTheDownStreamRouteFinderReturns(DownstreamRoute downstreamRoute) private void GivenTheDownStreamRouteFinderReturns(DownstreamRoute downstreamRoute)
{ {
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute); _downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
_finder _finder
.Setup(x => x.FindDownstreamRoute(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IOcelotConfiguration>(), It.IsAny<string>())) .Setup(x => x.FindDownstreamRoute(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IInternalConfiguration>(), It.IsAny<string>()))
.Returns(_downstreamRoute); .Returns(_downstreamRoute);
} }

View File

@ -2,8 +2,6 @@
using Moq; using Moq;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Creator;
using Ocelot.Configuration.Provider;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.DownstreamRouteFinder.Finder;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
@ -23,7 +21,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
private string _upstreamUrlPath; private string _upstreamUrlPath;
private Response<DownstreamRoute> _result; private Response<DownstreamRoute> _result;
private List<ReRoute> _reRoutesConfig; private List<ReRoute> _reRoutesConfig;
private OcelotConfiguration _config; private InternalConfiguration _config;
private Response<UrlMatch> _match; private Response<UrlMatch> _match;
private string _upstreamHttpMethod; private string _upstreamHttpMethod;
private string _upstreamHost; private string _upstreamHost;
@ -711,7 +709,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
private void GivenTheConfigurationIs(List<ReRoute> reRoutesConfig, string adminPath, ServiceProviderConfiguration serviceProviderConfig) private void GivenTheConfigurationIs(List<ReRoute> reRoutesConfig, string adminPath, ServiceProviderConfiguration serviceProviderConfig)
{ {
_reRoutesConfig = reRoutesConfig; _reRoutesConfig = reRoutesConfig;
_config = new OcelotConfiguration(_reRoutesConfig, adminPath, serviceProviderConfig, ""); _config = new InternalConfiguration(_reRoutesConfig, adminPath, serviceProviderConfig, "");
} }
private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath) private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath)

View File

@ -9,17 +9,17 @@ namespace Ocelot.UnitTests.Errors
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Ocelot.Configuration.Provider;
using Moq; using Moq;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Errors; using Ocelot.Errors;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Middleware; using Ocelot.Middleware;
using Ocelot.Configuration.Repository;
public class ExceptionHandlerMiddlewareTests public class ExceptionHandlerMiddlewareTests
{ {
bool _shouldThrowAnException; bool _shouldThrowAnException;
private readonly Mock<IOcelotConfigurationProvider> _provider; private readonly Mock<IInternalConfigurationRepository> _configRepo;
private readonly Mock<IRequestScopedDataRepository> _repo; private readonly Mock<IRequestScopedDataRepository> _repo;
private Mock<IOcelotLoggerFactory> _loggerFactory; private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger; private Mock<IOcelotLogger> _logger;
@ -29,7 +29,7 @@ namespace Ocelot.UnitTests.Errors
public ExceptionHandlerMiddlewareTests() public ExceptionHandlerMiddlewareTests()
{ {
_provider = new Mock<IOcelotConfigurationProvider>(); _configRepo = new Mock<IInternalConfigurationRepository>();
_repo = new Mock<IRequestScopedDataRepository>(); _repo = new Mock<IRequestScopedDataRepository>();
_downstreamContext = new DownstreamContext(new DefaultHttpContext()); _downstreamContext = new DownstreamContext(new DefaultHttpContext());
_loggerFactory = new Mock<IOcelotLoggerFactory>(); _loggerFactory = new Mock<IOcelotLoggerFactory>();
@ -45,13 +45,13 @@ namespace Ocelot.UnitTests.Errors
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.OK; context.HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;
}; };
_middleware = new ExceptionHandlerMiddleware(_next, _loggerFactory.Object, _provider.Object, _repo.Object); _middleware = new ExceptionHandlerMiddleware(_next, _loggerFactory.Object, _configRepo.Object, _repo.Object);
} }
[Fact] [Fact]
public void NoDownstreamException() public void NoDownstreamException()
{ {
var config = new OcelotConfiguration(null, null, null, null); var config = new InternalConfiguration(null, null, null, null);
this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream()) this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
.And(_ => GivenTheConfigurationIs(config)) .And(_ => GivenTheConfigurationIs(config))
@ -64,7 +64,7 @@ namespace Ocelot.UnitTests.Errors
[Fact] [Fact]
public void DownstreamException() public void DownstreamException()
{ {
var config = new OcelotConfiguration(null, null, null, null); var config = new InternalConfiguration(null, null, null, null);
this.Given(_ => GivenAnExceptionWillBeThrownDownstream()) this.Given(_ => GivenAnExceptionWillBeThrownDownstream())
.And(_ => GivenTheConfigurationIs(config)) .And(_ => GivenTheConfigurationIs(config))
@ -76,7 +76,7 @@ namespace Ocelot.UnitTests.Errors
[Fact] [Fact]
public void ShouldSetRequestId() public void ShouldSetRequestId()
{ {
var config = new OcelotConfiguration(null, null, null, "requestidkey"); var config = new InternalConfiguration(null, null, null, "requestidkey");
this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream()) this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
.And(_ => GivenTheConfigurationIs(config)) .And(_ => GivenTheConfigurationIs(config))
@ -89,7 +89,7 @@ namespace Ocelot.UnitTests.Errors
[Fact] [Fact]
public void ShouldSetAspDotNetRequestId() public void ShouldSetAspDotNetRequestId()
{ {
var config = new OcelotConfiguration(null, null, null, null); var config = new InternalConfiguration(null, null, null, null);
this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream()) this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
.And(_ => GivenTheConfigurationIs(config)) .And(_ => GivenTheConfigurationIs(config))
@ -133,8 +133,8 @@ namespace Ocelot.UnitTests.Errors
private void GivenTheConfigThrows() private void GivenTheConfigThrows()
{ {
var ex = new Exception("outer", new Exception("inner")); var ex = new Exception("outer", new Exception("inner"));
_provider _configRepo
.Setup(x => x.Get()).ThrowsAsync(ex); .Setup(x => x.Get()).Throws(ex);
} }
private void ThenAnExceptionIsThrown() private void ThenAnExceptionIsThrown()
@ -144,9 +144,9 @@ namespace Ocelot.UnitTests.Errors
private void GivenTheConfigReturnsError() private void GivenTheConfigReturnsError()
{ {
var response = new Responses.ErrorResponse<IOcelotConfiguration>(new FakeError()); var response = new Responses.ErrorResponse<IInternalConfiguration>(new FakeError());
_provider _configRepo
.Setup(x => x.Get()).ReturnsAsync(response); .Setup(x => x.Get()).Returns(response);
} }
private void TheRequestIdIsSet(string key, string value) private void TheRequestIdIsSet(string key, string value)
@ -154,11 +154,11 @@ namespace Ocelot.UnitTests.Errors
_repo.Verify(x => x.Add(key, value), Times.Once); _repo.Verify(x => x.Add(key, value), Times.Once);
} }
private void GivenTheConfigurationIs(IOcelotConfiguration config) private void GivenTheConfigurationIs(IInternalConfiguration config)
{ {
var response = new Responses.OkResponse<IOcelotConfiguration>(config); var response = new Responses.OkResponse<IInternalConfiguration>(config);
_provider _configRepo
.Setup(x => x.Get()).ReturnsAsync(response); .Setup(x => x.Get()).Returns(response);
} }
private void GivenAnExceptionWillNotBeThrownDownstream() private void GivenAnExceptionWillNotBeThrownDownstream()

View File

@ -28,12 +28,6 @@
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" /> <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Update="idsrv3test.pfx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.2" /> <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.2" />

View File

@ -1 +0,0 @@
{"ReRoutes":[{"DownstreamPathTemplate":"/test/test/{test}","UpstreamPathTemplate":null,"UpstreamHttpMethod":null,"AuthenticationOptions":{"Provider":null,"ProviderRootUrl":null,"ApiName":null,"RequireHttps":false,"AllowedScopes":[],"ApiSecret":null},"AddHeadersToRequest":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{},"AddQueriesToRequest":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0},"ReRouteIsCaseSensitive":false,"ServiceName":null,"DownstreamScheme":"https","DownstreamHost":"localhost","DownstreamPort":80,"QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancer":null}],"GlobalConfiguration":{"RequestIdKey":null,"ServiceDiscoveryProvider":{"Provider":"consul","Host":"blah","Port":198},"AdministrationPath":"testy"}}

Binary file not shown.