Merge pull request #26 from TomPallister/develop

merge newest code
This commit is contained in:
geffzhang 2017-06-12 09:09:25 +08:00 committed by GitHub
commit 88698d487f
59 changed files with 1205 additions and 703 deletions

View File

@ -92,7 +92,7 @@ Task("Version")
if (AppVeyor.IsRunningOnAppVeyor)
{
Information("Persisting version number...");
PersistVersion(nugetVersion);
PersistVersion(committedVersion, nugetVersion);
buildVersion = nugetVersion;
}
else
@ -229,7 +229,7 @@ Task("CreatePackages")
EnsureDirectoryExists(packagesDir);
CopyFiles("./src/**/Ocelot.*.nupkg", packagesDir);
GenerateReleaseNotes();
GenerateReleaseNotes(releaseNotesFile);
System.IO.File.WriteAllLines(artifactsFile, new[]{
"nuget:Ocelot." + buildVersion + ".nupkg",
@ -251,9 +251,9 @@ Task("ReleasePackagesToUnstableFeed")
.IsDependentOn("CreatePackages")
.Does(() =>
{
if (ShouldPublishToUnstableFeed())
if (ShouldPublishToUnstableFeed(nugetFeedUnstableBranchFilter, versioning.BranchName))
{
PublishPackages(nugetFeedUnstableKey, nugetFeedUnstableUploadUrl, nugetFeedUnstableSymbolsUploadUrl);
PublishPackages(packagesDir, artifactsFile, nugetFeedUnstableKey, nugetFeedUnstableUploadUrl, nugetFeedUnstableSymbolsUploadUrl);
}
});
@ -306,7 +306,7 @@ Task("ReleasePackagesToStableFeed")
.IsDependentOn("DownloadGitHubReleaseArtifacts")
.Does(() =>
{
PublishPackages(nugetFeedStableKey, nugetFeedStableUploadUrl, nugetFeedStableSymbolsUploadUrl);
PublishPackages(packagesDir, artifactsFile, nugetFeedStableKey, nugetFeedStableUploadUrl, nugetFeedStableSymbolsUploadUrl);
});
Task("Release")
@ -326,9 +326,9 @@ private GitVersion GetNuGetVersionForCommit()
}
/// Updates project version in all of our projects
private void PersistVersion(string version)
private void PersistVersion(string committedVersion, string newVersion)
{
Information(string.Format("We'll search all csproj files for {0} and replace with {1}...", committedVersion, version));
Information(string.Format("We'll search all csproj files for {0} and replace with {1}...", committedVersion, newVersion));
var projectFiles = GetFiles("./**/*.csproj");
@ -339,24 +339,30 @@ private void PersistVersion(string version)
Information(string.Format("Updating {0}...", file));
var updatedProjectFile = System.IO.File.ReadAllText(file)
.Replace(committedVersion, version);
.Replace(committedVersion, newVersion);
System.IO.File.WriteAllText(file, updatedProjectFile);
}
}
/// generates release notes based on issues closed in GitHub since the last release
private void GenerateReleaseNotes()
private void GenerateReleaseNotes(ConvertableFilePath file)
{
Information("Generating release notes at " + releaseNotesFile);
if(!IsRunningOnWindows())
{
Warning("We are not running on Windows so we cannot generate release notes.");
return;
}
Information("Generating release notes at " + file);
var releaseNotesExitCode = StartProcess(
@"tools/GitReleaseNotes/tools/gitreleasenotes.exe",
new ProcessSettings { Arguments = ". /o " + releaseNotesFile });
new ProcessSettings { Arguments = ". /o " + file });
if (string.IsNullOrEmpty(System.IO.File.ReadAllText(releaseNotesFile)))
if (string.IsNullOrEmpty(System.IO.File.ReadAllText(file)))
{
System.IO.File.WriteAllText(releaseNotesFile, "No issues closed since last release");
System.IO.File.WriteAllText(file, "No issues closed since last release");
}
if (releaseNotesExitCode != 0)
@ -366,7 +372,7 @@ private void GenerateReleaseNotes()
}
/// Publishes code and symbols packages to nuget feed, based on contents of artifacts file
private void PublishPackages(string feedApiKey, string codeFeedUrl, string symbolFeedUrl)
private void PublishPackages(ConvertableDirectoryPath packagesDir, ConvertableFilePath artifactsFile, string feedApiKey, string codeFeedUrl, string symbolFeedUrl)
{
var artifacts = System.IO.File
.ReadAllLines(artifactsFile)
@ -375,6 +381,8 @@ private void PublishPackages(string feedApiKey, string codeFeedUrl, string symbo
var codePackage = packagesDir + File(artifacts["nuget"]);
Information("Pushing package " + codePackage);
NuGetPush(
codePackage,
new NuGetPushSettings {
@ -401,17 +409,17 @@ private string GetResource(string url)
}
}
private bool ShouldPublishToUnstableFeed()
private bool ShouldPublishToUnstableFeed(string filter, string branchName)
{
var regex = new System.Text.RegularExpressions.Regex(nugetFeedUnstableBranchFilter);
var publish = regex.IsMatch(versioning.BranchName);
var regex = new System.Text.RegularExpressions.Regex(filter);
var publish = regex.IsMatch(branchName);
if (publish)
{
Information("Branch " + versioning.BranchName + " will be published to the unstable feed");
Information("Branch " + branchName + " will be published to the unstable feed");
}
else
{
Information("Branch " + versioning.BranchName + " will not be published to the unstable feed");
Information("Branch " + branchName + " will not be published to the unstable feed");
}
return publish;
}

View File

@ -7,7 +7,7 @@ namespace Ocelot.Authorisation
{
using Infrastructure.Claims.Parser;
public class ClaimsAuthoriser : IAuthoriser
public class ClaimsAuthoriser : IClaimsAuthoriser
{
private readonly IClaimsParser _claimsParser;

View File

@ -5,9 +5,8 @@ namespace Ocelot.Authorisation
{
using System.Collections.Generic;
public interface IAuthoriser
public interface IClaimsAuthoriser
{
Response<bool> Authorise(ClaimsPrincipal claimsPrincipal,
Dictionary<string, string> routeClaimsRequirement);
Response<bool> Authorise(ClaimsPrincipal claimsPrincipal, Dictionary<string, string> routeClaimsRequirement);
}
}

View File

@ -0,0 +1,12 @@
using System.Security.Claims;
using Ocelot.Responses;
namespace Ocelot.Authorisation
{
using System.Collections.Generic;
public interface IScopesAuthoriser
{
Response<bool> Authorise(ClaimsPrincipal claimsPrincipal, List<string> routeAllowedScopes);
}
}

View File

@ -1,6 +1,7 @@
using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Responses;
using Ocelot.Configuration;
namespace Ocelot.Authorisation.Middleware
{
@ -13,17 +14,20 @@ namespace Ocelot.Authorisation.Middleware
public class AuthorisationMiddleware : OcelotMiddleware
{
private readonly RequestDelegate _next;
private readonly IAuthoriser _authoriser;
private readonly IClaimsAuthoriser _claimsAuthoriser;
private readonly IScopesAuthoriser _scopesAuthoriser;
private readonly IOcelotLogger _logger;
public AuthorisationMiddleware(RequestDelegate next,
IRequestScopedDataRepository requestScopedDataRepository,
IAuthoriser authoriser,
IClaimsAuthoriser claimsAuthoriser,
IScopesAuthoriser scopesAuthoriser,
IOcelotLoggerFactory loggerFactory)
: base(requestScopedDataRepository)
{
_next = next;
_authoriser = authoriser;
_claimsAuthoriser = claimsAuthoriser;
_scopesAuthoriser = scopesAuthoriser;
_logger = loggerFactory.CreateLogger<AuthorisationMiddleware>();
}
@ -31,11 +35,41 @@ namespace Ocelot.Authorisation.Middleware
{
_logger.LogDebug("started authorisation");
if (DownstreamRoute.ReRoute.IsAuthorised)
if (IsAuthenticatedRoute(DownstreamRoute.ReRoute))
{
_logger.LogDebug("route is authenticated scopes must be checked");
var authorised = _scopesAuthoriser.Authorise(context.User, DownstreamRoute.ReRoute.AuthenticationOptions.AllowedScopes);
if (authorised.IsError)
{
_logger.LogDebug("error authorising user scopes");
SetPipelineError(authorised.Errors);
return;
}
if (IsAuthorised(authorised))
{
_logger.LogDebug("user scopes is authorised calling next authorisation checks");
}
else
{
_logger.LogDebug("user scopes is not authorised setting pipeline error");
SetPipelineError(new List<Error>
{
new UnauthorisedError(
$"{context.User.Identity.Name} unable to access {DownstreamRoute.ReRoute.UpstreamPathTemplate.Value}")
});
}
}
if (IsAuthorisedRoute(DownstreamRoute.ReRoute))
{
_logger.LogDebug("route is authorised");
var authorised = _authoriser.Authorise(context.User, DownstreamRoute.ReRoute.RouteClaimsRequirement);
var authorised = _claimsAuthoriser.Authorise(context.User, DownstreamRoute.ReRoute.RouteClaimsRequirement);
if (authorised.IsError)
{
@ -78,5 +112,15 @@ namespace Ocelot.Authorisation.Middleware
{
return authorised.Data;
}
private static bool IsAuthenticatedRoute(ReRoute reRoute)
{
return reRoute.IsAuthenticated;
}
private static bool IsAuthorisedRoute(ReRoute reRoute)
{
return reRoute.IsAuthorised;
}
}
}

View File

@ -0,0 +1,12 @@
using Ocelot.Errors;
namespace Ocelot.Authorisation
{
public class ScopeNotAuthorisedError : Error
{
public ScopeNotAuthorisedError(string message)
: base(message, OcelotErrorCode.ScopeNotAuthorisedError)
{
}
}
}

View File

@ -0,0 +1,51 @@
using IdentityModel;
using Ocelot.Errors;
using Ocelot.Responses;
using System.Collections.Generic;
using System.Security.Claims;
using System.Linq;
namespace Ocelot.Authorisation
{
using Infrastructure.Claims.Parser;
public class ScopesAuthoriser : IScopesAuthoriser
{
private readonly IClaimsParser _claimsParser;
public ScopesAuthoriser(IClaimsParser claimsParser)
{
_claimsParser = claimsParser;
}
public Response<bool> Authorise(ClaimsPrincipal claimsPrincipal, List<string> routeAllowedScopes)
{
if (routeAllowedScopes == null || routeAllowedScopes.Count == 0)
{
return new OkResponse<bool>(true);
}
var values = _claimsParser.GetValuesByClaimType(claimsPrincipal.Claims, JwtClaimTypes.Scope);
if (values.IsError)
{
return new ErrorResponse<bool>(values.Errors);
}
var userScopes = values.Data;
List<string> matchesScopes = routeAllowedScopes.Intersect(userScopes).ToList();
if (matchesScopes == null || matchesScopes.Count == 0)
{
return new ErrorResponse<bool>(new List<Error>
{
new ScopeNotAuthorisedError(
$"no one user scope: '{string.Join(",", userScopes)}' match with some allowed scope: '{string.Join(",", routeAllowedScopes)}'")
});
}
return new OkResponse<bool>(true);
}
}
}

View File

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Net.Http;
using Ocelot.Values;
using System.Linq;
namespace Ocelot.Configuration.Builder
{
@ -11,7 +12,7 @@ namespace Ocelot.Configuration.Builder
private string _downstreamPathTemplate;
private string _upstreamTemplate;
private string _upstreamTemplatePattern;
private string _upstreamHttpMethod;
private List<HttpMethod> _upstreamHttpMethod;
private bool _isAuthenticated;
private List<ClaimToThing> _configHeaderExtractorProperties;
private List<ClaimToThing> _claimToClaims;
@ -66,11 +67,13 @@ namespace Ocelot.Configuration.Builder
_upstreamTemplatePattern = input;
return this;
}
public ReRouteBuilder WithUpstreamHttpMethod(string input)
public ReRouteBuilder WithUpstreamHttpMethod(List<string> input)
{
_upstreamHttpMethod = input;
_upstreamHttpMethod = (input.Count == 0) ? new List<HttpMethod>() : input.Select(x => new HttpMethod(x.Trim())).ToList();
return this;
}
public ReRouteBuilder WithIsAuthenticated(bool input)
{
_isAuthenticated = input;
@ -143,7 +146,6 @@ namespace Ocelot.Configuration.Builder
return this;
}
public ReRouteBuilder WithLoadBalancerKey(string loadBalancerKey)
{
_loadBalancerKey = loadBalancerKey;
@ -180,7 +182,7 @@ namespace Ocelot.Configuration.Builder
return new ReRoute(
new PathTemplate(_downstreamPathTemplate),
new PathTemplate(_upstreamTemplate),
new HttpMethod(_upstreamHttpMethod),
_upstreamHttpMethod,
_upstreamTemplatePattern,
_isAuthenticated,
_authenticationOptions,

View File

@ -6,6 +6,7 @@ namespace Ocelot.Configuration.File
{
public FileReRoute()
{
UpstreamHttpMethod = new List<string>();
AddHeadersToRequest = new Dictionary<string, string>();
AddClaimsToRequest = new Dictionary<string, string>();
RouteClaimsRequirement = new Dictionary<string, string>();
@ -18,7 +19,7 @@ namespace Ocelot.Configuration.File
public string DownstreamPathTemplate { get; set; }
public string UpstreamPathTemplate { get; set; }
public string UpstreamHttpMethod { get; set; }
public List<string> UpstreamHttpMethod { get; set; }
public FileAuthenticationOptions AuthenticationOptions { get; set; }
public Dictionary<string, string> AddHeadersToRequest { get; set; }
public Dictionary<string, string> AddClaimsToRequest { get; set; }

View File

@ -8,7 +8,7 @@ namespace Ocelot.Configuration
{
public ReRoute(PathTemplate downstreamPathTemplate,
PathTemplate upstreamPathTemplate,
HttpMethod upstreamHttpMethod,
List<HttpMethod> upstreamHttpMethod,
string upstreamTemplatePattern,
bool isAuthenticated,
AuthenticationOptions authenticationOptions,
@ -64,7 +64,7 @@ namespace Ocelot.Configuration
public PathTemplate DownstreamPathTemplate { get; private set; }
public PathTemplate UpstreamPathTemplate { get; private set; }
public string UpstreamTemplatePattern { get; private set; }
public HttpMethod UpstreamHttpMethod { get; private set; }
public List<HttpMethod> UpstreamHttpMethod { get; private set; }
public bool IsAuthenticated { get; private set; }
public bool IsAuthorised { get; private set; }
public AuthenticationOptions AuthenticationOptions { get; private set; }

View File

@ -12,7 +12,7 @@ namespace Ocelot.Configuration.Validator
{
public Response<ConfigurationValidationResult> IsValid(FileConfiguration configuration)
{
var result = CheckForDupliateReRoutes(configuration);
var result = CheckForDuplicateReRoutes(configuration);
if (result.IsError)
{
@ -97,25 +97,41 @@ namespace Ocelot.Configuration.Validator
return new ConfigurationValidationResult(false, errors);
}
private ConfigurationValidationResult CheckForDupliateReRoutes(FileConfiguration configuration)
private ConfigurationValidationResult CheckForDuplicateReRoutes(FileConfiguration configuration)
{
var hasDupes = configuration.ReRoutes
.GroupBy(x => new { x.UpstreamPathTemplate, x.UpstreamHttpMethod }).Any(x => x.Skip(1).Any());
var duplicatedUpstreamPathTemplates = new List<string>();
if (!hasDupes)
var distinctUpstreamPathTemplates = configuration.ReRoutes.Select(x => x.UpstreamPathTemplate).Distinct();
foreach (string upstreamPathTemplate in distinctUpstreamPathTemplates)
{
var reRoutesWithUpstreamPathTemplate = configuration.ReRoutes.Where(x => x.UpstreamPathTemplate == upstreamPathTemplate);
var hasEmptyListToAllowAllHttpVerbs = reRoutesWithUpstreamPathTemplate.Where(x => x.UpstreamHttpMethod.Count() == 0).Any();
var hasDuplicateEmptyListToAllowAllHttpVerbs = reRoutesWithUpstreamPathTemplate.Where(x => x.UpstreamHttpMethod.Count() == 0).Count() > 1;
var hasSpecificHttpVerbs = reRoutesWithUpstreamPathTemplate.Where(x => x.UpstreamHttpMethod.Count() > 0).Any();
var hasDuplicateSpecificHttpVerbs = reRoutesWithUpstreamPathTemplate.SelectMany(x => x.UpstreamHttpMethod).GroupBy(x => x.ToLower()).SelectMany(x => x.Skip(1)).Any();
if (hasDuplicateEmptyListToAllowAllHttpVerbs || hasDuplicateSpecificHttpVerbs || (hasEmptyListToAllowAllHttpVerbs && hasSpecificHttpVerbs))
{
duplicatedUpstreamPathTemplates.Add(upstreamPathTemplate);
}
}
if (duplicatedUpstreamPathTemplates.Count() == 0)
{
return new ConfigurationValidationResult(false);
}
else
{
var errors = duplicatedUpstreamPathTemplates
.Select(d => new DownstreamPathTemplateAlreadyUsedError(string.Format("Duplicate DownstreamPath: {0}", d)))
.Cast<Error>()
.ToList();
var dupes = configuration.ReRoutes.GroupBy(x => new { x.UpstreamPathTemplate, x.UpstreamHttpMethod })
.Where(x => x.Skip(1).Any());
return new ConfigurationValidationResult(true, errors);
}
var errors = dupes
.Select(d => new DownstreamPathTemplateAlreadyUsedError(string.Format("Duplicate DownstreamPath: {0}", d.Key.UpstreamPathTemplate)))
.Cast<Error>()
.ToList();
return new ConfigurationValidationResult(true, errors);
}
private ConfigurationValidationResult CheckForReRoutesRateLimitOptions(FileConfiguration configuration)

View File

@ -144,7 +144,8 @@ namespace Ocelot.DependencyInjection
services.TryAddSingleton<IRemoveOutputHeaders, RemoveOutputHeaders>();
services.TryAddSingleton<IOcelotConfigurationProvider, OcelotConfigurationProvider>();
services.TryAddSingleton<IClaimToThingConfigurationParser, ClaimToThingConfigurationParser>();
services.TryAddSingleton<IAuthoriser, ClaimsAuthoriser>();
services.TryAddSingleton<IClaimsAuthoriser, ClaimsAuthoriser>();
services.TryAddSingleton<IScopesAuthoriser, ScopesAuthoriser>();
services.TryAddSingleton<IAddClaimsToRequest, AddClaimsToRequest>();
services.TryAddSingleton<IAddHeadersToRequest, AddHeadersToRequest>();
services.TryAddSingleton<IAddQueriesToRequest, AddQueriesToRequest>();

View File

@ -26,7 +26,7 @@ namespace Ocelot.DownstreamRouteFinder.Finder
{
var configuration = await _configProvider.Get();
var applicableReRoutes = configuration.Data.ReRoutes.Where(r => string.Equals(r.UpstreamHttpMethod.Method.ToLower(), upstreamHttpMethod.ToLower(), StringComparison.CurrentCultureIgnoreCase));
var applicableReRoutes = configuration.Data.ReRoutes.Where(r => r.UpstreamHttpMethod.Count == 0 || r.UpstreamHttpMethod.Select(x => x.Method.ToLower()).Contains(upstreamHttpMethod.ToLower()));
foreach (var reRoute in applicableReRoutes)
{

View File

@ -70,7 +70,7 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher
private bool CharactersDontMatch(char characterOne, char characterTwo)
{
return characterOne != characterTwo;
return char.ToLower(characterOne) != char.ToLower(characterTwo);
}
private bool ContinueScanningUrl(int counterForUrl, int urlLength)

View File

@ -17,6 +17,7 @@
InstructionNotForClaimsError,
UnauthorizedError,
ClaimValueNotAuthorisedError,
ScopeNotAuthorisedError,
UserDoesNotHaveClaimError,
DownstreamPathTemplateContainsSchemeError,
DownstreamPathNullOrEmptyError,

View File

@ -1,10 +1,10 @@
namespace Ocelot.Infrastructure.Claims.Parser
{
using Errors;
using Responses;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using Errors;
using Responses;
public class ClaimsParser : IClaimsParser
{
@ -37,6 +37,17 @@
return new OkResponse<string>(value);
}
public Response<List<string>> GetValuesByClaimType(IEnumerable<Claim> claims, string claimType)
{
List<string> values = new List<string>();
values.AddRange(claims.Where(x => x.Type == claimType).Select(x => x.Value).ToList());
return new OkResponse<List<string>>(values);
}
private Response<string> GetValue(IEnumerable<Claim> claims, string key)
{
var claim = claims.FirstOrDefault(c => c.Type == key);

View File

@ -7,5 +7,6 @@
public interface IClaimsParser
{
Response<string> GetValue(IEnumerable<Claim> claims, string key, string delimiter, int index);
Response<List<string>> GetValuesByClaimType(IEnumerable<Claim> claims, string claimType);
}
}

View File

@ -45,7 +45,7 @@
<PackageReference Include="Microsoft.AspNetCore.Authentication.Twitter" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="1.1.1" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.0.2" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1" />
<PackageReference Include="CacheManager.Core" Version="0.9.2" />
@ -53,7 +53,7 @@
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="0.9.2" />
<PackageReference Include="Consul" Version="0.7.2.1" />
<PackageReference Include="Polly" Version="5.0.3" />
<PackageReference Include="IdentityServer4" Version="1.0.1" />
<PackageReference Include="IdentityServer4" Version="1.5.1" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="1.1.1" />
</ItemGroup>

View File

@ -22,9 +22,12 @@ namespace Ocelot.Requester
public async Task<Response<HttpResponseMessage>> GetResponse(Request.Request request)
{
var cacheKey = GetCacheKey(request);
var builder = new HttpClientBuilder();
var cacheKey = GetCacheKey(request, builder);
var httpClient = GetHttpClient(cacheKey, builder);
IHttpClient httpClient = GetHttpClient(cacheKey);
try
{
var response = await httpClient.SendAsync(request.HttpRequestMessage);
@ -51,11 +54,10 @@ namespace Ocelot.Requester
}
private IHttpClient GetHttpClient(string cacheKey)
private IHttpClient GetHttpClient(string cacheKey, IHttpClientBuilder builder)
{
var builder = new HttpClientBuilder();
var httpClient = _cacheHandlers.Get(cacheKey);
if (httpClient == null)
{
httpClient = builder.Create();
@ -63,9 +65,16 @@ namespace Ocelot.Requester
return httpClient;
}
private string GetCacheKey(Request.Request request)
private string GetCacheKey(Request.Request request, IHttpClientBuilder builder)
{
string baseUrl = $"{request.HttpRequestMessage.RequestUri.Scheme}://{request.HttpRequestMessage.RequestUri.Authority}";
if (request.IsQos)
{
builder.WithQos(request.QosProvider, _logger);
baseUrl = $"{baseUrl}{request.QosProvider.CircuitBreaker.CircuitBreakerPolicy.PolicyKey}";
}
return baseUrl;
}
}

View File

@ -15,6 +15,7 @@ namespace Ocelot.Responder
if (errors.Any(e => e.Code == OcelotErrorCode.UnauthorizedError
|| e.Code == OcelotErrorCode.ClaimValueNotAuthorisedError
|| e.Code == OcelotErrorCode.ScopeNotAuthorisedError
|| e.Code == OcelotErrorCode.UserDoesNotHaveClaimError
|| e.Code == OcelotErrorCode.CannotFindClaimError))
{

View File

@ -48,21 +48,21 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = _downstreamServiceHost,
DownstreamScheme = _downstreamServiceScheme,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Post",
UpstreamHttpMethod = new List<string> { "Post" },
AuthenticationOptions = new FileAuthenticationOptions
{
AllowedScopes = new List<string>(),
AllowedScopes = new List<string>(),
Provider = "IdentityServer",
ProviderRootUrl = _identityServerRootUrl,
RequireHttps = false,
ApiName = "api",
ApiName = "api",
ApiSecret = "secret"
}
}
}
};
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt))
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
.And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
@ -86,21 +86,21 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = _downstreamServiceHost,
DownstreamScheme = _downstreamServiceScheme,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Post",
UpstreamHttpMethod = new List<string> { "Post" },
AuthenticationOptions = new FileAuthenticationOptions
{
AllowedScopes = new List<string>(),
AllowedScopes = new List<string>(),
Provider = "IdentityServer",
ProviderRootUrl = _identityServerRootUrl,
RequireHttps = false,
ApiName = "api",
ApiName = "api",
ApiSecret = "secret"
}
}
}
};
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Reference))
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())
@ -124,21 +124,21 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = _downstreamServiceHost,
DownstreamScheme = _downstreamServiceScheme,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
AuthenticationOptions = new FileAuthenticationOptions
{
AllowedScopes = new List<string>(),
AllowedScopes = new List<string>(),
Provider = "IdentityServer",
ProviderRootUrl = _identityServerRootUrl,
RequireHttps = false,
ApiName = "api",
ApiName = "api",
ApiSecret = "secret"
}
}
}
};
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt))
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
.And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 200, "Hello from Laura"))
.And(x => _steps.GivenIHaveAToken(_identityServerRootUrl))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
@ -150,6 +150,45 @@ namespace Ocelot.AcceptanceTests
.BDDfy();
}
[Fact]
public void should_return_response_401_using_identity_server_with_token_requested_for_other_api()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = _downstreamServicePath,
DownstreamPort = _downstreamServicePort,
DownstreamHost = _downstreamServiceHost,
DownstreamScheme = _downstreamServiceScheme,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" },
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.Jwt))
.And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 200, "Hello from Laura"))
.And(x => _steps.GivenIHaveATokenForApi2(_identityServerRootUrl))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.And(x => _steps.GivenIHaveAddedATokenToMyRequest())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Unauthorized))
.BDDfy();
}
[Fact]
public void should_return_201_using_identity_server_access_token()
{
@ -164,22 +203,22 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = _downstreamServiceHost,
DownstreamScheme = _downstreamServiceScheme,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Post",
UpstreamHttpMethod = new List<string> { "Post" },
AuthenticationOptions = new FileAuthenticationOptions
{
AllowedScopes = new List<string>(),
AllowedScopes = new List<string>(),
Provider = "IdentityServer",
ProviderRootUrl = _identityServerRootUrl,
RequireHttps = false,
ApiName = "api",
ApiName = "api",
ApiSecret = "secret"
}
}
}
};
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt))
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
.And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty))
.And(x => _steps.GivenIHaveAToken(_identityServerRootUrl))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
@ -205,21 +244,21 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = _downstreamServiceHost,
DownstreamScheme = _downstreamServiceScheme,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Post",
AuthenticationOptions = new FileAuthenticationOptions
UpstreamHttpMethod = new List<string> { "Post" },
AuthenticationOptions = new FileAuthenticationOptions
{
AllowedScopes = new List<string>(),
AllowedScopes = new List<string>(),
Provider = "IdentityServer",
ProviderRootUrl = _identityServerRootUrl,
RequireHttps = false,
ApiName = "api",
ApiName = "api",
ApiSecret = "secret"
}
}
}
};
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Reference))
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Reference))
.And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty))
.And(x => _steps.GivenIHaveAToken(_identityServerRootUrl))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
@ -252,7 +291,7 @@ namespace Ocelot.AcceptanceTests
_servicebuilder.Start();
}
private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType)
private void GivenThereIsAnIdentityServerOn(string url, string apiName, string api2Name, AccessTokenType tokenType)
{
_identityServerBuilder = new WebHostBuilder()
.UseUrls(url)
@ -276,6 +315,32 @@ namespace Ocelot.AcceptanceTests
Scopes = new List<Scope>()
{
new Scope("api"),
new Scope("api.readOnly"),
new Scope("openid"),
new Scope("offline_access")
},
ApiSecrets = new List<Secret>()
{
new Secret
{
Value = "secret".Sha256()
}
},
UserClaims = new List<string>()
{
"CustomerId", "LocationId"
}
},
new ApiResource
{
Name = api2Name,
Description = "My second API",
Enabled = true,
DisplayName = "second test",
Scopes = new List<Scope>()
{
new Scope("api2"),
new Scope("api2.readOnly"),
new Scope("openid"),
new Scope("offline_access")
},
@ -299,7 +364,7 @@ namespace Ocelot.AcceptanceTests
ClientId = "client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
AllowedScopes = new List<string> { apiName, "openid", "offline_access" },
AllowedScopes = new List<string> { apiName, api2Name, "api.readOnly", "openid", "offline_access" },
AccessTokenType = tokenType,
Enabled = true,
RequireClientSecret = false

View File

@ -42,7 +42,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
AuthenticationOptions = new FileAuthenticationOptions
{
AllowedScopes = new List<string>(),
@ -99,7 +99,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
AuthenticationOptions = new FileAuthenticationOptions
{
AllowedScopes = new List<string>(),
@ -140,6 +140,84 @@ namespace Ocelot.AcceptanceTests
.BDDfy();
}
[Fact]
public void should_return_response_200_using_identity_server_with_allowed_scope()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamPort = 51876,
DownstreamHost = "localhost",
DownstreamScheme = "http",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" },
AuthenticationOptions = new FileAuthenticationOptions
{
AllowedScopes = new List<string>{ "api", "api.readOnly", "openid", "offline_access" },
Provider = "IdentityServer",
ProviderRootUrl = "http://localhost:51888",
RequireHttps = false,
ApiName = "api",
ApiSecret = "secret"
}
}
}
};
this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:51888", "api", AccessTokenType.Jwt))
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51876", 200, "Hello from Laura"))
.And(x => _steps.GivenIHaveATokenForApiReadOnlyScope("http://localhost:51888"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.And(x => _steps.GivenIHaveAddedATokenToMyRequest())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.BDDfy();
}
[Fact]
public void should_return_response_403_using_identity_server_with_scope_not_allowed()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamPort = 51876,
DownstreamHost = "localhost",
DownstreamScheme = "http",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" },
AuthenticationOptions = new FileAuthenticationOptions
{
AllowedScopes = new List<string>{ "api", "openid", "offline_access" },
Provider = "IdentityServer",
ProviderRootUrl = "http://localhost:51888",
RequireHttps = false,
ApiName = "api",
ApiSecret = "secret"
}
}
}
};
this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:51888", "api", AccessTokenType.Jwt))
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51876", 200, "Hello from Laura"))
.And(x => _steps.GivenIHaveATokenForApiReadOnlyScope("http://localhost:51888"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.And(x => _steps.GivenIHaveAddedATokenToMyRequest())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Forbidden))
.BDDfy();
}
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
{
_servicebuilder = new WebHostBuilder()
@ -185,6 +263,7 @@ namespace Ocelot.AcceptanceTests
Scopes = new List<Scope>()
{
new Scope("api"),
new Scope("api.readOnly"),
new Scope("openid"),
new Scope("offline_access")
},
@ -209,7 +288,7 @@ namespace Ocelot.AcceptanceTests
ClientId = "client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
AllowedScopes = new List<string> { apiName, "openid", "offline_access" },
AllowedScopes = new List<string> { apiName, "api.readOnly", "openid", "offline_access" },
AccessTokenType = tokenType,
Enabled = true,
RequireClientSecret = false

View File

@ -36,7 +36,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
FileCacheOptions = new FileCacheOptions
{
TtlSeconds = 100
@ -72,7 +72,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
FileCacheOptions = new FileCacheOptions
{
TtlSeconds = 1

View File

@ -35,7 +35,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
@ -62,7 +62,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
ReRouteIsCaseSensitive = false,
}
}
@ -90,7 +90,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
ReRouteIsCaseSensitive = true,
}
}
@ -118,7 +118,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/PRODUCTS/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
ReRouteIsCaseSensitive = true,
}
}
@ -146,7 +146,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
ReRouteIsCaseSensitive = true,
}
}
@ -174,7 +174,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/PRODUCTS/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
ReRouteIsCaseSensitive = true,
}
}

