mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:22:50 +08:00
commit
2c4aaaadaa
1
.gitignore
vendored
1
.gitignore
vendored
@ -183,6 +183,7 @@ ClientBin/
|
|||||||
*.dbmdl
|
*.dbmdl
|
||||||
*.dbproj.schemaview
|
*.dbproj.schemaview
|
||||||
*.pfx
|
*.pfx
|
||||||
|
!idsrv3test.pfx
|
||||||
*.publishsettings
|
*.publishsettings
|
||||||
node_modules/
|
node_modules/
|
||||||
orleans.codegen.cs
|
orleans.codegen.cs
|
||||||
|
@ -16,7 +16,7 @@ var artifactsDir = Directory("artifacts");
|
|||||||
// unit testing
|
// unit testing
|
||||||
var artifactsForUnitTestsDir = artifactsDir + Directory("UnitTests");
|
var artifactsForUnitTestsDir = artifactsDir + Directory("UnitTests");
|
||||||
var unitTestAssemblies = @"./test/Ocelot.UnitTests/Ocelot.UnitTests.csproj";
|
var unitTestAssemblies = @"./test/Ocelot.UnitTests/Ocelot.UnitTests.csproj";
|
||||||
var minCodeCoverage = 75d;
|
var minCodeCoverage = 76.4d;
|
||||||
var coverallsRepoToken = "coveralls-repo-token-ocelot";
|
var coverallsRepoToken = "coveralls-repo-token-ocelot";
|
||||||
var coverallsRepo = "https://coveralls.io/github/TomPallister/Ocelot";
|
var coverallsRepo = "https://coveralls.io/github/TomPallister/Ocelot";
|
||||||
|
|
||||||
@ -229,11 +229,11 @@ Task("CreatePackages")
|
|||||||
EnsureDirectoryExists(packagesDir);
|
EnsureDirectoryExists(packagesDir);
|
||||||
CopyFiles("./src/**/Ocelot.*.nupkg", packagesDir);
|
CopyFiles("./src/**/Ocelot.*.nupkg", packagesDir);
|
||||||
|
|
||||||
GenerateReleaseNotes(releaseNotesFile);
|
//GenerateReleaseNotes(releaseNotesFile);
|
||||||
|
|
||||||
System.IO.File.WriteAllLines(artifactsFile, new[]{
|
System.IO.File.WriteAllLines(artifactsFile, new[]{
|
||||||
"nuget:Ocelot." + buildVersion + ".nupkg",
|
"nuget:Ocelot." + buildVersion + ".nupkg",
|
||||||
"releaseNotes:releasenotes.md"
|
//"releaseNotes:releasenotes.md"
|
||||||
});
|
});
|
||||||
|
|
||||||
if (AppVeyor.IsRunningOnAppVeyor)
|
if (AppVeyor.IsRunningOnAppVeyor)
|
||||||
|
@ -1,103 +0,0 @@
|
|||||||
{
|
|
||||||
"ReRoutes": [
|
|
||||||
{
|
|
||||||
# The downstream path we are forwarding the request to, ocelot will not add a trailing slash.
|
|
||||||
# Ocelot replaces any placeholders {etc} with matched values from the incoming request.
|
|
||||||
"DownstreamPathTemplate": "/identityserverexample/{someid}/something",
|
|
||||||
# The scheme you want Ocelot to use when making the downstream request
|
|
||||||
"DownstreamScheme": "https",
|
|
||||||
# The port you want Ocelot to use when making the downstream request, will default to
|
|
||||||
# scheme if nothing set
|
|
||||||
"DownstreamPort": 80,
|
|
||||||
# The host address of the downstream service, should not have a trailing slash or scheme
|
|
||||||
# if there is a trailing slash Ocelot will remove it.
|
|
||||||
"DownstreamHost" "localhost"
|
|
||||||
# The path template we are listening on for this re route, Ocelot will add a trailing
|
|
||||||
# slash to this property. Then when a request is made Ocelot makes sure a trailing
|
|
||||||
# slash is added, so everything matches
|
|
||||||
"UpstreamPathTemplate": "/identityserverexample",
|
|
||||||
# The method we are listening for on this re route
|
|
||||||
"UpstreamHttpMethod": "Get",
|
|
||||||
# Only support identity server at the moment
|
|
||||||
"AuthenticationOptions": {
|
|
||||||
"Provider": "IdentityServer",
|
|
||||||
"ProviderRootUrl": "http://localhost:52888",
|
|
||||||
"ApiName": "api",
|
|
||||||
"AllowedScopes": [
|
|
||||||
"openid",
|
|
||||||
"offline_access"
|
|
||||||
],
|
|
||||||
# Required if using reference tokens
|
|
||||||
"ApiSecret": "secret"
|
|
||||||
},
|
|
||||||
# WARNING - will overwrite any headers already in the request with these values.
|
|
||||||
# Ocelot will look in the user claims for the key in [] then return the value and save
|
|
||||||
# it as a header with the given key before the colon (:). The index selection on value
|
|
||||||
# means that Ocelot will use the delimiter specified after the next > to split the
|
|
||||||
# claim value and return the index specified.
|
|
||||||
"AddHeadersToRequest": {
|
|
||||||
"CustomerId": "Claims[CustomerId] > value",
|
|
||||||
"LocationId": "Claims[LocationId] > value",
|
|
||||||
"UserType": "Claims[sub] > value[0] > |",
|
|
||||||
"UserId": "Claims[sub] > value[1] > |"
|
|
||||||
},
|
|
||||||
# WARNING - will overwrite any claims already in the request with these values.
|
|
||||||
# Ocelot will look in the user claims for the key in [] then return the value and save
|
|
||||||
# it as a claim with the given key before the colon (:). The index selection on value
|
|
||||||
# means that Ocelot will use the delimiter specified after the next > to split the
|
|
||||||
# claim value and return the index specified.
|
|
||||||
"AddClaimsToRequest": {
|
|
||||||
"CustomerId": "Claims[CustomerId] > value",
|
|
||||||
"LocationId": "Claims[LocationId] > value",
|
|
||||||
"UserType": "Claims[sub] > value[0] > |",
|
|
||||||
"UserId": "Claims[sub] > value[1] > |"
|
|
||||||
},
|
|
||||||
# WARNING - will overwrite any query string entries already in the request with these values.
|
|
||||||
# Ocelot will look in the user claims for the key in [] then return the value and save
|
|
||||||
# it as a query string with the given key before the colon (:). The index selection on value
|
|
||||||
# means that Ocelot will use the delimiter specified after the next > to split the
|
|
||||||
# claim value and return the index specified.
|
|
||||||
"AddQueriesToRequest": {
|
|
||||||
"CustomerId": "Claims[CustomerId] > value",
|
|
||||||
"LocationId": "Claims[LocationId] > value",
|
|
||||||
"UserType": "Claims[sub] > value[0] > |",
|
|
||||||
"UserId": "Claims[sub] > value[1] > |"
|
|
||||||
},
|
|
||||||
# This specifies any claims that are required for the user to access this re route.
|
|
||||||
# In this example the user must have the claim type UserType and
|
|
||||||
# the value must be registered
|
|
||||||
"RouteClaimsRequirement": {
|
|
||||||
"UserType": "registered"
|
|
||||||
},
|
|
||||||
# This tells Ocelot to look for a header and use its value as a request/correlation id.
|
|
||||||
# If it is set here then the id will be forwarded to the downstream service. If it
|
|
||||||
# does not then it will not be forwarded
|
|
||||||
"RequestIdKey": "OcRequestId",
|
|
||||||
# If this is set the response from the downstream service will be cached using the key that called it.
|
|
||||||
# This gives the user a chance to influence the key by adding some random query string paramter for
|
|
||||||
# a user id or something that would get ignored by the downstream service. This is a hack and I
|
|
||||||
# intend to provide a mechanism the user can specify for the ttl caching. Also want to expand
|
|
||||||
# the caching a lot.
|
|
||||||
"FileCacheOptions": { "TtlSeconds": 15 },
|
|
||||||
# The value of this is used when matching the upstream template to an upstream url.
|
|
||||||
"ReRouteIsCaseSensitive": false,
|
|
||||||
# Tells Ocelot the name of the service it is looking when making requests to service discovery
|
|
||||||
# for hosts and ports
|
|
||||||
"ServiceName": "product"
|
|
||||||
# Tells Ocelot which load balancer to use when making downstream requests.
|
|
||||||
"LoadBalancer": "RoundRobin"
|
|
||||||
},
|
|
||||||
# This section is meant to be for global configuration settings
|
|
||||||
"GlobalConfiguration": {
|
|
||||||
# If this is set it will override any route specific request id keys, behaves the same
|
|
||||||
# otherwise
|
|
||||||
"RequestIdKey": "OcRequestId",
|
|
||||||
# If set Ocelot will try and use service discovery to locate downstream hosts and ports
|
|
||||||
"ServiceDiscoveryProvider":
|
|
||||||
{
|
|
||||||
"Provider":"Consul",
|
|
||||||
"Host":"localhost",
|
|
||||||
"Port":8500
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
{"ReRoutes":[{"DownstreamPathTemplate":"/","UpstreamPathTemplate":"/","UpstreamHttpMethod":"get","AuthenticationOptions":{"Provider":null,"ProviderRootUrl":null,"ScopeName":null,"RequireHttps":false,"AdditionalScopes":[],"ScopeSecret":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,"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0}},{"DownstreamPathTemplate":"/","UpstreamPathTemplate":"/test","UpstreamHttpMethod":"get","AuthenticationOptions":{"Provider":null,"ProviderRootUrl":null,"ScopeName":null,"RequireHttps":false,"AdditionalScopes":[],"ScopeSecret":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,"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0}}],"GlobalConfiguration":{"RequestIdKey":"RequestId","ServiceDiscoveryProvider":{"Provider":"test","Host":"127.0.0.1","Port":0},"AdministrationPath":"/administration","RateLimitOptions":{"ClientIdHeader":"ClientId","QuotaExceededMessage":null,"RateLimitCounterPrefix":"ocelot","DisableRateLimitHeaders":false,"HttpStatusCode":429}}}
|
|
@ -1,3 +0,0 @@
|
|||||||
Routes:
|
|
||||||
- Downstream: http://localhost:51879/
|
|
||||||
Upstream: /heee
|
|
@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using IdentityServer4.AccessTokenValidation;
|
using IdentityServer4.AccessTokenValidation;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
@ -5,6 +6,8 @@ using Ocelot.Responses;
|
|||||||
|
|
||||||
namespace Ocelot.Authentication.Handler.Creator
|
namespace Ocelot.Authentication.Handler.Creator
|
||||||
{
|
{
|
||||||
|
using Ocelot.Configuration;
|
||||||
|
|
||||||
using AuthenticationOptions = Configuration.AuthenticationOptions;
|
using AuthenticationOptions = Configuration.AuthenticationOptions;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -16,15 +19,31 @@ namespace Ocelot.Authentication.Handler.Creator
|
|||||||
{
|
{
|
||||||
var builder = app.New();
|
var builder = app.New();
|
||||||
|
|
||||||
|
if (authOptions.Provider.ToLower() == "jwt")
|
||||||
|
{
|
||||||
|
var authenticationConfig = authOptions.Config as JwtConfig;
|
||||||
|
|
||||||
|
builder.UseJwtBearerAuthentication(
|
||||||
|
new JwtBearerOptions()
|
||||||
|
{
|
||||||
|
Authority = authenticationConfig.Authority,
|
||||||
|
Audience = authenticationConfig.Audience
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var authenticationConfig = authOptions.Config as IdentityServerConfig;
|
||||||
|
|
||||||
builder.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
|
builder.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
|
||||||
{
|
{
|
||||||
Authority = authOptions.ProviderRootUrl,
|
Authority = authenticationConfig.ProviderRootUrl,
|
||||||
ApiName = authOptions.ApiName,
|
ApiName = authenticationConfig.ApiName,
|
||||||
RequireHttpsMetadata = authOptions.RequireHttps,
|
RequireHttpsMetadata = authenticationConfig.RequireHttps,
|
||||||
AllowedScopes = authOptions.AllowedScopes,
|
AllowedScopes = authOptions.AllowedScopes,
|
||||||
SupportedTokens = SupportedTokens.Both,
|
SupportedTokens = SupportedTokens.Both,
|
||||||
ApiSecret = authOptions.ApiSecret
|
ApiSecret = authenticationConfig.ApiSecret
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var authenticationNext = builder.Build();
|
var authenticationNext = builder.Build();
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
{
|
{
|
||||||
public enum SupportedAuthenticationProviders
|
public enum SupportedAuthenticationProviders
|
||||||
{
|
{
|
||||||
IdentityServer
|
IdentityServer,
|
||||||
|
Jwt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Ocelot.Configuration;
|
||||||
|
|
||||||
|
namespace Ocelot.Authentication.JsonConverters
|
||||||
|
{
|
||||||
|
public class AuthenticationConfigConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override bool CanWrite => false;
|
||||||
|
|
||||||
|
public override bool CanRead => true;
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Use default serialization.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
var jsonObject = JObject.Load(reader);
|
||||||
|
var setting = default(IAuthenticationConfig);
|
||||||
|
|
||||||
|
if (jsonObject["Provider"] != null)
|
||||||
|
{
|
||||||
|
switch (jsonObject["Provider"].Value<string>())
|
||||||
|
{
|
||||||
|
case "Jwt":
|
||||||
|
setting = new JwtConfig(
|
||||||
|
jsonObject["Authority"].Value<string>(),
|
||||||
|
jsonObject["Audience"].Value<string>());
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
setting = new IdentityServerConfig(
|
||||||
|
jsonObject["ProviderRootUrl"].Value<string>(),
|
||||||
|
jsonObject["ApiName"].Value<string>(),
|
||||||
|
jsonObject["RequireHttps"].Value<bool>(),
|
||||||
|
jsonObject["ApiSecret"].Value<string>());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setting = new IdentityServerConfig(string.Empty, string.Empty, false, string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
serializer.Populate(jsonObject.CreateReader(), setting);
|
||||||
|
return setting;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
return objectType == typeof(IAuthenticationConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -34,11 +34,9 @@ namespace Ocelot.Authentication.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
_logger.TraceMiddlewareEntry();
|
|
||||||
|
|
||||||
if (IsAuthenticatedRoute(DownstreamRoute.ReRoute))
|
if (IsAuthenticatedRoute(DownstreamRoute.ReRoute))
|
||||||
{
|
{
|
||||||
_logger.LogDebug($"{context.Request.Path} is an authenticated route. {MiddlwareName} checking if client is authenticated");
|
_logger.LogDebug($"{context.Request.Path} is an authenticated route. {MiddlewareName} checking if client is authenticated");
|
||||||
|
|
||||||
var authenticationHandler = _authHandlerFactory.Get(_app, DownstreamRoute.ReRoute.AuthenticationOptions);
|
var authenticationHandler = _authHandlerFactory.Get(_app, DownstreamRoute.ReRoute.AuthenticationOptions);
|
||||||
|
|
||||||
@ -46,7 +44,6 @@ namespace Ocelot.Authentication.Middleware
|
|||||||
{
|
{
|
||||||
_logger.LogError($"Error getting authentication handler for {context.Request.Path}. {authenticationHandler.Errors.ToErrorString()}");
|
_logger.LogError($"Error getting authentication handler for {context.Request.Path}. {authenticationHandler.Errors.ToErrorString()}");
|
||||||
SetPipelineError(authenticationHandler.Errors);
|
SetPipelineError(authenticationHandler.Errors);
|
||||||
_logger.TraceMiddlewareCompleted();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,11 +53,7 @@ namespace Ocelot.Authentication.Middleware
|
|||||||
if (context.User.Identity.IsAuthenticated)
|
if (context.User.Identity.IsAuthenticated)
|
||||||
{
|
{
|
||||||
_logger.LogDebug($"Client has been authenticated for {context.Request.Path}");
|
_logger.LogDebug($"Client has been authenticated for {context.Request.Path}");
|
||||||
|
|
||||||
_logger.TraceInvokeNext();
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
_logger.TraceInvokeNextCompleted();
|
|
||||||
_logger.TraceMiddlewareCompleted();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -72,8 +65,6 @@ namespace Ocelot.Authentication.Middleware
|
|||||||
|
|
||||||
_logger.LogError($"Client has NOT been authenticated for {context.Request.Path} and pipeline error set. {error.ToErrorString()}");
|
_logger.LogError($"Client has NOT been authenticated for {context.Request.Path} and pipeline error set. {error.ToErrorString()}");
|
||||||
SetPipelineError(error);
|
SetPipelineError(error);
|
||||||
|
|
||||||
_logger.TraceMiddlewareCompleted();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,10 +72,7 @@ namespace Ocelot.Authentication.Middleware
|
|||||||
{
|
{
|
||||||
_logger.LogTrace($"No authentication needed for {context.Request.Path}");
|
_logger.LogTrace($"No authentication needed for {context.Request.Path}");
|
||||||
|
|
||||||
_logger.TraceInvokeNext();
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
_logger.TraceInvokeNextCompleted();
|
|
||||||
_logger.TraceMiddlewareCompleted();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,8 +33,6 @@ namespace Ocelot.Authorisation.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("started authorisation");
|
|
||||||
|
|
||||||
if (IsAuthenticatedRoute(DownstreamRoute.ReRoute))
|
if (IsAuthenticatedRoute(DownstreamRoute.ReRoute))
|
||||||
{
|
{
|
||||||
_logger.LogDebug("route is authenticated scopes must be checked");
|
_logger.LogDebug("route is authenticated scopes must be checked");
|
||||||
@ -73,7 +71,7 @@ namespace Ocelot.Authorisation.Middleware
|
|||||||
|
|
||||||
if (authorised.IsError)
|
if (authorised.IsError)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("error authorising user");
|
_logger.LogDebug($"Error whilst authorising {context.User.Identity.Name} for {context.User.Identity.Name}. Setting pipeline error");
|
||||||
|
|
||||||
SetPipelineError(authorised.Errors);
|
SetPipelineError(authorised.Errors);
|
||||||
return;
|
return;
|
||||||
@ -81,30 +79,23 @@ namespace Ocelot.Authorisation.Middleware
|
|||||||
|
|
||||||
if (IsAuthorised(authorised))
|
if (IsAuthorised(authorised))
|
||||||
{
|
{
|
||||||
_logger.LogDebug("user is authorised calling next middleware");
|
_logger.LogDebug($"{context.User.Identity.Name} has succesfully been authorised for {DownstreamRoute.ReRoute.UpstreamPathTemplate.Value}. Calling next middleware");
|
||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
_logger.LogDebug("succesfully called next middleware");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogDebug("user is not authorised setting pipeline error");
|
_logger.LogDebug($"{context.User.Identity.Name} is not authorised to access {DownstreamRoute.ReRoute.UpstreamPathTemplate.Value}. Setting pipeline error");
|
||||||
|
|
||||||
SetPipelineError(new List<Error>
|
SetPipelineError(new List<Error>
|
||||||
{
|
{
|
||||||
new UnauthorisedError(
|
new UnauthorisedError($"{context.User.Identity.Name} is not authorised to access {DownstreamRoute.ReRoute.UpstreamPathTemplate.Value}")
|
||||||
$"{context.User.Identity.Name} unable to access {DownstreamRoute.ReRoute.UpstreamPathTemplate.Value}")
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogDebug("AuthorisationMiddleware.Invoke route is not authorised calling next middleware");
|
_logger.LogDebug($"{DownstreamRoute.ReRoute.DownstreamPathTemplate.Value} route does not require user to be authorised");
|
||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
_logger.LogDebug("succesfully called next middleware");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ocelot.Cache
|
namespace Ocelot.Cache
|
||||||
{
|
{
|
||||||
public interface IOcelotCache<T>
|
public interface IOcelotCache<T>
|
||||||
{
|
{
|
||||||
void Add(string key, T value, TimeSpan ttl);
|
void Add(string key, T value, TimeSpan ttl, string region);
|
||||||
void AddAndDelete(string key, T value, TimeSpan ttl);
|
void AddAndDelete(string key, T value, TimeSpan ttl, string region);
|
||||||
T Get(string key);
|
T Get(string key, string region);
|
||||||
|
void ClearRegion(string region);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
src/Ocelot/Cache/IRegionCreator.cs
Normal file
9
src/Ocelot/Cache/IRegionCreator.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using Ocelot.Configuration.File;
|
||||||
|
|
||||||
|
namespace Ocelot.Cache
|
||||||
|
{
|
||||||
|
public interface IRegionCreator
|
||||||
|
{
|
||||||
|
string Create(FileReRoute reRoute);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
@ -13,16 +14,19 @@ namespace Ocelot.Cache.Middleware
|
|||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly IOcelotLogger _logger;
|
private readonly IOcelotLogger _logger;
|
||||||
private readonly IOcelotCache<HttpResponseMessage> _outputCache;
|
private readonly IOcelotCache<HttpResponseMessage> _outputCache;
|
||||||
|
private readonly IRegionCreator _regionCreator;
|
||||||
|
|
||||||
public OutputCacheMiddleware(RequestDelegate next,
|
public OutputCacheMiddleware(RequestDelegate next,
|
||||||
IOcelotLoggerFactory loggerFactory,
|
IOcelotLoggerFactory loggerFactory,
|
||||||
IRequestScopedDataRepository scopedDataRepository,
|
IRequestScopedDataRepository scopedDataRepository,
|
||||||
IOcelotCache<HttpResponseMessage> outputCache)
|
IOcelotCache<HttpResponseMessage> outputCache,
|
||||||
|
IRegionCreator regionCreator)
|
||||||
:base(scopedDataRepository)
|
:base(scopedDataRepository)
|
||||||
{
|
{
|
||||||
_next = next;
|
_next = next;
|
||||||
_outputCache = outputCache;
|
_outputCache = outputCache;
|
||||||
_logger = loggerFactory.CreateLogger<OutputCacheMiddleware>();
|
_logger = loggerFactory.CreateLogger<OutputCacheMiddleware>();
|
||||||
|
_regionCreator = regionCreator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
@ -33,11 +37,11 @@ namespace Ocelot.Cache.Middleware
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var downstreamUrlKey = DownstreamRequest.RequestUri.OriginalString;
|
var downstreamUrlKey = $"{DownstreamRequest.Method.Method}-{DownstreamRequest.RequestUri.OriginalString}";
|
||||||
|
|
||||||
_logger.LogDebug("started checking cache for {downstreamUrlKey}", downstreamUrlKey);
|
_logger.LogDebug("started checking cache for {downstreamUrlKey}", downstreamUrlKey);
|
||||||
|
|
||||||
var cached = _outputCache.Get(downstreamUrlKey);
|
var cached = _outputCache.Get(downstreamUrlKey, DownstreamRoute.ReRoute.CacheOptions.Region);
|
||||||
|
|
||||||
if (cached != null)
|
if (cached != null)
|
||||||
{
|
{
|
||||||
@ -54,8 +58,6 @@ namespace Ocelot.Cache.Middleware
|
|||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
_logger.LogDebug("succesfully called next middleware");
|
|
||||||
|
|
||||||
if (PipelineError)
|
if (PipelineError)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("there was a pipeline error for {downstreamUrlKey}", downstreamUrlKey);
|
_logger.LogDebug("there was a pipeline error for {downstreamUrlKey}", downstreamUrlKey);
|
||||||
@ -65,7 +67,7 @@ namespace Ocelot.Cache.Middleware
|
|||||||
|
|
||||||
var response = HttpResponseMessage;
|
var response = HttpResponseMessage;
|
||||||
|
|
||||||
_outputCache.Add(downstreamUrlKey, response, TimeSpan.FromSeconds(DownstreamRoute.ReRoute.FileCacheOptions.TtlSeconds));
|
_outputCache.Add(downstreamUrlKey, response, TimeSpan.FromSeconds(DownstreamRoute.ReRoute.CacheOptions.TtlSeconds), DownstreamRoute.ReRoute.CacheOptions.Region);
|
||||||
|
|
||||||
_logger.LogDebug("finished response added to cache for {downstreamUrlKey}", downstreamUrlKey);
|
_logger.LogDebug("finished response added to cache for {downstreamUrlKey}", downstreamUrlKey);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using CacheManager.Core;
|
using CacheManager.Core;
|
||||||
|
|
||||||
namespace Ocelot.Cache
|
namespace Ocelot.Cache
|
||||||
@ -12,12 +14,12 @@ namespace Ocelot.Cache
|
|||||||
_cacheManager = cacheManager;
|
_cacheManager = cacheManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(string key, T value, TimeSpan ttl)
|
public void Add(string key, T value, TimeSpan ttl, string region)
|
||||||
{
|
{
|
||||||
_cacheManager.Add(new CacheItem<T>(key, value, ExpirationMode.Absolute, ttl));
|
_cacheManager.Add(new CacheItem<T>(key, region, value, ExpirationMode.Absolute, ttl));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddAndDelete(string key, T value, TimeSpan ttl)
|
public void AddAndDelete(string key, T value, TimeSpan ttl, string region)
|
||||||
{
|
{
|
||||||
var exists = _cacheManager.Get(key);
|
var exists = _cacheManager.Get(key);
|
||||||
|
|
||||||
@ -26,12 +28,17 @@ namespace Ocelot.Cache
|
|||||||
_cacheManager.Remove(key);
|
_cacheManager.Remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
_cacheManager.Add(new CacheItem<T>(key, value, ExpirationMode.Absolute, ttl));
|
Add(key, value, ttl, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T Get(string key)
|
public T Get(string key, string region)
|
||||||
{
|
{
|
||||||
return _cacheManager.Get<T>(key);
|
return _cacheManager.Get<T>(key, region);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearRegion(string region)
|
||||||
|
{
|
||||||
|
_cacheManager.ClearRegion(region);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
24
src/Ocelot/Cache/RegionCreator.cs
Normal file
24
src/Ocelot/Cache/RegionCreator.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Ocelot.Configuration;
|
||||||
|
using Ocelot.Configuration.File;
|
||||||
|
|
||||||
|
namespace Ocelot.Cache
|
||||||
|
{
|
||||||
|
|
||||||
|
public class RegionCreator : IRegionCreator
|
||||||
|
{
|
||||||
|
public string Create(FileReRoute reRoute)
|
||||||
|
{
|
||||||
|
if(!string.IsNullOrEmpty(reRoute?.FileCacheOptions?.Region))
|
||||||
|
{
|
||||||
|
return reRoute?.FileCacheOptions?.Region;
|
||||||
|
}
|
||||||
|
|
||||||
|
var methods = string.Join("", reRoute.UpstreamHttpMethod.Select(m => m));
|
||||||
|
|
||||||
|
var region = $"{methods}{reRoute.UpstreamPathTemplate.Replace("/", "")}";
|
||||||
|
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
src/Ocelot/Cache/Regions.cs
Normal file
13
src/Ocelot/Cache/Regions.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ocelot.Cache
|
||||||
|
{
|
||||||
|
public class Regions
|
||||||
|
{
|
||||||
|
public Regions(List<string> value)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
public List<string> Value {get;private set;}
|
||||||
|
}
|
||||||
|
}
|
@ -26,8 +26,6 @@ namespace Ocelot.Claims.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("started claims middleware");
|
|
||||||
|
|
||||||
if (DownstreamRoute.ReRoute.ClaimsToClaims.Any())
|
if (DownstreamRoute.ReRoute.ClaimsToClaims.Any())
|
||||||
{
|
{
|
||||||
_logger.LogDebug("this route has instructions to convert claims to other claims");
|
_logger.LogDebug("this route has instructions to convert claims to other claims");
|
||||||
@ -42,12 +40,7 @@ namespace Ocelot.Claims.Middleware
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogDebug("calling next middleware");
|
|
||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
_logger.LogDebug("succesfully called next middleware");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,24 +2,52 @@
|
|||||||
|
|
||||||
namespace Ocelot.Configuration
|
namespace Ocelot.Configuration
|
||||||
{
|
{
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
public class AuthenticationOptions
|
public class AuthenticationOptions
|
||||||
{
|
{
|
||||||
public AuthenticationOptions(string provider, string providerRootUrl, string apiName, bool requireHttps, List<string> allowedScopes, string apiSecret)
|
public AuthenticationOptions(string provider, List<string> allowedScopes, IAuthenticationConfig config)
|
||||||
{
|
{
|
||||||
Provider = provider;
|
Provider = provider;
|
||||||
ProviderRootUrl = providerRootUrl;
|
|
||||||
ApiName = apiName;
|
|
||||||
RequireHttps = requireHttps;
|
|
||||||
AllowedScopes = allowedScopes;
|
AllowedScopes = allowedScopes;
|
||||||
ApiSecret = apiSecret;
|
Config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Provider { get; private set; }
|
public string Provider { get; private set; }
|
||||||
|
|
||||||
|
public List<string> AllowedScopes { get; private set; }
|
||||||
|
|
||||||
|
public IAuthenticationConfig Config { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IdentityServerConfig : IAuthenticationConfig
|
||||||
|
{
|
||||||
|
public IdentityServerConfig(string providerRootUrl, string apiName, bool requireHttps, string apiSecret)
|
||||||
|
{
|
||||||
|
ProviderRootUrl = providerRootUrl;
|
||||||
|
ApiName = apiName;
|
||||||
|
RequireHttps = requireHttps;
|
||||||
|
ApiSecret = apiSecret;
|
||||||
|
}
|
||||||
|
|
||||||
public string ProviderRootUrl { get; private set; }
|
public string ProviderRootUrl { get; private set; }
|
||||||
public string ApiName { get; private set; }
|
public string ApiName { get; private set; }
|
||||||
public string ApiSecret { get; private set; }
|
public string ApiSecret { get; private set; }
|
||||||
public bool RequireHttps { get; private set; }
|
public bool RequireHttps { get; private set; }
|
||||||
public List<string> AllowedScopes { get; private set; }
|
}
|
||||||
|
|
||||||
|
public class JwtConfig : IAuthenticationConfig
|
||||||
|
{
|
||||||
|
public JwtConfig(string authority, string audience)
|
||||||
|
{
|
||||||
|
Audience = audience;
|
||||||
|
Authority = authority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string Audience { get; }
|
||||||
|
|
||||||
|
public string Authority { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IAuthenticationConfig {}
|
||||||
}
|
}
|
||||||
|
@ -6,51 +6,93 @@ namespace Ocelot.Configuration.Builder
|
|||||||
{
|
{
|
||||||
|
|
||||||
private string _provider;
|
private string _provider;
|
||||||
private string _providerRootUrl;
|
|
||||||
private string _apiName;
|
|
||||||
private string _apiSecret;
|
|
||||||
private bool _requireHttps;
|
|
||||||
private List<string> _allowedScopes;
|
private List<string> _allowedScopes;
|
||||||
|
|
||||||
|
private IAuthenticationConfig _identityServerConfig;
|
||||||
|
|
||||||
public AuthenticationOptionsBuilder WithProvider(string provider)
|
public AuthenticationOptionsBuilder WithProvider(string provider)
|
||||||
{
|
{
|
||||||
_provider = provider;
|
_provider = provider;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthenticationOptionsBuilder WithProviderRootUrl(string providerRootUrl)
|
|
||||||
{
|
|
||||||
_providerRootUrl = providerRootUrl;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthenticationOptionsBuilder WithApiName(string apiName)
|
|
||||||
{
|
|
||||||
_apiName = apiName;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthenticationOptionsBuilder WithApiSecret(string apiSecret)
|
|
||||||
{
|
|
||||||
_apiSecret = apiSecret;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthenticationOptionsBuilder WithRequireHttps(bool requireHttps)
|
|
||||||
{
|
|
||||||
_requireHttps = requireHttps;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthenticationOptionsBuilder WithAllowedScopes(List<string> allowedScopes)
|
public AuthenticationOptionsBuilder WithAllowedScopes(List<string> allowedScopes)
|
||||||
{
|
{
|
||||||
_allowedScopes = allowedScopes;
|
_allowedScopes = allowedScopes;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AuthenticationOptionsBuilder WithConfig(IAuthenticationConfig config)
|
||||||
|
{
|
||||||
|
_identityServerConfig = config;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public AuthenticationOptions Build()
|
public AuthenticationOptions Build()
|
||||||
{
|
{
|
||||||
return new AuthenticationOptions(_provider, _providerRootUrl, _apiName, _requireHttps, _allowedScopes, _apiSecret);
|
return new AuthenticationOptions(_provider, _allowedScopes, _identityServerConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IdentityServerConfigBuilder
|
||||||
|
{
|
||||||
|
private string _providerRootUrl;
|
||||||
|
private string _apiName;
|
||||||
|
private string _apiSecret;
|
||||||
|
private bool _requireHttps;
|
||||||
|
|
||||||
|
public IdentityServerConfigBuilder WithProviderRootUrl(string providerRootUrl)
|
||||||
|
{
|
||||||
|
_providerRootUrl = providerRootUrl;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdentityServerConfigBuilder WithApiName(string apiName)
|
||||||
|
{
|
||||||
|
_apiName = apiName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdentityServerConfigBuilder WithApiSecret(string apiSecret)
|
||||||
|
{
|
||||||
|
_apiSecret = apiSecret;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdentityServerConfigBuilder WithRequireHttps(bool requireHttps)
|
||||||
|
{
|
||||||
|
_requireHttps = requireHttps;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdentityServerConfig Build()
|
||||||
|
{
|
||||||
|
return new IdentityServerConfig(_providerRootUrl, _apiName, _requireHttps, _apiSecret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class JwtConfigBuilder
|
||||||
|
{
|
||||||
|
public string _authority;
|
||||||
|
|
||||||
|
public string _audience;
|
||||||
|
|
||||||
|
public JwtConfigBuilder WithAuthority(string authority)
|
||||||
|
{
|
||||||
|
_authority = authority;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JwtConfigBuilder WithAudience(string audience)
|
||||||
|
{
|
||||||
|
_audience = audience;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JwtConfig Build()
|
||||||
|
{
|
||||||
|
return new JwtConfig(_authority, _audience);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,11 +2,13 @@
|
|||||||
{
|
{
|
||||||
public class CacheOptions
|
public class CacheOptions
|
||||||
{
|
{
|
||||||
public CacheOptions(int ttlSeconds)
|
public CacheOptions(int ttlSeconds, string region)
|
||||||
{
|
{
|
||||||
TtlSeconds = ttlSeconds;
|
TtlSeconds = ttlSeconds;
|
||||||
|
Region = region;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int TtlSeconds { get; private set; }
|
public int TtlSeconds { get; private set; }
|
||||||
|
public string Region {get;private set;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,26 @@
|
|||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.Configuration.File;
|
using Ocelot.Configuration.File;
|
||||||
|
using Ocelot.Creator.Configuration;
|
||||||
|
|
||||||
namespace Ocelot.Configuration.Creator
|
namespace Ocelot.Configuration.Creator
|
||||||
{
|
{
|
||||||
public class AuthenticationOptionsCreator : IAuthenticationOptionsCreator
|
public class AuthenticationOptionsCreator : IAuthenticationOptionsCreator
|
||||||
{
|
{
|
||||||
|
private readonly IAuthenticationProviderConfigCreator _creator;
|
||||||
|
|
||||||
|
public AuthenticationOptionsCreator(IAuthenticationProviderConfigCreator creator)
|
||||||
|
{
|
||||||
|
_creator = creator;
|
||||||
|
}
|
||||||
|
|
||||||
public AuthenticationOptions Create(FileReRoute fileReRoute)
|
public AuthenticationOptions Create(FileReRoute fileReRoute)
|
||||||
{
|
{
|
||||||
|
var authenticationConfig = _creator.Create(fileReRoute.AuthenticationOptions);
|
||||||
|
|
||||||
return new AuthenticationOptionsBuilder()
|
return new AuthenticationOptionsBuilder()
|
||||||
.WithProvider(fileReRoute.AuthenticationOptions?.Provider)
|
.WithProvider(fileReRoute.AuthenticationOptions?.Provider)
|
||||||
.WithProviderRootUrl(fileReRoute.AuthenticationOptions?.ProviderRootUrl)
|
|
||||||
.WithApiName(fileReRoute.AuthenticationOptions?.ApiName)
|
|
||||||
.WithRequireHttps(fileReRoute.AuthenticationOptions.RequireHttps)
|
|
||||||
.WithAllowedScopes(fileReRoute.AuthenticationOptions?.AllowedScopes)
|
.WithAllowedScopes(fileReRoute.AuthenticationOptions?.AllowedScopes)
|
||||||
.WithApiSecret(fileReRoute.AuthenticationOptions?.ApiSecret)
|
.WithConfig(authenticationConfig)
|
||||||
.Build();
|
.Build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
using Ocelot.Creator.Configuration;
|
||||||
|
|
||||||
|
namespace Ocelot.Configuration.Creator
|
||||||
|
{
|
||||||
|
using Ocelot.Configuration.Builder;
|
||||||
|
using Ocelot.Configuration.File;
|
||||||
|
|
||||||
|
public class AuthenticationProviderConfigCreator : IAuthenticationProviderConfigCreator
|
||||||
|
{
|
||||||
|
public IAuthenticationConfig Create(FileAuthenticationOptions authenticationOptions)
|
||||||
|
{
|
||||||
|
if (authenticationOptions.Provider?.ToLower() == "jwt")
|
||||||
|
{
|
||||||
|
return CreateJwt(authenticationOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CreateIdentityServer(authenticationOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JwtConfig CreateJwt(FileAuthenticationOptions authenticationOptions)
|
||||||
|
{
|
||||||
|
return new JwtConfigBuilder()
|
||||||
|
.WithAudience(authenticationOptions.JwtConfig?.Audience)
|
||||||
|
.WithAuthority(authenticationOptions.JwtConfig?.Authority)
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IdentityServerConfig CreateIdentityServer(FileAuthenticationOptions authenticationOptions)
|
||||||
|
{
|
||||||
|
return new IdentityServerConfigBuilder()
|
||||||
|
.WithApiName(authenticationOptions.IdentityServerConfig?.ApiName)
|
||||||
|
.WithApiSecret(authenticationOptions.IdentityServerConfig?.ApiSecret)
|
||||||
|
.WithProviderRootUrl(authenticationOptions.IdentityServerConfig?.ProviderRootUrl)
|
||||||
|
.WithRequireHttps(authenticationOptions.IdentityServerConfig.RequireHttps).Build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using Ocelot.Cache;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.Configuration.File;
|
using Ocelot.Configuration.File;
|
||||||
using Ocelot.Configuration.Parser;
|
using Ocelot.Configuration.Parser;
|
||||||
@ -30,12 +31,13 @@ namespace Ocelot.Configuration.Creator
|
|||||||
private readonly IQosProviderHouse _qosProviderHouse;
|
private readonly IQosProviderHouse _qosProviderHouse;
|
||||||
private readonly IClaimsToThingCreator _claimsToThingCreator;
|
private readonly IClaimsToThingCreator _claimsToThingCreator;
|
||||||
private readonly IAuthenticationOptionsCreator _authOptionsCreator;
|
private readonly IAuthenticationOptionsCreator _authOptionsCreator;
|
||||||
private IUpstreamTemplatePatternCreator _upstreamTemplatePatternCreator;
|
private readonly IUpstreamTemplatePatternCreator _upstreamTemplatePatternCreator;
|
||||||
private IRequestIdKeyCreator _requestIdKeyCreator;
|
private readonly IRequestIdKeyCreator _requestIdKeyCreator;
|
||||||
private IServiceProviderConfigurationCreator _serviceProviderConfigCreator;
|
private readonly IServiceProviderConfigurationCreator _serviceProviderConfigCreator;
|
||||||
private IQoSOptionsCreator _qosOptionsCreator;
|
private readonly IQoSOptionsCreator _qosOptionsCreator;
|
||||||
private IReRouteOptionsCreator _fileReRouteOptionsCreator;
|
private readonly IReRouteOptionsCreator _fileReRouteOptionsCreator;
|
||||||
private IRateLimitOptionsCreator _rateLimitOptionsCreator;
|
private readonly IRateLimitOptionsCreator _rateLimitOptionsCreator;
|
||||||
|
private readonly IRegionCreator _regionCreator;
|
||||||
|
|
||||||
public FileOcelotConfigurationCreator(
|
public FileOcelotConfigurationCreator(
|
||||||
IOptions<FileConfiguration> options,
|
IOptions<FileConfiguration> options,
|
||||||
@ -52,9 +54,11 @@ namespace Ocelot.Configuration.Creator
|
|||||||
IServiceProviderConfigurationCreator serviceProviderConfigCreator,
|
IServiceProviderConfigurationCreator serviceProviderConfigCreator,
|
||||||
IQoSOptionsCreator qosOptionsCreator,
|
IQoSOptionsCreator qosOptionsCreator,
|
||||||
IReRouteOptionsCreator fileReRouteOptionsCreator,
|
IReRouteOptionsCreator fileReRouteOptionsCreator,
|
||||||
IRateLimitOptionsCreator rateLimitOptionsCreator
|
IRateLimitOptionsCreator rateLimitOptionsCreator,
|
||||||
|
IRegionCreator regionCreator
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
_regionCreator = regionCreator;
|
||||||
_rateLimitOptionsCreator = rateLimitOptionsCreator;
|
_rateLimitOptionsCreator = rateLimitOptionsCreator;
|
||||||
_requestIdKeyCreator = requestIdKeyCreator;
|
_requestIdKeyCreator = requestIdKeyCreator;
|
||||||
_upstreamTemplatePatternCreator = upstreamTemplatePatternCreator;
|
_upstreamTemplatePatternCreator = upstreamTemplatePatternCreator;
|
||||||
@ -137,6 +141,8 @@ namespace Ocelot.Configuration.Creator
|
|||||||
|
|
||||||
var rateLimitOption = _rateLimitOptionsCreator.Create(fileReRoute, globalConfiguration, fileReRouteOptions.EnableRateLimiting);
|
var rateLimitOption = _rateLimitOptionsCreator.Create(fileReRoute, globalConfiguration, fileReRouteOptions.EnableRateLimiting);
|
||||||
|
|
||||||
|
var region = _regionCreator.Create(fileReRoute);
|
||||||
|
|
||||||
var reRoute = new ReRouteBuilder()
|
var reRoute = new ReRouteBuilder()
|
||||||
.WithDownstreamPathTemplate(fileReRoute.DownstreamPathTemplate)
|
.WithDownstreamPathTemplate(fileReRoute.DownstreamPathTemplate)
|
||||||
.WithUpstreamPathTemplate(fileReRoute.UpstreamPathTemplate)
|
.WithUpstreamPathTemplate(fileReRoute.UpstreamPathTemplate)
|
||||||
@ -151,7 +157,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
.WithClaimsToQueries(claimsToQueries)
|
.WithClaimsToQueries(claimsToQueries)
|
||||||
.WithRequestIdKey(requestIdKey)
|
.WithRequestIdKey(requestIdKey)
|
||||||
.WithIsCached(fileReRouteOptions.IsCached)
|
.WithIsCached(fileReRouteOptions.IsCached)
|
||||||
.WithCacheOptions(new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds))
|
.WithCacheOptions(new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds, region))
|
||||||
.WithDownstreamScheme(fileReRoute.DownstreamScheme)
|
.WithDownstreamScheme(fileReRoute.DownstreamScheme)
|
||||||
.WithLoadBalancer(fileReRoute.LoadBalancer)
|
.WithLoadBalancer(fileReRoute.LoadBalancer)
|
||||||
.WithDownstreamHost(fileReRoute.DownstreamHost)
|
.WithDownstreamHost(fileReRoute.DownstreamHost)
|
||||||
|
@ -13,6 +13,8 @@ namespace Ocelot.Configuration.Creator
|
|||||||
var username = Environment.GetEnvironmentVariable("OCELOT_USERNAME");
|
var username = Environment.GetEnvironmentVariable("OCELOT_USERNAME");
|
||||||
var hash = Environment.GetEnvironmentVariable("OCELOT_HASH");
|
var hash = Environment.GetEnvironmentVariable("OCELOT_HASH");
|
||||||
var salt = Environment.GetEnvironmentVariable("OCELOT_SALT");
|
var salt = Environment.GetEnvironmentVariable("OCELOT_SALT");
|
||||||
|
var credentialsSigningCertificateLocation = Environment.GetEnvironmentVariable("OCELOT_CERTIFICATE");
|
||||||
|
var credentialsSigningCertificatePassword = Environment.GetEnvironmentVariable("OCELOT_CERTIFICATE_PASSWORD");
|
||||||
|
|
||||||
return new IdentityServerConfiguration(
|
return new IdentityServerConfiguration(
|
||||||
"admin",
|
"admin",
|
||||||
@ -28,7 +30,9 @@ namespace Ocelot.Configuration.Creator
|
|||||||
new List<User>
|
new List<User>
|
||||||
{
|
{
|
||||||
new User("admin", username, hash, salt)
|
new User("admin", username, hash, salt)
|
||||||
}
|
},
|
||||||
|
credentialsSigningCertificateLocation,
|
||||||
|
credentialsSigningCertificatePassword
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,13 @@ namespace Ocelot.Configuration.File
|
|||||||
public FileAuthenticationOptions()
|
public FileAuthenticationOptions()
|
||||||
{
|
{
|
||||||
AllowedScopes = new List<string>();
|
AllowedScopes = new List<string>();
|
||||||
|
IdentityServerConfig = new FileIdentityServerConfig();
|
||||||
|
JwtConfig = new FileJwtConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Provider { get; set; }
|
public string Provider { get; set; }
|
||||||
public string ProviderRootUrl { get; set; }
|
|
||||||
public string ApiName { get; set; }
|
|
||||||
public bool RequireHttps { get; set; }
|
|
||||||
public List<string> AllowedScopes { get; set; }
|
public List<string> AllowedScopes { get; set; }
|
||||||
public string ApiSecret { get; set; }
|
public FileIdentityServerConfig IdentityServerConfig { get; set; }
|
||||||
|
public FileJwtConfig JwtConfig { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,5 +3,6 @@
|
|||||||
public class FileCacheOptions
|
public class FileCacheOptions
|
||||||
{
|
{
|
||||||
public int TtlSeconds { get; set; }
|
public int TtlSeconds { get; set; }
|
||||||
|
public string Region {get; set;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
src/Ocelot/Configuration/File/FileIdentityServerConfig.cs
Normal file
10
src/Ocelot/Configuration/File/FileIdentityServerConfig.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace Ocelot.Configuration.File
|
||||||
|
{
|
||||||
|
public class FileIdentityServerConfig
|
||||||
|
{
|
||||||
|
public string ProviderRootUrl { get; set; }
|
||||||
|
public string ApiName { get; set; }
|
||||||
|
public bool RequireHttps { get; set; }
|
||||||
|
public string ApiSecret { get; set; }
|
||||||
|
}
|
||||||
|
}
|
9
src/Ocelot/Configuration/File/FileJwtConfig.cs
Normal file
9
src/Ocelot/Configuration/File/FileJwtConfig.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace Ocelot.Configuration.File
|
||||||
|
{
|
||||||
|
public class FileJwtConfig
|
||||||
|
{
|
||||||
|
public string Authority { get; set; }
|
||||||
|
|
||||||
|
public string Audience { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -17,5 +17,7 @@ namespace Ocelot.Configuration.Provider
|
|||||||
AccessTokenType AccessTokenType {get;}
|
AccessTokenType AccessTokenType {get;}
|
||||||
bool RequireClientSecret {get;}
|
bool RequireClientSecret {get;}
|
||||||
List<User> Users {get;}
|
List<User> Users {get;}
|
||||||
|
string CredentialsSigningCertificateLocation { get; }
|
||||||
|
string CredentialsSigningCertificatePassword { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,7 +17,7 @@ namespace Ocelot.Configuration.Provider
|
|||||||
IEnumerable<string> grantType,
|
IEnumerable<string> grantType,
|
||||||
AccessTokenType accessTokenType,
|
AccessTokenType accessTokenType,
|
||||||
bool requireClientSecret,
|
bool requireClientSecret,
|
||||||
List<User> users)
|
List<User> users, string credentialsSigningCertificateLocation, string credentialsSigningCertificatePassword)
|
||||||
{
|
{
|
||||||
ApiName = apiName;
|
ApiName = apiName;
|
||||||
RequireHttps = requireHttps;
|
RequireHttps = requireHttps;
|
||||||
@ -30,6 +30,8 @@ namespace Ocelot.Configuration.Provider
|
|||||||
AccessTokenType = accessTokenType;
|
AccessTokenType = accessTokenType;
|
||||||
RequireClientSecret = requireClientSecret;
|
RequireClientSecret = requireClientSecret;
|
||||||
Users = users;
|
Users = users;
|
||||||
|
CredentialsSigningCertificateLocation = credentialsSigningCertificateLocation;
|
||||||
|
CredentialsSigningCertificatePassword = credentialsSigningCertificatePassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ApiName { get; private set; }
|
public string ApiName { get; private set; }
|
||||||
@ -43,5 +45,7 @@ namespace Ocelot.Configuration.Provider
|
|||||||
public AccessTokenType AccessTokenType {get;private set;}
|
public AccessTokenType AccessTokenType {get;private set;}
|
||||||
public bool RequireClientSecret {get;private set;}
|
public bool RequireClientSecret {get;private set;}
|
||||||
public List<User> Users {get;private set;}
|
public List<User> Users {get;private set;}
|
||||||
|
public string CredentialsSigningCertificateLocation { get; private set; }
|
||||||
|
public string CredentialsSigningCertificatePassword { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -46,7 +46,7 @@ namespace Ocelot.Configuration
|
|||||||
IsAuthorised = isAuthorised;
|
IsAuthorised = isAuthorised;
|
||||||
RequestIdKey = requestIdKey;
|
RequestIdKey = requestIdKey;
|
||||||
IsCached = isCached;
|
IsCached = isCached;
|
||||||
FileCacheOptions = fileCacheOptions;
|
CacheOptions = fileCacheOptions;
|
||||||
ClaimsToQueries = claimsToQueries
|
ClaimsToQueries = claimsToQueries
|
||||||
?? new List<ClaimToThing>();
|
?? new List<ClaimToThing>();
|
||||||
ClaimsToClaims = claimsToClaims
|
ClaimsToClaims = claimsToClaims
|
||||||
@ -74,7 +74,7 @@ namespace Ocelot.Configuration
|
|||||||
public Dictionary<string, string> RouteClaimsRequirement { get; private set; }
|
public Dictionary<string, string> RouteClaimsRequirement { get; private set; }
|
||||||
public string RequestIdKey { get; private set; }
|
public string RequestIdKey { get; private set; }
|
||||||
public bool IsCached { get; private set; }
|
public bool IsCached { get; private set; }
|
||||||
public CacheOptions FileCacheOptions { get; private set; }
|
public CacheOptions CacheOptions { get; private set; }
|
||||||
public string DownstreamScheme {get;private set;}
|
public string DownstreamScheme {get;private set;}
|
||||||
public bool IsQos { get; private set; }
|
public bool IsQos { get; private set; }
|
||||||
public QoSOptions QosOptionsOptions { get; private set; }
|
public QoSOptions QosOptionsOptions { get; private set; }
|
||||||
|
@ -4,6 +4,7 @@ using System.Threading.Tasks;
|
|||||||
using Consul;
|
using Consul;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Ocelot.Authentication.JsonConverters;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using Ocelot.ServiceDiscovery;
|
using Ocelot.ServiceDiscovery;
|
||||||
|
|
||||||
@ -30,7 +31,7 @@ namespace Ocelot.Configuration.Repository
|
|||||||
|
|
||||||
public async Task<Response<IOcelotConfiguration>> Get()
|
public async Task<Response<IOcelotConfiguration>> Get()
|
||||||
{
|
{
|
||||||
var config = _cache.Get(_ocelotConfiguration);
|
var config = _cache.Get(_ocelotConfiguration, _ocelotConfiguration);
|
||||||
|
|
||||||
if (config != null)
|
if (config != null)
|
||||||
{
|
{
|
||||||
@ -48,7 +49,9 @@ namespace Ocelot.Configuration.Repository
|
|||||||
|
|
||||||
var json = Encoding.UTF8.GetString(bytes);
|
var json = Encoding.UTF8.GetString(bytes);
|
||||||
|
|
||||||
var consulConfig = JsonConvert.DeserializeObject<OcelotConfiguration>(json);
|
var settings = new JsonSerializerSettings();
|
||||||
|
settings.Converters.Add(new AuthenticationConfigConverter());
|
||||||
|
var consulConfig = JsonConvert.DeserializeObject<OcelotConfiguration>(json, settings);
|
||||||
|
|
||||||
return new OkResponse<IOcelotConfiguration>(consulConfig);
|
return new OkResponse<IOcelotConfiguration>(consulConfig);
|
||||||
}
|
}
|
||||||
@ -68,7 +71,7 @@ namespace Ocelot.Configuration.Repository
|
|||||||
|
|
||||||
if (result.Response)
|
if (result.Response)
|
||||||
{
|
{
|
||||||
_cache.AddAndDelete(_ocelotConfiguration, ocelotConfiguration, TimeSpan.FromSeconds(3));
|
_cache.AddAndDelete(_ocelotConfiguration, ocelotConfiguration, TimeSpan.FromSeconds(3), _ocelotConfiguration);
|
||||||
|
|
||||||
return new OkResponse();
|
return new OkResponse();
|
||||||
}
|
}
|
||||||
|
29
src/Ocelot/Controllers/OutputCacheController.cs
Normal file
29
src/Ocelot/Controllers/OutputCacheController.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Ocelot.Cache;
|
||||||
|
using Ocelot.Configuration.Provider;
|
||||||
|
|
||||||
|
namespace Ocelot.Controllers
|
||||||
|
{
|
||||||
|
[Authorize]
|
||||||
|
[Route("outputcache")]
|
||||||
|
public class OutputCacheController : Controller
|
||||||
|
{
|
||||||
|
private IOcelotCache<HttpResponseMessage> _cache;
|
||||||
|
|
||||||
|
public OutputCacheController(IOcelotCache<HttpResponseMessage> cache)
|
||||||
|
{
|
||||||
|
_cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete]
|
||||||
|
[Route("{region}")]
|
||||||
|
public IActionResult Delete(string region)
|
||||||
|
{
|
||||||
|
_cache.ClearRegion(region);
|
||||||
|
return new NoContentResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
using Ocelot.Configuration;
|
||||||
|
using Ocelot.Configuration.File;
|
||||||
|
|
||||||
|
namespace Ocelot.Creator.Configuration
|
||||||
|
{
|
||||||
|
public interface IAuthenticationProviderConfigCreator
|
||||||
|
{
|
||||||
|
IAuthenticationConfig Create(FileAuthenticationOptions authenticationOptions);
|
||||||
|
}
|
||||||
|
}
|
@ -41,7 +41,10 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
|
using Ocelot.Creator.Configuration;
|
||||||
using FileConfigurationProvider = Ocelot.Configuration.Provider.FileConfigurationProvider;
|
using FileConfigurationProvider = Ocelot.Configuration.Provider.FileConfigurationProvider;
|
||||||
|
|
||||||
namespace Ocelot.DependencyInjection
|
namespace Ocelot.DependencyInjection
|
||||||
@ -69,6 +72,7 @@ namespace Ocelot.DependencyInjection
|
|||||||
|
|
||||||
services.Configure<FileConfiguration>(configurationRoot);
|
services.Configure<FileConfiguration>(configurationRoot);
|
||||||
services.TryAddSingleton<IOcelotConfigurationCreator, FileOcelotConfigurationCreator>();
|
services.TryAddSingleton<IOcelotConfigurationCreator, FileOcelotConfigurationCreator>();
|
||||||
|
services.TryAddSingleton<IAuthenticationProviderConfigCreator, AuthenticationProviderConfigCreator>();
|
||||||
services.TryAddSingleton<IOcelotConfigurationRepository, InMemoryOcelotConfigurationRepository>();
|
services.TryAddSingleton<IOcelotConfigurationRepository, InMemoryOcelotConfigurationRepository>();
|
||||||
services.TryAddSingleton<IConfigurationValidator, FileConfigurationValidator>();
|
services.TryAddSingleton<IConfigurationValidator, FileConfigurationValidator>();
|
||||||
services.TryAddSingleton<IBaseUrlFinder, BaseUrlFinder>();
|
services.TryAddSingleton<IBaseUrlFinder, BaseUrlFinder>();
|
||||||
@ -87,8 +91,10 @@ namespace Ocelot.DependencyInjection
|
|||||||
{
|
{
|
||||||
services.TryAddSingleton<IIdentityServerConfiguration>(identityServerConfiguration);
|
services.TryAddSingleton<IIdentityServerConfiguration>(identityServerConfiguration);
|
||||||
services.TryAddSingleton<IHashMatcher, HashMatcher>();
|
services.TryAddSingleton<IHashMatcher, HashMatcher>();
|
||||||
services.AddIdentityServer()
|
var identityServerBuilder = services
|
||||||
.AddTemporarySigningCredential()
|
.AddIdentityServer(options => {
|
||||||
|
options.IssuerUri = "Ocelot";
|
||||||
|
})
|
||||||
.AddInMemoryApiResources(new List<ApiResource>
|
.AddInMemoryApiResources(new List<ApiResource>
|
||||||
{
|
{
|
||||||
new ApiResource
|
new ApiResource
|
||||||
@ -120,6 +126,16 @@ namespace Ocelot.DependencyInjection
|
|||||||
RequireClientSecret = identityServerConfiguration.RequireClientSecret
|
RequireClientSecret = identityServerConfiguration.RequireClientSecret
|
||||||
}
|
}
|
||||||
}).AddResourceOwnerValidator<OcelotResourceOwnerPasswordValidator>();
|
}).AddResourceOwnerValidator<OcelotResourceOwnerPasswordValidator>();
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(identityServerConfiguration.CredentialsSigningCertificateLocation) || string.IsNullOrEmpty(identityServerConfiguration.CredentialsSigningCertificatePassword))
|
||||||
|
{
|
||||||
|
identityServerBuilder.AddTemporarySigningCredential();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var cert = new X509Certificate2(identityServerConfiguration.CredentialsSigningCertificateLocation, identityServerConfiguration.CredentialsSigningCertificatePassword);
|
||||||
|
identityServerBuilder.AddSigningCredential(cert);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var assembly = typeof(FileConfigurationController).GetTypeInfo().Assembly;
|
var assembly = typeof(FileConfigurationController).GetTypeInfo().Assembly;
|
||||||
@ -131,6 +147,7 @@ namespace Ocelot.DependencyInjection
|
|||||||
.AddJsonFormatters();
|
.AddJsonFormatters();
|
||||||
|
|
||||||
services.AddLogging();
|
services.AddLogging();
|
||||||
|
services.TryAddSingleton<IRegionCreator, RegionCreator>();
|
||||||
services.TryAddSingleton<IFileConfigurationRepository, FileConfigurationRepository>();
|
services.TryAddSingleton<IFileConfigurationRepository, FileConfigurationRepository>();
|
||||||
services.TryAddSingleton<IFileConfigurationSetter, FileConfigurationSetter>();
|
services.TryAddSingleton<IFileConfigurationSetter, FileConfigurationSetter>();
|
||||||
services.TryAddSingleton<IFileConfigurationProvider, FileConfigurationProvider>();
|
services.TryAddSingleton<IFileConfigurationProvider, FileConfigurationProvider>();
|
||||||
@ -169,6 +186,11 @@ namespace Ocelot.DependencyInjection
|
|||||||
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
services.TryAddScoped<IRequestScopedDataRepository, HttpDataRepository>();
|
services.TryAddScoped<IRequestScopedDataRepository, HttpDataRepository>();
|
||||||
services.AddMemoryCache();
|
services.AddMemoryCache();
|
||||||
|
|
||||||
|
//Used to log the the start and ending of middleware
|
||||||
|
services.TryAddSingleton<OcelotDiagnosticListener>();
|
||||||
|
services.AddMiddlewareAnalysis();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,6 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
_logger.TraceMiddlewareEntry();
|
|
||||||
|
|
||||||
var upstreamUrlPath = context.Request.Path.ToString().SetLastCharacterAs('/');
|
var upstreamUrlPath = context.Request.Path.ToString().SetLastCharacterAs('/');
|
||||||
|
|
||||||
_logger.LogDebug("upstream url path is {upstreamUrlPath}", upstreamUrlPath);
|
_logger.LogDebug("upstream url path is {upstreamUrlPath}", upstreamUrlPath);
|
||||||
@ -40,11 +38,9 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
|
|||||||
|
|
||||||
if (downstreamRoute.IsError)
|
if (downstreamRoute.IsError)
|
||||||
{
|
{
|
||||||
_logger.LogError($"{MiddlwareName} setting pipeline errors. IDownstreamRouteFinder returned {downstreamRoute.Errors.ToErrorString()}");
|
_logger.LogError($"{MiddlewareName} setting pipeline errors. IDownstreamRouteFinder returned {downstreamRoute.Errors.ToErrorString()}");
|
||||||
|
|
||||||
SetPipelineError(downstreamRoute.Errors);
|
SetPipelineError(downstreamRoute.Errors);
|
||||||
|
|
||||||
_logger.TraceMiddlewareCompleted();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,12 +48,7 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
|
|||||||
|
|
||||||
SetDownstreamRouteForThisRequest(downstreamRoute.Data);
|
SetDownstreamRouteForThisRequest(downstreamRoute.Data);
|
||||||
|
|
||||||
_logger.TraceInvokeNext();
|
|
||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
_logger.TraceInvokeNextCompleted();
|
|
||||||
_logger.TraceMiddlewareCompleted();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,8 +30,6 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("started calling downstream url creator middleware");
|
|
||||||
|
|
||||||
var dsPath = _replacer
|
var dsPath = _replacer
|
||||||
.Replace(DownstreamRoute.ReRoute.DownstreamPathTemplate, DownstreamRoute.TemplatePlaceholderNameAndValues);
|
.Replace(DownstreamRoute.ReRoute.DownstreamPathTemplate, DownstreamRoute.TemplatePlaceholderNameAndValues);
|
||||||
|
|
||||||
@ -53,11 +51,7 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
|
|||||||
|
|
||||||
_logger.LogDebug("downstream url is {downstreamUrl.Data.Value}", DownstreamRequest.RequestUri);
|
_logger.LogDebug("downstream url is {downstreamUrl.Data.Value}", DownstreamRequest.RequestUri);
|
||||||
|
|
||||||
_logger.LogDebug("calling next middleware");
|
|
||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
_logger.LogDebug("succesfully called next middleware");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,17 +26,15 @@ namespace Ocelot.Headers.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("started calling headers builder middleware");
|
|
||||||
|
|
||||||
if (DownstreamRoute.ReRoute.ClaimsToHeaders.Any())
|
if (DownstreamRoute.ReRoute.ClaimsToHeaders.Any())
|
||||||
{
|
{
|
||||||
_logger.LogDebug("this route has instructions to convert claims to headers");
|
_logger.LogDebug($"{ DownstreamRoute.ReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to headers");
|
||||||
|
|
||||||
var response = _addHeadersToRequest.SetHeadersOnDownstreamRequest(DownstreamRoute.ReRoute.ClaimsToHeaders, context.User.Claims, DownstreamRequest);
|
var response = _addHeadersToRequest.SetHeadersOnDownstreamRequest(DownstreamRoute.ReRoute.ClaimsToHeaders, context.User.Claims, DownstreamRequest);
|
||||||
|
|
||||||
if (response.IsError)
|
if (response.IsError)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("there was an error setting headers on context, setting pipeline error");
|
_logger.LogDebug("Error setting headers on context, setting pipeline error");
|
||||||
|
|
||||||
SetPipelineError(response.Errors);
|
SetPipelineError(response.Errors);
|
||||||
return;
|
return;
|
||||||
@ -45,11 +43,7 @@ namespace Ocelot.Headers.Middleware
|
|||||||
_logger.LogDebug("headers have been set on context");
|
_logger.LogDebug("headers have been set on context");
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogDebug("calling next middleware");
|
|
||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
_logger.LogDebug("succesfully called next middleware");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,11 +28,10 @@ namespace Ocelot.LoadBalancer.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("started calling load balancing middleware");
|
|
||||||
|
|
||||||
var loadBalancer = _loadBalancerHouse.Get(DownstreamRoute.ReRoute.ReRouteKey);
|
var loadBalancer = _loadBalancerHouse.Get(DownstreamRoute.ReRoute.ReRouteKey);
|
||||||
if(loadBalancer.IsError)
|
if(loadBalancer.IsError)
|
||||||
{
|
{
|
||||||
|
_logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error");
|
||||||
SetPipelineError(loadBalancer.Errors);
|
SetPipelineError(loadBalancer.Errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -40,6 +39,7 @@ namespace Ocelot.LoadBalancer.Middleware
|
|||||||
var hostAndPort = await loadBalancer.Data.Lease();
|
var hostAndPort = await loadBalancer.Data.Lease();
|
||||||
if(hostAndPort.IsError)
|
if(hostAndPort.IsError)
|
||||||
{
|
{
|
||||||
|
_logger.LogDebug("there was an error leasing the loadbalancer, setting pipeline error");
|
||||||
SetPipelineError(hostAndPort.Errors);
|
SetPipelineError(hostAndPort.Errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -52,23 +52,19 @@ namespace Ocelot.LoadBalancer.Middleware
|
|||||||
}
|
}
|
||||||
DownstreamRequest.RequestUri = uriBuilder.Uri;
|
DownstreamRequest.RequestUri = uriBuilder.Uri;
|
||||||
|
|
||||||
_logger.LogDebug("calling next middleware");
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
loadBalancer.Data.Release(hostAndPort.Data);
|
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
loadBalancer.Data.Release(hostAndPort.Data);
|
_logger.LogDebug("Exception calling next middleware, exception will be thrown to global handler");
|
||||||
|
|
||||||
_logger.LogDebug("error calling next middleware, exception will be thrown to global handler");
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
_logger.LogDebug("succesfully called next middleware");
|
{
|
||||||
|
loadBalancer.Data.Release(hostAndPort.Data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
34
src/Ocelot/Logging/OcelotDiagnosticListener.cs
Normal file
34
src/Ocelot/Logging/OcelotDiagnosticListener.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.DiagnosticAdapter;
|
||||||
|
|
||||||
|
namespace Ocelot.Logging
|
||||||
|
{
|
||||||
|
public class OcelotDiagnosticListener
|
||||||
|
{
|
||||||
|
private IOcelotLogger _logger;
|
||||||
|
|
||||||
|
public OcelotDiagnosticListener(IOcelotLoggerFactory factory)
|
||||||
|
{
|
||||||
|
_logger = factory.CreateLogger<OcelotDiagnosticListener>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareStarting")]
|
||||||
|
public virtual void OnMiddlewareStarting(HttpContext httpContext, string name)
|
||||||
|
{
|
||||||
|
_logger.LogTrace($"MiddlewareStarting: {name}; {httpContext.Request.Path}");
|
||||||
|
}
|
||||||
|
|
||||||
|
[DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareException")]
|
||||||
|
public virtual void OnMiddlewareException(Exception exception, string name)
|
||||||
|
{
|
||||||
|
_logger.LogTrace($"MiddlewareException: {name}; {exception.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
[DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareFinished")]
|
||||||
|
public virtual void OnMiddlewareFinished(HttpContext httpContext, string name)
|
||||||
|
{
|
||||||
|
_logger.LogTrace($"MiddlewareFinished: {name}; {httpContext.Response.StatusCode}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,29 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Ocelot.Logging
|
|
||||||
{
|
|
||||||
public static class OcelotLoggerExtensions
|
|
||||||
{
|
|
||||||
public static void TraceMiddlewareEntry(this IOcelotLogger logger)
|
|
||||||
{
|
|
||||||
logger.LogTrace($"entered {logger.Name}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void TraceInvokeNext(this IOcelotLogger logger)
|
|
||||||
{
|
|
||||||
logger.LogTrace($"invoking next middleware from {logger.Name}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void TraceInvokeNextCompleted(this IOcelotLogger logger)
|
|
||||||
{
|
|
||||||
logger.LogTrace($"returned to {logger.Name} after next middleware completed");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void TraceMiddlewareCompleted(this IOcelotLogger logger)
|
|
||||||
{
|
|
||||||
logger.LogTrace($"completed {logger.Name}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,10 +13,10 @@ namespace Ocelot.Middleware
|
|||||||
protected OcelotMiddleware(IRequestScopedDataRepository requestScopedDataRepository)
|
protected OcelotMiddleware(IRequestScopedDataRepository requestScopedDataRepository)
|
||||||
{
|
{
|
||||||
_requestScopedDataRepository = requestScopedDataRepository;
|
_requestScopedDataRepository = requestScopedDataRepository;
|
||||||
MiddlwareName = this.GetType().Name;
|
MiddlewareName = this.GetType().Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string MiddlwareName { get; }
|
public string MiddlewareName { get; }
|
||||||
|
|
||||||
public bool PipelineError => _requestScopedDataRepository.Get<bool>("OcelotMiddlewareError").Data;
|
public bool PipelineError => _requestScopedDataRepository.Get<bool>("OcelotMiddlewareError").Data;
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using IdentityServer4.AccessTokenValidation;
|
using IdentityServer4.AccessTokenValidation;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Ocelot.Authentication.Middleware;
|
using Ocelot.Authentication.Middleware;
|
||||||
@ -8,6 +9,7 @@ using Ocelot.DownstreamRouteFinder.Middleware;
|
|||||||
using Ocelot.DownstreamUrlCreator.Middleware;
|
using Ocelot.DownstreamUrlCreator.Middleware;
|
||||||
using Ocelot.Errors.Middleware;
|
using Ocelot.Errors.Middleware;
|
||||||
using Ocelot.Headers.Middleware;
|
using Ocelot.Headers.Middleware;
|
||||||
|
using Ocelot.Logging;
|
||||||
using Ocelot.QueryStrings.Middleware;
|
using Ocelot.QueryStrings.Middleware;
|
||||||
using Ocelot.Request.Middleware;
|
using Ocelot.Request.Middleware;
|
||||||
using Ocelot.Requester.Middleware;
|
using Ocelot.Requester.Middleware;
|
||||||
@ -53,6 +55,8 @@ namespace Ocelot.Middleware
|
|||||||
{
|
{
|
||||||
await CreateAdministrationArea(builder);
|
await CreateAdministrationArea(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
|
||||||
builder.UseExceptionHandlerMiddleware();
|
builder.UseExceptionHandlerMiddleware();
|
||||||
|
|
||||||
@ -181,7 +185,6 @@ namespace Ocelot.Middleware
|
|||||||
builder.Map(configuration.AdministrationPath, app =>
|
builder.Map(configuration.AdministrationPath, app =>
|
||||||
{
|
{
|
||||||
var identityServerUrl = $"{baseSchemeUrlAndPort}/{configuration.AdministrationPath.Remove(0,1)}";
|
var identityServerUrl = $"{baseSchemeUrlAndPort}/{configuration.AdministrationPath.Remove(0,1)}";
|
||||||
|
|
||||||
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
|
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
|
||||||
{
|
{
|
||||||
Authority = identityServerUrl,
|
Authority = identityServerUrl,
|
||||||
@ -206,5 +209,22 @@ namespace Ocelot.Middleware
|
|||||||
builder.Use(middleware);
|
builder.Use(middleware);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Configure a DiagnosticListener to listen for diagnostic events when the middleware starts and ends
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder"></param>
|
||||||
|
private static void ConfigureDiagnosticListener(IApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
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 diagnosticListener = (DiagnosticListener)builder.ApplicationServices.GetService(typeof(DiagnosticListener));
|
||||||
|
diagnosticListener.SubscribeWithAdapter(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,10 +26,12 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.MiddlewareAnalysis" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" Version="1.1.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
|
||||||
|
@ -26,11 +26,9 @@ namespace Ocelot.QueryStrings.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
_logger.LogDebug("started calling query string builder middleware");
|
|
||||||
|
|
||||||
if (DownstreamRoute.ReRoute.ClaimsToQueries.Any())
|
if (DownstreamRoute.ReRoute.ClaimsToQueries.Any())
|
||||||
{
|
{
|
||||||
_logger.LogDebug("this route has instructions to convert claims to queries");
|
_logger.LogDebug($"{DownstreamRoute.ReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to queries");
|
||||||
|
|
||||||
var response = _addQueriesToRequest.SetQueriesOnDownstreamRequest(DownstreamRoute.ReRoute.ClaimsToQueries, context.User.Claims, DownstreamRequest);
|
var response = _addQueriesToRequest.SetQueriesOnDownstreamRequest(DownstreamRoute.ReRoute.ClaimsToQueries, context.User.Claims, DownstreamRequest);
|
||||||
|
|
||||||
@ -43,11 +41,7 @@ namespace Ocelot.QueryStrings.Middleware
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogDebug("calling next middleware");
|
|
||||||
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
|
|
||||||
_logger.LogDebug("succesfully called next middleware");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,18 +31,12 @@ namespace Ocelot.RateLimit.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
_logger.TraceMiddlewareEntry();
|
|
||||||
|
|
||||||
var options = DownstreamRoute.ReRoute.RateLimitOptions;
|
var options = DownstreamRoute.ReRoute.RateLimitOptions;
|
||||||
// check if rate limiting is enabled
|
// check if rate limiting is enabled
|
||||||
if (!DownstreamRoute.ReRoute.EnableEndpointEndpointRateLimiting)
|
if (!DownstreamRoute.ReRoute.EnableEndpointEndpointRateLimiting)
|
||||||
{
|
{
|
||||||
_logger.LogDebug($"EndpointRateLimiting is not enabled for {DownstreamRoute.ReRoute.DownstreamPathTemplate}");
|
_logger.LogDebug($"EndpointRateLimiting is not enabled for {DownstreamRoute.ReRoute.DownstreamPathTemplate}");
|
||||||
|
|
||||||
_logger.TraceInvokeNext();
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
_logger.TraceInvokeNextCompleted();
|
|
||||||
_logger.TraceMiddlewareCompleted();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// compute identity from request
|
// compute identity from request
|
||||||
@ -52,11 +46,7 @@ namespace Ocelot.RateLimit.Middleware
|
|||||||
if (IsWhitelisted(identity, options))
|
if (IsWhitelisted(identity, options))
|
||||||
{
|
{
|
||||||
_logger.LogDebug($"{DownstreamRoute.ReRoute.DownstreamPathTemplate} is white listed from rate limiting");
|
_logger.LogDebug($"{DownstreamRoute.ReRoute.DownstreamPathTemplate} is white listed from rate limiting");
|
||||||
|
|
||||||
_logger.TraceInvokeNext();
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
_logger.TraceInvokeNextCompleted();
|
|
||||||
_logger.TraceMiddlewareCompleted();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +68,6 @@ namespace Ocelot.RateLimit.Middleware
|
|||||||
var retrystring = retryAfter.ToString(System.Globalization.CultureInfo.InvariantCulture);
|
var retrystring = retryAfter.ToString(System.Globalization.CultureInfo.InvariantCulture);
|
||||||
// break execution
|
// break execution
|
||||||
await ReturnQuotaExceededResponse(context, options, retrystring);
|
await ReturnQuotaExceededResponse(context, options, retrystring);
|
||||||
_logger.TraceMiddlewareCompleted();
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -91,10 +80,7 @@ namespace Ocelot.RateLimit.Middleware
|
|||||||
context.Response.OnStarting(SetRateLimitHeaders, state: headers);
|
context.Response.OnStarting(SetRateLimitHeaders, state: headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.TraceInvokeNext();
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
_logger.TraceInvokeNextCompleted();
|
|
||||||
_logger.TraceMiddlewareCompleted();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual ClientRequestIdentity SetIdentity(HttpContext httpContext, RateLimitOptions option)
|
public virtual ClientRequestIdentity SetIdentity(HttpContext httpContext, RateLimitOptions option)
|
||||||
|
@ -29,14 +29,8 @@ namespace Ocelot.RequestId.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
_logger.TraceMiddlewareEntry();
|
|
||||||
|
|
||||||
SetOcelotRequestId(context);
|
SetOcelotRequestId(context);
|
||||||
|
|
||||||
_logger.TraceInvokeNext();
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
_logger.TraceInvokeNextCompleted();
|
|
||||||
_logger.TraceMiddlewareCompleted();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetOcelotRequestId(HttpContext context)
|
private void SetOcelotRequestId(HttpContext context)
|
||||||
|
@ -62,14 +62,6 @@ namespace Ocelot.Responder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddHeaderIfDoesntExist(HttpContext context, KeyValuePair<string, IEnumerable<string>> httpResponseHeader)
|
|
||||||
{
|
|
||||||
if (!context.Response.Headers.ContainsKey(httpResponseHeader.Key))
|
|
||||||
{
|
|
||||||
context.Response.Headers.Add(httpResponseHeader.Key, new StringValues(httpResponseHeader.Value.ToArray()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetErrorResponseOnContext(HttpContext context, int statusCode)
|
public void SetErrorResponseOnContext(HttpContext context, int statusCode)
|
||||||
{
|
{
|
||||||
context.Response.OnStarting(x =>
|
context.Response.OnStarting(x =>
|
||||||
@ -78,5 +70,13 @@ namespace Ocelot.Responder
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}, context);
|
}, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void AddHeaderIfDoesntExist(HttpContext context, KeyValuePair<string, IEnumerable<string>> httpResponseHeader)
|
||||||
|
{
|
||||||
|
if (!context.Response.Headers.ContainsKey(httpResponseHeader.Key))
|
||||||
|
{
|
||||||
|
context.Response.Headers.Add(httpResponseHeader.Key, new StringValues(httpResponseHeader.Value.ToArray()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -34,15 +34,12 @@ namespace Ocelot.Responder.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
_logger.TraceMiddlewareEntry();
|
|
||||||
_logger.TraceInvokeNext();
|
|
||||||
await _next.Invoke(context);
|
await _next.Invoke(context);
|
||||||
_logger.TraceInvokeNextCompleted();
|
|
||||||
|
|
||||||
if (PipelineError)
|
if (PipelineError)
|
||||||
{
|
{
|
||||||
var errors = PipelineErrors;
|
var errors = PipelineErrors;
|
||||||
_logger.LogError($"{errors.Count} pipeline errors found in {MiddlwareName}. Setting error response status code");
|
_logger.LogError($"{PipelineErrors.Count} pipeline errors found in {MiddlewareName}. Setting error response status code");
|
||||||
|
|
||||||
SetErrorResponse(context, errors);
|
SetErrorResponse(context, errors);
|
||||||
}
|
}
|
||||||
@ -51,13 +48,11 @@ namespace Ocelot.Responder.Middleware
|
|||||||
_logger.LogDebug("no pipeline errors, setting and returning completed response");
|
_logger.LogDebug("no pipeline errors, setting and returning completed response");
|
||||||
await _responder.SetResponseOnHttpContext(context, HttpResponseMessage);
|
await _responder.SetResponseOnHttpContext(context, HttpResponseMessage);
|
||||||
}
|
}
|
||||||
_logger.TraceMiddlewareCompleted();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetErrorResponse(HttpContext context, List<Error> errors)
|
private void SetErrorResponse(HttpContext context, List<Error> errors)
|
||||||
{
|
{
|
||||||
var statusCode = _codeMapper.Map(errors);
|
var statusCode = _codeMapper.Map(errors);
|
||||||
|
|
||||||
_responder.SetErrorResponseOnContext(context, statusCode);
|
_responder.SetErrorResponseOnContext(context, statusCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
AllowedScopes = new List<string>(),
|
AllowedScopes = new List<string>(),
|
||||||
Provider = "IdentityServer",
|
Provider = "IdentityServer",
|
||||||
|
IdentityServerConfig = new FileIdentityServerConfig{
|
||||||
ProviderRootUrl = _identityServerRootUrl,
|
ProviderRootUrl = _identityServerRootUrl,
|
||||||
RequireHttps = false,
|
RequireHttps = false,
|
||||||
ApiName = "api",
|
ApiName = "api",
|
||||||
@ -60,6 +61,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
|
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
|
||||||
@ -72,44 +74,6 @@ namespace Ocelot.AcceptanceTests
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void should_return_401_using_identity_server_reference_token()
|
|
||||||
{
|
|
||||||
var configuration = new FileConfiguration
|
|
||||||
{
|
|
||||||
ReRoutes = new List<FileReRoute>
|
|
||||||
{
|
|
||||||
new FileReRoute
|
|
||||||
{
|
|
||||||
DownstreamPathTemplate = _downstreamServicePath,
|
|
||||||
DownstreamPort = _downstreamServicePort,
|
|
||||||
DownstreamHost = _downstreamServiceHost,
|
|
||||||
DownstreamScheme = _downstreamServiceScheme,
|
|
||||||
UpstreamPathTemplate = "/",
|
|
||||||
UpstreamHttpMethod = new List<string> { "Post" },
|
|
||||||
AuthenticationOptions = new FileAuthenticationOptions
|
|
||||||
{
|
|
||||||
AllowedScopes = new List<string>(),
|
|
||||||
Provider = "IdentityServer",
|
|
||||||
ProviderRootUrl = _identityServerRootUrl,
|
|
||||||
RequireHttps = false,
|
|
||||||
ApiName = "api",
|
|
||||||
ApiSecret = "secret"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Reference))
|
|
||||||
.And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty))
|
|
||||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
|
||||||
.And(x => _steps.GivenOcelotIsRunning())
|
|
||||||
.And(x => _steps.GivenThePostHasContent("postContent"))
|
|
||||||
.When(x => _steps.WhenIPostUrlOnTheApiGateway("/"))
|
|
||||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Unauthorized))
|
|
||||||
.BDDfy();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_response_200_using_identity_server()
|
public void should_return_response_200_using_identity_server()
|
||||||
{
|
{
|
||||||
@ -129,6 +93,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
AllowedScopes = new List<string>(),
|
AllowedScopes = new List<string>(),
|
||||||
Provider = "IdentityServer",
|
Provider = "IdentityServer",
|
||||||
|
IdentityServerConfig = new FileIdentityServerConfig{
|
||||||
ProviderRootUrl = _identityServerRootUrl,
|
ProviderRootUrl = _identityServerRootUrl,
|
||||||
RequireHttps = false,
|
RequireHttps = false,
|
||||||
ApiName = "api",
|
ApiName = "api",
|
||||||
@ -136,6 +101,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
|
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
|
||||||
@ -169,6 +135,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
AllowedScopes = new List<string>(),
|
AllowedScopes = new List<string>(),
|
||||||
Provider = "IdentityServer",
|
Provider = "IdentityServer",
|
||||||
|
IdentityServerConfig = new FileIdentityServerConfig{
|
||||||
ProviderRootUrl = _identityServerRootUrl,
|
ProviderRootUrl = _identityServerRootUrl,
|
||||||
RequireHttps = false,
|
RequireHttps = false,
|
||||||
ApiName = "api",
|
ApiName = "api",
|
||||||
@ -176,6 +143,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
|
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
|
||||||
@ -209,6 +177,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
AllowedScopes = new List<string>(),
|
AllowedScopes = new List<string>(),
|
||||||
Provider = "IdentityServer",
|
Provider = "IdentityServer",
|
||||||
|
IdentityServerConfig = new FileIdentityServerConfig{
|
||||||
ProviderRootUrl = _identityServerRootUrl,
|
ProviderRootUrl = _identityServerRootUrl,
|
||||||
RequireHttps = false,
|
RequireHttps = false,
|
||||||
ApiName = "api",
|
ApiName = "api",
|
||||||
@ -216,6 +185,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
|
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
|
||||||
@ -249,6 +219,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
AllowedScopes = new List<string>(),
|
AllowedScopes = new List<string>(),
|
||||||
Provider = "IdentityServer",
|
Provider = "IdentityServer",
|
||||||
|
IdentityServerConfig = new FileIdentityServerConfig{
|
||||||
ProviderRootUrl = _identityServerRootUrl,
|
ProviderRootUrl = _identityServerRootUrl,
|
||||||
RequireHttps = false,
|
RequireHttps = false,
|
||||||
ApiName = "api",
|
ApiName = "api",
|
||||||
@ -256,6 +227,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Reference))
|
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Reference))
|
||||||
|
@ -47,10 +47,12 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
AllowedScopes = new List<string>(),
|
AllowedScopes = new List<string>(),
|
||||||
Provider = "IdentityServer",
|
Provider = "IdentityServer",
|
||||||
|
IdentityServerConfig = new FileIdentityServerConfig{
|
||||||
ProviderRootUrl = "http://localhost:51888",
|
ProviderRootUrl = "http://localhost:51888",
|
||||||
RequireHttps = false,
|
RequireHttps = false,
|
||||||
ApiName = "api",
|
ApiName = "api",
|
||||||
ApiSecret = "secret"
|
ApiSecret = "secret"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
AddHeadersToRequest =
|
AddHeadersToRequest =
|
||||||
{
|
{
|
||||||
@ -104,10 +106,12 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
AllowedScopes = new List<string>(),
|
AllowedScopes = new List<string>(),
|
||||||
Provider = "IdentityServer",
|
Provider = "IdentityServer",
|
||||||
|
IdentityServerConfig = new FileIdentityServerConfig{
|
||||||
ProviderRootUrl = "http://localhost:51888",
|
ProviderRootUrl = "http://localhost:51888",
|
||||||
RequireHttps = false,
|
RequireHttps = false,
|
||||||
ApiName = "api",
|
ApiName = "api",
|
||||||
ApiSecret = "secret"
|
ApiSecret = "secret"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
AddHeadersToRequest =
|
AddHeadersToRequest =
|
||||||
{
|
{
|
||||||
@ -159,6 +163,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
AllowedScopes = new List<string>{ "api", "api.readOnly", "openid", "offline_access" },
|
AllowedScopes = new List<string>{ "api", "api.readOnly", "openid", "offline_access" },
|
||||||
Provider = "IdentityServer",
|
Provider = "IdentityServer",
|
||||||
|
IdentityServerConfig = new FileIdentityServerConfig{
|
||||||
ProviderRootUrl = "http://localhost:51888",
|
ProviderRootUrl = "http://localhost:51888",
|
||||||
RequireHttps = false,
|
RequireHttps = false,
|
||||||
ApiName = "api",
|
ApiName = "api",
|
||||||
@ -166,6 +171,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:51888", "api", AccessTokenType.Jwt))
|
this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:51888", "api", AccessTokenType.Jwt))
|
||||||
@ -198,6 +204,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
AllowedScopes = new List<string>{ "api", "openid", "offline_access" },
|
AllowedScopes = new List<string>{ "api", "openid", "offline_access" },
|
||||||
Provider = "IdentityServer",
|
Provider = "IdentityServer",
|
||||||
|
IdentityServerConfig = new FileIdentityServerConfig{
|
||||||
ProviderRootUrl = "http://localhost:51888",
|
ProviderRootUrl = "http://localhost:51888",
|
||||||
RequireHttps = false,
|
RequireHttps = false,
|
||||||
ApiName = "api",
|
ApiName = "api",
|
||||||
@ -205,6 +212,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:51888", "api", AccessTokenType.Jwt))
|
this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:51888", "api", AccessTokenType.Jwt))
|
||||||
|
@ -64,10 +64,12 @@ namespace Ocelot.AcceptanceTests
|
|||||||
"openid", "offline_access", "api"
|
"openid", "offline_access", "api"
|
||||||
},
|
},
|
||||||
Provider = "IdentityServer",
|
Provider = "IdentityServer",
|
||||||
|
IdentityServerConfig = new FileIdentityServerConfig{
|
||||||
ProviderRootUrl = "http://localhost:52888",
|
ProviderRootUrl = "http://localhost:52888",
|
||||||
RequireHttps = false,
|
RequireHttps = false,
|
||||||
ApiName = "api",
|
ApiName = "api",
|
||||||
ApiSecret = "secret",
|
ApiSecret = "secret"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
AddHeadersToRequest =
|
AddHeadersToRequest =
|
||||||
{
|
{
|
||||||
|
@ -64,10 +64,12 @@ namespace Ocelot.AcceptanceTests
|
|||||||
"openid", "offline_access", "api"
|
"openid", "offline_access", "api"
|
||||||
},
|
},
|
||||||
Provider = "IdentityServer",
|
Provider = "IdentityServer",
|
||||||
|
IdentityServerConfig = new FileIdentityServerConfig{
|
||||||
ProviderRootUrl = "http://localhost:57888",
|
ProviderRootUrl = "http://localhost:57888",
|
||||||
RequireHttps = false,
|
RequireHttps = false,
|
||||||
ApiName = "api",
|
ApiName = "api",
|
||||||
ApiSecret = "secret",
|
ApiSecret = "secret"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
AddQueriesToRequest =
|
AddQueriesToRequest =
|
||||||
{
|
{
|
||||||
|
@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Builder;
|
|||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Ocelot.Authentication.JsonConverters;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
using Ocelot.Configuration.File;
|
using Ocelot.Configuration.File;
|
||||||
using Ocelot.Configuration.Repository;
|
using Ocelot.Configuration.Repository;
|
||||||
@ -29,7 +30,6 @@ namespace Ocelot.AcceptanceTests
|
|||||||
_steps = new Steps();
|
_steps = new Steps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_response_200_with_simple_url()
|
public void should_return_response_200_with_simple_url()
|
||||||
{
|
{
|
||||||
@ -105,7 +105,9 @@ namespace Ocelot.AcceptanceTests
|
|||||||
|
|
||||||
var json = reader.ReadToEnd();
|
var json = reader.ReadToEnd();
|
||||||
|
|
||||||
_config = JsonConvert.DeserializeObject<OcelotConfiguration>(json);
|
var settings = new JsonSerializerSettings();
|
||||||
|
settings.Converters.Add(new AuthenticationConfigConverter());
|
||||||
|
_config = JsonConvert.DeserializeObject<OcelotConfiguration>(json, settings);
|
||||||
|
|
||||||
var response = JsonConvert.SerializeObject(true);
|
var response = JsonConvert.SerializeObject(true);
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="configuration.json">
|
<None Update="configuration.json;appsettings.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@ -30,6 +30,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.MiddlewareAnalysis" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-preview-20170106-08" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-preview-20170106-08" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta2-build1317" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta2-build1317" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
|
||||||
|
10
test/Ocelot.AcceptanceTests/appsettings.json
Normal file
10
test/Ocelot.AcceptanceTests/appsettings.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"IncludeScopes": true,
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Error",
|
||||||
|
"System": "Error",
|
||||||
|
"Microsoft": "Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ using System.Net.Http.Headers;
|
|||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Ocelot.Cache;
|
||||||
using Ocelot.Configuration.File;
|
using Ocelot.Configuration.File;
|
||||||
using Ocelot.ManualTest;
|
using Ocelot.ManualTest;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
@ -19,15 +20,19 @@ namespace Ocelot.IntegrationTests
|
|||||||
public class AdministrationTests : IDisposable
|
public class AdministrationTests : IDisposable
|
||||||
{
|
{
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
|
private readonly HttpClient _httpClientTwo;
|
||||||
private HttpResponseMessage _response;
|
private HttpResponseMessage _response;
|
||||||
private IWebHost _builder;
|
private IWebHost _builder;
|
||||||
private IWebHostBuilder _webHostBuilder;
|
private IWebHostBuilder _webHostBuilder;
|
||||||
private readonly string _ocelotBaseUrl;
|
private readonly string _ocelotBaseUrl;
|
||||||
private BearerToken _token;
|
private BearerToken _token;
|
||||||
|
private IWebHostBuilder _webHostBuilderTwo;
|
||||||
|
private IWebHost _builderTwo;
|
||||||
|
|
||||||
public AdministrationTests()
|
public AdministrationTests()
|
||||||
{
|
{
|
||||||
_httpClient = new HttpClient();
|
_httpClient = new HttpClient();
|
||||||
|
_httpClientTwo = new HttpClient();
|
||||||
_ocelotBaseUrl = "http://localhost:5000";
|
_ocelotBaseUrl = "http://localhost:5000";
|
||||||
_httpClient.BaseAddress = new Uri(_ocelotBaseUrl);
|
_httpClient.BaseAddress = new Uri(_ocelotBaseUrl);
|
||||||
}
|
}
|
||||||
@ -70,6 +75,27 @@ namespace Ocelot.IntegrationTests
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_be_able_to_use_token_from_ocelot_a_on_ocelot_b()
|
||||||
|
{
|
||||||
|
var configuration = new FileConfiguration
|
||||||
|
{
|
||||||
|
GlobalConfiguration = new FileGlobalConfiguration
|
||||||
|
{
|
||||||
|
AdministrationPath = "/administration"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => GivenThereIsAConfiguration(configuration))
|
||||||
|
.And(x => GivenIdentityServerSigningEnvironmentalVariablesAreSet())
|
||||||
|
.And(x => GivenOcelotIsRunning())
|
||||||
|
.And(x => GivenIHaveAnOcelotToken("/administration"))
|
||||||
|
.And(x => GivenAnotherOcelotIsRunning("http://localhost:5007"))
|
||||||
|
.When(x => WhenIGetUrlOnTheSecondOcelot("/administration/configuration"))
|
||||||
|
.Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_file_configuration()
|
public void should_return_file_configuration()
|
||||||
{
|
{
|
||||||
@ -95,7 +121,12 @@ namespace Ocelot.IntegrationTests
|
|||||||
DownstreamScheme = "https",
|
DownstreamScheme = "https",
|
||||||
DownstreamPathTemplate = "/",
|
DownstreamPathTemplate = "/",
|
||||||
UpstreamHttpMethod = new List<string> { "get" },
|
UpstreamHttpMethod = new List<string> { "get" },
|
||||||
UpstreamPathTemplate = "/"
|
UpstreamPathTemplate = "/",
|
||||||
|
FileCacheOptions = new FileCacheOptions
|
||||||
|
{
|
||||||
|
TtlSeconds = 10,
|
||||||
|
Region = "Geoff"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
new FileReRoute()
|
new FileReRoute()
|
||||||
{
|
{
|
||||||
@ -104,7 +135,12 @@ namespace Ocelot.IntegrationTests
|
|||||||
DownstreamScheme = "https",
|
DownstreamScheme = "https",
|
||||||
DownstreamPathTemplate = "/",
|
DownstreamPathTemplate = "/",
|
||||||
UpstreamHttpMethod = new List<string> { "get" },
|
UpstreamHttpMethod = new List<string> { "get" },
|
||||||
UpstreamPathTemplate = "/test"
|
UpstreamPathTemplate = "/test",
|
||||||
|
FileCacheOptions = new FileCacheOptions
|
||||||
|
{
|
||||||
|
TtlSeconds = 10,
|
||||||
|
Region = "Dave"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -193,6 +229,87 @@ namespace Ocelot.IntegrationTests
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_clear_region()
|
||||||
|
{
|
||||||
|
var initialConfiguration = new FileConfiguration
|
||||||
|
{
|
||||||
|
GlobalConfiguration = new FileGlobalConfiguration
|
||||||
|
{
|
||||||
|
AdministrationPath = "/administration"
|
||||||
|
},
|
||||||
|
ReRoutes = new List<FileReRoute>()
|
||||||
|
{
|
||||||
|
new FileReRoute()
|
||||||
|
{
|
||||||
|
DownstreamHost = "localhost",
|
||||||
|
DownstreamPort = 80,
|
||||||
|
DownstreamScheme = "https",
|
||||||
|
DownstreamPathTemplate = "/",
|
||||||
|
UpstreamHttpMethod = new List<string> { "get" },
|
||||||
|
UpstreamPathTemplate = "/",
|
||||||
|
FileCacheOptions = new FileCacheOptions
|
||||||
|
{
|
||||||
|
TtlSeconds = 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new FileReRoute()
|
||||||
|
{
|
||||||
|
DownstreamHost = "localhost",
|
||||||
|
DownstreamPort = 80,
|
||||||
|
DownstreamScheme = "https",
|
||||||
|
DownstreamPathTemplate = "/",
|
||||||
|
UpstreamHttpMethod = new List<string> { "get" },
|
||||||
|
UpstreamPathTemplate = "/test",
|
||||||
|
FileCacheOptions = new FileCacheOptions
|
||||||
|
{
|
||||||
|
TtlSeconds = 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var regionToClear = "gettest";
|
||||||
|
|
||||||
|
this.Given(x => GivenThereIsAConfiguration(initialConfiguration))
|
||||||
|
.And(x => GivenOcelotIsRunning())
|
||||||
|
.And(x => GivenIHaveAnOcelotToken("/administration"))
|
||||||
|
.And(x => GivenIHaveAddedATokenToMyRequest())
|
||||||
|
.When(x => WhenIDeleteOnTheApiGateway($"/administration/outputcache/{regionToClear}"))
|
||||||
|
.Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.NoContent))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenAnotherOcelotIsRunning(string baseUrl)
|
||||||
|
{
|
||||||
|
_httpClientTwo.BaseAddress = new Uri(baseUrl);
|
||||||
|
|
||||||
|
_webHostBuilderTwo = new WebHostBuilder()
|
||||||
|
.UseUrls(baseUrl)
|
||||||
|
.UseKestrel()
|
||||||
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
|
.ConfigureServices(x => {
|
||||||
|
x.AddSingleton(_webHostBuilderTwo);
|
||||||
|
})
|
||||||
|
.UseStartup<Startup>();
|
||||||
|
|
||||||
|
_builderTwo = _webHostBuilderTwo.Build();
|
||||||
|
|
||||||
|
_builderTwo.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenIdentityServerSigningEnvironmentalVariablesAreSet()
|
||||||
|
{
|
||||||
|
Environment.SetEnvironmentVariable("OCELOT_CERTIFICATE", "idsrv3test.pfx");
|
||||||
|
Environment.SetEnvironmentVariable("OCELOT_CERTIFICATE_PASSWORD", "idsrv3test");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenIGetUrlOnTheSecondOcelot(string url)
|
||||||
|
{
|
||||||
|
_httpClientTwo.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token.AccessToken);
|
||||||
|
_response = _httpClientTwo.GetAsync(url).Result;
|
||||||
|
}
|
||||||
|
|
||||||
private void WhenIPostOnTheApiGateway(string url, FileConfiguration updatedConfiguration)
|
private void WhenIPostOnTheApiGateway(string url, FileConfiguration updatedConfiguration)
|
||||||
{
|
{
|
||||||
var json = JsonConvert.SerializeObject(updatedConfiguration);
|
var json = JsonConvert.SerializeObject(updatedConfiguration);
|
||||||
@ -201,6 +318,13 @@ namespace Ocelot.IntegrationTests
|
|||||||
_response = _httpClient.PostAsync(url, content).Result;
|
_response = _httpClient.PostAsync(url, content).Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ThenTheResponseShouldBe(List<string> expected)
|
||||||
|
{
|
||||||
|
var content = _response.Content.ReadAsStringAsync().Result;
|
||||||
|
var result = JsonConvert.DeserializeObject<Regions>(content);
|
||||||
|
result.Value.ShouldBe(expected);
|
||||||
|
}
|
||||||
|
|
||||||
private void ThenTheResponseShouldBe(FileConfiguration expected)
|
private void ThenTheResponseShouldBe(FileConfiguration expected)
|
||||||
{
|
{
|
||||||
var response = JsonConvert.DeserializeObject<FileConfiguration>(_response.Content.ReadAsStringAsync().Result);
|
var response = JsonConvert.DeserializeObject<FileConfiguration>(_response.Content.ReadAsStringAsync().Result);
|
||||||
@ -298,6 +422,11 @@ namespace Ocelot.IntegrationTests
|
|||||||
_response = _httpClient.GetAsync(url).Result;
|
_response = _httpClient.GetAsync(url).Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WhenIDeleteOnTheApiGateway(string url)
|
||||||
|
{
|
||||||
|
_response = _httpClient.DeleteAsync(url).Result;
|
||||||
|
}
|
||||||
|
|
||||||
private void ThenTheStatusCodeShouldBe(HttpStatusCode expectedHttpStatusCode)
|
private void ThenTheStatusCodeShouldBe(HttpStatusCode expectedHttpStatusCode)
|
||||||
{
|
{
|
||||||
_response.StatusCode.ShouldBe(expectedHttpStatusCode);
|
_response.StatusCode.ShouldBe(expectedHttpStatusCode);
|
||||||
@ -305,6 +434,8 @@ namespace Ocelot.IntegrationTests
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
Environment.SetEnvironmentVariable("OCELOT_CERTIFICATE", "");
|
||||||
|
Environment.SetEnvironmentVariable("OCELOT_CERTIFICATE_PASSWORD", "");
|
||||||
_builder?.Dispose();
|
_builder?.Dispose();
|
||||||
_httpClient?.Dispose();
|
_httpClient?.Dispose();
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="configuration.json;appsettings.json">
|
<None Update="configuration.json;appsettings.json;idsrv3test.pfx">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@ -30,6 +30,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.MiddlewareAnalysis" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-preview-20170106-08" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-preview-20170106-08" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta2-build1317" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta2-build1317" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.1" />
|
||||||
|
@ -15,7 +15,6 @@ using TestStack.BDDfy;
|
|||||||
using Xunit;
|
using Xunit;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Threading;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
namespace Ocelot.IntegrationTests
|
namespace Ocelot.IntegrationTests
|
||||||
@ -23,11 +22,9 @@ namespace Ocelot.IntegrationTests
|
|||||||
public class ThreadSafeHeadersTests : IDisposable
|
public class ThreadSafeHeadersTests : IDisposable
|
||||||
{
|
{
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
private HttpResponseMessage _response;
|
|
||||||
private IWebHost _builder;
|
private IWebHost _builder;
|
||||||
private IWebHostBuilder _webHostBuilder;
|
private IWebHostBuilder _webHostBuilder;
|
||||||
private readonly string _ocelotBaseUrl;
|
private readonly string _ocelotBaseUrl;
|
||||||
private BearerToken _token;
|
|
||||||
private IWebHost _downstreamBuilder;
|
private IWebHost _downstreamBuilder;
|
||||||
private readonly Random _random;
|
private readonly Random _random;
|
||||||
private readonly ConcurrentBag<ThreadSafeHeadersTestResult> _results;
|
private readonly ConcurrentBag<ThreadSafeHeadersTestResult> _results;
|
||||||
@ -135,7 +132,7 @@ namespace Ocelot.IntegrationTests
|
|||||||
text = File.ReadAllText(configurationPath);
|
text = File.ReadAllText(configurationPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WhenIGetUrlOnTheApiGatewayMultipleTimesWithDifferentHeaderValues(string url, int times)
|
private void WhenIGetUrlOnTheApiGatewayMultipleTimesWithDifferentHeaderValues(string url, int times)
|
||||||
{
|
{
|
||||||
var tasks = new Task[times];
|
var tasks = new Task[times];
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
"IncludeScopes": true,
|
"IncludeScopes": true,
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Error",
|
"Default": "Error",
|
||||||
"System": "Information",
|
"System": "Error",
|
||||||
"Microsoft": "Information"
|
"Microsoft": "Error"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
test/Ocelot.IntegrationTests/idsrv3test.pfx
Normal file
BIN
test/Ocelot.IntegrationTests/idsrv3test.pfx
Normal file
Binary file not shown.
@ -22,6 +22,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.MiddlewareAnalysis" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="1.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Http" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.1" />
|
||||||
|
@ -14,13 +14,16 @@
|
|||||||
},
|
},
|
||||||
"AuthenticationOptions": {
|
"AuthenticationOptions": {
|
||||||
"Provider": "IdentityServer",
|
"Provider": "IdentityServer",
|
||||||
"ProviderRootUrl": "http://localhost:52888",
|
|
||||||
"ApiName": "api",
|
|
||||||
"AllowedScopes": [
|
"AllowedScopes": [
|
||||||
"openid",
|
"openid",
|
||||||
"offline_access"
|
"offline_access"
|
||||||
],
|
],
|
||||||
"ApiSecret": "secret"
|
"IdentityServerConfig": {
|
||||||
|
"ProviderRootUrl": "http://localhost:52888",
|
||||||
|
"ApiName": "api",
|
||||||
|
"ApiSecret": "secret",
|
||||||
|
"RequireHttps": false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"AddHeadersToRequest": {
|
"AddHeadersToRequest": {
|
||||||
"CustomerId": "Claims[CustomerId] > value",
|
"CustomerId": "Claims[CustomerId] > value",
|
||||||
|
@ -31,17 +31,19 @@ namespace Ocelot.UnitTests.Authentication
|
|||||||
_authenticationHandlerFactory = new AuthenticationHandlerFactory(_creator.Object);
|
_authenticationHandlerFactory = new AuthenticationHandlerFactory(_creator.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Theory]
|
||||||
public void should_return_identity_server_access_token_handler()
|
[InlineData("IdentityServer")]
|
||||||
|
[InlineData("Jwt")]
|
||||||
|
public void should_return_access_token_handler(string provider)
|
||||||
{
|
{
|
||||||
var authenticationOptions = new AuthenticationOptionsBuilder()
|
var authenticationOptions = new AuthenticationOptionsBuilder()
|
||||||
.WithProvider("IdentityServer")
|
.WithProvider(provider)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenTheAuthenticationOptionsAre(authenticationOptions))
|
this.Given(x => x.GivenTheAuthenticationOptionsAre(authenticationOptions))
|
||||||
.And(x => x.GivenTheCreatorReturns())
|
.And(x => x.GivenTheCreatorReturns())
|
||||||
.When(x => x.WhenIGetFromTheFactory())
|
.When(x => x.WhenIGetFromTheFactory())
|
||||||
.Then(x => x.ThenTheHandlerIsReturned("IdentityServer"))
|
.Then(x => x.ThenTheHandlerIsReturned(provider))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,60 +1,55 @@
|
|||||||
using System;
|
namespace Ocelot.UnitTests.Authentication
|
||||||
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Net.Http;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Authentication.Handler;
|
|
||||||
using Ocelot.Authentication.Handler.Factory;
|
using Ocelot.Authentication.Handler.Factory;
|
||||||
using Ocelot.Authentication.Middleware;
|
using Ocelot.Authentication.Middleware;
|
||||||
using Ocelot.Cache.Middleware;
|
|
||||||
using Ocelot.Configuration;
|
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.DownstreamRouteFinder;
|
using Ocelot.DownstreamRouteFinder;
|
||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
using Ocelot.Infrastructure.RequestData;
|
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Authentication
|
public class AuthenticationMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
{
|
||||||
public class AuthenticationMiddlewareTests : IDisposable
|
|
||||||
{
|
|
||||||
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
|
|
||||||
private readonly Mock<IAuthenticationHandlerFactory> _authFactory;
|
private readonly Mock<IAuthenticationHandlerFactory> _authFactory;
|
||||||
private readonly string _url;
|
|
||||||
private readonly TestServer _server;
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private HttpResponseMessage _result;
|
|
||||||
private OkResponse<DownstreamRoute> _downstreamRoute;
|
private OkResponse<DownstreamRoute> _downstreamRoute;
|
||||||
|
|
||||||
public AuthenticationMiddlewareTests()
|
public AuthenticationMiddlewareTests()
|
||||||
{
|
{
|
||||||
_url = "http://localhost:51879";
|
|
||||||
_scopedRepository = new Mock<IRequestScopedDataRepository>();
|
|
||||||
_authFactory = new Mock<IAuthenticationHandlerFactory>();
|
_authFactory = new Mock<IAuthenticationHandlerFactory>();
|
||||||
var builder = new WebHostBuilder()
|
|
||||||
.ConfigureServices(x =>
|
GivenTheTestServerIsConfigured();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_call_next_middleware_if_route_is_not_authenticated()
|
||||||
{
|
{
|
||||||
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||||
x.AddLogging();
|
new DownstreamRoute(
|
||||||
x.AddSingleton(_authFactory.Object);
|
new List<UrlPathPlaceholderNameAndValue>(),
|
||||||
x.AddSingleton(_scopedRepository.Object);
|
new ReRouteBuilder().WithUpstreamHttpMethod(new List<string> { "Get" }).Build())))
|
||||||
})
|
.When(x => x.WhenICallTheMiddleware())
|
||||||
.UseUrls(_url)
|
.Then(x => x.ThenTheUserIsAuthenticated())
|
||||||
.UseKestrel()
|
.BDDfy();
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
}
|
||||||
.UseIISIntegration()
|
|
||||||
.UseUrls(_url)
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
.Configure(app =>
|
{
|
||||||
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
|
services.AddLogging();
|
||||||
|
services.AddSingleton(_authFactory.Object);
|
||||||
|
services.AddSingleton(ScopedRepository.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
{
|
{
|
||||||
app.UseAuthenticationMiddleware();
|
app.UseAuthenticationMiddleware();
|
||||||
|
|
||||||
@ -62,47 +57,20 @@ namespace Ocelot.UnitTests.Authentication
|
|||||||
{
|
{
|
||||||
await x.Response.WriteAsync("The user is authenticated");
|
await x.Response.WriteAsync("The user is authenticated");
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
_server = new TestServer(builder);
|
|
||||||
_client = _server.CreateClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void should_call_next_middleware_if_route_is_not_authenticated()
|
|
||||||
{
|
|
||||||
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder()
|
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
|
||||||
.Build())))
|
|
||||||
.When(x => x.WhenICallTheMiddleware())
|
|
||||||
.Then(x => x.ThenTheUserIsAuthenticated())
|
|
||||||
.BDDfy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheUserIsAuthenticated()
|
private void ThenTheUserIsAuthenticated()
|
||||||
{
|
{
|
||||||
var content = _result.Content.ReadAsStringAsync().Result;
|
var content = ResponseMessage.Content.ReadAsStringAsync().Result;
|
||||||
content.ShouldBe("The user is authenticated");
|
content.ShouldBe("The user is authenticated");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||||
{
|
{
|
||||||
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
||||||
.Returns(_downstreamRoute);
|
.Returns(_downstreamRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
|
||||||
{
|
|
||||||
_result = _client.GetAsync(_url).Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_client.Dispose();
|
|
||||||
_server.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,66 +1,32 @@
|
|||||||
using System;
|
namespace Ocelot.UnitTests.Authorization
|
||||||
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Authorisation;
|
using Ocelot.Authorisation;
|
||||||
|
using Ocelot.Authorisation.Middleware;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.DownstreamRouteFinder;
|
using Ocelot.DownstreamRouteFinder;
|
||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
using Ocelot.Infrastructure.RequestData;
|
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Authorization
|
public class AuthorisationMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
{
|
||||||
using Authorisation.Middleware;
|
|
||||||
|
|
||||||
public class AuthorisationMiddlewareTests : IDisposable
|
|
||||||
{
|
|
||||||
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
|
|
||||||
private readonly Mock<IClaimsAuthoriser> _authService;
|
private readonly Mock<IClaimsAuthoriser> _authService;
|
||||||
private readonly Mock<IScopesAuthoriser> _authScopesService;
|
private readonly Mock<IScopesAuthoriser> _authScopesService;
|
||||||
private readonly string _url;
|
|
||||||
private readonly TestServer _server;
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private HttpResponseMessage _result;
|
|
||||||
private OkResponse<DownstreamRoute> _downstreamRoute;
|
private OkResponse<DownstreamRoute> _downstreamRoute;
|
||||||
|
|
||||||
public AuthorisationMiddlewareTests()
|
public AuthorisationMiddlewareTests()
|
||||||
{
|
{
|
||||||
_url = "http://localhost:51879";
|
|
||||||
_scopedRepository = new Mock<IRequestScopedDataRepository>();
|
|
||||||
_authService = new Mock<IClaimsAuthoriser>();
|
_authService = new Mock<IClaimsAuthoriser>();
|
||||||
_authScopesService = new Mock<IScopesAuthoriser>();
|
_authScopesService = new Mock<IScopesAuthoriser>();
|
||||||
|
|
||||||
var builder = new WebHostBuilder()
|
GivenTheTestServerIsConfigured();
|
||||||
.ConfigureServices(x =>
|
|
||||||
{
|
|
||||||
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
|
||||||
x.AddLogging();
|
|
||||||
x.AddSingleton(_authService.Object);
|
|
||||||
x.AddSingleton(_authScopesService.Object);
|
|
||||||
x.AddSingleton(_scopedRepository.Object);
|
|
||||||
})
|
|
||||||
.UseUrls(_url)
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.UseIISIntegration()
|
|
||||||
.UseUrls(_url)
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseAuthorisationMiddleware();
|
|
||||||
});
|
|
||||||
|
|
||||||
_server = new TestServer(builder);
|
|
||||||
_client = _server.CreateClient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -77,6 +43,28 @@ namespace Ocelot.UnitTests.Authorization
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
|
services.AddLogging();
|
||||||
|
services.AddSingleton(_authService.Object);
|
||||||
|
services.AddSingleton(_authScopesService.Object);
|
||||||
|
services.AddSingleton(ScopedRepository.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseAuthorisationMiddleware();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||||
|
{
|
||||||
|
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||||
|
ScopedRepository
|
||||||
|
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
||||||
|
.Returns(_downstreamRoute);
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheAuthServiceReturns(Response<bool> expected)
|
private void GivenTheAuthServiceReturns(Response<bool> expected)
|
||||||
{
|
{
|
||||||
_authService
|
_authService
|
||||||
@ -90,25 +78,5 @@ namespace Ocelot.UnitTests.Authorization
|
|||||||
.Verify(x => x.Authorise(It.IsAny<ClaimsPrincipal>(),
|
.Verify(x => x.Authorise(It.IsAny<ClaimsPrincipal>(),
|
||||||
It.IsAny<Dictionary<string, string>>()), Times.Once);
|
It.IsAny<Dictionary<string, string>>()), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
|
||||||
{
|
|
||||||
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
|
||||||
_scopedRepository
|
|
||||||
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
|
||||||
.Returns(_downstreamRoute);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
|
||||||
{
|
|
||||||
_result = _client.GetAsync(_url).Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_client.Dispose();
|
|
||||||
_server.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,20 +16,21 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
private string _value;
|
private string _value;
|
||||||
private string _resultGet;
|
private string _resultGet;
|
||||||
private TimeSpan _ttlSeconds;
|
private TimeSpan _ttlSeconds;
|
||||||
|
private string _region;
|
||||||
|
|
||||||
public CacheManagerCacheTests()
|
public CacheManagerCacheTests()
|
||||||
{
|
{
|
||||||
_mockCacheManager = new Mock<ICacheManager<string>>();
|
_mockCacheManager = new Mock<ICacheManager<string>>();
|
||||||
_ocelotOcelotCacheManager = new OcelotCacheManagerCache<string>(_mockCacheManager.Object);
|
_ocelotOcelotCacheManager = new OcelotCacheManagerCache<string>(_mockCacheManager.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_get_from_cache()
|
public void should_get_from_cache()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenTheFollowingIsCached("someKey", "someValue"))
|
this.Given(x => x.GivenTheFollowingIsCached("someKey", "someRegion", "someValue"))
|
||||||
.When(x => x.WhenIGetFromTheCache())
|
.When(x => x.WhenIGetFromTheCache())
|
||||||
.Then(x => x.ThenTheResultIs("someValue"))
|
.Then(x => x.ThenTheResultIs("someValue"))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -40,13 +41,37 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_delete_key_from_cache()
|
||||||
|
{
|
||||||
|
this.Given(_ => GivenTheFollowingRegion("fookey"))
|
||||||
|
.When(_ => WhenIDeleteTheRegion("fookey"))
|
||||||
|
.Then(_ => ThenTheRegionIsDeleted("fookey"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenIDeleteTheRegion(string region)
|
||||||
|
{
|
||||||
|
_ocelotOcelotCacheManager.ClearRegion(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheRegionIsDeleted(string region)
|
||||||
|
{
|
||||||
|
_mockCacheManager
|
||||||
|
.Verify(x => x.ClearRegion(region), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheFollowingRegion(string key)
|
||||||
|
{
|
||||||
|
_ocelotOcelotCacheManager.Add(key, "doesnt matter", TimeSpan.FromSeconds(10), "region");
|
||||||
|
}
|
||||||
|
|
||||||
private void WhenIAddToTheCache(string key, string value, TimeSpan ttlSeconds)
|
private void WhenIAddToTheCache(string key, string value, TimeSpan ttlSeconds)
|
||||||
{
|
{
|
||||||
_key = key;
|
_key = key;
|
||||||
_value = value;
|
_value = value;
|
||||||
_ttlSeconds = ttlSeconds;
|
_ttlSeconds = ttlSeconds;
|
||||||
|
_ocelotOcelotCacheManager.Add(_key, _value, _ttlSeconds, "region");
|
||||||
_ocelotOcelotCacheManager.Add(_key, _value, _ttlSeconds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheCacheIsCalledCorrectly()
|
private void ThenTheCacheIsCalledCorrectly()
|
||||||
@ -62,15 +87,16 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
|
|
||||||
private void WhenIGetFromTheCache()
|
private void WhenIGetFromTheCache()
|
||||||
{
|
{
|
||||||
_resultGet = _ocelotOcelotCacheManager.Get(_key);
|
_resultGet = _ocelotOcelotCacheManager.Get(_key, _region);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheFollowingIsCached(string key, string value)
|
private void GivenTheFollowingIsCached(string key, string region, string value)
|
||||||
{
|
{
|
||||||
_key = key;
|
_key = key;
|
||||||
_value = value;
|
_value = value;
|
||||||
|
_region = region;
|
||||||
_mockCacheManager
|
_mockCacheManager
|
||||||
.Setup(x => x.Get<string>(It.IsAny<string>()))
|
.Setup(x => x.Get<string>(It.IsAny<string>(), It.IsAny<string>()))
|
||||||
.Returns(value);
|
.Returns(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
using System;
|
namespace Ocelot.UnitTests.Cache
|
||||||
|
{
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Cache;
|
using Ocelot.Cache;
|
||||||
@ -12,54 +12,25 @@ using Ocelot.Configuration;
|
|||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.DownstreamRouteFinder;
|
using Ocelot.DownstreamRouteFinder;
|
||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
using Ocelot.Infrastructure.RequestData;
|
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Cache
|
public class OutputCacheMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
|
||||||
public class OutputCacheMiddlewareTests
|
|
||||||
{
|
{
|
||||||
private readonly Mock<IOcelotCache<HttpResponseMessage>> _cacheManager;
|
private readonly Mock<IOcelotCache<HttpResponseMessage>> _cacheManager;
|
||||||
private readonly Mock<IRequestScopedDataRepository> _scopedRepo;
|
|
||||||
private readonly string _url;
|
|
||||||
private readonly TestServer _server;
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private HttpResponseMessage _result;
|
|
||||||
private HttpResponseMessage _response;
|
private HttpResponseMessage _response;
|
||||||
|
|
||||||
public OutputCacheMiddlewareTests()
|
public OutputCacheMiddlewareTests()
|
||||||
{
|
{
|
||||||
_cacheManager = new Mock<IOcelotCache<HttpResponseMessage>>();
|
_cacheManager = new Mock<IOcelotCache<HttpResponseMessage>>();
|
||||||
_scopedRepo = new Mock<IRequestScopedDataRepository>();
|
|
||||||
|
|
||||||
_url = "http://localhost:51879";
|
ScopedRepository
|
||||||
var builder = new WebHostBuilder()
|
|
||||||
.ConfigureServices(x =>
|
|
||||||
{
|
|
||||||
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
|
||||||
x.AddLogging();
|
|
||||||
x.AddSingleton(_cacheManager.Object);
|
|
||||||
x.AddSingleton(_scopedRepo.Object);
|
|
||||||
})
|
|
||||||
.UseUrls(_url)
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.UseIISIntegration()
|
|
||||||
.UseUrls(_url)
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseOutputCacheMiddleware();
|
|
||||||
});
|
|
||||||
|
|
||||||
_scopedRepo
|
|
||||||
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
||||||
.Returns(new OkResponse<HttpRequestMessage>(new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123")));
|
.Returns(new OkResponse<HttpRequestMessage>(new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123")));
|
||||||
|
|
||||||
_server = new TestServer(builder);
|
GivenTheTestServerIsConfigured();
|
||||||
_client = _server.CreateClient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -85,32 +56,60 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
|
services.AddLogging();
|
||||||
|
services.AddSingleton(_cacheManager.Object);
|
||||||
|
services.AddSingleton(ScopedRepository.Object);
|
||||||
|
services.AddSingleton<IRegionCreator, RegionCreator>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseOutputCacheMiddleware();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenThereIsACachedResponse(HttpResponseMessage response)
|
||||||
|
{
|
||||||
|
_response = response;
|
||||||
|
_cacheManager
|
||||||
|
.Setup(x => x.Get(It.IsAny<string>(), It.IsAny<string>()))
|
||||||
|
.Returns(_response);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenResponseIsNotCached()
|
||||||
|
{
|
||||||
|
ScopedRepository
|
||||||
|
.Setup(x => x.Get<HttpResponseMessage>("HttpResponseMessage"))
|
||||||
|
.Returns(new OkResponse<HttpResponseMessage>(new HttpResponseMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheDownstreamRouteIs()
|
private void GivenTheDownstreamRouteIs()
|
||||||
{
|
{
|
||||||
var reRoute = new ReRouteBuilder()
|
var reRoute = new ReRouteBuilder()
|
||||||
.WithIsCached(true)
|
.WithIsCached(true)
|
||||||
.WithCacheOptions(new CacheOptions(100))
|
.WithCacheOptions(new CacheOptions(100, "kanken"))
|
||||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), reRoute);
|
var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), reRoute);
|
||||||
|
|
||||||
_scopedRepo
|
ScopedRepository
|
||||||
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
||||||
.Returns(new OkResponse<DownstreamRoute>(downstreamRoute));
|
.Returns(new OkResponse<DownstreamRoute>(downstreamRoute));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenThereAreNoErrors()
|
private void GivenThereAreNoErrors()
|
||||||
{
|
{
|
||||||
_scopedRepo
|
ScopedRepository
|
||||||
.Setup(x => x.Get<bool>("OcelotMiddlewareError"))
|
.Setup(x => x.Get<bool>("OcelotMiddlewareError"))
|
||||||
.Returns(new OkResponse<bool>(false));
|
.Returns(new OkResponse<bool>(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenThereIsADownstreamUrl()
|
private void GivenThereIsADownstreamUrl()
|
||||||
{
|
{
|
||||||
_scopedRepo
|
ScopedRepository
|
||||||
.Setup(x => x.Get<string>("DownstreamUrl"))
|
.Setup(x => x.Get<string>("DownstreamUrl"))
|
||||||
.Returns(new OkResponse<string>("anything"));
|
.Returns(new OkResponse<string>("anything"));
|
||||||
}
|
}
|
||||||
@ -118,33 +117,13 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
private void ThenTheCacheGetIsCalledCorrectly()
|
private void ThenTheCacheGetIsCalledCorrectly()
|
||||||
{
|
{
|
||||||
_cacheManager
|
_cacheManager
|
||||||
.Verify(x => x.Get(It.IsAny<string>()), Times.Once);
|
.Verify(x => x.Get(It.IsAny<string>(), It.IsAny<string>()), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheCacheAddIsCalledCorrectly()
|
private void ThenTheCacheAddIsCalledCorrectly()
|
||||||
{
|
{
|
||||||
_cacheManager
|
_cacheManager
|
||||||
.Verify(x => x.Add(It.IsAny<string>(), It.IsAny<HttpResponseMessage>(), It.IsAny<TimeSpan>()), Times.Once);
|
.Verify(x => x.Add(It.IsAny<string>(), It.IsAny<HttpResponseMessage>(), It.IsAny<TimeSpan>(), It.IsAny<string>()), Times.Once);
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenResponseIsNotCached()
|
|
||||||
{
|
|
||||||
_scopedRepo
|
|
||||||
.Setup(x => x.Get<HttpResponseMessage>("HttpResponseMessage"))
|
|
||||||
.Returns(new OkResponse<HttpResponseMessage>(new HttpResponseMessage()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenThereIsACachedResponse(HttpResponseMessage response)
|
|
||||||
{
|
|
||||||
_response = response;
|
|
||||||
_cacheManager
|
|
||||||
.Setup(x => x.Get(It.IsAny<string>()))
|
|
||||||
.Returns(_response);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
|
||||||
{
|
|
||||||
_result = _client.GetAsync(_url).Result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
65
test/Ocelot.UnitTests/Cache/RegionCreatorTests.cs
Normal file
65
test/Ocelot.UnitTests/Cache/RegionCreatorTests.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Ocelot.Cache;
|
||||||
|
using Ocelot.Configuration;
|
||||||
|
using Ocelot.Configuration.Builder;
|
||||||
|
using Ocelot.Configuration.File;
|
||||||
|
using Shouldly;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Ocelot.UnitTests.Cache
|
||||||
|
{
|
||||||
|
public class RegionCreatorTests
|
||||||
|
{
|
||||||
|
private string _result;
|
||||||
|
private FileReRoute _reRoute;
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_create_region()
|
||||||
|
{
|
||||||
|
var reRoute = new FileReRoute
|
||||||
|
{
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
UpstreamPathTemplate = "/testdummy"
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(_ => GivenTheReRoute(reRoute))
|
||||||
|
.When(_ => WhenICreateTheRegion())
|
||||||
|
.Then(_ => ThenTheRegionIs("Gettestdummy"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_use_region()
|
||||||
|
{
|
||||||
|
var reRoute = new FileReRoute
|
||||||
|
{
|
||||||
|
FileCacheOptions = new FileCacheOptions
|
||||||
|
{
|
||||||
|
Region = "region"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(_ => GivenTheReRoute(reRoute))
|
||||||
|
.When(_ => WhenICreateTheRegion())
|
||||||
|
.Then(_ => ThenTheRegionIs("region"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheReRoute(FileReRoute reRoute)
|
||||||
|
{
|
||||||
|
_reRoute = reRoute;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenICreateTheRegion()
|
||||||
|
{
|
||||||
|
RegionCreator regionCreator = new RegionCreator();
|
||||||
|
_result = regionCreator.Create(_reRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheRegionIs(string expected)
|
||||||
|
{
|
||||||
|
_result.ShouldBe(expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,65 +1,31 @@
|
|||||||
using System;
|
namespace Ocelot.UnitTests.Claims
|
||||||
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using System.Net.Http;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Cache.Middleware;
|
|
||||||
using Ocelot.Claims;
|
using Ocelot.Claims;
|
||||||
using Ocelot.Claims.Middleware;
|
using Ocelot.Claims.Middleware;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.DownstreamRouteFinder;
|
using Ocelot.DownstreamRouteFinder;
|
||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
using Ocelot.Infrastructure.RequestData;
|
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Claims
|
public class ClaimsBuilderMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
{
|
||||||
public class ClaimsBuilderMiddlewareTests : IDisposable
|
|
||||||
{
|
|
||||||
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
|
|
||||||
private readonly Mock<IAddClaimsToRequest> _addHeaders;
|
private readonly Mock<IAddClaimsToRequest> _addHeaders;
|
||||||
private readonly string _url;
|
|
||||||
private readonly TestServer _server;
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private Response<DownstreamRoute> _downstreamRoute;
|
private Response<DownstreamRoute> _downstreamRoute;
|
||||||
private HttpResponseMessage _result;
|
|
||||||
|
|
||||||
public ClaimsBuilderMiddlewareTests()
|
public ClaimsBuilderMiddlewareTests()
|
||||||
{
|
{
|
||||||
_url = "http://localhost:51879";
|
|
||||||
_scopedRepository = new Mock<IRequestScopedDataRepository>();
|
|
||||||
_addHeaders = new Mock<IAddClaimsToRequest>();
|
_addHeaders = new Mock<IAddClaimsToRequest>();
|
||||||
|
|
||||||
var builder = new WebHostBuilder()
|
GivenTheTestServerIsConfigured();
|
||||||
.ConfigureServices(x =>
|
|
||||||
{
|
|
||||||
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
|
||||||
|
|
||||||
x.AddLogging();
|
|
||||||
x.AddSingleton(_addHeaders.Object);
|
|
||||||
x.AddSingleton(_scopedRepository.Object);
|
|
||||||
})
|
|
||||||
.UseUrls(_url)
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.UseIISIntegration()
|
|
||||||
.UseUrls(_url)
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseClaimsBuilderMiddleware();
|
|
||||||
});
|
|
||||||
|
|
||||||
_server = new TestServer(builder);
|
|
||||||
_client = _server.CreateClient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -82,6 +48,27 @@ namespace Ocelot.UnitTests.Claims
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
|
services.AddLogging();
|
||||||
|
services.AddSingleton(_addHeaders.Object);
|
||||||
|
services.AddSingleton(ScopedRepository.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseClaimsBuilderMiddleware();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||||
|
{
|
||||||
|
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||||
|
ScopedRepository
|
||||||
|
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
||||||
|
.Returns(_downstreamRoute);
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheAddClaimsToRequestReturns()
|
private void GivenTheAddClaimsToRequestReturns()
|
||||||
{
|
{
|
||||||
_addHeaders
|
_addHeaders
|
||||||
@ -96,24 +83,5 @@ namespace Ocelot.UnitTests.Claims
|
|||||||
.Verify(x => x.SetClaimsOnContext(It.IsAny<List<ClaimToThing>>(),
|
.Verify(x => x.SetClaimsOnContext(It.IsAny<List<ClaimToThing>>(),
|
||||||
It.IsAny<HttpContext>()), Times.Once);
|
It.IsAny<HttpContext>()), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
|
||||||
{
|
|
||||||
_result = _client.GetAsync(_url).Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
|
||||||
{
|
|
||||||
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
|
||||||
_scopedRepository
|
|
||||||
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
|
||||||
.Returns(_downstreamRoute);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_client.Dispose();
|
|
||||||
_server.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,13 +11,13 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
{
|
{
|
||||||
public class AuthenticationOptionsCreatorTests
|
public class AuthenticationOptionsCreatorTests
|
||||||
{
|
{
|
||||||
private AuthenticationOptionsCreator _authOptionsCreator;
|
private readonly AuthenticationOptionsCreator _authOptionsCreator;
|
||||||
private FileReRoute _fileReRoute;
|
private FileReRoute _fileReRoute;
|
||||||
private AuthenticationOptions _result;
|
private AuthenticationOptions _result;
|
||||||
|
|
||||||
public AuthenticationOptionsCreatorTests()
|
public AuthenticationOptionsCreatorTests()
|
||||||
{
|
{
|
||||||
_authOptionsCreator = new AuthenticationOptionsCreator();
|
_authOptionsCreator = new AuthenticationOptionsCreator(new AuthenticationProviderConfigCreator());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -28,26 +28,68 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
AuthenticationOptions = new FileAuthenticationOptions
|
AuthenticationOptions = new FileAuthenticationOptions
|
||||||
{
|
{
|
||||||
Provider = "Geoff",
|
Provider = "Geoff",
|
||||||
|
IdentityServerConfig = new FileIdentityServerConfig()
|
||||||
|
{
|
||||||
ProviderRootUrl = "http://www.bbc.co.uk/",
|
ProviderRootUrl = "http://www.bbc.co.uk/",
|
||||||
ApiName = "Laura",
|
ApiName = "Laura",
|
||||||
RequireHttps = true,
|
RequireHttps = true,
|
||||||
AllowedScopes = new List<string> {"cheese"},
|
|
||||||
ApiSecret = "secret"
|
ApiSecret = "secret"
|
||||||
|
},
|
||||||
|
AllowedScopes = new List<string> { "cheese" },
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var authenticationConfig = new IdentityServerConfigBuilder()
|
||||||
|
.WithProviderRootUrl(fileReRoute.AuthenticationOptions?.IdentityServerConfig?.ProviderRootUrl)
|
||||||
|
.WithApiName(fileReRoute.AuthenticationOptions?.IdentityServerConfig?.ApiName)
|
||||||
|
.WithRequireHttps(fileReRoute.AuthenticationOptions.IdentityServerConfig.RequireHttps)
|
||||||
|
.WithApiSecret(fileReRoute.AuthenticationOptions?.IdentityServerConfig?.ApiSecret)
|
||||||
|
.Build();
|
||||||
|
|
||||||
var expected = new AuthenticationOptionsBuilder()
|
var expected = new AuthenticationOptionsBuilder()
|
||||||
.WithProvider(fileReRoute.AuthenticationOptions?.Provider)
|
.WithProvider(fileReRoute.AuthenticationOptions?.Provider)
|
||||||
.WithProviderRootUrl(fileReRoute.AuthenticationOptions?.ProviderRootUrl)
|
|
||||||
.WithApiName(fileReRoute.AuthenticationOptions?.ApiName)
|
|
||||||
.WithRequireHttps(fileReRoute.AuthenticationOptions.RequireHttps)
|
|
||||||
.WithAllowedScopes(fileReRoute.AuthenticationOptions?.AllowedScopes)
|
.WithAllowedScopes(fileReRoute.AuthenticationOptions?.AllowedScopes)
|
||||||
.WithApiSecret(fileReRoute.AuthenticationOptions?.ApiSecret)
|
.WithConfig(authenticationConfig)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.Given(x => x.GivenTheFollowing(fileReRoute))
|
this.Given(x => x.GivenTheFollowing(fileReRoute))
|
||||||
.When(x => x.WhenICreateTheAuthenticationOptions())
|
.When(x => x.WhenICreateTheAuthenticationOptions())
|
||||||
.Then(x => x.ThenTheFollowingIsReturned(expected))
|
.Then(x => x.ThenTheFollowingIdentityServerConfigIsReturned(expected))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_Jwt_auth_options()
|
||||||
|
{
|
||||||
|
var fileReRoute = new FileReRoute()
|
||||||
|
{
|
||||||
|
AuthenticationOptions = new FileAuthenticationOptions
|
||||||
|
{
|
||||||
|
Provider = "Jwt",
|
||||||
|
JwtConfig = new FileJwtConfig()
|
||||||
|
{
|
||||||
|
Audience = "Audience",
|
||||||
|
Authority = "Authority"
|
||||||
|
},
|
||||||
|
AllowedScopes = new List<string> { "cheese" }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var authenticationConfig = new JwtConfigBuilder()
|
||||||
|
.WithAudience(fileReRoute.AuthenticationOptions?.JwtConfig?.Audience)
|
||||||
|
.WithAuthority(fileReRoute.AuthenticationOptions?.JwtConfig?.Authority)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var expected = new AuthenticationOptionsBuilder()
|
||||||
|
.WithProvider(fileReRoute.AuthenticationOptions?.Provider)
|
||||||
|
.WithAllowedScopes(fileReRoute.AuthenticationOptions?.AllowedScopes)
|
||||||
|
.WithConfig(authenticationConfig)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
this.Given(x => x.GivenTheFollowing(fileReRoute))
|
||||||
|
.When(x => x.WhenICreateTheAuthenticationOptions())
|
||||||
|
.Then(x => x.ThenTheFollowingJwtConfigIsReturned(expected))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,14 +103,31 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
_result = _authOptionsCreator.Create(_fileReRoute);
|
_result = _authOptionsCreator.Create(_fileReRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheFollowingIsReturned(AuthenticationOptions expected)
|
private void ThenTheFollowingJwtConfigIsReturned(AuthenticationOptions expected)
|
||||||
{
|
{
|
||||||
_result.AllowedScopes.ShouldBe(expected.AllowedScopes);
|
_result.AllowedScopes.ShouldBe(expected.AllowedScopes);
|
||||||
_result.Provider.ShouldBe(expected.Provider);
|
_result.Provider.ShouldBe(expected.Provider);
|
||||||
_result.ProviderRootUrl.ShouldBe(expected.ProviderRootUrl);
|
|
||||||
_result.RequireHttps.ShouldBe(expected.RequireHttps);
|
var _resultSettings = _result.Config as JwtConfig;
|
||||||
_result.ApiName.ShouldBe(expected.ApiName);
|
var expectedSettngs = expected.Config as JwtConfig;
|
||||||
_result.ApiSecret.ShouldBe(expected.ApiSecret);
|
|
||||||
|
_resultSettings.Audience.ShouldBe(expectedSettngs.Audience);
|
||||||
|
_resultSettings.Authority.ShouldBe(expectedSettngs.Authority);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheFollowingIdentityServerConfigIsReturned(AuthenticationOptions expected)
|
||||||
|
{
|
||||||
|
_result.AllowedScopes.ShouldBe(expected.AllowedScopes);
|
||||||
|
_result.Provider.ShouldBe(expected.Provider);
|
||||||
|
|
||||||
|
var _resultSettings = _result.Config as IdentityServerConfig;
|
||||||
|
var expectedSettngs = expected.Config as IdentityServerConfig;
|
||||||
|
|
||||||
|
_resultSettings.ProviderRootUrl.ShouldBe(expectedSettngs.ProviderRootUrl);
|
||||||
|
_resultSettings.RequireHttps.ShouldBe(expectedSettngs.RequireHttps);
|
||||||
|
_resultSettings.ApiName.ShouldBe(expectedSettngs.ApiName);
|
||||||
|
_resultSettings.ApiSecret.ShouldBe(expectedSettngs.ApiSecret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
using Ocelot.Cache;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.Configuration.Creator;
|
using Ocelot.Configuration.Creator;
|
||||||
@ -17,6 +18,10 @@ using Xunit;
|
|||||||
|
|
||||||
namespace Ocelot.UnitTests.Configuration
|
namespace Ocelot.UnitTests.Configuration
|
||||||
{
|
{
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
using Ocelot.UnitTests.TestData;
|
||||||
|
|
||||||
public class FileConfigurationCreatorTests
|
public class FileConfigurationCreatorTests
|
||||||
{
|
{
|
||||||
private readonly Mock<IOptions<FileConfiguration>> _fileConfig;
|
private readonly Mock<IOptions<FileConfiguration>> _fileConfig;
|
||||||
@ -39,6 +44,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
private Mock<IQoSOptionsCreator> _qosOptionsCreator;
|
private Mock<IQoSOptionsCreator> _qosOptionsCreator;
|
||||||
private Mock<IReRouteOptionsCreator> _fileReRouteOptionsCreator;
|
private Mock<IReRouteOptionsCreator> _fileReRouteOptionsCreator;
|
||||||
private Mock<IRateLimitOptionsCreator> _rateLimitOptions;
|
private Mock<IRateLimitOptionsCreator> _rateLimitOptions;
|
||||||
|
private Mock<IRegionCreator> _regionCreator;
|
||||||
|
|
||||||
public FileConfigurationCreatorTests()
|
public FileConfigurationCreatorTests()
|
||||||
{
|
{
|
||||||
@ -59,6 +65,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
_qosOptionsCreator = new Mock<IQoSOptionsCreator>();
|
_qosOptionsCreator = new Mock<IQoSOptionsCreator>();
|
||||||
_fileReRouteOptionsCreator = new Mock<IReRouteOptionsCreator>();
|
_fileReRouteOptionsCreator = new Mock<IReRouteOptionsCreator>();
|
||||||
_rateLimitOptions = new Mock<IRateLimitOptionsCreator>();
|
_rateLimitOptions = new Mock<IRateLimitOptionsCreator>();
|
||||||
|
_regionCreator = new Mock<IRegionCreator>();
|
||||||
|
|
||||||
_ocelotConfigurationCreator = new FileOcelotConfigurationCreator(
|
_ocelotConfigurationCreator = new FileOcelotConfigurationCreator(
|
||||||
_fileConfig.Object, _validator.Object, _logger.Object,
|
_fileConfig.Object, _validator.Object, _logger.Object,
|
||||||
@ -66,7 +73,51 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
_qosProviderFactory.Object, _qosProviderHouse.Object, _claimsToThingCreator.Object,
|
_qosProviderFactory.Object, _qosProviderHouse.Object, _claimsToThingCreator.Object,
|
||||||
_authOptionsCreator.Object, _upstreamTemplatePatternCreator.Object, _requestIdKeyCreator.Object,
|
_authOptionsCreator.Object, _upstreamTemplatePatternCreator.Object, _requestIdKeyCreator.Object,
|
||||||
_serviceProviderConfigCreator.Object, _qosOptionsCreator.Object, _fileReRouteOptionsCreator.Object,
|
_serviceProviderConfigCreator.Object, _qosOptionsCreator.Object, _fileReRouteOptionsCreator.Object,
|
||||||
_rateLimitOptions.Object);
|
_rateLimitOptions.Object, _regionCreator.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_call_region_creator()
|
||||||
|
{
|
||||||
|
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
DownstreamHost = "127.0.0.1",
|
||||||
|
UpstreamPathTemplate = "/api/products/{productId}",
|
||||||
|
DownstreamPathTemplate = "/products/{productId}",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
FileCacheOptions = new FileCacheOptions
|
||||||
|
{
|
||||||
|
Region = "region"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
||||||
|
.And(x => x.GivenTheConfigIsValid())
|
||||||
|
.And(x => x.GivenTheFollowingRegionIsReturned("region"))
|
||||||
|
.When(x => x.WhenICreateTheConfig())
|
||||||
|
.Then(x => x.ThenTheRegionCreatorIsCalledCorrectly("region"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheFollowingRegionIsReturned(string region)
|
||||||
|
{
|
||||||
|
_regionCreator
|
||||||
|
.Setup(x => x.Create(It.IsAny<FileReRoute>()))
|
||||||
|
.Returns(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheRegionCreatorIsCalledCorrectly(string expected)
|
||||||
|
{
|
||||||
|
_regionCreator
|
||||||
|
.Verify(x => x.Create(_fileConfiguration.ReRoutes[0]), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -393,20 +444,18 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Theory]
|
||||||
public void should_create_with_headers_to_extract()
|
[MemberData(nameof(AuthenticationConfigTestData.GetAuthenticationData), MemberType = typeof(AuthenticationConfigTestData))]
|
||||||
|
public void should_create_with_headers_to_extract(string provider, IAuthenticationConfig config, FileConfiguration fileConfig)
|
||||||
{
|
{
|
||||||
var reRouteOptions = new ReRouteOptionsBuilder()
|
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||||
.WithIsAuthenticated(true)
|
.WithIsAuthenticated(true)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var authenticationOptions = new AuthenticationOptionsBuilder()
|
var authenticationOptions = new AuthenticationOptionsBuilder()
|
||||||
.WithProvider("IdentityServer")
|
.WithProvider(provider)
|
||||||
.WithProviderRootUrl("http://localhost:51888")
|
|
||||||
.WithRequireHttps(false)
|
|
||||||
.WithApiSecret("secret")
|
|
||||||
.WithApiName("api")
|
|
||||||
.WithAllowedScopes(new List<string>())
|
.WithAllowedScopes(new List<string>())
|
||||||
|
.WithConfig(config)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var expected = new List<ReRoute>
|
var expected = new List<ReRoute>
|
||||||
@ -423,32 +472,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.Build()
|
.Build()
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
this.Given(x => x.GivenTheConfigIs(fileConfig))
|
||||||
{
|
|
||||||
ReRoutes = new List<FileReRoute>
|
|
||||||
{
|
|
||||||
new FileReRoute
|
|
||||||
{
|
|
||||||
UpstreamPathTemplate = "/api/products/{productId}",
|
|
||||||
DownstreamPathTemplate = "/products/{productId}",
|
|
||||||
UpstreamHttpMethod = new List<string> { "Get" },
|
|
||||||
ReRouteIsCaseSensitive = true,
|
|
||||||
AuthenticationOptions = new FileAuthenticationOptions
|
|
||||||
{
|
|
||||||
AllowedScopes= new List<string>(),
|
|
||||||
Provider = "IdentityServer",
|
|
||||||
ProviderRootUrl = "http://localhost:51888",
|
|
||||||
RequireHttps = false,
|
|
||||||
ApiName= "api",
|
|
||||||
ApiSecret = "secret"
|
|
||||||
},
|
|
||||||
AddHeadersToRequest =
|
|
||||||
{
|
|
||||||
{"CustomerId", "Claims[CustomerId] > value"},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
.And(x => x.GivenTheConfigIsValid())
|
.And(x => x.GivenTheConfigIsValid())
|
||||||
.And(x => x.GivenTheAuthOptionsCreatorReturns(authenticationOptions))
|
.And(x => x.GivenTheAuthOptionsCreatorReturns(authenticationOptions))
|
||||||
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
||||||
@ -456,25 +480,23 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.And(x => x.GivenTheLoadBalancerFactoryReturns())
|
.And(x => x.GivenTheLoadBalancerFactoryReturns())
|
||||||
.When(x => x.WhenICreateTheConfig())
|
.When(x => x.WhenICreateTheConfig())
|
||||||
.Then(x => x.ThenTheReRoutesAre(expected))
|
.Then(x => x.ThenTheReRoutesAre(expected))
|
||||||
.And(x => x.ThenTheAuthenticationOptionsAre(expected))
|
.And(x => x.ThenTheAuthenticationOptionsAre(provider, expected))
|
||||||
.And(x => x.ThenTheAuthOptionsCreatorIsCalledCorrectly())
|
.And(x => x.ThenTheAuthOptionsCreatorIsCalledCorrectly())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Theory]
|
||||||
public void should_create_with_authentication_properties()
|
[MemberData(nameof(AuthenticationConfigTestData.GetAuthenticationData), MemberType = typeof(AuthenticationConfigTestData))]
|
||||||
|
public void should_create_with_authentication_properties(string provider, IAuthenticationConfig config, FileConfiguration fileConfig)
|
||||||
{
|
{
|
||||||
var reRouteOptions = new ReRouteOptionsBuilder()
|
var reRouteOptions = new ReRouteOptionsBuilder()
|
||||||
.WithIsAuthenticated(true)
|
.WithIsAuthenticated(true)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var authenticationOptions = new AuthenticationOptionsBuilder()
|
var authenticationOptions = new AuthenticationOptionsBuilder()
|
||||||
.WithProvider("IdentityServer")
|
.WithProvider(provider)
|
||||||
.WithProviderRootUrl("http://localhost:51888")
|
|
||||||
.WithRequireHttps(false)
|
|
||||||
.WithApiSecret("secret")
|
|
||||||
.WithApiName("api")
|
|
||||||
.WithAllowedScopes(new List<string>())
|
.WithAllowedScopes(new List<string>())
|
||||||
|
.WithConfig(config)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var expected = new List<ReRoute>
|
var expected = new List<ReRoute>
|
||||||
@ -487,35 +509,14 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
.Build()
|
.Build()
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
|
this.Given(x => x.GivenTheConfigIs(fileConfig))
|
||||||
{
|
|
||||||
ReRoutes = new List<FileReRoute>
|
|
||||||
{
|
|
||||||
new FileReRoute
|
|
||||||
{
|
|
||||||
UpstreamPathTemplate = "/api/products/{productId}",
|
|
||||||
DownstreamPathTemplate = "/products/{productId}",
|
|
||||||
UpstreamHttpMethod = new List<string> { "Get" },
|
|
||||||
ReRouteIsCaseSensitive = true,
|
|
||||||
AuthenticationOptions = new FileAuthenticationOptions
|
|
||||||
{
|
|
||||||
AllowedScopes = new List<string>(),
|
|
||||||
Provider = "IdentityServer",
|
|
||||||
ProviderRootUrl = "http://localhost:51888",
|
|
||||||
RequireHttps = false,
|
|
||||||
ApiName= "api",
|
|
||||||
ApiSecret = "secret"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
.And(x => x.GivenTheConfigIsValid())
|
.And(x => x.GivenTheConfigIsValid())
|
||||||
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
|
||||||
.And(x => x.GivenTheAuthOptionsCreatorReturns(authenticationOptions))
|
.And(x => x.GivenTheAuthOptionsCreatorReturns(authenticationOptions))
|
||||||
.And(x => x.GivenTheLoadBalancerFactoryReturns())
|
.And(x => x.GivenTheLoadBalancerFactoryReturns())
|
||||||
.When(x => x.WhenICreateTheConfig())
|
.When(x => x.WhenICreateTheConfig())
|
||||||
.Then(x => x.ThenTheReRoutesAre(expected))
|
.Then(x => x.ThenTheReRoutesAre(expected))
|
||||||
.And(x => x.ThenTheAuthenticationOptionsAre(expected))
|
.And(x => x.ThenTheAuthenticationOptionsAre(provider, expected))
|
||||||
.And(x => x.ThenTheAuthOptionsCreatorIsCalledCorrectly())
|
.And(x => x.ThenTheAuthOptionsCreatorIsCalledCorrectly())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
@ -586,7 +587,7 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheAuthenticationOptionsAre(List<ReRoute> expectedReRoutes)
|
private void ThenTheAuthenticationOptionsAre(string provider, List<ReRoute> expectedReRoutes)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _config.Data.ReRoutes.Count; i++)
|
for (int i = 0; i < _config.Data.ReRoutes.Count; i++)
|
||||||
{
|
{
|
||||||
@ -595,11 +596,25 @@ namespace Ocelot.UnitTests.Configuration
|
|||||||
|
|
||||||
result.AllowedScopes.ShouldBe(expected.AllowedScopes);
|
result.AllowedScopes.ShouldBe(expected.AllowedScopes);
|
||||||
result.Provider.ShouldBe(expected.Provider);
|
result.Provider.ShouldBe(expected.Provider);
|
||||||
result.ProviderRootUrl.ShouldBe(expected.ProviderRootUrl);
|
|
||||||
result.RequireHttps.ShouldBe(expected.RequireHttps);
|
|
||||||
result.ApiName.ShouldBe(expected.ApiName);
|
|
||||||
result.ApiSecret.ShouldBe(expected.ApiSecret);
|
|
||||||
|
|
||||||
|
if (provider.ToLower() == "identityserver")
|
||||||
|
{
|
||||||
|
var config = result.Config as IdentityServerConfig;
|
||||||
|
var expectedConfig = expected.Config as IdentityServerConfig;
|
||||||
|
|
||||||
|
config.ProviderRootUrl.ShouldBe(expectedConfig.ProviderRootUrl);
|
||||||
|
config.RequireHttps.ShouldBe(expectedConfig.RequireHttps);
|
||||||
|
config.ApiName.ShouldBe(expectedConfig.ApiName);
|
||||||
|
config.ApiSecret.ShouldBe(expectedConfig.ApiSecret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var config = result.Config as JwtConfig;
|
||||||
|
var expectedConfig = expected.Config as JwtConfig;
|
||||||
|
|
||||||
|
config.Audience.ShouldBe(expectedConfig.Audience);
|
||||||
|
config.Authority.ShouldBe(expectedConfig.Authority);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
using Ocelot.Configuration.Creator;
|
||||||
|
using Shouldly;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Ocelot.UnitTests.Configuration
|
||||||
|
{
|
||||||
|
public class IdentityServerConfigurationCreatorTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void happy_path_only_exists_for_test_coverage_even_uncle_bob_probably_wouldnt_test_this()
|
||||||
|
{
|
||||||
|
var result = IdentityServerConfigurationCreator.GetIdentityServerConfiguration();
|
||||||
|
result.ApiName.ShouldBe("admin");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
using Xunit;
|
||||||
|
using Shouldly;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Ocelot.Controllers;
|
||||||
|
using System;
|
||||||
|
using Moq;
|
||||||
|
using Ocelot.Cache;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Ocelot.UnitTests.Controllers
|
||||||
|
{
|
||||||
|
public class OutputCacheControllerTests
|
||||||
|
{
|
||||||
|
private OutputCacheController _controller;
|
||||||
|
private Mock<IOcelotCache<HttpResponseMessage>> _cache;
|
||||||
|
private IActionResult _result;
|
||||||
|
|
||||||
|
public OutputCacheControllerTests()
|
||||||
|
{
|
||||||
|
_cache = new Mock<IOcelotCache<HttpResponseMessage>>();
|
||||||
|
_controller = new OutputCacheController(_cache.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_delete_key()
|
||||||
|
{
|
||||||
|
this.When(_ => WhenIDeleteTheKey("a"))
|
||||||
|
.Then(_ => ThenTheKeyIsDeleted("a"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheKeyIsDeleted(string key)
|
||||||
|
{
|
||||||
|
_result.ShouldBeOfType<NoContentResult>();
|
||||||
|
_cache
|
||||||
|
.Verify(x => x.ClearRegion(key), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenIDeleteTheKey(string key)
|
||||||
|
{
|
||||||
|
_result = _controller.Delete(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,61 +1,29 @@
|
|||||||
using System;
|
namespace Ocelot.UnitTests.DownstreamRouteFinder
|
||||||
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using System.Net.Http;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.DownstreamRouteFinder;
|
using Ocelot.DownstreamRouteFinder;
|
||||||
using Ocelot.DownstreamRouteFinder.Finder;
|
using Ocelot.DownstreamRouteFinder.Finder;
|
||||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
using Ocelot.Infrastructure.RequestData;
|
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.DownstreamRouteFinder
|
public class DownstreamRouteFinderMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
|
||||||
public class DownstreamRouteFinderMiddlewareTests : IDisposable
|
|
||||||
{
|
{
|
||||||
private readonly Mock<IDownstreamRouteFinder> _downstreamRouteFinder;
|
private readonly Mock<IDownstreamRouteFinder> _downstreamRouteFinder;
|
||||||
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
|
|
||||||
private readonly string _url;
|
|
||||||
private readonly TestServer _server;
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private Response<DownstreamRoute> _downstreamRoute;
|
private Response<DownstreamRoute> _downstreamRoute;
|
||||||
private HttpResponseMessage _result;
|
|
||||||
|
|
||||||
public DownstreamRouteFinderMiddlewareTests()
|
public DownstreamRouteFinderMiddlewareTests()
|
||||||
{
|
{
|
||||||
_url = "http://localhost:51879";
|
|
||||||
_downstreamRouteFinder = new Mock<IDownstreamRouteFinder>();
|
_downstreamRouteFinder = new Mock<IDownstreamRouteFinder>();
|
||||||
_scopedRepository = new Mock<IRequestScopedDataRepository>();
|
|
||||||
|
|
||||||
var builder = new WebHostBuilder()
|
GivenTheTestServerIsConfigured();
|
||||||
.ConfigureServices(x =>
|
|
||||||
{
|
|
||||||
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
|
||||||
x.AddLogging();
|
|
||||||
x.AddSingleton(_downstreamRouteFinder.Object);
|
|
||||||
x.AddSingleton(_scopedRepository.Object);
|
|
||||||
})
|
|
||||||
.UseUrls(_url)
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.UseIISIntegration()
|
|
||||||
.UseUrls(_url)
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseDownstreamRouteFinderMiddleware();
|
|
||||||
});
|
|
||||||
|
|
||||||
_server = new TestServer(builder);
|
|
||||||
_client = _server.CreateClient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -73,16 +41,17 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
private void ThenTheScopedDataRepositoryIsCalledCorrectly()
|
|
||||||
{
|
{
|
||||||
_scopedRepository
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
.Verify(x => x.Add("DownstreamRoute", _downstreamRoute.Data), Times.Once());
|
services.AddLogging();
|
||||||
|
services.AddSingleton(_downstreamRouteFinder.Object);
|
||||||
|
services.AddSingleton(ScopedRepository.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
{
|
{
|
||||||
_result = _client.GetAsync(_url).Result;
|
app.UseDownstreamRouteFinderMiddleware();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheDownStreamRouteFinderReturns(DownstreamRoute downstreamRoute)
|
private void GivenTheDownStreamRouteFinderReturns(DownstreamRoute downstreamRoute)
|
||||||
@ -93,10 +62,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.ReturnsAsync(_downstreamRoute);
|
.ReturnsAsync(_downstreamRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
private void ThenTheScopedDataRepositoryIsCalledCorrectly()
|
||||||
{
|
{
|
||||||
_client.Dispose();
|
ScopedRepository
|
||||||
_server.Dispose();
|
.Verify(x => x.Add("DownstreamRoute", _downstreamRoute.Data), Times.Once());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
using System;
|
namespace Ocelot.UnitTests.DownstreamUrlCreator
|
||||||
|
{
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
@ -20,54 +20,26 @@ using TestStack.BDDfy;
|
|||||||
using Xunit;
|
using Xunit;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.DownstreamUrlCreator
|
public class DownstreamUrlCreatorMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
|
||||||
public class DownstreamUrlCreatorMiddlewareTests : IDisposable
|
|
||||||
{
|
{
|
||||||
private readonly Mock<IDownstreamPathPlaceholderReplacer> _downstreamUrlTemplateVariableReplacer;
|
private readonly Mock<IDownstreamPathPlaceholderReplacer> _downstreamUrlTemplateVariableReplacer;
|
||||||
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
|
|
||||||
private readonly Mock<IUrlBuilder> _urlBuilder;
|
private readonly Mock<IUrlBuilder> _urlBuilder;
|
||||||
private readonly string _url;
|
|
||||||
private readonly TestServer _server;
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private Response<DownstreamRoute> _downstreamRoute;
|
private Response<DownstreamRoute> _downstreamRoute;
|
||||||
private OkResponse<DownstreamPath> _downstreamPath;
|
private OkResponse<DownstreamPath> _downstreamPath;
|
||||||
private HttpRequestMessage _downstreamRequest;
|
private HttpRequestMessage _downstreamRequest;
|
||||||
private HttpResponseMessage _result;
|
|
||||||
|
|
||||||
public DownstreamUrlCreatorMiddlewareTests()
|
public DownstreamUrlCreatorMiddlewareTests()
|
||||||
{
|
{
|
||||||
_url = "http://localhost:51879";
|
|
||||||
_downstreamUrlTemplateVariableReplacer = new Mock<IDownstreamPathPlaceholderReplacer>();
|
_downstreamUrlTemplateVariableReplacer = new Mock<IDownstreamPathPlaceholderReplacer>();
|
||||||
_scopedRepository = new Mock<IRequestScopedDataRepository>();
|
|
||||||
_urlBuilder = new Mock<IUrlBuilder>();
|
_urlBuilder = new Mock<IUrlBuilder>();
|
||||||
var builder = new WebHostBuilder()
|
|
||||||
.ConfigureServices(x =>
|
|
||||||
{
|
|
||||||
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
|
||||||
x.AddLogging();
|
|
||||||
x.AddSingleton(_downstreamUrlTemplateVariableReplacer.Object);
|
|
||||||
x.AddSingleton(_scopedRepository.Object);
|
|
||||||
x.AddSingleton(_urlBuilder.Object);
|
|
||||||
})
|
|
||||||
.UseUrls(_url)
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.UseIISIntegration()
|
|
||||||
.UseUrls(_url)
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseDownstreamUrlCreatorMiddleware();
|
|
||||||
});
|
|
||||||
|
|
||||||
_downstreamRequest = new HttpRequestMessage(HttpMethod.Get, "https://my.url/abc/?q=123");
|
_downstreamRequest = new HttpRequestMessage(HttpMethod.Get, "https://my.url/abc/?q=123");
|
||||||
|
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
||||||
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
|
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
|
||||||
|
|
||||||
_server = new TestServer(builder);
|
GivenTheTestServerIsConfigured();
|
||||||
_client = _server.CreateClient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -88,10 +60,24 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
|
services.AddLogging();
|
||||||
|
services.AddSingleton(_downstreamUrlTemplateVariableReplacer.Object);
|
||||||
|
services.AddSingleton(ScopedRepository.Object);
|
||||||
|
services.AddSingleton(_urlBuilder.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseDownstreamUrlCreatorMiddleware();
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||||
{
|
{
|
||||||
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
||||||
.Returns(_downstreamRoute);
|
.Returns(_downstreamRoute);
|
||||||
}
|
}
|
||||||
@ -109,20 +95,9 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
|
|||||||
.Returns(_downstreamPath);
|
.Returns(_downstreamPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
|
||||||
{
|
|
||||||
_result = _client.GetAsync(_url).Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThenTheDownstreamRequestUriIs(string expectedUri)
|
private void ThenTheDownstreamRequestUriIs(string expectedUri)
|
||||||
{
|
{
|
||||||
_downstreamRequest.RequestUri.OriginalString.ShouldBe(expectedUri);
|
_downstreamRequest.RequestUri.OriginalString.ShouldBe(expectedUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_client.Dispose();
|
|
||||||
_server.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
namespace Ocelot.UnitTests.Errors
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Ocelot.Errors.Middleware;
|
||||||
|
using Ocelot.Logging;
|
||||||
|
using Shouldly;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Xunit;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
|
public class ExceptionHandlerMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
|
{
|
||||||
|
bool _shouldThrowAnException = false;
|
||||||
|
|
||||||
|
public ExceptionHandlerMiddlewareTests()
|
||||||
|
{
|
||||||
|
GivenTheTestServerIsConfigured();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NoDownstreamException()
|
||||||
|
{
|
||||||
|
this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
|
||||||
|
.When(_ => WhenICallTheMiddleware())
|
||||||
|
.Then(_ => ThenTheResponseIsOk())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DownstreamException()
|
||||||
|
{
|
||||||
|
this.Given(_ => GivenAnExceptionWillBeThrownDownstream())
|
||||||
|
.When(_ => WhenICallTheMiddleware())
|
||||||
|
.Then(_ => ThenTheResponseIsError())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
|
services.AddLogging();
|
||||||
|
services.AddSingleton(ScopedRepository.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseExceptionHandlerMiddleware();
|
||||||
|
app.Run(DownstreamExceptionSimulator);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DownstreamExceptionSimulator(HttpContext context)
|
||||||
|
{
|
||||||
|
await Task.CompletedTask;
|
||||||
|
|
||||||
|
if (_shouldThrowAnException)
|
||||||
|
{
|
||||||
|
throw new Exception("BOOM");
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Response.StatusCode = (int)HttpStatusCode.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenAnExceptionWillNotBeThrownDownstream()
|
||||||
|
{
|
||||||
|
_shouldThrowAnException = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenAnExceptionWillBeThrownDownstream()
|
||||||
|
{
|
||||||
|
_shouldThrowAnException = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheResponseIsOk()
|
||||||
|
{
|
||||||
|
ResponseMessage.StatusCode.ShouldBe(HttpStatusCode.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheResponseIsError()
|
||||||
|
{
|
||||||
|
ResponseMessage.StatusCode.ShouldBe(HttpStatusCode.InternalServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,8 @@
|
|||||||
using System;
|
namespace Ocelot.UnitTests.Headers
|
||||||
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
@ -12,58 +11,27 @@ using Ocelot.DownstreamRouteFinder;
|
|||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
using Ocelot.Headers;
|
using Ocelot.Headers;
|
||||||
using Ocelot.Headers.Middleware;
|
using Ocelot.Headers.Middleware;
|
||||||
using Ocelot.Infrastructure.RequestData;
|
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Headers
|
public class HttpRequestHeadersBuilderMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
{
|
||||||
public class HttpRequestHeadersBuilderMiddlewareTests : IDisposable
|
|
||||||
{
|
|
||||||
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
|
|
||||||
private readonly Mock<IAddHeadersToRequest> _addHeaders;
|
private readonly Mock<IAddHeadersToRequest> _addHeaders;
|
||||||
private readonly HttpRequestMessage _downstreamRequest;
|
private readonly HttpRequestMessage _downstreamRequest;
|
||||||
private readonly string _url;
|
|
||||||
private readonly TestServer _server;
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private Response<DownstreamRoute> _downstreamRoute;
|
private Response<DownstreamRoute> _downstreamRoute;
|
||||||
private HttpResponseMessage _result;
|
|
||||||
|
|
||||||
public HttpRequestHeadersBuilderMiddlewareTests()
|
public HttpRequestHeadersBuilderMiddlewareTests()
|
||||||
{
|
{
|
||||||
_url = "http://localhost:51879";
|
|
||||||
_scopedRepository = new Mock<IRequestScopedDataRepository>();
|
|
||||||
_addHeaders = new Mock<IAddHeadersToRequest>();
|
_addHeaders = new Mock<IAddHeadersToRequest>();
|
||||||
|
|
||||||
|
|
||||||
var builder = new WebHostBuilder()
|
|
||||||
.ConfigureServices(x =>
|
|
||||||
{
|
|
||||||
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
|
||||||
x.AddLogging();
|
|
||||||
x.AddSingleton(_addHeaders.Object);
|
|
||||||
x.AddSingleton(_scopedRepository.Object);
|
|
||||||
})
|
|
||||||
.UseUrls(_url)
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.UseIISIntegration()
|
|
||||||
.UseUrls(_url)
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseHttpRequestHeadersBuilderMiddleware();
|
|
||||||
});
|
|
||||||
|
|
||||||
_downstreamRequest = new HttpRequestMessage();
|
_downstreamRequest = new HttpRequestMessage();
|
||||||
|
ScopedRepository
|
||||||
_scopedRepository
|
|
||||||
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
||||||
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
|
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
|
||||||
|
|
||||||
_server = new TestServer(builder);
|
GivenTheTestServerIsConfigured();
|
||||||
_client = _server.CreateClient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -86,6 +54,27 @@ namespace Ocelot.UnitTests.Headers
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
|
services.AddLogging();
|
||||||
|
services.AddSingleton(_addHeaders.Object);
|
||||||
|
services.AddSingleton(ScopedRepository.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseHttpRequestHeadersBuilderMiddleware();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||||
|
{
|
||||||
|
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||||
|
ScopedRepository
|
||||||
|
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
||||||
|
.Returns(_downstreamRoute);
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheAddHeadersToDownstreamRequestReturnsOk()
|
private void GivenTheAddHeadersToDownstreamRequestReturnsOk()
|
||||||
{
|
{
|
||||||
_addHeaders
|
_addHeaders
|
||||||
@ -104,24 +93,5 @@ namespace Ocelot.UnitTests.Headers
|
|||||||
It.IsAny<IEnumerable<System.Security.Claims.Claim>>(),
|
It.IsAny<IEnumerable<System.Security.Claims.Claim>>(),
|
||||||
_downstreamRequest), Times.Once);
|
_downstreamRequest), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
|
||||||
{
|
|
||||||
_result = _client.GetAsync(_url).Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
|
||||||
{
|
|
||||||
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
|
||||||
_scopedRepository
|
|
||||||
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
|
||||||
.Returns(_downstreamRoute);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_client.Dispose();
|
|
||||||
_server.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,26 @@
|
|||||||
|
namespace Ocelot.UnitTests.LoadBalancer
|
||||||
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.DownstreamRouteFinder;
|
using Ocelot.DownstreamRouteFinder;
|
||||||
using Ocelot.Errors;
|
using Ocelot.Errors;
|
||||||
using Ocelot.Infrastructure.RequestData;
|
|
||||||
using Ocelot.LoadBalancer.LoadBalancers;
|
using Ocelot.LoadBalancer.LoadBalancers;
|
||||||
using Ocelot.LoadBalancer.Middleware;
|
using Ocelot.LoadBalancer.Middleware;
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using Ocelot.Values;
|
using Ocelot.Values;
|
||||||
|
using Shouldly;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Shouldly;
|
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.LoadBalancer
|
public class LoadBalancerMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
|
||||||
public class LoadBalancerMiddlewareTests
|
|
||||||
{
|
{
|
||||||
private readonly Mock<ILoadBalancerHouse> _loadBalancerHouse;
|
private readonly Mock<ILoadBalancerHouse> _loadBalancerHouse;
|
||||||
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
|
|
||||||
private readonly Mock<ILoadBalancer> _loadBalancer;
|
private readonly Mock<ILoadBalancer> _loadBalancer;
|
||||||
private readonly string _url;
|
|
||||||
private readonly TestServer _server;
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private HttpResponseMessage _result;
|
|
||||||
private HostAndPort _hostAndPort;
|
private HostAndPort _hostAndPort;
|
||||||
private OkResponse<DownstreamRoute> _downstreamRoute;
|
private OkResponse<DownstreamRoute> _downstreamRoute;
|
||||||
private ErrorResponse<ILoadBalancer> _getLoadBalancerHouseError;
|
private ErrorResponse<ILoadBalancer> _getLoadBalancerHouseError;
|
||||||
@ -37,35 +29,17 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
|
|
||||||
public LoadBalancerMiddlewareTests()
|
public LoadBalancerMiddlewareTests()
|
||||||
{
|
{
|
||||||
_url = "http://localhost:51879";
|
|
||||||
_loadBalancerHouse = new Mock<ILoadBalancerHouse>();
|
_loadBalancerHouse = new Mock<ILoadBalancerHouse>();
|
||||||
_scopedRepository = new Mock<IRequestScopedDataRepository>();
|
|
||||||
_loadBalancer = new Mock<ILoadBalancer>();
|
_loadBalancer = new Mock<ILoadBalancer>();
|
||||||
_loadBalancerHouse = new Mock<ILoadBalancerHouse>();
|
_loadBalancerHouse = new Mock<ILoadBalancerHouse>();
|
||||||
var builder = new WebHostBuilder()
|
|
||||||
.ConfigureServices(x =>
|
|
||||||
{
|
|
||||||
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
|
||||||
x.AddLogging();
|
|
||||||
x.AddSingleton(_loadBalancerHouse.Object);
|
|
||||||
x.AddSingleton(_scopedRepository.Object);
|
|
||||||
})
|
|
||||||
.UseUrls(_url)
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.UseIISIntegration()
|
|
||||||
.UseUrls(_url)
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseLoadBalancingMiddleware();
|
|
||||||
});
|
|
||||||
|
|
||||||
_downstreamRequest = new HttpRequestMessage(HttpMethod.Get, "");
|
_downstreamRequest = new HttpRequestMessage(HttpMethod.Get, "");
|
||||||
_scopedRepository
|
|
||||||
|
ScopedRepository
|
||||||
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
||||||
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
|
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
|
||||||
_server = new TestServer(builder);
|
|
||||||
_client = _server.CreateClient();
|
GivenTheTestServerIsConfigured();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -118,6 +92,19 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
|
services.AddLogging();
|
||||||
|
services.AddSingleton(_loadBalancerHouse.Object);
|
||||||
|
services.AddSingleton(ScopedRepository.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseLoadBalancingMiddleware();
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheDownStreamUrlIs(string downstreamUrl)
|
private void GivenTheDownStreamUrlIs(string downstreamUrl)
|
||||||
{
|
{
|
||||||
_downstreamRequest.RequestUri = new System.Uri(downstreamUrl);
|
_downstreamRequest.RequestUri = new System.Uri(downstreamUrl);
|
||||||
@ -142,7 +129,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||||
{
|
{
|
||||||
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
||||||
.Returns(_downstreamRoute);
|
.Returns(_downstreamRoute);
|
||||||
}
|
}
|
||||||
@ -154,7 +141,6 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
.Returns(new OkResponse<ILoadBalancer>(_loadBalancer.Object));
|
.Returns(new OkResponse<ILoadBalancer>(_loadBalancer.Object));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void GivenTheLoadBalancerHouseReturnsAnError()
|
private void GivenTheLoadBalancerHouseReturnsAnError()
|
||||||
{
|
{
|
||||||
_getLoadBalancerHouseError = new ErrorResponse<ILoadBalancer>(new List<Ocelot.Errors.Error>()
|
_getLoadBalancerHouseError = new ErrorResponse<ILoadBalancer>(new List<Ocelot.Errors.Error>()
|
||||||
@ -167,49 +153,36 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
.Returns(_getLoadBalancerHouseError);
|
.Returns(_getLoadBalancerHouseError);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
|
||||||
{
|
|
||||||
_result = _client.GetAsync(_url).Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThenAnErrorStatingLoadBalancerCouldNotBeFoundIsSetOnPipeline()
|
private void ThenAnErrorStatingLoadBalancerCouldNotBeFoundIsSetOnPipeline()
|
||||||
{
|
{
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once);
|
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once);
|
||||||
|
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Verify(x => x.Add("OcelotMiddlewareErrors", _getLoadBalancerHouseError.Errors), Times.Once);
|
.Verify(x => x.Add("OcelotMiddlewareErrors", _getLoadBalancerHouseError.Errors), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenAnErrorSayingReleaseFailedIsSetOnThePipeline()
|
private void ThenAnErrorSayingReleaseFailedIsSetOnThePipeline()
|
||||||
{
|
{
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once);
|
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once);
|
||||||
|
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Verify(x => x.Add("OcelotMiddlewareErrors", It.IsAny<List<Error>>()), Times.Once);
|
.Verify(x => x.Add("OcelotMiddlewareErrors", It.IsAny<List<Error>>()), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenAnErrorStatingHostAndPortCouldNotBeFoundIsSetOnPipeline()
|
private void ThenAnErrorStatingHostAndPortCouldNotBeFoundIsSetOnPipeline()
|
||||||
{
|
{
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once);
|
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once);
|
||||||
|
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Verify(x => x.Add("OcelotMiddlewareErrors", _getHostAndPortError.Errors), Times.Once);
|
.Verify(x => x.Add("OcelotMiddlewareErrors", _getHostAndPortError.Errors), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void ThenTheDownstreamUrlIsReplacedWith(string expectedUri)
|
private void ThenTheDownstreamUrlIsReplacedWith(string expectedUri)
|
||||||
{
|
{
|
||||||
_downstreamRequest.RequestUri.OriginalString.ShouldBe(expectedUri);
|
_downstreamRequest.RequestUri.OriginalString.ShouldBe(expectedUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_client.Dispose();
|
|
||||||
_server.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -19,6 +19,10 @@
|
|||||||
<DebugSymbols>True</DebugSymbols>
|
<DebugSymbols>True</DebugSymbols>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Responder\HttpContextResponderTests.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
using System;
|
namespace Ocelot.UnitTests.QueryStrings
|
||||||
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.DownstreamRouteFinder;
|
using Ocelot.DownstreamRouteFinder;
|
||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
using Ocelot.Infrastructure.RequestData;
|
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.QueryStrings;
|
using Ocelot.QueryStrings;
|
||||||
using Ocelot.QueryStrings.Middleware;
|
using Ocelot.QueryStrings.Middleware;
|
||||||
@ -18,50 +15,23 @@ using Ocelot.Responses;
|
|||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.QueryStrings
|
public class QueryStringBuilderMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
{
|
||||||
public class QueryStringBuilderMiddlewareTests : IDisposable
|
|
||||||
{
|
|
||||||
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
|
|
||||||
private readonly Mock<IAddQueriesToRequest> _addQueries;
|
private readonly Mock<IAddQueriesToRequest> _addQueries;
|
||||||
private readonly string _url;
|
|
||||||
private readonly TestServer _server;
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private readonly HttpRequestMessage _downstreamRequest;
|
private readonly HttpRequestMessage _downstreamRequest;
|
||||||
private Response<DownstreamRoute> _downstreamRoute;
|
private Response<DownstreamRoute> _downstreamRoute;
|
||||||
private HttpResponseMessage _result;
|
|
||||||
|
|
||||||
public QueryStringBuilderMiddlewareTests()
|
public QueryStringBuilderMiddlewareTests()
|
||||||
{
|
{
|
||||||
_url = "http://localhost:51879";
|
|
||||||
_scopedRepository = new Mock<IRequestScopedDataRepository>();
|
|
||||||
_addQueries = new Mock<IAddQueriesToRequest>();
|
_addQueries = new Mock<IAddQueriesToRequest>();
|
||||||
var builder = new WebHostBuilder()
|
|
||||||
.ConfigureServices(x =>
|
|
||||||
{
|
|
||||||
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
|
||||||
x.AddLogging();
|
|
||||||
x.AddSingleton(_addQueries.Object);
|
|
||||||
x.AddSingleton(_scopedRepository.Object);
|
|
||||||
})
|
|
||||||
.UseUrls(_url)
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.UseIISIntegration()
|
|
||||||
.UseUrls(_url)
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseQueryStringBuilderMiddleware();
|
|
||||||
});
|
|
||||||
|
|
||||||
_downstreamRequest = new HttpRequestMessage();
|
_downstreamRequest = new HttpRequestMessage();
|
||||||
|
ScopedRepository.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
||||||
_scopedRepository.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
|
||||||
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
|
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
|
||||||
|
|
||||||
_server = new TestServer(builder);
|
GivenTheTestServerIsConfigured();
|
||||||
_client = _server.CreateClient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -84,6 +54,19 @@ namespace Ocelot.UnitTests.QueryStrings
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
|
services.AddLogging();
|
||||||
|
services.AddSingleton(_addQueries.Object);
|
||||||
|
services.AddSingleton(ScopedRepository.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseQueryStringBuilderMiddleware();
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheAddHeadersToRequestReturnsOk()
|
private void GivenTheAddHeadersToRequestReturnsOk()
|
||||||
{
|
{
|
||||||
_addQueries
|
_addQueries
|
||||||
@ -103,23 +86,12 @@ namespace Ocelot.UnitTests.QueryStrings
|
|||||||
_downstreamRequest), Times.Once);
|
_downstreamRequest), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
|
||||||
{
|
|
||||||
_result = _client.GetAsync(_url).Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||||
{
|
{
|
||||||
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
||||||
.Returns(_downstreamRoute);
|
.Returns(_downstreamRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_client.Dispose();
|
|
||||||
_server.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,71 +1,33 @@
|
|||||||
using Microsoft.AspNetCore.Hosting;
|
namespace Ocelot.UnitTests.RateLimit
|
||||||
using Microsoft.AspNetCore.Builder;
|
{
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Moq;
|
|
||||||
using Ocelot.Infrastructure.RequestData;
|
|
||||||
using Ocelot.RateLimit;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Ocelot.Logging;
|
using Moq;
|
||||||
using System.IO;
|
|
||||||
using Ocelot.RateLimit.Middleware;
|
|
||||||
using Ocelot.DownstreamRouteFinder;
|
|
||||||
using Ocelot.Responses;
|
|
||||||
using Xunit;
|
|
||||||
using TestStack.BDDfy;
|
|
||||||
using Ocelot.Configuration.Builder;
|
|
||||||
using Shouldly;
|
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
|
using Ocelot.Configuration.Builder;
|
||||||
|
using Ocelot.DownstreamRouteFinder;
|
||||||
|
using Ocelot.Logging;
|
||||||
|
using Ocelot.RateLimit;
|
||||||
|
using Ocelot.RateLimit.Middleware;
|
||||||
|
using Ocelot.Responses;
|
||||||
|
using Shouldly;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.RateLimit
|
public class ClientRateLimitMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
{
|
||||||
public class ClientRateLimitMiddlewareTests
|
|
||||||
{
|
|
||||||
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
|
|
||||||
private readonly string _url;
|
|
||||||
private readonly TestServer _server;
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private OkResponse<DownstreamRoute> _downstreamRoute;
|
private OkResponse<DownstreamRoute> _downstreamRoute;
|
||||||
private int responseStatusCode;
|
private int responseStatusCode;
|
||||||
|
|
||||||
public ClientRateLimitMiddlewareTests()
|
public ClientRateLimitMiddlewareTests()
|
||||||
{
|
{
|
||||||
_url = "http://localhost:51879/api/ClientRateLimit";
|
GivenTheTestServerIsConfigured();
|
||||||
_scopedRepository = new Mock<IRequestScopedDataRepository>();
|
|
||||||
var builder = new WebHostBuilder()
|
|
||||||
.ConfigureServices(x =>
|
|
||||||
{
|
|
||||||
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
|
||||||
x.AddLogging();
|
|
||||||
x.AddMemoryCache();
|
|
||||||
x.AddSingleton<IRateLimitCounterHandler, MemoryCacheRateLimitCounterHandler>();
|
|
||||||
x.AddSingleton(_scopedRepository.Object);
|
|
||||||
})
|
|
||||||
.UseUrls(_url)
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.UseIISIntegration()
|
|
||||||
.UseUrls(_url)
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseRateLimiting();
|
|
||||||
app.Run(async context =>
|
|
||||||
{
|
|
||||||
context.Response.StatusCode = 200;
|
|
||||||
await context.Response.WriteAsync("This is ratelimit test");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
_server = new TestServer(builder);
|
|
||||||
_client = _server.CreateClient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_call_middleware_and_ratelimiting()
|
public void should_call_middleware_and_ratelimiting()
|
||||||
{
|
{
|
||||||
@ -98,11 +60,29 @@ namespace Ocelot.UnitTests.RateLimit
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
|
services.AddLogging();
|
||||||
|
services.AddMemoryCache();
|
||||||
|
services.AddSingleton<IRateLimitCounterHandler, MemoryCacheRateLimitCounterHandler>();
|
||||||
|
services.AddSingleton(ScopedRepository.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseRateLimiting();
|
||||||
|
app.Run(async context =>
|
||||||
|
{
|
||||||
|
context.Response.StatusCode = 200;
|
||||||
|
await context.Response.WriteAsync("This is ratelimit test");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||||
{
|
{
|
||||||
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
||||||
.Returns(_downstreamRoute);
|
.Returns(_downstreamRoute);
|
||||||
}
|
}
|
||||||
@ -110,28 +90,27 @@ namespace Ocelot.UnitTests.RateLimit
|
|||||||
private void WhenICallTheMiddlewareMultipleTime(int times)
|
private void WhenICallTheMiddlewareMultipleTime(int times)
|
||||||
{
|
{
|
||||||
var clientId = "ocelotclient1";
|
var clientId = "ocelotclient1";
|
||||||
// Act
|
|
||||||
for (int i = 0; i < times; i++)
|
for (int i = 0; i < times; i++)
|
||||||
{
|
{
|
||||||
var request = new HttpRequestMessage(new HttpMethod("GET"), _url);
|
var request = new HttpRequestMessage(new HttpMethod("GET"), Url);
|
||||||
request.Headers.Add("ClientId", clientId);
|
request.Headers.Add("ClientId", clientId);
|
||||||
|
|
||||||
var response = _client.SendAsync(request);
|
var response = Client.SendAsync(request);
|
||||||
responseStatusCode = (int)response.Result.StatusCode;
|
responseStatusCode = (int)response.Result.StatusCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenICallTheMiddlewareWithWhiteClient()
|
private void WhenICallTheMiddlewareWithWhiteClient()
|
||||||
{
|
{
|
||||||
var clientId = "ocelotclient2";
|
var clientId = "ocelotclient2";
|
||||||
// Act
|
|
||||||
for (int i = 0; i < 10; i++)
|
for (int i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
var request = new HttpRequestMessage(new HttpMethod("GET"), _url);
|
var request = new HttpRequestMessage(new HttpMethod("GET"), Url);
|
||||||
request.Headers.Add("ClientId", clientId);
|
request.Headers.Add("ClientId", clientId);
|
||||||
|
|
||||||
var response = _client.SendAsync(request);
|
var response = Client.SendAsync(request);
|
||||||
responseStatusCode = (int)response.Result.StatusCode;
|
responseStatusCode = (int)response.Result.StatusCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
using System;
|
namespace Ocelot.UnitTests.Request
|
||||||
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
@ -17,47 +15,23 @@ using Ocelot.Responses;
|
|||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Ocelot.Requester.QoS;
|
using Ocelot.Requester.QoS;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Request
|
public class HttpRequestBuilderMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
|
||||||
public class HttpRequestBuilderMiddlewareTests : IDisposable
|
|
||||||
{
|
{
|
||||||
private readonly Mock<IRequestCreator> _requestBuilder;
|
private readonly Mock<IRequestCreator> _requestBuilder;
|
||||||
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
|
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
|
||||||
private readonly Mock<IQosProviderHouse> _qosProviderHouse;
|
private readonly Mock<IQosProviderHouse> _qosProviderHouse;
|
||||||
private readonly HttpRequestMessage _downstreamRequest;
|
private readonly HttpRequestMessage _downstreamRequest;
|
||||||
private readonly string _url;
|
|
||||||
private readonly TestServer _server;
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private HttpResponseMessage _result;
|
|
||||||
private OkResponse<Ocelot.Request.Request> _request;
|
private OkResponse<Ocelot.Request.Request> _request;
|
||||||
private OkResponse<string> _downstreamUrl;
|
private OkResponse<string> _downstreamUrl;
|
||||||
private OkResponse<DownstreamRoute> _downstreamRoute;
|
private OkResponse<DownstreamRoute> _downstreamRoute;
|
||||||
|
|
||||||
public HttpRequestBuilderMiddlewareTests()
|
public HttpRequestBuilderMiddlewareTests()
|
||||||
{
|
{
|
||||||
_url = "http://localhost:51879";
|
|
||||||
_qosProviderHouse = new Mock<IQosProviderHouse>();
|
_qosProviderHouse = new Mock<IQosProviderHouse>();
|
||||||
_requestBuilder = new Mock<IRequestCreator>();
|
_requestBuilder = new Mock<IRequestCreator>();
|
||||||
_scopedRepository = new Mock<IRequestScopedDataRepository>();
|
_scopedRepository = new Mock<IRequestScopedDataRepository>();
|
||||||
var builder = new WebHostBuilder()
|
|
||||||
.ConfigureServices(x =>
|
|
||||||
{
|
|
||||||
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
|
||||||
x.AddLogging();
|
|
||||||
x.AddSingleton(_qosProviderHouse.Object);
|
|
||||||
x.AddSingleton(_requestBuilder.Object);
|
|
||||||
x.AddSingleton(_scopedRepository.Object);
|
|
||||||
})
|
|
||||||
.UseUrls(_url)
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.UseIISIntegration()
|
|
||||||
.UseUrls(_url)
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseHttpRequestBuilderMiddleware();
|
|
||||||
});
|
|
||||||
|
|
||||||
_downstreamRequest = new HttpRequestMessage();
|
_downstreamRequest = new HttpRequestMessage();
|
||||||
|
|
||||||
@ -65,8 +39,7 @@ namespace Ocelot.UnitTests.Request
|
|||||||
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
||||||
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
|
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
|
||||||
|
|
||||||
_server = new TestServer(builder);
|
GivenTheTestServerIsConfigured();
|
||||||
_client = _server.CreateClient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -88,6 +61,28 @@ namespace Ocelot.UnitTests.Request
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
|
services.AddLogging();
|
||||||
|
services.AddSingleton(_qosProviderHouse.Object);
|
||||||
|
services.AddSingleton(_requestBuilder.Object);
|
||||||
|
services.AddSingleton(_scopedRepository.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseHttpRequestBuilderMiddleware();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheDownStreamUrlIs(string downstreamUrl)
|
||||||
|
{
|
||||||
|
_downstreamUrl = new OkResponse<string>(downstreamUrl);
|
||||||
|
_scopedRepository
|
||||||
|
.Setup(x => x.Get<string>(It.IsAny<string>()))
|
||||||
|
.Returns(_downstreamUrl);
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheQosProviderHouseReturns(Response<IQoSProvider> qosProvider)
|
private void GivenTheQosProviderHouseReturns(Response<IQoSProvider> qosProvider)
|
||||||
{
|
{
|
||||||
_qosProviderHouse
|
_qosProviderHouse
|
||||||
@ -117,24 +112,5 @@ namespace Ocelot.UnitTests.Request
|
|||||||
_scopedRepository
|
_scopedRepository
|
||||||
.Verify(x => x.Add("Request", _request.Data), Times.Once());
|
.Verify(x => x.Add("Request", _request.Data), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
|
||||||
{
|
|
||||||
_result = _client.GetAsync(_url).Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenTheDownStreamUrlIs(string downstreamUrl)
|
|
||||||
{
|
|
||||||
_downstreamUrl = new OkResponse<string>(downstreamUrl);
|
|
||||||
_scopedRepository
|
|
||||||
.Setup(x => x.Get<string>(It.IsAny<string>()))
|
|
||||||
.Returns(_downstreamUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_client.Dispose();
|
|
||||||
_server.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
using System;
|
namespace Ocelot.UnitTests.RequestId
|
||||||
|
{
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.DownstreamRouteFinder;
|
using Ocelot.DownstreamRouteFinder;
|
||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
using Ocelot.Infrastructure.RequestData;
|
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.RequestId.Middleware;
|
using Ocelot.RequestId.Middleware;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
@ -20,55 +19,22 @@ using Shouldly;
|
|||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.RequestId
|
public class RequestIdMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
{
|
||||||
public class RequestIdMiddlewareTests
|
|
||||||
{
|
|
||||||
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
|
|
||||||
private readonly HttpRequestMessage _downstreamRequest;
|
private readonly HttpRequestMessage _downstreamRequest;
|
||||||
private readonly string _url;
|
|
||||||
private readonly TestServer _server;
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private Response<DownstreamRoute> _downstreamRoute;
|
private Response<DownstreamRoute> _downstreamRoute;
|
||||||
private HttpResponseMessage _result;
|
|
||||||
private string _value;
|
private string _value;
|
||||||
private string _key;
|
private string _key;
|
||||||
|
|
||||||
public RequestIdMiddlewareTests()
|
public RequestIdMiddlewareTests()
|
||||||
{
|
{
|
||||||
_url = "http://localhost:51879";
|
|
||||||
_scopedRepository = new Mock<IRequestScopedDataRepository>();
|
|
||||||
var builder = new WebHostBuilder()
|
|
||||||
.ConfigureServices(x =>
|
|
||||||
{
|
|
||||||
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
|
||||||
x.AddLogging();
|
|
||||||
x.AddSingleton(_scopedRepository.Object);
|
|
||||||
})
|
|
||||||
.UseUrls(_url)
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.UseIISIntegration()
|
|
||||||
.UseUrls(_url)
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseRequestIdMiddleware();
|
|
||||||
|
|
||||||
app.Run(x =>
|
|
||||||
{
|
|
||||||
x.Response.Headers.Add("LSRequestId", x.TraceIdentifier);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
_server = new TestServer(builder);
|
|
||||||
_client = _server.CreateClient();
|
|
||||||
|
|
||||||
_downstreamRequest = new HttpRequestMessage();
|
_downstreamRequest = new HttpRequestMessage();
|
||||||
|
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
|
||||||
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
|
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
|
||||||
|
|
||||||
|
GivenTheTestServerIsConfigured();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -106,10 +72,28 @@ namespace Ocelot.UnitTests.RequestId
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
|
services.AddLogging();
|
||||||
|
services.AddSingleton(ScopedRepository.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseRequestIdMiddleware();
|
||||||
|
|
||||||
|
app.Run(x =>
|
||||||
|
{
|
||||||
|
x.Response.Headers.Add("LSRequestId", x.TraceIdentifier);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||||
{
|
{
|
||||||
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
|
||||||
.Returns(_downstreamRoute);
|
.Returns(_downstreamRoute);
|
||||||
}
|
}
|
||||||
@ -118,28 +102,17 @@ namespace Ocelot.UnitTests.RequestId
|
|||||||
{
|
{
|
||||||
_key = key;
|
_key = key;
|
||||||
_value = value;
|
_value = value;
|
||||||
_client.DefaultRequestHeaders.TryAddWithoutValidation(_key, _value);
|
Client.DefaultRequestHeaders.TryAddWithoutValidation(_key, _value);
|
||||||
}
|
|
||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
|
||||||
{
|
|
||||||
_result = _client.GetAsync(_url).Result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheTraceIdIsAnything()
|
private void ThenTheTraceIdIsAnything()
|
||||||
{
|
{
|
||||||
_result.Headers.GetValues("LSRequestId").First().ShouldNotBeNullOrEmpty();
|
ResponseMessage.Headers.GetValues("LSRequestId").First().ShouldNotBeNullOrEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheTraceIdIs(string expected)
|
private void ThenTheTraceIdIs(string expected)
|
||||||
{
|
{
|
||||||
_result.Headers.GetValues("LSRequestId").First().ShouldBe(expected);
|
ResponseMessage.Headers.GetValues("LSRequestId").First().ShouldBe(expected);
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_client.Dispose();
|
|
||||||
_server.Dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,62 +1,28 @@
|
|||||||
using System;
|
namespace Ocelot.UnitTests.Requester
|
||||||
using System.IO;
|
{
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Infrastructure.RequestData;
|
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.QueryStrings.Middleware;
|
|
||||||
using Ocelot.Requester;
|
using Ocelot.Requester;
|
||||||
using Ocelot.Requester.Middleware;
|
using Ocelot.Requester.Middleware;
|
||||||
using Ocelot.Requester.QoS;
|
using Ocelot.Requester.QoS;
|
||||||
using Ocelot.Responder;
|
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Requester
|
public class HttpRequesterMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
|
||||||
public class HttpRequesterMiddlewareTests : IDisposable
|
|
||||||
{
|
{
|
||||||
private readonly Mock<IHttpRequester> _requester;
|
private readonly Mock<IHttpRequester> _requester;
|
||||||
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
|
|
||||||
private readonly string _url;
|
|
||||||
private readonly TestServer _server;
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private HttpResponseMessage _result;
|
|
||||||
private OkResponse<HttpResponseMessage> _response;
|
private OkResponse<HttpResponseMessage> _response;
|
||||||
private OkResponse<Ocelot.Request.Request> _request;
|
private OkResponse<Ocelot.Request.Request> _request;
|
||||||
|
|
||||||
public HttpRequesterMiddlewareTests()
|
public HttpRequesterMiddlewareTests()
|
||||||
{
|
{
|
||||||
_url = "http://localhost:51879";
|
|
||||||
_requester = new Mock<IHttpRequester>();
|
_requester = new Mock<IHttpRequester>();
|
||||||
_scopedRepository = new Mock<IRequestScopedDataRepository>();
|
|
||||||
var builder = new WebHostBuilder()
|
|
||||||
.ConfigureServices(x =>
|
|
||||||
{
|
|
||||||
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
|
||||||
x.AddLogging();
|
|
||||||
x.AddSingleton(_requester.Object);
|
|
||||||
x.AddSingleton(_scopedRepository.Object);
|
|
||||||
})
|
|
||||||
.UseUrls(_url)
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.UseIISIntegration()
|
|
||||||
.UseUrls(_url)
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseHttpRequesterMiddleware();
|
|
||||||
});
|
|
||||||
|
|
||||||
_server = new TestServer(builder);
|
GivenTheTestServerIsConfigured();
|
||||||
_client = _server.CreateClient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -70,6 +36,27 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
|
services.AddLogging();
|
||||||
|
services.AddSingleton(_requester.Object);
|
||||||
|
services.AddSingleton(ScopedRepository.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseHttpRequesterMiddleware();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheRequestIs(Ocelot.Request.Request request)
|
||||||
|
{
|
||||||
|
_request = new OkResponse<Ocelot.Request.Request>(request);
|
||||||
|
ScopedRepository
|
||||||
|
.Setup(x => x.Get<Ocelot.Request.Request>(It.IsAny<string>()))
|
||||||
|
.Returns(_request);
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheRequesterReturns(HttpResponseMessage response)
|
private void GivenTheRequesterReturns(HttpResponseMessage response)
|
||||||
{
|
{
|
||||||
_response = new OkResponse<HttpResponseMessage>(response);
|
_response = new OkResponse<HttpResponseMessage>(response);
|
||||||
@ -80,34 +67,15 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
|
|
||||||
private void GivenTheScopedRepoReturns()
|
private void GivenTheScopedRepoReturns()
|
||||||
{
|
{
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Setup(x => x.Add(It.IsAny<string>(), _response.Data))
|
.Setup(x => x.Add(It.IsAny<string>(), _response.Data))
|
||||||
.Returns(new OkResponse());
|
.Returns(new OkResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheScopedRepoIsCalledCorrectly()
|
private void ThenTheScopedRepoIsCalledCorrectly()
|
||||||
{
|
{
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Verify(x => x.Add("HttpResponseMessage", _response.Data), Times.Once());
|
.Verify(x => x.Add("HttpResponseMessage", _response.Data), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
|
||||||
{
|
|
||||||
_result = _client.GetAsync(_url).Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenTheRequestIs(Ocelot.Request.Request request)
|
|
||||||
{
|
|
||||||
_request = new OkResponse<Ocelot.Request.Request>(request);
|
|
||||||
_scopedRepository
|
|
||||||
.Setup(x => x.Get<Ocelot.Request.Request>(It.IsAny<string>()))
|
|
||||||
.Returns(_request);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_client.Dispose();
|
|
||||||
_server.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
test/Ocelot.UnitTests/Responder/AnyError.cs
Normal file
15
test/Ocelot.UnitTests/Responder/AnyError.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Ocelot.Errors;
|
||||||
|
|
||||||
|
namespace Ocelot.UnitTests.Responder
|
||||||
|
{
|
||||||
|
class AnyError : Error
|
||||||
|
{
|
||||||
|
public AnyError() : base("blahh", OcelotErrorCode.UnknownError)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnyError(OcelotErrorCode errorCode) : base("blah", errorCode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
using Ocelot.Errors;
|
using Ocelot.Errors;
|
||||||
using Ocelot.Middleware;
|
|
||||||
using Ocelot.Requester;
|
|
||||||
using Ocelot.Responder;
|
using Ocelot.Responder;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
@ -21,47 +20,127 @@ namespace Ocelot.UnitTests.Responder
|
|||||||
_codeMapper = new ErrorsToHttpStatusCodeMapper();
|
_codeMapper = new ErrorsToHttpStatusCodeMapper();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Theory]
|
||||||
public void should_return_timeout()
|
[InlineData(OcelotErrorCode.UnauthenticatedError)]
|
||||||
|
public void should_return_unauthorized(OcelotErrorCode errorCode)
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereAreErrors(new List<Error>
|
ShouldMapErrorToStatusCode(errorCode, HttpStatusCode.Unauthorized);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(OcelotErrorCode.CannotFindClaimError)]
|
||||||
|
[InlineData(OcelotErrorCode.ClaimValueNotAuthorisedError)]
|
||||||
|
[InlineData(OcelotErrorCode.ScopeNotAuthorisedError)]
|
||||||
|
[InlineData(OcelotErrorCode.UnauthorizedError)]
|
||||||
|
[InlineData(OcelotErrorCode.UserDoesNotHaveClaimError)]
|
||||||
|
public void should_return_forbidden(OcelotErrorCode errorCode)
|
||||||
{
|
{
|
||||||
new RequestTimedOutError(new Exception())
|
ShouldMapErrorToStatusCode(errorCode, HttpStatusCode.Forbidden);
|
||||||
}))
|
}
|
||||||
.When(x => x.WhenIGetErrorStatusCode())
|
|
||||||
.Then(x => x.ThenTheResponseIsStatusCodeIs(503))
|
[Theory]
|
||||||
.BDDfy();
|
[InlineData(OcelotErrorCode.RequestTimedOutError)]
|
||||||
|
public void should_return_service_unavailable(OcelotErrorCode errorCode)
|
||||||
|
{
|
||||||
|
ShouldMapErrorToStatusCode(errorCode, HttpStatusCode.ServiceUnavailable);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(OcelotErrorCode.CannotAddDataError)]
|
||||||
|
[InlineData(OcelotErrorCode.CannotFindDataError)]
|
||||||
|
[InlineData(OcelotErrorCode.DownstreamHostNullOrEmptyError)]
|
||||||
|
[InlineData(OcelotErrorCode.DownstreamPathNullOrEmptyError)]
|
||||||
|
[InlineData(OcelotErrorCode.DownstreampathTemplateAlreadyUsedError)]
|
||||||
|
[InlineData(OcelotErrorCode.DownstreamPathTemplateContainsSchemeError)]
|
||||||
|
[InlineData(OcelotErrorCode.DownstreamSchemeNullOrEmptyError)]
|
||||||
|
[InlineData(OcelotErrorCode.InstructionNotForClaimsError)]
|
||||||
|
[InlineData(OcelotErrorCode.NoInstructionsError)]
|
||||||
|
[InlineData(OcelotErrorCode.ParsingConfigurationHeaderError)]
|
||||||
|
[InlineData(OcelotErrorCode.RateLimitOptionsError)]
|
||||||
|
[InlineData(OcelotErrorCode.ServicesAreEmptyError)]
|
||||||
|
[InlineData(OcelotErrorCode.ServicesAreNullError)]
|
||||||
|
[InlineData(OcelotErrorCode.UnableToCompleteRequestError)]
|
||||||
|
[InlineData(OcelotErrorCode.UnableToCreateAuthenticationHandlerError)]
|
||||||
|
[InlineData(OcelotErrorCode.UnableToFindDownstreamRouteError)]
|
||||||
|
[InlineData(OcelotErrorCode.UnableToFindLoadBalancerError)]
|
||||||
|
[InlineData(OcelotErrorCode.UnableToFindServiceDiscoveryProviderError)]
|
||||||
|
[InlineData(OcelotErrorCode.UnableToFindQoSProviderError)]
|
||||||
|
[InlineData(OcelotErrorCode.UnableToSetConfigInConsulError)]
|
||||||
|
[InlineData(OcelotErrorCode.UnknownError)]
|
||||||
|
[InlineData(OcelotErrorCode.UnmappableRequestError)]
|
||||||
|
[InlineData(OcelotErrorCode.UnsupportedAuthenticationProviderError)]
|
||||||
|
public void should_return_not_found(OcelotErrorCode errorCode)
|
||||||
|
{
|
||||||
|
ShouldMapErrorToStatusCode(errorCode, HttpStatusCode.NotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_create_unauthenticated_response_code()
|
public void AuthenticationErrorsHaveHighestPriority()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereAreErrors(new List<Error>
|
var errors = new List<OcelotErrorCode>
|
||||||
{
|
{
|
||||||
new UnauthenticatedError("no matter")
|
OcelotErrorCode.CannotAddDataError,
|
||||||
}))
|
OcelotErrorCode.CannotFindClaimError,
|
||||||
.When(x => x.WhenIGetErrorStatusCode())
|
OcelotErrorCode.UnauthenticatedError,
|
||||||
.Then(x => x.ThenTheResponseIsStatusCodeIs(401))
|
OcelotErrorCode.RequestTimedOutError,
|
||||||
.BDDfy();
|
};
|
||||||
|
|
||||||
|
ShouldMapErrorsToStatusCode(errors, HttpStatusCode.Unauthorized);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_create_not_found_response_response_code()
|
public void AuthorisationErrorsHaveSecondHighestPriority()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereAreErrors(new List<Error>
|
var errors = new List<OcelotErrorCode>
|
||||||
{
|
{
|
||||||
new AnyError()
|
OcelotErrorCode.CannotAddDataError,
|
||||||
}))
|
OcelotErrorCode.CannotFindClaimError,
|
||||||
.When(x => x.WhenIGetErrorStatusCode())
|
OcelotErrorCode.RequestTimedOutError
|
||||||
.Then(x => x.ThenTheResponseIsStatusCodeIs(404))
|
};
|
||||||
.BDDfy();
|
|
||||||
|
ShouldMapErrorsToStatusCode(errors, HttpStatusCode.Forbidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
class AnyError : Error
|
[Fact]
|
||||||
|
public void ServiceUnavailableErrorsHaveThirdHighestPriority()
|
||||||
{
|
{
|
||||||
public AnyError() : base("blahh", OcelotErrorCode.UnknownError)
|
var errors = new List<OcelotErrorCode>
|
||||||
{
|
{
|
||||||
|
OcelotErrorCode.CannotAddDataError,
|
||||||
|
OcelotErrorCode.RequestTimedOutError
|
||||||
|
};
|
||||||
|
|
||||||
|
ShouldMapErrorsToStatusCode(errors, HttpStatusCode.ServiceUnavailable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void check_we_have_considered_all_errors_in_these_tests()
|
||||||
|
{
|
||||||
|
// If this test fails then it's because the number of error codes has changed.
|
||||||
|
// You should make the appropriate changes to the test cases here to ensure
|
||||||
|
// they cover all the error codes, and then modify this assertion.
|
||||||
|
Enum.GetNames(typeof(OcelotErrorCode)).Length.ShouldBe(30, "Looks like the number of error codes has changed. Do you need to modify ErrorsToHttpStatusCodeMapper?");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShouldMapErrorToStatusCode(OcelotErrorCode errorCode, HttpStatusCode expectedHttpStatusCode)
|
||||||
|
{
|
||||||
|
ShouldMapErrorsToStatusCode(new List<OcelotErrorCode> { errorCode }, expectedHttpStatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShouldMapErrorsToStatusCode(List<OcelotErrorCode> errorCodes, HttpStatusCode expectedHttpStatusCode)
|
||||||
|
{
|
||||||
|
var errors = new List<Error>();
|
||||||
|
|
||||||
|
foreach(var errorCode in errorCodes)
|
||||||
|
{
|
||||||
|
errors.Add(new AnyError(errorCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Given(x => x.GivenThereAreErrors(errors))
|
||||||
|
.When(x => x.WhenIGetErrorStatusCode())
|
||||||
|
.Then(x => x.ThenTheResponseIsStatusCodeIs(expectedHttpStatusCode))
|
||||||
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenThereAreErrors(List<Error> errors)
|
private void GivenThereAreErrors(List<Error> errors)
|
||||||
@ -78,5 +157,10 @@ namespace Ocelot.UnitTests.Responder
|
|||||||
{
|
{
|
||||||
_result.ShouldBe(expectedCode);
|
_result.ShouldBe(expectedCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ThenTheResponseIsStatusCodeIs(HttpStatusCode expectedCode)
|
||||||
|
{
|
||||||
|
_result.ShouldBe((int)expectedCode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
using System;
|
namespace Ocelot.UnitTests.Responder
|
||||||
using System.IO;
|
{
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Infrastructure.RequestData;
|
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.Responder;
|
using Ocelot.Responder;
|
||||||
using Ocelot.Responder.Middleware;
|
using Ocelot.Responder.Middleware;
|
||||||
@ -15,46 +11,18 @@ using Ocelot.Responses;
|
|||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Responder
|
public class ResponderMiddlewareTests : ServerHostedMiddlewareTest
|
||||||
{
|
|
||||||
public class ResponderMiddlewareTests : IDisposable
|
|
||||||
{
|
{
|
||||||
private readonly Mock<IHttpResponder> _responder;
|
private readonly Mock<IHttpResponder> _responder;
|
||||||
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
|
|
||||||
private readonly Mock<IErrorsToHttpStatusCodeMapper> _codeMapper;
|
private readonly Mock<IErrorsToHttpStatusCodeMapper> _codeMapper;
|
||||||
private readonly string _url;
|
|
||||||
private readonly TestServer _server;
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
private HttpResponseMessage _result;
|
|
||||||
private OkResponse<HttpResponseMessage> _response;
|
private OkResponse<HttpResponseMessage> _response;
|
||||||
|
|
||||||
public ResponderMiddlewareTests()
|
public ResponderMiddlewareTests()
|
||||||
{
|
{
|
||||||
_url = "http://localhost:51879";
|
|
||||||
_responder = new Mock<IHttpResponder>();
|
_responder = new Mock<IHttpResponder>();
|
||||||
_scopedRepository = new Mock<IRequestScopedDataRepository>();
|
|
||||||
_codeMapper = new Mock<IErrorsToHttpStatusCodeMapper>();
|
_codeMapper = new Mock<IErrorsToHttpStatusCodeMapper>();
|
||||||
var builder = new WebHostBuilder()
|
|
||||||
.ConfigureServices(x =>
|
|
||||||
{
|
|
||||||
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
|
||||||
x.AddLogging();
|
|
||||||
x.AddSingleton(_codeMapper.Object);
|
|
||||||
x.AddSingleton(_responder.Object);
|
|
||||||
x.AddSingleton(_scopedRepository.Object);
|
|
||||||
})
|
|
||||||
.UseUrls(_url)
|
|
||||||
.UseKestrel()
|
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
||||||
.UseIISIntegration()
|
|
||||||
.UseUrls(_url)
|
|
||||||
.Configure(app =>
|
|
||||||
{
|
|
||||||
app.UseResponderMiddleware();
|
|
||||||
});
|
|
||||||
|
|
||||||
_server = new TestServer(builder);
|
GivenTheTestServerIsConfigured();
|
||||||
_client = _server.CreateClient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -67,9 +35,31 @@ namespace Ocelot.UnitTests.Responder
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
|
||||||
|
services.AddLogging();
|
||||||
|
services.AddSingleton(_codeMapper.Object);
|
||||||
|
services.AddSingleton(_responder.Object);
|
||||||
|
services.AddSingleton(ScopedRepository.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseResponderMiddleware();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheHttpResponseMessageIs(HttpResponseMessage response)
|
||||||
|
{
|
||||||
|
_response = new OkResponse<HttpResponseMessage>(response);
|
||||||
|
ScopedRepository
|
||||||
|
.Setup(x => x.Get<HttpResponseMessage>(It.IsAny<string>()))
|
||||||
|
.Returns(_response);
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenThereAreNoPipelineErrors()
|
private void GivenThereAreNoPipelineErrors()
|
||||||
{
|
{
|
||||||
_scopedRepository
|
ScopedRepository
|
||||||
.Setup(x => x.Get<bool>(It.IsAny<string>()))
|
.Setup(x => x.Get<bool>(It.IsAny<string>()))
|
||||||
.Returns(new OkResponse<bool>(false));
|
.Returns(new OkResponse<bool>(false));
|
||||||
}
|
}
|
||||||
@ -78,24 +68,5 @@ namespace Ocelot.UnitTests.Responder
|
|||||||
{
|
{
|
||||||
//todo a better assert?
|
//todo a better assert?
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
|
||||||
{
|
|
||||||
_result = _client.GetAsync(_url).Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenTheHttpResponseMessageIs(HttpResponseMessage response)
|
|
||||||
{
|
|
||||||
_response = new OkResponse<HttpResponseMessage>(response);
|
|
||||||
_scopedRepository
|
|
||||||
.Setup(x => x.Get<HttpResponseMessage>(It.IsAny<string>()))
|
|
||||||
.Returns(_response);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_client.Dispose();
|
|
||||||
_server.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
62
test/Ocelot.UnitTests/ServerHostedMiddlewareTest.cs
Normal file
62
test/Ocelot.UnitTests/ServerHostedMiddlewareTest.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
namespace Ocelot.UnitTests
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Microsoft.AspNetCore.TestHost;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Moq;
|
||||||
|
using Ocelot.Infrastructure.RequestData;
|
||||||
|
|
||||||
|
public abstract class ServerHostedMiddlewareTest : IDisposable
|
||||||
|
{
|
||||||
|
protected TestServer Server { get; private set; }
|
||||||
|
protected HttpClient Client { get; private set; }
|
||||||
|
protected string Url { get; private set; }
|
||||||
|
protected HttpResponseMessage ResponseMessage { get; private set; }
|
||||||
|
protected Mock<IRequestScopedDataRepository> ScopedRepository { get; private set; }
|
||||||
|
|
||||||
|
public ServerHostedMiddlewareTest()
|
||||||
|
{
|
||||||
|
Url = "http://localhost:51879";
|
||||||
|
ScopedRepository = new Mock<IRequestScopedDataRepository>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void GivenTheTestServerIsConfigured()
|
||||||
|
{
|
||||||
|
var builder = new WebHostBuilder()
|
||||||
|
.ConfigureServices(x => GivenTheTestServerServicesAreConfigured(x))
|
||||||
|
.UseUrls(Url)
|
||||||
|
.UseKestrel()
|
||||||
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
|
.UseIISIntegration()
|
||||||
|
.Configure(app => GivenTheTestServerPipelineIsConfigured(app));
|
||||||
|
|
||||||
|
Server = new TestServer(builder);
|
||||||
|
Client = Server.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
|
||||||
|
{
|
||||||
|
// override this in your test fixture to set up service dependencies
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
// override this in your test fixture to set up the test server pipeline
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void WhenICallTheMiddleware()
|
||||||
|
{
|
||||||
|
ResponseMessage = Client.GetAsync(Url).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Client.Dispose();
|
||||||
|
Server.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -28,6 +28,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
public void should_lookup_service()
|
public void should_lookup_service()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenAServiceIsRegistered("product", "localhost:600", 80))
|
this.Given(x => x.GivenAServiceIsRegistered("product", "localhost:600", 80))
|
||||||
|
@ -0,0 +1,89 @@
|
|||||||
|
namespace Ocelot.UnitTests.TestData
|
||||||
|
{
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Ocelot.Configuration.Builder;
|
||||||
|
using Ocelot.Configuration.File;
|
||||||
|
|
||||||
|
public class AuthenticationConfigTestData
|
||||||
|
{
|
||||||
|
public static IEnumerable<object[]> GetAuthenticationData()
|
||||||
|
{
|
||||||
|
yield return new object[]
|
||||||
|
{
|
||||||
|
"IdentityServer",
|
||||||
|
new IdentityServerConfigBuilder()
|
||||||
|
.WithRequireHttps(true)
|
||||||
|
.WithApiName("test")
|
||||||
|
.WithApiSecret("test")
|
||||||
|
.WithProviderRootUrl("test")
|
||||||
|
.Build(),
|
||||||
|
new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
UpstreamPathTemplate = "/api/products/{productId}",
|
||||||
|
DownstreamPathTemplate = "/products/{productId}",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
ReRouteIsCaseSensitive = true,
|
||||||
|
AuthenticationOptions = new FileAuthenticationOptions
|
||||||
|
{
|
||||||
|
AllowedScopes = new List<string>(),
|
||||||
|
Provider = "IdentityServer",
|
||||||
|
IdentityServerConfig = new FileIdentityServerConfig
|
||||||
|
{
|
||||||
|
ProviderRootUrl = "http://localhost:51888",
|
||||||
|
RequireHttps = false,
|
||||||
|
ApiName = "api",
|
||||||
|
ApiSecret = "secret"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AddHeadersToRequest =
|
||||||
|
{
|
||||||
|
{ "CustomerId", "Claims[CustomerId] > value" },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
yield return new object[]
|
||||||
|
{
|
||||||
|
"Jwt",
|
||||||
|
new JwtConfigBuilder()
|
||||||
|
.WithAudience("a")
|
||||||
|
.WithAuthority("au")
|
||||||
|
.Build(),
|
||||||
|
new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
UpstreamPathTemplate = "/api/products/{productId}",
|
||||||
|
DownstreamPathTemplate = "/products/{productId}",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
ReRouteIsCaseSensitive = true,
|
||||||
|
AuthenticationOptions = new FileAuthenticationOptions
|
||||||
|
{
|
||||||
|
AllowedScopes = new List<string>(),
|
||||||
|
Provider = "IdentityServer",
|
||||||
|
JwtConfig = new FileJwtConfig
|
||||||
|
{
|
||||||
|
Audience = "a",
|
||||||
|
Authority = "au"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AddHeadersToRequest =
|
||||||
|
{
|
||||||
|
{ "CustomerId", "Claims[CustomerId] > value" },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user