mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:22:50 +08:00
Merge branch 'release-2.0.8'
This commit is contained in:
commit
5d2889aaee
@ -3,11 +3,11 @@ Logging
|
|||||||
|
|
||||||
Ocelot uses the standard logging interfaces ILoggerFactory / ILogger<T> at the moment.
|
Ocelot uses the standard logging interfaces ILoggerFactory / ILogger<T> at the moment.
|
||||||
This is encapsulated in IOcelotLogger / IOcelotLoggerFactory with an implementation
|
This is encapsulated in IOcelotLogger / IOcelotLoggerFactory with an implementation
|
||||||
for the standard asp.net core logging stuff at the moment.
|
for the standard asp.net core logging stuff at the moment. This is because Ocelot add's some extra info to the logs such as request id if it is configured.
|
||||||
|
|
||||||
There are a bunch of debugging logs in the ocelot middlewares however I think the
|
There is a global error handler that should catch any exceptions thrown and log them as errors.
|
||||||
system probably needs more logging in the code it calls into. Other than the debugging
|
|
||||||
there is a global error handler that should catch any errors thrown and log them as errors.
|
Finally if logging is set to trace level Ocelot will log starting, finishing and any middlewares that throw an exception which can be quite useful.
|
||||||
|
|
||||||
The reason for not just using bog standard framework logging is that I could not
|
The reason for not just using bog standard framework logging is that I could not
|
||||||
work out how to override the request id that get's logged when setting IncludeScopes
|
work out how to override the request id that get's logged when setting IncludeScopes
|
||||||
|
@ -4,25 +4,57 @@ Request Id / Correlation Id
|
|||||||
Ocelot supports a client sending a request id in the form of a header. If set Ocelot will
|
Ocelot supports a client sending a request id in the form of a header. If set Ocelot will
|
||||||
use the requestid for logging as soon as it becomes available in the middleware pipeline.
|
use the requestid for logging as soon as it becomes available in the middleware pipeline.
|
||||||
Ocelot will also forward the request id with the specified header to the downstream service.
|
Ocelot will also forward the request id with the specified header to the downstream service.
|
||||||
I'm not sure if have this spot on yet in terms of the pipeline order becasue there are a few logs
|
|
||||||
that don't get the users request id at the moment and ocelot just logs not set for request id
|
|
||||||
which sucks. You can still get the framework request id in the logs if you set
|
|
||||||
IncludeScopes true in your logging config. This can then be used to match up later logs that do
|
|
||||||
have an OcelotRequestId.
|
|
||||||
|
|
||||||
In order to use the requestid feature in your ReRoute configuration add this setting
|
You can still get the asp.net core request id in the logs if you set
|
||||||
|
IncludeScopes true in your logging config.
|
||||||
|
|
||||||
|
In order to use the reques tid feature you have two options.
|
||||||
|
|
||||||
|
*Global*
|
||||||
|
|
||||||
|
In your configuration.json set the following in the GlobalConfiguration section. This will be used for all requests into Ocelot.
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
"GlobalConfiguration": {
|
||||||
|
"RequestIdKey": "OcRequestId"
|
||||||
|
}
|
||||||
|
|
||||||
|
I reccomend using the GlobalConfiguration unless you really need it to be ReRoute specific.
|
||||||
|
|
||||||
|
*ReRoute*
|
||||||
|
|
||||||
|
If you want to override this for a specific ReRoute add the following to configuration.json for the specific ReRoute.
|
||||||
|
|
||||||
.. code-block:: json
|
.. code-block:: json
|
||||||
|
|
||||||
"RequestIdKey": "OcRequestId"
|
"RequestIdKey": "OcRequestId"
|
||||||
|
|
||||||
In this example OcRequestId is the request header that contains the clients request id.
|
Once Ocelot has identified the incoming requests matching ReRoute object it will set the request id based on the ReRoute configuration.
|
||||||
|
|
||||||
There is also a setting in the GlobalConfiguration section which will override whatever has been
|
This can lead to a small gotcha. If you set a GlobalConfiguration it is possible to get one request id until the ReRoute is identified and then another after that because the request id key can change. This is by design and is the best solution I can think of at the moment. In this case the OcelotLogger will show the request id and previous request id in the logs.
|
||||||
set at ReRoute level for the request id. The setting is as fllows.
|
|
||||||
|
|
||||||
.. code-block:: json
|
Below is an example of the logging when set at Debug level for a normal request..
|
||||||
|
|
||||||
"RequestIdKey": "OcRequestId"
|
.. code-block:: bash
|
||||||
|
|
||||||
It behaves in exactly the same way as the ReRoute level RequestIdKey settings.
|
dbug: Ocelot.Errors.Middleware.ExceptionHandlerMiddleware[0]
|
||||||
|
requestId: asdf, previousRequestId: no previous request id, message: ocelot pipeline started,
|
||||||
|
dbug: Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware[0]
|
||||||
|
requestId: asdf, previousRequestId: no previous request id, message: upstream url path is {upstreamUrlPath},
|
||||||
|
dbug: Ocelot.DownstreamRouteFinder.Middleware.DownstreamRouteFinderMiddleware[0]
|
||||||
|
requestId: asdf, previousRequestId: no previous request id, message: downstream template is {downstreamRoute.Data.ReRoute.DownstreamPath},
|
||||||
|
dbug: Ocelot.RateLimit.Middleware.ClientRateLimitMiddleware[0]
|
||||||
|
requestId: asdf, previousRequestId: no previous request id, message: EndpointRateLimiting is not enabled for Ocelot.Values.PathTemplate,
|
||||||
|
dbug: Ocelot.Authorisation.Middleware.AuthorisationMiddleware[0]
|
||||||
|
requestId: 1234, previousRequestId: asdf, message: /posts/{postId} route does not require user to be authorised,
|
||||||
|
dbug: Ocelot.DownstreamUrlCreator.Middleware.DownstreamUrlCreatorMiddleware[0]
|
||||||
|
requestId: 1234, previousRequestId: asdf, message: downstream url is {downstreamUrl.Data.Value},
|
||||||
|
dbug: Ocelot.Request.Middleware.HttpRequestBuilderMiddleware[0]
|
||||||
|
requestId: 1234, previousRequestId: asdf, message: setting upstream request,
|
||||||
|
dbug: Ocelot.Requester.Middleware.HttpRequesterMiddleware[0]
|
||||||
|
requestId: 1234, previousRequestId: asdf, message: setting http response message,
|
||||||
|
dbug: Ocelot.Responder.Middleware.ResponderMiddleware[0]
|
||||||
|
requestId: 1234, previousRequestId: asdf, message: no pipeline errors, setting and returning completed response,
|
||||||
|
dbug: Ocelot.Errors.Middleware.ExceptionHandlerMiddleware[0]
|
||||||
|
requestId: 1234, previousRequestId: asdf, message: ocelot pipeline finished,
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
Getting Started
|
Getting Started
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Ocelot is designed to work with ASP.NET core only and is currently
|
Ocelot is designed to work with .NET Core only and is currently
|
||||||
built to netcoreapp2.0 `this <https://docs.microsoft.com/en-us/dotnet/articles/standard/library>`_ documentation may prove helpful when working out if Ocelot would be suitable for you.
|
built to netcoreapp2.0 `this <https://docs.microsoft.com/en-us/dotnet/articles/standard/library>`_ documentation may prove helpful when working out if Ocelot would be suitable for you.
|
||||||
|
|
||||||
|
.NET Core 2.0
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
**Install NuGet package**
|
**Install NuGet package**
|
||||||
|
|
||||||
@ -30,6 +32,86 @@ The following is a very basic configuration.json. It won't do anything but shoul
|
|||||||
Then in your Program.cs you will want to have the following. This can be changed if you
|
Then in your Program.cs you will want to have the following. This can be changed if you
|
||||||
don't wan't to use the default url e.g. UseUrls(someUrls) and should work as long as you keep the WebHostBuilder registration.
|
don't wan't to use the default url e.g. UseUrls(someUrls) and should work as long as you keep the WebHostBuilder registration.
|
||||||
|
|
||||||
|
.. code-block:: csharp
|
||||||
|
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
IWebHostBuilder builder = new WebHostBuilder();
|
||||||
|
builder.ConfigureServices(s => {
|
||||||
|
s.AddSingleton(builder);
|
||||||
|
});
|
||||||
|
builder.UseKestrel()
|
||||||
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
|
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||||
|
{
|
||||||
|
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
|
||||||
|
var env = hostingContext.HostingEnvironment;
|
||||||
|
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||||
|
config.AddJsonFile("configuration.json");
|
||||||
|
config.AddEnvironmentVariables();
|
||||||
|
})
|
||||||
|
.ConfigureLogging((hostingContext, logging) =>
|
||||||
|
{
|
||||||
|
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
|
||||||
|
logging.AddConsole();
|
||||||
|
})
|
||||||
|
.UseIISIntegration()
|
||||||
|
.UseStartup<ManualTestStartup>();
|
||||||
|
var host = builder.Build();
|
||||||
|
host.Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Sadly we need to inject the IWebHostBuilder interface to get the applications scheme, url and port later. I cannot find a better way of doing this at the moment without setting this in a static or some kind of config.
|
||||||
|
|
||||||
|
**Startup**
|
||||||
|
|
||||||
|
An example startup using a json file for configuration can be seen below. This is the most basic startup and Ocelot has quite a few more options. Detailed in the rest of these docs! If you get a stuck a good place to look is at the ManualTests project in the source code.
|
||||||
|
|
||||||
|
.. code-block:: csharp
|
||||||
|
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddOcelot();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Configure(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseOcelot().Wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.NET Core 1.0
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
**Install NuGet package**
|
||||||
|
|
||||||
|
Install Ocelot and it's dependecies using nuget. You will need to create a netcoreapp1.0+ projct and bring the package into it. Then follow the Startup below and :doc:`../features/configuration` sections
|
||||||
|
to get up and running. Please note you will need to choose one of the Ocelot packages from the NuGet feed.
|
||||||
|
|
||||||
|
All versions can be found `here <https://www.nuget.org/packages/Ocelot/>`_.
|
||||||
|
|
||||||
|
**Configuration**
|
||||||
|
|
||||||
|
The following is a very basic configuration.json. It won't do anything but should get Ocelot starting.
|
||||||
|
|
||||||
|
.. code-block:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"ReRoutes": [],
|
||||||
|
"GlobalConfiguration": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
**Program**
|
||||||
|
|
||||||
|
Then in your Program.cs you will want to have the following. This can be changed if you
|
||||||
|
don't wan't to use the default url e.g. UseUrls(someUrls) and should work as long as you keep the WebHostBuilder registration.
|
||||||
|
|
||||||
.. code-block:: csharp
|
.. code-block:: csharp
|
||||||
|
|
||||||
public class Program
|
public class Program
|
||||||
@ -57,7 +139,6 @@ Sadly we need to inject the IWebHostBuilder interface to get the applications sc
|
|||||||
**Startup**
|
**Startup**
|
||||||
|
|
||||||
An example startup using a json file for configuration can be seen below.
|
An example startup using a json file for configuration can be seen below.
|
||||||
Currently this is the only way to get configuration into Ocelot.
|
|
||||||
|
|
||||||
.. code-block:: csharp
|
.. code-block:: csharp
|
||||||
|
|
||||||
@ -79,22 +160,13 @@ Currently this is the only way to get configuration into Ocelot.
|
|||||||
|
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddOcelot(Configuration)
|
services.AddOcelot(Configuration);
|
||||||
.AddCacheManager(x => {
|
|
||||||
x.WithMicrosoftLogging(log =>
|
|
||||||
{
|
|
||||||
log.AddConsole(LogLevel.Debug);
|
|
||||||
})
|
|
||||||
.WithDictionaryHandle();
|
|
||||||
});;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
public void Configure(IApplicationBuilder app)
|
||||||
{
|
{
|
||||||
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
|
||||||
|
|
||||||
app.UseOcelot().Wait();
|
app.UseOcelot().Wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
This is pretty much all you need to get going.......more to come!
|
This is pretty much all you need to get going.
|
@ -97,7 +97,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
|
|
||||||
var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration);
|
var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration);
|
||||||
|
|
||||||
var config = new OcelotConfiguration(reRoutes, _adminPath.Path, serviceProviderConfiguration);
|
var config = new OcelotConfiguration(reRoutes, _adminPath.Path, serviceProviderConfiguration, fileConfiguration.GlobalConfiguration.RequestIdKey);
|
||||||
|
|
||||||
return new OkResponse<IOcelotConfiguration>(config);
|
return new OkResponse<IOcelotConfiguration>(config);
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,11 @@ namespace Ocelot.Configuration.Creator
|
|||||||
{
|
{
|
||||||
public string Create(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
|
public string Create(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
|
||||||
{
|
{
|
||||||
var globalRequestIdConfiguration = !string.IsNullOrEmpty(globalConfiguration?.RequestIdKey);
|
var reRouteId = !string.IsNullOrEmpty(fileReRoute.RequestIdKey);
|
||||||
|
|
||||||
var requestIdKey = globalRequestIdConfiguration
|
var requestIdKey = reRouteId
|
||||||
? globalConfiguration.RequestIdKey
|
? fileReRoute.RequestIdKey
|
||||||
: fileReRoute.RequestIdKey;
|
: globalConfiguration.RequestIdKey;
|
||||||
|
|
||||||
return requestIdKey;
|
return requestIdKey;
|
||||||
}
|
}
|
||||||
|
@ -7,5 +7,6 @@ namespace Ocelot.Configuration
|
|||||||
List<ReRoute> ReRoutes { get; }
|
List<ReRoute> ReRoutes { get; }
|
||||||
string AdministrationPath {get;}
|
string AdministrationPath {get;}
|
||||||
ServiceProviderConfiguration ServiceProviderConfiguration {get;}
|
ServiceProviderConfiguration ServiceProviderConfiguration {get;}
|
||||||
|
string RequestId {get;}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,15 +4,17 @@ namespace Ocelot.Configuration
|
|||||||
{
|
{
|
||||||
public class OcelotConfiguration : IOcelotConfiguration
|
public class OcelotConfiguration : IOcelotConfiguration
|
||||||
{
|
{
|
||||||
public OcelotConfiguration(List<ReRoute> reRoutes, string administrationPath, ServiceProviderConfiguration serviceProviderConfiguration)
|
public OcelotConfiguration(List<ReRoute> reRoutes, string administrationPath, ServiceProviderConfiguration serviceProviderConfiguration, string requestId)
|
||||||
{
|
{
|
||||||
ReRoutes = reRoutes;
|
ReRoutes = reRoutes;
|
||||||
AdministrationPath = administrationPath;
|
AdministrationPath = administrationPath;
|
||||||
ServiceProviderConfiguration = serviceProviderConfiguration;
|
ServiceProviderConfiguration = serviceProviderConfiguration;
|
||||||
|
RequestId = requestId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ReRoute> ReRoutes { get; }
|
public List<ReRoute> ReRoutes { get; }
|
||||||
public string AdministrationPath {get;}
|
public string AdministrationPath {get;}
|
||||||
public ServiceProviderConfiguration ServiceProviderConfiguration {get;}
|
public ServiceProviderConfiguration ServiceProviderConfiguration {get;}
|
||||||
|
public string RequestId {get;}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -58,9 +58,9 @@ namespace Ocelot.DependencyInjection
|
|||||||
public class OcelotBuilder : IOcelotBuilder
|
public class OcelotBuilder : IOcelotBuilder
|
||||||
{
|
{
|
||||||
private IServiceCollection _services;
|
private IServiceCollection _services;
|
||||||
private IConfigurationRoot _configurationRoot;
|
private IConfiguration _configurationRoot;
|
||||||
|
|
||||||
public OcelotBuilder(IServiceCollection services, IConfigurationRoot configurationRoot)
|
public OcelotBuilder(IServiceCollection services, IConfiguration configurationRoot)
|
||||||
{
|
{
|
||||||
_configurationRoot = configurationRoot;
|
_configurationRoot = configurationRoot;
|
||||||
_services = services;
|
_services = services;
|
||||||
@ -280,9 +280,9 @@ namespace Ocelot.DependencyInjection
|
|||||||
public class OcelotAdministrationBuilder : IOcelotAdministrationBuilder
|
public class OcelotAdministrationBuilder : IOcelotAdministrationBuilder
|
||||||
{
|
{
|
||||||
private IServiceCollection _services;
|
private IServiceCollection _services;
|
||||||
private IConfigurationRoot _configurationRoot;
|
private IConfiguration _configurationRoot;
|
||||||
|
|
||||||
public OcelotAdministrationBuilder(IServiceCollection services, IConfigurationRoot configurationRoot)
|
public OcelotAdministrationBuilder(IServiceCollection services, IConfiguration configurationRoot)
|
||||||
{
|
{
|
||||||
_configurationRoot = configurationRoot;
|
_configurationRoot = configurationRoot;
|
||||||
_services = services;
|
_services = services;
|
||||||
|
@ -7,10 +7,16 @@ namespace Ocelot.DependencyInjection
|
|||||||
{
|
{
|
||||||
public static class ServiceCollectionExtensions
|
public static class ServiceCollectionExtensions
|
||||||
{
|
{
|
||||||
public static IOcelotBuilder AddOcelot(this IServiceCollection services,
|
public static IOcelotBuilder AddOcelot(this IServiceCollection services)
|
||||||
IConfigurationRoot configurationRoot)
|
|
||||||
{
|
{
|
||||||
return new OcelotBuilder(services, configurationRoot);
|
var service = services.First(x => x.ServiceType == typeof(IConfiguration));
|
||||||
|
var configuration = (IConfiguration)service.ImplementationInstance;
|
||||||
|
return new OcelotBuilder(services, configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IOcelotBuilder AddOcelot(this IServiceCollection services, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
return new OcelotBuilder(services, configuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,6 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
|
|||||||
{
|
{
|
||||||
var upstreamUrlPath = context.Request.Path.ToString();
|
var upstreamUrlPath = context.Request.Path.ToString();
|
||||||
|
|
||||||
//todo make this getting config its own middleware one day?
|
|
||||||
var configuration = await _configProvider.Get();
|
var configuration = await _configProvider.Get();
|
||||||
|
|
||||||
if(configuration.IsError)
|
if(configuration.IsError)
|
||||||
|
@ -1,24 +1,34 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
|
using Ocelot.Configuration.Provider;
|
||||||
|
using Ocelot.Infrastructure.Extensions;
|
||||||
using Ocelot.Infrastructure.RequestData;
|
using Ocelot.Infrastructure.RequestData;
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
|
using Ocelot.Middleware;
|
||||||
|
|
||||||
namespace Ocelot.Errors.Middleware
|
namespace Ocelot.Errors.Middleware
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Catches all unhandled exceptions thrown by middleware, logs and returns a 500
|
/// Catches all unhandled exceptions thrown by middleware, logs and returns a 500
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ExceptionHandlerMiddleware
|
public class ExceptionHandlerMiddleware : OcelotMiddleware
|
||||||
{
|
{
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly IOcelotLogger _logger;
|
private readonly IOcelotLogger _logger;
|
||||||
private readonly IRequestScopedDataRepository _requestScopedDataRepository;
|
private readonly IRequestScopedDataRepository _requestScopedDataRepository;
|
||||||
|
private readonly IOcelotConfigurationProvider _configProvider;
|
||||||
|
|
||||||
|
|
||||||
public ExceptionHandlerMiddleware(RequestDelegate next,
|
public ExceptionHandlerMiddleware(RequestDelegate next,
|
||||||
IOcelotLoggerFactory loggerFactory,
|
IOcelotLoggerFactory loggerFactory,
|
||||||
IRequestScopedDataRepository requestScopedDataRepository)
|
IRequestScopedDataRepository requestScopedDataRepository,
|
||||||
|
IOcelotConfigurationProvider configProvider)
|
||||||
|
:base(requestScopedDataRepository)
|
||||||
{
|
{
|
||||||
|
_configProvider = configProvider;
|
||||||
_next = next;
|
_next = next;
|
||||||
_requestScopedDataRepository = requestScopedDataRepository;
|
_requestScopedDataRepository = requestScopedDataRepository;
|
||||||
_logger = loggerFactory.CreateLogger<ExceptionHandlerMiddleware>();
|
_logger = loggerFactory.CreateLogger<ExceptionHandlerMiddleware>();
|
||||||
@ -28,26 +38,51 @@ namespace Ocelot.Errors.Middleware
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.LogDebug("ocelot pipeline started");
|
await TrySetGlobalRequestId(context);
|
||||||
|
|
||||||
_logger.LogDebug("calling next middleware");
|
_logger.LogDebug("ocelot pipeline started");
|
||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
_logger.LogDebug("succesfully called middleware");
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("error calling middleware");
|
_logger.LogDebug("error calling middleware");
|
||||||
|
|
||||||
var message = CreateMessage(context, e);
|
var message = CreateMessage(context, e);
|
||||||
|
|
||||||
_logger.LogError(message, e);
|
_logger.LogError(message, e);
|
||||||
|
|
||||||
SetInternalServerErrorOnResponse(context);
|
SetInternalServerErrorOnResponse(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogDebug("ocelot pipeline finished");
|
_logger.LogDebug("ocelot pipeline finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task TrySetGlobalRequestId(HttpContext context)
|
||||||
|
{
|
||||||
|
//try and get the global request id and set it for logs...
|
||||||
|
//shoudl this basically be immutable per request...i guess it should!
|
||||||
|
//first thing is get config
|
||||||
|
var configuration = await _configProvider.Get();
|
||||||
|
|
||||||
|
//if error throw to catch below..
|
||||||
|
if(configuration.IsError)
|
||||||
|
{
|
||||||
|
throw new Exception($"{MiddlewareName} setting pipeline errors. IOcelotConfigurationProvider returned {configuration.Errors.ToErrorString()}");
|
||||||
|
}
|
||||||
|
|
||||||
|
//else set the request id?
|
||||||
|
var key = configuration.Data.RequestId;
|
||||||
|
|
||||||
|
StringValues upstreamRequestIds;
|
||||||
|
if (!string.IsNullOrEmpty(key) && context.Request.Headers.TryGetValue(key, out upstreamRequestIds))
|
||||||
|
{
|
||||||
|
context.TraceIdentifier = upstreamRequestIds.First();
|
||||||
|
_requestScopedDataRepository.Add<string>("RequestId", context.TraceIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void SetInternalServerErrorOnResponse(HttpContext context)
|
private void SetInternalServerErrorOnResponse(HttpContext context)
|
||||||
{
|
{
|
||||||
context.Response.StatusCode = 500;
|
context.Response.StatusCode = 500;
|
||||||
|
@ -31,6 +31,22 @@ namespace Ocelot.Infrastructure.RequestData
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Response Update<T>(string key, T value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_httpContextAccessor.HttpContext.Items[key] = value;
|
||||||
|
return new OkResponse();
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
return new ErrorResponse(new List<Error>
|
||||||
|
{
|
||||||
|
new CannotAddDataError(string.Format($"Unable to update data for key: {key}, exception: {exception.Message}"))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Response<T> Get<T>(string key)
|
public Response<T> Get<T>(string key)
|
||||||
{
|
{
|
||||||
object obj;
|
object obj;
|
||||||
|
@ -5,6 +5,7 @@ namespace Ocelot.Infrastructure.RequestData
|
|||||||
public interface IRequestScopedDataRepository
|
public interface IRequestScopedDataRepository
|
||||||
{
|
{
|
||||||
Response Add<T>(string key, T value);
|
Response Add<T>(string key, T value);
|
||||||
|
Response Update<T>(string key, T value);
|
||||||
Response<T> Get<T>(string key);
|
Response<T> Get<T>(string key);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,33 +20,68 @@ namespace Ocelot.Logging
|
|||||||
|
|
||||||
public void LogTrace(string message, params object[] args)
|
public void LogTrace(string message, params object[] args)
|
||||||
{
|
{
|
||||||
_logger.LogTrace(GetMessageWithOcelotRequestId(message), args);
|
var requestId = GetOcelotRequestId();
|
||||||
|
var previousRequestId = GetOcelotPreviousRequestId();
|
||||||
|
_logger.LogTrace("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message},", requestId, previousRequestId, message, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogDebug(string message, params object[] args)
|
public void LogDebug(string message, params object[] args)
|
||||||
{
|
{
|
||||||
_logger.LogDebug(GetMessageWithOcelotRequestId(message), args);
|
var requestId = GetOcelotRequestId();
|
||||||
|
var previousRequestId = GetOcelotPreviousRequestId();
|
||||||
|
_logger.LogDebug("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message},", requestId, previousRequestId, message, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void LogInformation(string message, params object[] args)
|
||||||
|
{
|
||||||
|
var requestId = GetOcelotRequestId();
|
||||||
|
var previousRequestId = GetOcelotPreviousRequestId();
|
||||||
|
_logger.LogInformation("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message},", requestId, previousRequestId, message, args);
|
||||||
|
}
|
||||||
|
|
||||||
public void LogError(string message, Exception exception)
|
public void LogError(string message, Exception exception)
|
||||||
{
|
{
|
||||||
_logger.LogError(GetMessageWithOcelotRequestId(message), exception);
|
var requestId = GetOcelotRequestId();
|
||||||
|
var previousRequestId = GetOcelotPreviousRequestId();
|
||||||
|
_logger.LogError("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}, exception: {exception}", requestId, previousRequestId, message, exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogError(string message, params object[] args)
|
public void LogError(string message, params object[] args)
|
||||||
{
|
{
|
||||||
_logger.LogError(GetMessageWithOcelotRequestId(message), args);
|
var requestId = GetOcelotRequestId();
|
||||||
|
var previousRequestId = GetOcelotPreviousRequestId();
|
||||||
|
_logger.LogError("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}", requestId, previousRequestId, message, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetMessageWithOcelotRequestId(string message)
|
public void LogCritical(string message, Exception exception)
|
||||||
|
{
|
||||||
|
var requestId = GetOcelotRequestId();
|
||||||
|
var previousRequestId = GetOcelotPreviousRequestId();
|
||||||
|
_logger.LogError("requestId: {requestId}, previousRequestId: {previousRequestId}, message: {message}", requestId, previousRequestId, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetOcelotRequestId()
|
||||||
{
|
{
|
||||||
var requestId = _scopedDataRepository.Get<string>("RequestId");
|
var requestId = _scopedDataRepository.Get<string>("RequestId");
|
||||||
|
|
||||||
if (requestId == null || requestId.IsError)
|
if (requestId == null || requestId.IsError)
|
||||||
{
|
{
|
||||||
return $"{message} : OcelotRequestId - not set";
|
return $"no request id";
|
||||||
}
|
}
|
||||||
|
|
||||||
return $"{message} : OcelotRequestId - {requestId.Data}";
|
return requestId.Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetOcelotPreviousRequestId()
|
||||||
|
{
|
||||||
|
var requestId = _scopedDataRepository.Get<string>("PreviousRequestId");
|
||||||
|
|
||||||
|
if (requestId == null || requestId.IsError)
|
||||||
|
{
|
||||||
|
return $"no previous request id";
|
||||||
|
}
|
||||||
|
|
||||||
|
return requestId.Data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,8 +13,10 @@ namespace Ocelot.Logging
|
|||||||
{
|
{
|
||||||
void LogTrace(string message, params object[] args);
|
void LogTrace(string message, params object[] args);
|
||||||
void LogDebug(string message, params object[] args);
|
void LogDebug(string message, params object[] args);
|
||||||
|
void LogInformation(string message, params object[] args);
|
||||||
void LogError(string message, Exception exception);
|
void LogError(string message, Exception exception);
|
||||||
void LogError(string message, params object[] args);
|
void LogError(string message, params object[] args);
|
||||||
|
void LogCritical(string message, Exception exception);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the type the logger has been built for.
|
/// The name of the type the logger has been built for.
|
||||||
|
@ -77,6 +77,7 @@ namespace Ocelot.Middleware
|
|||||||
ConfigureDiagnosticListener(builder);
|
ConfigureDiagnosticListener(builder);
|
||||||
|
|
||||||
// This is registered to catch any global exceptions that are not handled
|
// This is registered to catch any global exceptions that are not handled
|
||||||
|
// It also sets the Request Id if anything is set globally
|
||||||
builder.UseExceptionHandlerMiddleware();
|
builder.UseExceptionHandlerMiddleware();
|
||||||
|
|
||||||
// Allow the user to respond with absolutely anything they want.
|
// Allow the user to respond with absolutely anything they want.
|
||||||
@ -94,7 +95,9 @@ namespace Ocelot.Middleware
|
|||||||
// We check whether the request is ratelimit, and if there is no continue processing
|
// We check whether the request is ratelimit, and if there is no continue processing
|
||||||
builder.UseRateLimiting();
|
builder.UseRateLimiting();
|
||||||
|
|
||||||
// Now we can look for the requestId
|
// This adds or updates the request id (initally we try and set this based on global config in the error handling middleware)
|
||||||
|
// If anything was set at global level and we have a different setting at re route level the global stuff will be overwritten
|
||||||
|
// This means you can get a scenario where you have a different request id from the first piece of middleware to the request id middleware.
|
||||||
builder.UseRequestIdMiddleware();
|
builder.UseRequestIdMiddleware();
|
||||||
|
|
||||||
// Allow pre authentication logic. The idea being people might want to run something custom before what is built in.
|
// Allow pre authentication logic. The idea being people might want to run something custom before what is built in.
|
||||||
@ -314,15 +317,10 @@ namespace Ocelot.Middleware
|
|||||||
private static void ConfigureDiagnosticListener(IApplicationBuilder builder)
|
private static void ConfigureDiagnosticListener(IApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
var env = (IHostingEnvironment)builder.ApplicationServices.GetService(typeof(IHostingEnvironment));
|
var env = (IHostingEnvironment)builder.ApplicationServices.GetService(typeof(IHostingEnvironment));
|
||||||
|
|
||||||
//https://github.com/TomPallister/Ocelot/pull/87 not sure why only for dev envs and marc disapeered so just merging and maybe change one day?
|
|
||||||
if (!env.IsProduction())
|
|
||||||
{
|
|
||||||
var listener = (OcelotDiagnosticListener)builder.ApplicationServices.GetService(typeof(OcelotDiagnosticListener));
|
var listener = (OcelotDiagnosticListener)builder.ApplicationServices.GetService(typeof(OcelotDiagnosticListener));
|
||||||
var diagnosticListener = (DiagnosticListener)builder.ApplicationServices.GetService(typeof(DiagnosticListener));
|
var diagnosticListener = (DiagnosticListener)builder.ApplicationServices.GetService(typeof(DiagnosticListener));
|
||||||
diagnosticListener.SubscribeWithAdapter(listener);
|
diagnosticListener.SubscribeWithAdapter(listener);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static void OnShutdown(IApplicationBuilder app)
|
private static void OnShutdown(IApplicationBuilder app)
|
||||||
{
|
{
|
||||||
|
@ -26,8 +26,6 @@ namespace Ocelot.Request.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("started calling request builder middleware");
|
|
||||||
|
|
||||||
var downstreamRequest = await _requestMapper.Map(context.Request);
|
var downstreamRequest = await _requestMapper.Map(context.Request);
|
||||||
if (downstreamRequest.IsError)
|
if (downstreamRequest.IsError)
|
||||||
{
|
{
|
||||||
@ -37,11 +35,7 @@ namespace Ocelot.Request.Middleware
|
|||||||
|
|
||||||
SetDownstreamRequest(downstreamRequest.Data);
|
SetDownstreamRequest(downstreamRequest.Data);
|
||||||
|
|
||||||
_logger.LogDebug("calling next middleware");
|
|
||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
_logger.LogDebug("succesfully called next middleware");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,8 +30,6 @@ namespace Ocelot.Request.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("started calling request builder middleware");
|
|
||||||
|
|
||||||
var qosProvider = _qosProviderHouse.Get(DownstreamRoute.ReRoute);
|
var qosProvider = _qosProviderHouse.Get(DownstreamRoute.ReRoute);
|
||||||
|
|
||||||
if (qosProvider.IsError)
|
if (qosProvider.IsError)
|
||||||
@ -62,11 +60,7 @@ namespace Ocelot.Request.Middleware
|
|||||||
|
|
||||||
SetUpstreamRequestForThisRequest(buildResult.Data);
|
SetUpstreamRequestForThisRequest(buildResult.Data);
|
||||||
|
|
||||||
_logger.LogDebug("calling next middleware");
|
|
||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
_logger.LogDebug("succesfully called next middleware");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,19 +11,19 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace Ocelot.RequestId.Middleware
|
namespace Ocelot.RequestId.Middleware
|
||||||
{
|
{
|
||||||
public class RequestIdMiddleware : OcelotMiddleware
|
public class ReRouteRequestIdMiddleware : OcelotMiddleware
|
||||||
{
|
{
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly IOcelotLogger _logger;
|
private readonly IOcelotLogger _logger;
|
||||||
private readonly IRequestScopedDataRepository _requestScopedDataRepository;
|
private readonly IRequestScopedDataRepository _requestScopedDataRepository;
|
||||||
|
|
||||||
public RequestIdMiddleware(RequestDelegate next,
|
public ReRouteRequestIdMiddleware(RequestDelegate next,
|
||||||
IOcelotLoggerFactory loggerFactory,
|
IOcelotLoggerFactory loggerFactory,
|
||||||
IRequestScopedDataRepository requestScopedDataRepository)
|
IRequestScopedDataRepository requestScopedDataRepository)
|
||||||
: base(requestScopedDataRepository)
|
: base(requestScopedDataRepository)
|
||||||
{
|
{
|
||||||
_next = next;
|
_next = next;
|
||||||
_logger = loggerFactory.CreateLogger<RequestIdMiddleware>();
|
_logger = loggerFactory.CreateLogger<ReRouteRequestIdMiddleware>();
|
||||||
_requestScopedDataRepository = requestScopedDataRepository;
|
_requestScopedDataRepository = requestScopedDataRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +41,22 @@ namespace Ocelot.RequestId.Middleware
|
|||||||
StringValues upstreamRequestIds;
|
StringValues upstreamRequestIds;
|
||||||
if (context.Request.Headers.TryGetValue(key, out upstreamRequestIds))
|
if (context.Request.Headers.TryGetValue(key, out upstreamRequestIds))
|
||||||
{
|
{
|
||||||
|
//set the traceidentifier
|
||||||
context.TraceIdentifier = upstreamRequestIds.First();
|
context.TraceIdentifier = upstreamRequestIds.First();
|
||||||
|
|
||||||
|
//check if we have previous id
|
||||||
|
var previousRequestId = _requestScopedDataRepository.Get<string>("RequestId");
|
||||||
|
if(!previousRequestId.IsError && !string.IsNullOrEmpty(previousRequestId.Data))
|
||||||
|
{
|
||||||
|
//we have a previous request id lets store it and update request id
|
||||||
|
_requestScopedDataRepository.Add<string>("PreviousRequestId", previousRequestId.Data);
|
||||||
|
_requestScopedDataRepository.Update<string>("RequestId", context.TraceIdentifier);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//else just add request id
|
||||||
|
_requestScopedDataRepository.Add<string>("RequestId", context.TraceIdentifier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set request ID on downstream request, if required
|
// set request ID on downstream request, if required
|
@ -6,7 +6,7 @@ namespace Ocelot.RequestId.Middleware
|
|||||||
{
|
{
|
||||||
public static IApplicationBuilder UseRequestIdMiddleware(this IApplicationBuilder builder)
|
public static IApplicationBuilder UseRequestIdMiddleware(this IApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
return builder.UseMiddleware<RequestIdMiddleware>();
|
return builder.UseMiddleware<ReRouteRequestIdMiddleware>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,8 +26,6 @@ namespace Ocelot.Requester.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("started calling requester middleware");
|
|
||||||
|
|
||||||
var response = await _requester.GetResponse(Request);
|
var response = await _requester.GetResponse(Request);
|
||||||
|
|
||||||
if (response.IsError)
|
if (response.IsError)
|
||||||
@ -41,8 +39,6 @@ namespace Ocelot.Requester.Middleware
|
|||||||
_logger.LogDebug("setting http response message");
|
_logger.LogDebug("setting http response message");
|
||||||
|
|
||||||
SetHttpResponseMessageThisRequest(response.Data);
|
SetHttpResponseMessageThisRequest(response.Data);
|
||||||
|
|
||||||
_logger.LogDebug("returning to calling middleware");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using CacheManager.Core;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
@ -8,7 +7,6 @@ using Microsoft.Extensions.Logging;
|
|||||||
using Ocelot.DependencyInjection;
|
using Ocelot.DependencyInjection;
|
||||||
using Ocelot.Middleware;
|
using Ocelot.Middleware;
|
||||||
using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder;
|
using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder;
|
||||||
using Ocelot.AcceptanceTests.Caching;
|
|
||||||
|
|
||||||
namespace Ocelot.AcceptanceTests
|
namespace Ocelot.AcceptanceTests
|
||||||
{
|
{
|
||||||
@ -26,7 +24,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
Configuration = builder.Build();
|
Configuration = builder.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IConfigurationRoot Configuration { get; }
|
public IConfiguration Configuration { get; }
|
||||||
|
|
||||||
public virtual void ConfigureServices(IServiceCollection services)
|
public virtual void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
@ -35,48 +33,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
|
|
||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
|
||||||
|
|
||||||
app.UseOcelot().Wait();
|
app.UseOcelot().Wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Startup_WithCustomCacheHandle : AcceptanceTestsStartup
|
|
||||||
{
|
|
||||||
public Startup_WithCustomCacheHandle(IHostingEnvironment env) : base(env) { }
|
|
||||||
|
|
||||||
public override void ConfigureServices(IServiceCollection services)
|
|
||||||
{
|
|
||||||
services.AddOcelot(Configuration)
|
|
||||||
.AddCacheManager((x) =>
|
|
||||||
{
|
|
||||||
x.WithMicrosoftLogging(log =>
|
|
||||||
{
|
|
||||||
log.AddConsole(LogLevel.Debug);
|
|
||||||
})
|
|
||||||
.WithJsonSerializer()
|
|
||||||
.WithHandle(typeof(InMemoryJsonHandle<>));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Startup_WithConsul_And_CustomCacheHandle : AcceptanceTestsStartup
|
|
||||||
{
|
|
||||||
public Startup_WithConsul_And_CustomCacheHandle(IHostingEnvironment env) : base(env) { }
|
|
||||||
|
|
||||||
public override void ConfigureServices(IServiceCollection services)
|
|
||||||
{
|
|
||||||
services.AddOcelot(Configuration)
|
|
||||||
.AddCacheManager((x) =>
|
|
||||||
{
|
|
||||||
x.WithMicrosoftLogging(log =>
|
|
||||||
{
|
|
||||||
log.AddConsole(LogLevel.Debug);
|
|
||||||
})
|
|
||||||
.WithJsonSerializer()
|
|
||||||
.WithHandle(typeof(InMemoryJsonHandle<>));
|
|
||||||
})
|
|
||||||
.AddStoreOcelotConfigurationInConsul();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -22,25 +22,18 @@ namespace Ocelot.AcceptanceTests
|
|||||||
.AddJsonFile("configuration.json")
|
.AddJsonFile("configuration.json")
|
||||||
.AddEnvironmentVariables();
|
.AddEnvironmentVariables();
|
||||||
|
|
||||||
Configuration = builder.Build();
|
Config = builder.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IConfigurationRoot Configuration { get; }
|
public static IConfiguration Config { get; private set; }
|
||||||
|
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
Action<ConfigurationBuilderCachePart> settings = (x) =>
|
services.AddOcelot(Config).AddStoreOcelotConfigurationInConsul();
|
||||||
{
|
|
||||||
x.WithDictionaryHandle();
|
|
||||||
};
|
|
||||||
|
|
||||||
services.AddOcelot(Configuration).AddStoreOcelotConfigurationInConsul();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
public void Configure(IApplicationBuilder app)
|
||||||
{
|
{
|
||||||
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
|
||||||
|
|
||||||
app.UseOcelot().Wait();
|
app.UseOcelot().Wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
using CacheManager.Core;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Ocelot.DependencyInjection;
|
||||||
|
using Ocelot.AcceptanceTests.Caching;
|
||||||
|
|
||||||
|
namespace Ocelot.AcceptanceTests
|
||||||
|
{
|
||||||
|
public class StartupWithConsulAndCustomCacheHandle : AcceptanceTestsStartup
|
||||||
|
{
|
||||||
|
public StartupWithConsulAndCustomCacheHandle(IHostingEnvironment env) : base(env) { }
|
||||||
|
|
||||||
|
public override void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddOcelot(Configuration)
|
||||||
|
.AddCacheManager((x) =>
|
||||||
|
{
|
||||||
|
x.WithMicrosoftLogging(log =>
|
||||||
|
{
|
||||||
|
log.AddConsole(LogLevel.Debug);
|
||||||
|
})
|
||||||
|
.WithJsonSerializer()
|
||||||
|
.WithHandle(typeof(InMemoryJsonHandle<>));
|
||||||
|
})
|
||||||
|
.AddStoreOcelotConfigurationInConsul();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
test/Ocelot.AcceptanceTests/StartupWithCustomCacheHandle.cs
Normal file
28
test/Ocelot.AcceptanceTests/StartupWithCustomCacheHandle.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using CacheManager.Core;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Ocelot.DependencyInjection;
|
||||||
|
using Ocelot.AcceptanceTests.Caching;
|
||||||
|
|
||||||
|
namespace Ocelot.AcceptanceTests
|
||||||
|
{
|
||||||
|
public class StartupWithCustomCacheHandle : AcceptanceTestsStartup
|
||||||
|
{
|
||||||
|
public StartupWithCustomCacheHandle(IHostingEnvironment env) : base(env) { }
|
||||||
|
|
||||||
|
public override void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddOcelot(Configuration)
|
||||||
|
.AddCacheManager((x) =>
|
||||||
|
{
|
||||||
|
x.WithMicrosoftLogging(log =>
|
||||||
|
{
|
||||||
|
log.AddConsole(LogLevel.Debug);
|
||||||
|
})
|
||||||
|
.WithJsonSerializer()
|
||||||
|
.WithHandle(typeof(InMemoryJsonHandle<>));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -118,7 +118,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
});
|
});
|
||||||
|
|
||||||
_ocelotServer = new TestServer(_webHostBuilder
|
_ocelotServer = new TestServer(_webHostBuilder
|
||||||
.UseStartup<Startup_WithCustomCacheHandle>());
|
.UseStartup<StartupWithCustomCacheHandle>());
|
||||||
|
|
||||||
_ocelotClient = _ocelotServer.CreateClient();
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
}
|
}
|
||||||
@ -148,7 +148,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
});
|
});
|
||||||
|
|
||||||
_ocelotServer = new TestServer(_webHostBuilder
|
_ocelotServer = new TestServer(_webHostBuilder
|
||||||
.UseStartup<Startup_WithConsul_And_CustomCacheHandle>());
|
.UseStartup<StartupWithConsulAndCustomCacheHandle>());
|
||||||
|
|
||||||
_ocelotClient = _ocelotServer.CreateClient();
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ namespace Ocelot.IntegrationTests
|
|||||||
Configuration = builder.Build();
|
Configuration = builder.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IConfigurationRoot Configuration { get; }
|
public IConfiguration Configuration { get; }
|
||||||
|
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
@ -45,8 +45,6 @@ namespace Ocelot.IntegrationTests
|
|||||||
|
|
||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
|
||||||
|
|
||||||
app.UseOcelot().Wait();
|
app.UseOcelot().Wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ namespace Ocelot.IntegrationTests
|
|||||||
Configuration = builder.Build();
|
Configuration = builder.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IConfigurationRoot Configuration { get; }
|
public IConfiguration Configuration { get; }
|
||||||
|
|
||||||
public virtual void ConfigureServices(IServiceCollection services)
|
public virtual void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
@ -46,9 +46,6 @@ namespace Ocelot.IntegrationTests
|
|||||||
|
|
||||||
public virtual void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
public virtual void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
|
|
||||||
//this is from Ocelot...so we need to move stuff below into it...
|
|
||||||
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
|
||||||
app.UseOcelot().Wait();
|
app.UseOcelot().Wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,29 +13,11 @@ namespace Ocelot.ManualTest
|
|||||||
{
|
{
|
||||||
public class ManualTestStartup
|
public class ManualTestStartup
|
||||||
{
|
{
|
||||||
public ManualTestStartup(IHostingEnvironment env)
|
|
||||||
{
|
|
||||||
var builder = new ConfigurationBuilder()
|
|
||||||
.SetBasePath(env.ContentRootPath)
|
|
||||||
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
|
||||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
|
|
||||||
.AddJsonFile("configuration.json")
|
|
||||||
.AddEnvironmentVariables();
|
|
||||||
|
|
||||||
Configuration = builder.Build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IConfigurationRoot Configuration { get; }
|
|
||||||
|
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
Action<ConfigurationBuilderCachePart> settings = (x) =>
|
Action<ConfigurationBuilderCachePart> settings = (x) =>
|
||||||
{
|
{
|
||||||
x.WithMicrosoftLogging(log =>
|
x.WithDictionaryHandle();
|
||||||
{
|
|
||||||
log.AddConsole(LogLevel.Debug);
|
|
||||||
})
|
|
||||||
.WithDictionaryHandle();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services.AddAuthentication()
|
services.AddAuthentication()
|
||||||
@ -45,14 +27,13 @@ namespace Ocelot.ManualTest
|
|||||||
x.Audience = "test";
|
x.Audience = "test";
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddOcelot(Configuration)
|
services.AddOcelot()
|
||||||
|
.AddCacheManager(settings)
|
||||||
.AddAdministration("/administration", "secret");
|
.AddAdministration("/administration", "secret");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
public void Configure(IApplicationBuilder app)
|
||||||
{
|
{
|
||||||
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
|
||||||
|
|
||||||
app.UseOcelot().Wait();
|
app.UseOcelot().Wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
namespace Ocelot.ManualTest
|
namespace Ocelot.ManualTest
|
||||||
{
|
{
|
||||||
@ -14,6 +16,20 @@ namespace Ocelot.ManualTest
|
|||||||
});
|
});
|
||||||
builder.UseKestrel()
|
builder.UseKestrel()
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
|
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||||
|
{
|
||||||
|
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
|
||||||
|
var env = hostingContext.HostingEnvironment;
|
||||||
|
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||||
|
config.AddJsonFile("configuration.json");
|
||||||
|
config.AddEnvironmentVariables();
|
||||||
|
})
|
||||||
|
.ConfigureLogging((hostingContext, logging) =>
|
||||||
|
{
|
||||||
|
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
|
||||||
|
logging.AddConsole();
|
||||||
|
})
|
||||||
.UseIISIntegration()
|
.UseIISIntegration()
|
||||||
.UseStartup<ManualTestStartup>();
|
.UseStartup<ManualTestStartup>();
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"IncludeScopes": true,
|
"IncludeScopes": false,
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Trace",
|
"Default": "Debug",
|
||||||
"System": "Information",
|
"System": "Error",
|
||||||
"Microsoft": "Information"
|
"Microsoft": "Error"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
"DownstreamPort": 80,
|
"DownstreamPort": 80,
|
||||||
"UpstreamPathTemplate": "/posts/{postId}",
|
"UpstreamPathTemplate": "/posts/{postId}",
|
||||||
"UpstreamHttpMethod": [ "Get" ],
|
"UpstreamHttpMethod": [ "Get" ],
|
||||||
|
"RequestIdKey": "ReRouteRequestId",
|
||||||
"QoSOptions": {
|
"QoSOptions": {
|
||||||
"ExceptionsAllowedBeforeBreaking": 3,
|
"ExceptionsAllowedBeforeBreaking": 3,
|
||||||
"DurationOfBreak": 10,
|
"DurationOfBreak": 10,
|
||||||
|
@ -38,7 +38,7 @@ 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);
|
var config = new OcelotConfiguration(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()))
|
||||||
|
@ -94,6 +94,8 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
public string AdministrationPath {get;}
|
public string AdministrationPath {get;}
|
||||||
|
|
||||||
public ServiceProviderConfiguration ServiceProviderConfiguration => throw new NotImplementedException();
|
public ServiceProviderConfiguration ServiceProviderConfiguration => throw new NotImplementedException();
|
||||||
|
|
||||||
|
public string RequestId {get;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,9 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
{
|
{
|
||||||
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
|
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenTheRepoReturns(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig))))
|
this.Given(x => x.GivenTheRepoReturns(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig, ""))))
|
||||||
.When(x => x.WhenIGetTheConfig())
|
.When(x => x.WhenIGetTheConfig())
|
||||||
.Then(x => x.TheFollowingIsReturned(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig))))
|
.Then(x => x.TheFollowingIsReturned(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig, ""))))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,14 +51,15 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_use_global_cofiguration_over_re_route_specific()
|
public void should_use_re_route_over_global_specific()
|
||||||
{
|
{
|
||||||
var reRoute = new FileReRoute
|
var reRoute = new FileReRoute
|
||||||
{
|
{
|
||||||
RequestIdKey = "cheese"
|
RequestIdKey = "cheese"
|
||||||
}; var globalConfig = new FileGlobalConfiguration
|
};
|
||||||
|
var globalConfig = new FileGlobalConfiguration
|
||||||
{
|
{
|
||||||
RequestIdKey = "cheese"
|
RequestIdKey = "test"
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenTheFollowingReRoute(reRoute))
|
this.Given(x => x.GivenTheFollowingReRoute(reRoute))
|
||||||
|
@ -24,7 +24,7 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
{
|
{
|
||||||
private IServiceCollection _services;
|
private IServiceCollection _services;
|
||||||
private IServiceProvider _serviceProvider;
|
private IServiceProvider _serviceProvider;
|
||||||
private IConfigurationRoot _configRoot;
|
private IConfiguration _configRoot;
|
||||||
private IOcelotBuilder _ocelotBuilder;
|
private IOcelotBuilder _ocelotBuilder;
|
||||||
private int _maxRetries;
|
private int _maxRetries;
|
||||||
|
|
||||||
@ -35,6 +35,7 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
_services = new ServiceCollection();
|
_services = new ServiceCollection();
|
||||||
_services.AddSingleton(builder);
|
_services.AddSingleton(builder);
|
||||||
_services.AddSingleton<IHostingEnvironment, HostingEnvironment>();
|
_services.AddSingleton<IHostingEnvironment, HostingEnvironment>();
|
||||||
|
_services.AddSingleton<IConfiguration>(_configRoot);
|
||||||
_maxRetries = 100;
|
_maxRetries = 100;
|
||||||
}
|
}
|
||||||
private Exception _ex;
|
private Exception _ex;
|
||||||
@ -95,6 +96,14 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_set_up_without_passing_in_config()
|
||||||
|
{
|
||||||
|
this.When(x => WhenISetUpOcelotServicesWithoutConfig())
|
||||||
|
.Then(x => ThenAnExceptionIsntThrown())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
private void ThenTheCorrectAdminPathIsRegitered()
|
private void ThenTheCorrectAdminPathIsRegitered()
|
||||||
{
|
{
|
||||||
_serviceProvider = _services.BuildServiceProvider();
|
_serviceProvider = _services.BuildServiceProvider();
|
||||||
@ -156,6 +165,19 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
_ex = e;
|
_ex = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WhenISetUpOcelotServicesWithoutConfig()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_ocelotBuilder = _services.AddOcelot();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_ex = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void WhenISetUpCacheManager()
|
private void WhenISetUpCacheManager()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
[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 OcelotConfiguration(null, null, new ServiceProviderConfigurationBuilder().Build(), "");
|
||||||
|
|
||||||
this.Given(x => x.GivenTheDownStreamRouteFinderReturns(
|
this.Given(x => x.GivenTheDownStreamRouteFinderReturns(
|
||||||
new DownstreamRoute(
|
new DownstreamRoute(
|
||||||
|
@ -422,7 +422,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 OcelotConfiguration(_reRoutesConfig, adminPath, serviceProviderConfig, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath)
|
private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath)
|
||||||
|
@ -11,39 +11,96 @@ 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 Ocelot.Configuration;
|
||||||
|
using Rafty.Concensus;
|
||||||
|
|
||||||
public class ExceptionHandlerMiddlewareTests : ServerHostedMiddlewareTest
|
public class ExceptionHandlerMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
{
|
||||||
bool _shouldThrowAnException = false;
|
bool _shouldThrowAnException = false;
|
||||||
|
private Mock<IOcelotConfigurationProvider> _provider;
|
||||||
|
|
||||||
public ExceptionHandlerMiddlewareTests()
|
public ExceptionHandlerMiddlewareTests()
|
||||||
{
|
{
|
||||||
|
_provider = new Mock<IOcelotConfigurationProvider>();
|
||||||
GivenTheTestServerIsConfigured();
|
GivenTheTestServerIsConfigured();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void NoDownstreamException()
|
public void NoDownstreamException()
|
||||||
{
|
{
|
||||||
|
var config = new OcelotConfiguration(null, null, null, null);
|
||||||
|
|
||||||
this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
|
this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
|
||||||
|
.And(_ => GivenTheConfigurationIs(config))
|
||||||
.When(_ => WhenICallTheMiddleware())
|
.When(_ => WhenICallTheMiddleware())
|
||||||
.Then(_ => ThenTheResponseIsOk())
|
.Then(_ => ThenTheResponseIsOk())
|
||||||
|
.And(_ => TheRequestIdIsNotSet())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TheRequestIdIsNotSet()
|
||||||
|
{
|
||||||
|
ScopedRepository.Verify(x => x.Add<string>(It.IsAny<string>(), It.IsAny<string>()), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void DownstreamException()
|
public void DownstreamException()
|
||||||
{
|
{
|
||||||
|
var config = new OcelotConfiguration(null, null, null, null);
|
||||||
|
|
||||||
this.Given(_ => GivenAnExceptionWillBeThrownDownstream())
|
this.Given(_ => GivenAnExceptionWillBeThrownDownstream())
|
||||||
|
.And(_ => GivenTheConfigurationIs(config))
|
||||||
.When(_ => WhenICallTheMiddleware())
|
.When(_ => WhenICallTheMiddleware())
|
||||||
.Then(_ => ThenTheResponseIsError())
|
.Then(_ => ThenTheResponseIsError())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ShouldSetRequestId()
|
||||||
|
{
|
||||||
|
var config = new OcelotConfiguration(null, null, null, "requestidkey");
|
||||||
|
|
||||||
|
this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
|
||||||
|
.And(_ => GivenTheConfigurationIs(config))
|
||||||
|
.When(_ => WhenICallTheMiddlewareWithTheRequestIdKey("requestidkey", "1234"))
|
||||||
|
.Then(_ => ThenTheResponseIsOk())
|
||||||
|
.And(_ => TheRequestIdIsSet("RequestId", "1234"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ShouldNotSetRequestId()
|
||||||
|
{
|
||||||
|
var config = new OcelotConfiguration(null, null, null, null);
|
||||||
|
|
||||||
|
this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
|
||||||
|
.And(_ => GivenTheConfigurationIs(config))
|
||||||
|
.When(_ => WhenICallTheMiddlewareWithTheRequestIdKey("requestidkey", "1234"))
|
||||||
|
.Then(_ => ThenTheResponseIsOk())
|
||||||
|
.And(_ => TheRequestIdIsNotSet())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TheRequestIdIsSet(string key, string value)
|
||||||
|
{
|
||||||
|
ScopedRepository.Verify(x => x.Add<string>(key, value), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheConfigurationIs(IOcelotConfiguration config)
|
||||||
|
{
|
||||||
|
var response = new Ocelot.Responses.OkResponse<IOcelotConfiguration>(config);
|
||||||
|
_provider
|
||||||
|
.Setup(x => x.Get()).ReturnsAsync(response);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
services.AddLogging();
|
services.AddLogging();
|
||||||
services.AddSingleton(ScopedRepository.Object);
|
services.AddSingleton(ScopedRepository.Object);
|
||||||
|
services.AddSingleton<IOcelotConfigurationProvider>(_provider.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
|
@ -25,7 +25,7 @@ namespace Ocelot.UnitTests.Infrastructure
|
|||||||
//TODO - Additional tests -> HttpContent null. This should never happen
|
//TODO - Additional tests -> HttpContent null. This should never happen
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Get_returns_correct_key_from_http_context()
|
public void get_returns_correct_key_from_http_context()
|
||||||
{
|
{
|
||||||
|
|
||||||
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
||||||
@ -35,7 +35,7 @@ namespace Ocelot.UnitTests.Infrastructure
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Get_returns_error_response_if_the_key_is_not_found() //Therefore does not return null
|
public void get_returns_error_response_if_the_key_is_not_found() //Therefore does not return null
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
||||||
.When(x => x.GetIsCalledWithKey<string>("keyDoesNotExist"))
|
.When(x => x.GetIsCalledWithKey<string>("keyDoesNotExist"))
|
||||||
@ -43,6 +43,21 @@ namespace Ocelot.UnitTests.Infrastructure
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_update()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
||||||
|
.And(x => x.UpdateIsCalledWith<string>("key", "new string"))
|
||||||
|
.When(x => x.GetIsCalledWithKey<string>("key"))
|
||||||
|
.Then(x => x.ThenTheResultIsAnOkResponse<string>("new string"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateIsCalledWith<T>(string key, string value)
|
||||||
|
{
|
||||||
|
_httpDataRepository.Update(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenAHttpContextContaining(string key, object o)
|
private void GivenAHttpContextContaining(string key, object o)
|
||||||
{
|
{
|
||||||
_httpContext.Items.Add(key, o);
|
_httpContext.Items.Add(key, o);
|
||||||
|
@ -19,14 +19,14 @@
|
|||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
public class RequestIdMiddlewareTests : ServerHostedMiddlewareTest
|
public class ReRouteRequestIdMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
{
|
||||||
private readonly HttpRequestMessage _downstreamRequest;
|
private readonly HttpRequestMessage _downstreamRequest;
|
||||||
private Response<DownstreamRoute> _downstreamRoute;
|
private Response<DownstreamRoute> _downstreamRoute;
|
||||||
private string _value;
|
private string _value;
|
||||||
private string _key;
|
private string _key;
|
||||||
|
|
||||||
public RequestIdMiddlewareTests()
|
public ReRouteRequestIdMiddlewareTests()
|
||||||
{
|
{
|
||||||
_downstreamRequest = new HttpRequestMessage();
|
_downstreamRequest = new HttpRequestMessage();
|
||||||
|
|
||||||
@ -50,6 +50,7 @@
|
|||||||
var requestId = Guid.NewGuid().ToString();
|
var requestId = Guid.NewGuid().ToString();
|
||||||
|
|
||||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||||
|
.And(x => GivenThereIsNoGlobalRequestId())
|
||||||
.And(x => x.GivenTheRequestIdIsAddedToTheRequest("LSRequestId", requestId))
|
.And(x => x.GivenTheRequestIdIsAddedToTheRequest("LSRequestId", requestId))
|
||||||
.When(x => x.WhenICallTheMiddleware())
|
.When(x => x.WhenICallTheMiddleware())
|
||||||
.Then(x => x.ThenTheTraceIdIs(requestId))
|
.Then(x => x.ThenTheTraceIdIs(requestId))
|
||||||
@ -67,11 +68,74 @@
|
|||||||
.Build());
|
.Build());
|
||||||
|
|
||||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||||
|
.And(x => GivenThereIsNoGlobalRequestId())
|
||||||
.When(x => x.WhenICallTheMiddleware())
|
.When(x => x.WhenICallTheMiddleware())
|
||||||
.Then(x => x.ThenTheTraceIdIsAnything())
|
.Then(x => x.ThenTheTraceIdIsAnything())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_add_request_id_scoped_repo_for_logging_later()
|
||||||
|
{
|
||||||
|
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||||
|
new ReRouteBuilder()
|
||||||
|
.WithDownstreamPathTemplate("any old string")
|
||||||
|
.WithRequestIdKey("LSRequestId")
|
||||||
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
|
.Build());
|
||||||
|
|
||||||
|
var requestId = Guid.NewGuid().ToString();
|
||||||
|
|
||||||
|
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||||
|
.And(x => GivenThereIsNoGlobalRequestId())
|
||||||
|
.And(x => x.GivenTheRequestIdIsAddedToTheRequest("LSRequestId", requestId))
|
||||||
|
.When(x => x.WhenICallTheMiddleware())
|
||||||
|
.Then(x => x.ThenTheTraceIdIs(requestId))
|
||||||
|
.And(x => ThenTheRequestIdIsSaved())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_update_request_id_scoped_repo_for_logging_later()
|
||||||
|
{
|
||||||
|
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||||
|
new ReRouteBuilder()
|
||||||
|
.WithDownstreamPathTemplate("any old string")
|
||||||
|
.WithRequestIdKey("LSRequestId")
|
||||||
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
|
.Build());
|
||||||
|
|
||||||
|
var requestId = Guid.NewGuid().ToString();
|
||||||
|
|
||||||
|
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||||
|
.And(x => GivenTheRequestIdWasSetGlobally())
|
||||||
|
.And(x => x.GivenTheRequestIdIsAddedToTheRequest("LSRequestId", requestId))
|
||||||
|
.When(x => x.WhenICallTheMiddleware())
|
||||||
|
.Then(x => x.ThenTheTraceIdIs(requestId))
|
||||||
|
.And(x => ThenTheRequestIdIsUpdated())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenThereIsNoGlobalRequestId()
|
||||||
|
{
|
||||||
|
ScopedRepository.Setup(x => x.Get<string>("RequestId")).Returns(new OkResponse<string>(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheRequestIdWasSetGlobally()
|
||||||
|
{
|
||||||
|
ScopedRepository.Setup(x => x.Get<string>("RequestId")).Returns(new OkResponse<string>("alreadyset"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheRequestIdIsSaved()
|
||||||
|
{
|
||||||
|
ScopedRepository.Verify(x => x.Add<string>("RequestId", _value), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheRequestIdIsUpdated()
|
||||||
|
{
|
||||||
|
ScopedRepository.Verify(x => x.Update<string>("RequestId", _value), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
@ -53,6 +53,12 @@
|
|||||||
ResponseMessage = Client.GetAsync(Url).Result;
|
ResponseMessage = Client.GetAsync(Url).Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void WhenICallTheMiddlewareWithTheRequestIdKey(string requestIdKey, string value)
|
||||||
|
{
|
||||||
|
Client.DefaultRequestHeaders.Add(requestIdKey, value);
|
||||||
|
ResponseMessage = Client.GetAsync(Url).Result;
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Client.Dispose();
|
Client.Dispose();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user