View File

@ -56,12 +56,12 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
AuthenticationOptions = new FileAuthenticationOptions
{
AllowedScopes = new List<string>
{
"openid", "offline_access"
"openid", "offline_access", "api"
},
Provider = "IdentityServer",
ProviderRootUrl = "http://localhost:52888",

View File

@ -56,12 +56,12 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
AuthenticationOptions = new FileAuthenticationOptions
{
AllowedScopes = new List<string>
{
"openid", "offline_access"
"openid", "offline_access", "api"
},
Provider = "IdentityServer",
ProviderRootUrl = "http://localhost:57888",

View File

@ -47,7 +47,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/api/ClientRateLimit",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
RequestIdKey = _steps.RequestIdKey,
RateLimitOptions = new FileRateLimitRule()
@ -102,7 +102,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/api/ClientRateLimit",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
RequestIdKey = _steps.RequestIdKey,
RateLimitOptions = new FileRateLimitRule()

View File

@ -44,8 +44,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost",
DownstreamPort = 51779,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
},
GlobalConfiguration = new FileGlobalConfiguration()

View File

@ -50,7 +50,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
@ -87,8 +87,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
@ -125,8 +124,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
@ -163,7 +161,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
@ -200,7 +198,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
@ -237,7 +235,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};

View File

@ -43,7 +43,6 @@
<PackageReference Include="Microsoft.AspNetCore.Http" Version="1.1.1" />
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.0" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="1.1.1" />
<PackageReference Include="IdentityServer4" Version="1.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="1.1.1" />

View File

@ -39,13 +39,14 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost",
DownstreamPort = 51879,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
QoSOptions = new FileQoSOptions
{
ExceptionsAllowedBeforeBreaking = 1,
TimeoutValue = 500,
DurationOfBreak = 1000
}
},
}
}
};
@ -83,7 +84,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost",
DownstreamPort = 51879,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
QoSOptions = new FileQoSOptions
{
ExceptionsAllowedBeforeBreaking = 1,
@ -98,7 +99,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost",
DownstreamPort = 51880,
UpstreamPathTemplate = "working",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};

View File

@ -38,7 +38,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
RequestIdKey = _steps.RequestIdKey,
}
}
@ -66,8 +66,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
@ -96,7 +95,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
},
GlobalConfiguration = new FileGlobalConfiguration

View File

@ -31,7 +31,7 @@ namespace Ocelot.AcceptanceTests
{
DownstreamPathTemplate = "/",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
DownstreamPort = 53876,
DownstreamScheme = "http",
DownstreamHost = "localhost"

View File

@ -45,7 +45,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost",
DownstreamPort = 51879,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
@ -73,8 +73,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost",
DownstreamPort = 51879,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
@ -102,8 +101,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost/",
DownstreamPort = 51879,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
@ -131,8 +129,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost",
DownstreamPort = 51879,
UpstreamPathTemplate = "/products/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
@ -160,7 +157,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost",
DownstreamPort = 51879,
UpstreamPathTemplate = "/products",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
@ -188,7 +185,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost",
DownstreamPort = 51879,
UpstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
QoSOptions = new FileQoSOptions()
{
ExceptionsAllowedBeforeBreaking = 3,
@ -221,7 +218,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost",
DownstreamPort = 51879,
UpstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
@ -249,7 +246,7 @@ namespace Ocelot.AcceptanceTests
DownstreamPort = 51879,
DownstreamScheme = "http",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Post",
UpstreamHttpMethod = new List<string> { "Post" },
}
}
};
@ -277,7 +274,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http",
DownstreamHost = "localhost",
DownstreamPort = 51879,
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
@ -305,7 +302,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost",
DownstreamPort = 51879,
UpstreamPathTemplate = "/myApp1Name/api/{urlPath}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
@ -319,6 +316,62 @@ namespace Ocelot.AcceptanceTests
.BDDfy();
}
[Fact]
public void should_return_response_201_with_simple_url_and_multiple_upstream_http_method()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamHost = "localhost",
DownstreamPort = 51879,
DownstreamScheme = "http",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get", "Post" },
}
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", 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.Created))
.BDDfy();
}
[Fact]
public void should_return_response_200_with_simple_url_and_any_upstream_http_method()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamHost = "localhost",
DownstreamPort = 51879,
DownstreamScheme = "http",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string>(),
}
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.BDDfy();
}
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
{
_builder = new WebHostBuilder()

View File

@ -69,7 +69,7 @@ namespace Ocelot.AcceptanceTests
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
ServiceName = serviceName,
LoadBalancer = "LeastConnection",
}

View File

@ -199,6 +199,52 @@ namespace Ocelot.AcceptanceTests
}
}
public void GivenIHaveATokenForApiReadOnlyScope(string url)
{
var tokenUrl = $"{url}/connect/token";
var formData = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("client_id", "client"),
new KeyValuePair<string, string>("client_secret", "secret"),
new KeyValuePair<string, string>("scope", "api.readOnly"),
new KeyValuePair<string, string>("username", "test"),
new KeyValuePair<string, string>("password", "test"),
new KeyValuePair<string, string>("grant_type", "password")
};
var content = new FormUrlEncodedContent(formData);
using (var httpClient = new HttpClient())
{
var response = httpClient.PostAsync(tokenUrl, content).Result;
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
}
}
public void GivenIHaveATokenForApi2(string url)
{
var tokenUrl = $"{url}/connect/token";
var formData = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("client_id", "client"),
new KeyValuePair<string, string>("client_secret", "secret"),
new KeyValuePair<string, string>("scope", "api2"),
new KeyValuePair<string, string>("username", "test"),
new KeyValuePair<string, string>("password", "test"),
new KeyValuePair<string, string>("grant_type", "password")
};
var content = new FormUrlEncodedContent(formData);
using (var httpClient = new HttpClient())
{
var response = httpClient.PostAsync(tokenUrl, content).Result;
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
}
}
public void GivenIHaveAnOcelotToken(string adminPath)
{
var tokenUrl = $"{adminPath}/connect/token";

View File

@ -94,7 +94,7 @@ namespace Ocelot.IntegrationTests
DownstreamPort = 80,
DownstreamScheme = "https",
DownstreamPathTemplate = "/",
UpstreamHttpMethod = "get",
UpstreamHttpMethod = new List<string> { "get" },
UpstreamPathTemplate = "/"
},
new FileReRoute()
@ -103,7 +103,7 @@ namespace Ocelot.IntegrationTests
DownstreamPort = 80,
DownstreamScheme = "https",
DownstreamPathTemplate = "/",
UpstreamHttpMethod = "get",
UpstreamHttpMethod = new List<string> { "get" },
UpstreamPathTemplate = "/test"
}
}
@ -136,7 +136,7 @@ namespace Ocelot.IntegrationTests
DownstreamPort = 80,
DownstreamScheme = "https",
DownstreamPathTemplate = "/",
UpstreamHttpMethod = "get",
UpstreamHttpMethod = new List<string> { "get" },
UpstreamPathTemplate = "/"
},
new FileReRoute()
@ -145,7 +145,7 @@ namespace Ocelot.IntegrationTests
DownstreamPort = 80,
DownstreamScheme = "https",
DownstreamPathTemplate = "/",
UpstreamHttpMethod = "get",
UpstreamHttpMethod = new List<string> { "get" },
UpstreamPathTemplate = "/test"
}
}
@ -165,7 +165,7 @@ namespace Ocelot.IntegrationTests
DownstreamPort = 80,
DownstreamScheme = "http",
DownstreamPathTemplate = "/geoffrey",
UpstreamHttpMethod = "get",
UpstreamHttpMethod = new List<string> { "get" },
UpstreamPathTemplate = "/"
},
new FileReRoute()
@ -174,7 +174,7 @@ namespace Ocelot.IntegrationTests
DownstreamPort = 443,
DownstreamScheme = "https",
DownstreamPathTemplate = "/blooper/{productId}",
UpstreamHttpMethod = "post",
UpstreamHttpMethod = new List<string> { "post" },
UpstreamPathTemplate = "/test"
}
}

View File

@ -44,7 +44,7 @@
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.0" />
<PackageReference Include="xunit" Version="2.3.0-beta2-build3683" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="1.1.1" />
<PackageReference Include="IdentityServer4" Version="1.0.1" />
<PackageReference Include="IdentityServer4" Version="1.5.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1" />
<PackageReference Include="Shouldly" Version="2.8.2" />

View File

@ -55,7 +55,7 @@ namespace Ocelot.IntegrationTests
DownstreamHost = "localhost",
DownstreamPort = 51879,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};

View File

@ -1,311 +1,311 @@
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/",
"DownstreamScheme": "http",
"DownstreamHost": "localhost",
"DownstreamPort": 52876,
"UpstreamPathTemplate": "/identityserverexample",
"UpstreamHttpMethod": "Get",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"AuthenticationOptions": {
"Provider": "IdentityServer",
"ProviderRootUrl": "http://localhost:52888",
"ApiName": "api",
"AllowedScopes": [
"openid",
"offline_access"
],
"ApiSecret": "secret"
},
"AddHeadersToRequest": {
"CustomerId": "Claims[CustomerId] > value",
"LocationId": "Claims[LocationId] > value",
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
},
"AddClaimsToRequest": {
"CustomerId": "Claims[CustomerId] > value",
"LocationId": "Claims[LocationId] > value",
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
},
"AddQueriesToRequest": {
"CustomerId": "Claims[CustomerId] > value",
"LocationId": "Claims[LocationId] > value",
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
},
"RouteClaimsRequirement": {
"UserType": "registered"
},
"RequestIdKey": "OcRequestId"
},
{
"DownstreamPathTemplate": "/posts",
"DownstreamScheme": "https",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 443,
"UpstreamPathTemplate": "/posts",
"UpstreamHttpMethod": "Get",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Get",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts/{postId}/comments",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/{postId}/comments",
"UpstreamHttpMethod": "Get",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/comments",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/comments",
"UpstreamHttpMethod": "Get",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/posts",
"UpstreamHttpMethod": "Post",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Put",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Patch",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Delete",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/api/products",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/products",
"UpstreamHttpMethod": "Get",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/products/{productId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/products/{productId}",
"UpstreamHttpMethod": "Get",
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/products",
"DownstreamScheme": "http",
"DownstreamHost": "products20161126090340.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/products",
"UpstreamHttpMethod": "Post",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/api/products/{productId}",
"DownstreamScheme": "http",
"DownstreamHost": "products20161126090340.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/products/{productId}",
"UpstreamHttpMethod": "Put",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/products/{productId}",
"DownstreamScheme": "http",
"DownstreamHost": "products20161126090340.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/products/{productId}",
"UpstreamHttpMethod": "Delete",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/customers",
"UpstreamHttpMethod": "Get",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers/{customerId}",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": "Get",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/customers",
"UpstreamHttpMethod": "Post",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers/{customerId}",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": "Put",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers/{customerId}",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": "Delete",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/posts",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/",
"UpstreamHttpMethod": "Get",
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/",
"DownstreamScheme": "http",
"DownstreamHost": "www.bbc.co.uk",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/bbc/",
"UpstreamHttpMethod": "Get"
}
],
"ReRoutes": [
{
"DownstreamPathTemplate": "/",
"DownstreamScheme": "http",
"DownstreamHost": "localhost",
"DownstreamPort": 52876,
"UpstreamPathTemplate": "/identityserverexample",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"AuthenticationOptions": {
"Provider": "IdentityServer",
"ProviderRootUrl": "http://localhost:52888",
"ApiName": "api",
"AllowedScopes": [
"openid",
"offline_access"
],
"ApiSecret": "secret"
},
"AddHeadersToRequest": {
"CustomerId": "Claims[CustomerId] > value",
"LocationId": "Claims[LocationId] > value",
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
},
"AddClaimsToRequest": {
"CustomerId": "Claims[CustomerId] > value",
"LocationId": "Claims[LocationId] > value",
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
},
"AddQueriesToRequest": {
"CustomerId": "Claims[CustomerId] > value",
"LocationId": "Claims[LocationId] > value",
"UserType": "Claims[sub] > value[0] > |",
"UserId": "Claims[sub] > value[1] > |"
},
"RouteClaimsRequirement": {
"UserType": "registered"
},
"RequestIdKey": "OcRequestId"
},
{
"DownstreamPathTemplate": "/posts",
"DownstreamScheme": "https",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 443,
"UpstreamPathTemplate": "/posts",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts/{postId}/comments",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/{postId}/comments",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/comments",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/comments",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/posts",
"UpstreamHttpMethod": [ "Post" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": [ "Put" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": [ "Patch" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/posts/{postId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": [ "Delete" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/api/products",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/products",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/products/{productId}",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/products/{productId}",
"UpstreamHttpMethod": [ "Get" ],
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/products",
"DownstreamScheme": "http",
"DownstreamHost": "products20161126090340.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/products",
"UpstreamHttpMethod": [ "Post" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
}
},
{
"DownstreamPathTemplate": "/api/products/{productId}",
"DownstreamScheme": "http",
"DownstreamHost": "products20161126090340.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/products/{productId}",
"UpstreamHttpMethod": [ "Put" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/products/{productId}",
"DownstreamScheme": "http",
"DownstreamHost": "products20161126090340.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/products/{productId}",
"UpstreamHttpMethod": [ "Delete" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/customers",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers/{customerId}",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/customers",
"UpstreamHttpMethod": [ "Post" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers/{customerId}",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": [ "Put" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/api/customers/{customerId}",
"DownstreamScheme": "http",
"DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": [ "Delete" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/posts",
"DownstreamScheme": "http",
"DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/",
"UpstreamHttpMethod": [ "Get" ],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10,
"TimeoutValue": 5000
},
"FileCacheOptions": { "TtlSeconds": 15 }
},
{
"DownstreamPathTemplate": "/",
"DownstreamScheme": "http",
"DownstreamHost": "www.bbc.co.uk",
"DownstreamPort": 80,
"UpstreamPathTemplate": "/bbc/",
"UpstreamHttpMethod": [ "Get" ],
}
],
"GlobalConfiguration": {
"RequestIdKey": "OcRequestId",

View File

@ -72,7 +72,7 @@ namespace Ocelot.UnitTests.Authentication
public void should_call_next_middleware_if_route_is_not_authenticated()
{
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder()
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheUserIsAuthenticated())

View File

@ -25,7 +25,8 @@ namespace Ocelot.UnitTests.Authorization
public class AuthorisationMiddlewareTests : IDisposable
{
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
private readonly Mock<IAuthoriser> _authService;
private readonly Mock<IClaimsAuthoriser> _authService;
private readonly Mock<IScopesAuthoriser> _authScopesService;
private readonly string _url;
private readonly TestServer _server;
private readonly HttpClient _client;
@ -36,7 +37,8 @@ namespace Ocelot.UnitTests.Authorization
{
_url = "http://localhost:51879";
_scopedRepository = new Mock<IRequestScopedDataRepository>();
_authService = new Mock<IAuthoriser>();
_authService = new Mock<IClaimsAuthoriser>();
_authScopesService = new Mock<IScopesAuthoriser>();
var builder = new WebHostBuilder()
.ConfigureServices(x =>
@ -44,6 +46,7 @@ namespace Ocelot.UnitTests.Authorization
x.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
x.AddLogging();
x.AddSingleton(_authService.Object);
x.AddSingleton(_authScopesService.Object);
x.AddSingleton(_scopedRepository.Object);
})
.UseUrls(_url)
@ -66,7 +69,7 @@ namespace Ocelot.UnitTests.Authorization
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithIsAuthorised(true)
.WithUpstreamHttpMethod("Get") .WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.And(x => x.GivenTheAuthServiceReturns(new OkResponse<bool>(true)))
.When(x => x.WhenICallTheMiddleware())

View File

@ -91,7 +91,7 @@ namespace Ocelot.UnitTests.Cache
var reRoute = new ReRouteBuilder()
.WithIsCached(true)
.WithCacheOptions(new CacheOptions(100))
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build();
var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), reRoute);

View File

@ -72,7 +72,7 @@ namespace Ocelot.UnitTests.Claims
{
new ClaimToThing("sub", "UserType", "|", 0)
})
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))

View File

@ -84,7 +84,7 @@ namespace Ocelot.UnitTests.Configuration
DownstreamHost = "127.0.0.1",
UpstreamPathTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
},
}))
@ -117,7 +117,7 @@ namespace Ocelot.UnitTests.Configuration
DownstreamHost = "127.0.0.1",
UpstreamPathTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
QoSOptions = new FileQoSOptions
{
TimeoutValue = 1,
@ -153,7 +153,7 @@ namespace Ocelot.UnitTests.Configuration
DownstreamHost = "127.0.0.1",
UpstreamPathTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
},
}))
@ -181,7 +181,7 @@ namespace Ocelot.UnitTests.Configuration
DownstreamHost = "127.0.0.1",
UpstreamPathTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
},
}))
@ -194,7 +194,7 @@ namespace Ocelot.UnitTests.Configuration
.WithDownstreamHost("127.0.0.1")
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()
}))
.BDDfy();
@ -215,7 +215,7 @@ namespace Ocelot.UnitTests.Configuration
DownstreamScheme = "https",
UpstreamPathTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
}
},
}))
@ -228,7 +228,7 @@ namespace Ocelot.UnitTests.Configuration
.WithDownstreamScheme("https")
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()
}))
.BDDfy();
@ -248,7 +248,7 @@ namespace Ocelot.UnitTests.Configuration
{
UpstreamPathTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
ReRouteIsCaseSensitive = false,
ServiceName = "ProductService"
}
@ -270,7 +270,7 @@ namespace Ocelot.UnitTests.Configuration
new ReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder()
.WithUseServiceDiscovery(true)
.WithServiceDiscoveryProvider("consul")
@ -296,7 +296,7 @@ namespace Ocelot.UnitTests.Configuration
{
UpstreamPathTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
ReRouteIsCaseSensitive = false,
}
}
@ -309,7 +309,7 @@ namespace Ocelot.UnitTests.Configuration
new ReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder()
.WithUseServiceDiscovery(false)
.Build())
@ -332,7 +332,7 @@ namespace Ocelot.UnitTests.Configuration
{
UpstreamPathTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
ReRouteIsCaseSensitive = false
}
}
@ -346,7 +346,7 @@ namespace Ocelot.UnitTests.Configuration
new ReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("(?i)/api/products/.*/$")
.Build()
}))
@ -367,7 +367,7 @@ namespace Ocelot.UnitTests.Configuration
{
UpstreamPathTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
ReRouteIsCaseSensitive = true
}
},
@ -385,7 +385,7 @@ namespace Ocelot.UnitTests.Configuration
new ReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithRequestIdKey("blahhhh")
.Build()
}))
@ -414,7 +414,7 @@ namespace Ocelot.UnitTests.Configuration
new ReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithAuthenticationOptions(authenticationOptions)
.WithClaimsToHeaders(new List<ClaimToThing>
{
@ -431,7 +431,7 @@ namespace Ocelot.UnitTests.Configuration
{
UpstreamPathTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
ReRouteIsCaseSensitive = true,
AuthenticationOptions = new FileAuthenticationOptions
{
@ -482,7 +482,7 @@ namespace Ocelot.UnitTests.Configuration
new ReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithAuthenticationOptions(authenticationOptions)
.Build()
};
@ -495,7 +495,7 @@ namespace Ocelot.UnitTests.Configuration
{
UpstreamPathTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get",
UpstreamHttpMethod = new List<string> { "Get" },
ReRouteIsCaseSensitive = true,
AuthenticationOptions = new FileAuthenticationOptions
{

View File

@ -87,7 +87,7 @@ namespace Ocelot.UnitTests.Configuration
{
new ReRouteBuilder()
.WithDownstreamPathTemplate(_downstreamTemplatePath)
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()
};

View File

@ -66,7 +66,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly())

View File

@ -45,7 +45,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("someUpstreamPath")
.Build()
}, string.Empty
@ -58,7 +58,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()
)))
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly())
@ -78,7 +78,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("someUpstreamPath")
.Build()
}, string.Empty
@ -90,7 +90,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()
)))
.And(x => x.ThenTheUrlMatcherIsNotCalled())
@ -110,13 +110,13 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("")
.Build(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPathForAPost")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod("Post")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern("")
.Build()
}, string.Empty
@ -128,7 +128,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPathForAPost")
.WithUpstreamHttpMethod("Post")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.Build()
)))
.BDDfy();
@ -143,7 +143,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
new ReRouteBuilder()
.WithDownstreamPathTemplate("somPath")
.WithUpstreamPathTemplate("somePath")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("somePath")
.Build(),
}, string.Empty
@ -157,6 +157,95 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.BDDfy();
}
[Fact]
public void should_return_correct_route_for_http_verb_setting_multiple_upstream_http_method()
{
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
.And(
x =>
x.GivenTheTemplateVariableAndNameFinderReturns(
new OkResponse<List<UrlPathPlaceholderNameAndValue>>(new List<UrlPathPlaceholderNameAndValue>())))
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get", "Post" })
.WithUpstreamTemplatePattern("")
.Build()
}, string.Empty
))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
.When(x => x.WhenICallTheFinder())
.Then(
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.Build()
)))
.BDDfy();
}
[Fact]
public void should_return_correct_route_for_http_verb_setting_all_upstream_http_method()
{
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
.And(
x =>
x.GivenTheTemplateVariableAndNameFinderReturns(
new OkResponse<List<UrlPathPlaceholderNameAndValue>>(new List<UrlPathPlaceholderNameAndValue>())))
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string>())
.WithUpstreamTemplatePattern("")
.Build()
}, string.Empty
))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
.When(x => x.WhenICallTheFinder())
.Then(
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.Build()
)))
.BDDfy();
}
[Fact]
public void should_not_return_route_for_http_verb_not_setting_in_upstream_http_method()
{
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
.And(
x =>
x.GivenTheTemplateVariableAndNameFinderReturns(
new OkResponse<List<UrlPathPlaceholderNameAndValue>>(new List<UrlPathPlaceholderNameAndValue>())))
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get", "Patch", "Delete" })
.WithUpstreamTemplatePattern("")
.Build()
}, string.Empty
))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
.When(x => x.WhenICallTheFinder())
.Then(
x => x.ThenAnErrorResponseIsReturned())
.And(x => x.ThenTheUrlMatcherIsNotCalled())
.BDDfy();
}
private void GivenTheTemplateVariableAndNameFinderReturns(Response<List<UrlPathPlaceholderNameAndValue>> response)
{
_finder

View File

@ -78,7 +78,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithDownstreamScheme("https")
.Build())))
.And(x => x.GivenTheDownstreamRequestUriIs("http://my.url/abc?q=123"))

View File

@ -29,7 +29,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
new DownstreamRoute(
new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
.Then(x => x.ThenTheDownstreamUrlPathIsReturned(""))
@ -44,7 +44,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("/")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("/"))
@ -57,7 +57,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("api")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("api"))
@ -70,7 +70,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("api/")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("api/"))
@ -83,7 +83,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("api/product/products/")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("api/product/products/"))
@ -101,7 +101,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables,
new ReRouteBuilder()
.WithDownstreamPathTemplate("productservice/products/{productId}/")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/products/1/"))
@ -119,7 +119,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables,
new ReRouteBuilder()
.WithDownstreamPathTemplate("productservice/products/{productId}/variants")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/products/1/variants"))
@ -138,7 +138,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables,
new ReRouteBuilder()
.WithDownstreamPathTemplate("productservice/products/{productId}/variants/{variantId}")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/products/1/variants/12"))
@ -158,7 +158,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables,
new ReRouteBuilder()
.WithDownstreamPathTemplate("productservice/category/{categoryId}/products/{productId}/variants/{variantId}")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/category/34/products/1/variants/12"))

View File

@ -76,7 +76,7 @@ namespace Ocelot.UnitTests.Headers
{
new ClaimToThing("UserId", "Subject", "", 0)
})
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))

View File

@ -4,6 +4,7 @@ using Ocelot.Configuration.Builder;
using Ocelot.LoadBalancer.LoadBalancers;
using Ocelot.ServiceDiscovery;
using Shouldly;
using System.Collections.Generic;
using TestStack.BDDfy;
using Xunit;
@ -29,7 +30,7 @@ namespace Ocelot.UnitTests.LoadBalancer
{
var reRoute = new ReRouteBuilder()
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build();
this.Given(x => x.GivenAReRoute(reRoute))
@ -44,7 +45,7 @@ namespace Ocelot.UnitTests.LoadBalancer
{
var reRoute = new ReRouteBuilder()
.WithLoadBalancer("RoundRobin")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
.Build();
@ -60,7 +61,7 @@ namespace Ocelot.UnitTests.LoadBalancer
{
var reRoute = new ReRouteBuilder()
.WithLoadBalancer("LeastConnection")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
.Build();
@ -76,7 +77,7 @@ namespace Ocelot.UnitTests.LoadBalancer
{
var reRoute = new ReRouteBuilder()
.WithLoadBalancer("RoundRobin")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
.Build();

View File

@ -73,7 +73,7 @@ namespace Ocelot.UnitTests.LoadBalancer
{
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123"))
@ -90,7 +90,7 @@ namespace Ocelot.UnitTests.LoadBalancer
{
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123"))
@ -106,7 +106,7 @@ namespace Ocelot.UnitTests.LoadBalancer
{
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123"))

View File

@ -74,7 +74,7 @@ namespace Ocelot.UnitTests.QueryStrings
{
new ClaimToThing("UserId", "Subject", "", 0)
})
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))

View File

@ -72,7 +72,7 @@ namespace Ocelot.UnitTests.RateLimit
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>(), false, "", "", new Ocelot.Configuration.RateLimitRule("1s", 100, 3), 429))
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
@ -89,7 +89,7 @@ namespace Ocelot.UnitTests.RateLimit
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>() { "ocelotclient2" }, false, "", "", new RateLimitRule( "1s", 100,3),429))
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))

View File

@ -76,7 +76,7 @@ namespace Ocelot.UnitTests.Request
var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithRequestIdKey("LSRequestId")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
this.Given(x => x.GivenTheDownStreamUrlIs("any old string"))

View File

@ -78,7 +78,7 @@ namespace Ocelot.UnitTests.RequestId
new ReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithRequestIdKey("LSRequestId")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
var requestId = Guid.NewGuid().ToString();
@ -97,7 +97,7 @@ namespace Ocelot.UnitTests.RequestId
new ReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithRequestIdKey("LSRequestId")
.WithUpstreamHttpMethod("Get")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))

View File

@ -4,6 +4,7 @@ using Ocelot.Configuration.Builder;
using Ocelot.Logging;
using Ocelot.Requester.QoS;
using Shouldly;
using System.Collections.Generic;
using TestStack.BDDfy;
using Xunit;
@ -31,7 +32,7 @@ namespace Ocelot.UnitTests.Requester
public void should_return_no_qos_provider()
{
var reRoute = new ReRouteBuilder()
.WithUpstreamHttpMethod("get")
.WithUpstreamHttpMethod(new List<string> { "get" })
.WithIsQos(false)
.Build();
@ -51,7 +52,7 @@ namespace Ocelot.UnitTests.Requester
.Build();
var reRoute = new ReRouteBuilder()
.WithUpstreamHttpMethod("get")
.WithUpstreamHttpMethod(new List<string> { "get" })
.WithIsQos(true)
.WithQosOptions(qosOptions)
.Build();