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) if (AppVeyor.IsRunningOnAppVeyor)
{ {
Information("Persisting version number..."); Information("Persisting version number...");
PersistVersion(nugetVersion); PersistVersion(committedVersion, nugetVersion);
buildVersion = nugetVersion; buildVersion = nugetVersion;
} }
else else
@ -229,7 +229,7 @@ Task("CreatePackages")
EnsureDirectoryExists(packagesDir); EnsureDirectoryExists(packagesDir);
CopyFiles("./src/**/Ocelot.*.nupkg", packagesDir); CopyFiles("./src/**/Ocelot.*.nupkg", packagesDir);
GenerateReleaseNotes(); GenerateReleaseNotes(releaseNotesFile);
System.IO.File.WriteAllLines(artifactsFile, new[]{ System.IO.File.WriteAllLines(artifactsFile, new[]{
"nuget:Ocelot." + buildVersion + ".nupkg", "nuget:Ocelot." + buildVersion + ".nupkg",
@ -251,9 +251,9 @@ Task("ReleasePackagesToUnstableFeed")
.IsDependentOn("CreatePackages") .IsDependentOn("CreatePackages")
.Does(() => .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") .IsDependentOn("DownloadGitHubReleaseArtifacts")
.Does(() => .Does(() =>
{ {
PublishPackages(nugetFeedStableKey, nugetFeedStableUploadUrl, nugetFeedStableSymbolsUploadUrl); PublishPackages(packagesDir, artifactsFile, nugetFeedStableKey, nugetFeedStableUploadUrl, nugetFeedStableSymbolsUploadUrl);
}); });
Task("Release") Task("Release")
@ -326,9 +326,9 @@ private GitVersion GetNuGetVersionForCommit()
} }
/// Updates project version in all of our projects /// 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"); var projectFiles = GetFiles("./**/*.csproj");
@ -339,24 +339,30 @@ private void PersistVersion(string version)
Information(string.Format("Updating {0}...", file)); Information(string.Format("Updating {0}...", file));
var updatedProjectFile = System.IO.File.ReadAllText(file) var updatedProjectFile = System.IO.File.ReadAllText(file)
.Replace(committedVersion, version); .Replace(committedVersion, newVersion);
System.IO.File.WriteAllText(file, updatedProjectFile); System.IO.File.WriteAllText(file, updatedProjectFile);
} }
} }
/// generates release notes based on issues closed in GitHub since the last release /// 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( var releaseNotesExitCode = StartProcess(
@"tools/GitReleaseNotes/tools/gitreleasenotes.exe", @"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) if (releaseNotesExitCode != 0)
@ -366,7 +372,7 @@ private void GenerateReleaseNotes()
} }
/// Publishes code and symbols packages to nuget feed, based on contents of artifacts file /// 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 var artifacts = System.IO.File
.ReadAllLines(artifactsFile) .ReadAllLines(artifactsFile)
@ -375,6 +381,8 @@ private void PublishPackages(string feedApiKey, string codeFeedUrl, string symbo
var codePackage = packagesDir + File(artifacts["nuget"]); var codePackage = packagesDir + File(artifacts["nuget"]);
Information("Pushing package " + codePackage);
NuGetPush( NuGetPush(
codePackage, codePackage,
new NuGetPushSettings { 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 regex = new System.Text.RegularExpressions.Regex(filter);
var publish = regex.IsMatch(versioning.BranchName); var publish = regex.IsMatch(branchName);
if (publish) if (publish)
{ {
Information("Branch " + versioning.BranchName + " will be published to the unstable feed"); Information("Branch " + branchName + " will be published to the unstable feed");
} }
else 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; return publish;
} }

View File

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

View File

@ -5,9 +5,8 @@ namespace Ocelot.Authorisation
{ {
using System.Collections.Generic; using System.Collections.Generic;
public interface IAuthoriser public interface IClaimsAuthoriser
{ {
Response<bool> Authorise(ClaimsPrincipal claimsPrincipal, Response<bool> Authorise(ClaimsPrincipal claimsPrincipal, Dictionary<string, string> routeClaimsRequirement);
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.Infrastructure.RequestData;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.Responses; using Ocelot.Responses;
using Ocelot.Configuration;
namespace Ocelot.Authorisation.Middleware namespace Ocelot.Authorisation.Middleware
{ {
@ -13,17 +14,20 @@ namespace Ocelot.Authorisation.Middleware
public class AuthorisationMiddleware : OcelotMiddleware public class AuthorisationMiddleware : OcelotMiddleware
{ {
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private readonly IAuthoriser _authoriser; private readonly IClaimsAuthoriser _claimsAuthoriser;
private readonly IScopesAuthoriser _scopesAuthoriser;
private readonly IOcelotLogger _logger; private readonly IOcelotLogger _logger;
public AuthorisationMiddleware(RequestDelegate next, public AuthorisationMiddleware(RequestDelegate next,
IRequestScopedDataRepository requestScopedDataRepository, IRequestScopedDataRepository requestScopedDataRepository,
IAuthoriser authoriser, IClaimsAuthoriser claimsAuthoriser,
IScopesAuthoriser scopesAuthoriser,
IOcelotLoggerFactory loggerFactory) IOcelotLoggerFactory loggerFactory)
: base(requestScopedDataRepository) : base(requestScopedDataRepository)
{ {
_next = next; _next = next;
_authoriser = authoriser; _claimsAuthoriser = claimsAuthoriser;
_scopesAuthoriser = scopesAuthoriser;
_logger = loggerFactory.CreateLogger<AuthorisationMiddleware>(); _logger = loggerFactory.CreateLogger<AuthorisationMiddleware>();
} }
@ -31,11 +35,41 @@ namespace Ocelot.Authorisation.Middleware
{ {
_logger.LogDebug("started authorisation"); _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"); _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) if (authorised.IsError)
{ {
@ -78,5 +112,15 @@ namespace Ocelot.Authorisation.Middleware
{ {
return authorised.Data; 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.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using Ocelot.Values; using Ocelot.Values;
using System.Linq;
namespace Ocelot.Configuration.Builder namespace Ocelot.Configuration.Builder
{ {
@ -11,7 +12,7 @@ namespace Ocelot.Configuration.Builder
private string _downstreamPathTemplate; private string _downstreamPathTemplate;
private string _upstreamTemplate; private string _upstreamTemplate;
private string _upstreamTemplatePattern; private string _upstreamTemplatePattern;
private string _upstreamHttpMethod; private List<HttpMethod> _upstreamHttpMethod;
private bool _isAuthenticated; private bool _isAuthenticated;
private List<ClaimToThing> _configHeaderExtractorProperties; private List<ClaimToThing> _configHeaderExtractorProperties;
private List<ClaimToThing> _claimToClaims; private List<ClaimToThing> _claimToClaims;
@ -66,11 +67,13 @@ namespace Ocelot.Configuration.Builder
_upstreamTemplatePattern = input; _upstreamTemplatePattern = input;
return this; 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; return this;
} }
public ReRouteBuilder WithIsAuthenticated(bool input) public ReRouteBuilder WithIsAuthenticated(bool input)
{ {
_isAuthenticated = input; _isAuthenticated = input;
@ -143,7 +146,6 @@ namespace Ocelot.Configuration.Builder
return this; return this;
} }
public ReRouteBuilder WithLoadBalancerKey(string loadBalancerKey) public ReRouteBuilder WithLoadBalancerKey(string loadBalancerKey)
{ {
_loadBalancerKey = loadBalancerKey; _loadBalancerKey = loadBalancerKey;
@ -180,7 +182,7 @@ namespace Ocelot.Configuration.Builder
return new ReRoute( return new ReRoute(
new PathTemplate(_downstreamPathTemplate), new PathTemplate(_downstreamPathTemplate),
new PathTemplate(_upstreamTemplate), new PathTemplate(_upstreamTemplate),
new HttpMethod(_upstreamHttpMethod), _upstreamHttpMethod,
_upstreamTemplatePattern, _upstreamTemplatePattern,
_isAuthenticated, _isAuthenticated,
_authenticationOptions, _authenticationOptions,

View File

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

View File

@ -8,7 +8,7 @@ namespace Ocelot.Configuration
{ {
public ReRoute(PathTemplate downstreamPathTemplate, public ReRoute(PathTemplate downstreamPathTemplate,
PathTemplate upstreamPathTemplate, PathTemplate upstreamPathTemplate,
HttpMethod upstreamHttpMethod, List<HttpMethod> upstreamHttpMethod,
string upstreamTemplatePattern, string upstreamTemplatePattern,
bool isAuthenticated, bool isAuthenticated,
AuthenticationOptions authenticationOptions, AuthenticationOptions authenticationOptions,
@ -64,7 +64,7 @@ namespace Ocelot.Configuration
public PathTemplate DownstreamPathTemplate { get; private set; } public PathTemplate DownstreamPathTemplate { get; private set; }
public PathTemplate UpstreamPathTemplate { get; private set; } public PathTemplate UpstreamPathTemplate { get; private set; }
public string UpstreamTemplatePattern { 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 IsAuthenticated { get; private set; }
public bool IsAuthorised { get; private set; } public bool IsAuthorised { get; private set; }
public AuthenticationOptions AuthenticationOptions { 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) public Response<ConfigurationValidationResult> IsValid(FileConfiguration configuration)
{ {
var result = CheckForDupliateReRoutes(configuration); var result = CheckForDuplicateReRoutes(configuration);
if (result.IsError) if (result.IsError)
{ {
@ -97,27 +97,43 @@ namespace Ocelot.Configuration.Validator
return new ConfigurationValidationResult(false, errors); return new ConfigurationValidationResult(false, errors);
} }
private ConfigurationValidationResult CheckForDupliateReRoutes(FileConfiguration configuration) private ConfigurationValidationResult CheckForDuplicateReRoutes(FileConfiguration configuration)
{ {
var hasDupes = configuration.ReRoutes var duplicatedUpstreamPathTemplates = new List<string>();
.GroupBy(x => new { x.UpstreamPathTemplate, x.UpstreamHttpMethod }).Any(x => x.Skip(1).Any());
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); return new ConfigurationValidationResult(false);
} }
else
var dupes = configuration.ReRoutes.GroupBy(x => new { x.UpstreamPathTemplate, x.UpstreamHttpMethod }) {
.Where(x => x.Skip(1).Any()); var errors = duplicatedUpstreamPathTemplates
.Select(d => new DownstreamPathTemplateAlreadyUsedError(string.Format("Duplicate DownstreamPath: {0}", d)))
var errors = dupes
.Select(d => new DownstreamPathTemplateAlreadyUsedError(string.Format("Duplicate DownstreamPath: {0}", d.Key.UpstreamPathTemplate)))
.Cast<Error>() .Cast<Error>()
.ToList(); .ToList();
return new ConfigurationValidationResult(true, errors); return new ConfigurationValidationResult(true, errors);
} }
}
private ConfigurationValidationResult CheckForReRoutesRateLimitOptions(FileConfiguration configuration) private ConfigurationValidationResult CheckForReRoutesRateLimitOptions(FileConfiguration configuration)
{ {
var errors = new List<Error>(); var errors = new List<Error>();

View File

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

View File

@ -26,7 +26,7 @@ namespace Ocelot.DownstreamRouteFinder.Finder
{ {
var configuration = await _configProvider.Get(); 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) foreach (var reRoute in applicableReRoutes)
{ {

View File

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

View File

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

View File

@ -1,10 +1,10 @@
namespace Ocelot.Infrastructure.Claims.Parser namespace Ocelot.Infrastructure.Claims.Parser
{ {
using Errors;
using Responses;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using Errors;
using Responses;
public class ClaimsParser : IClaimsParser public class ClaimsParser : IClaimsParser
{ {
@ -37,6 +37,17 @@
return new OkResponse<string>(value); 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) private Response<string> GetValue(IEnumerable<Claim> claims, string key)
{ {
var claim = claims.FirstOrDefault(c => c.Type == key); var claim = claims.FirstOrDefault(c => c.Type == key);

View File

@ -7,5 +7,6 @@
public interface IClaimsParser public interface IClaimsParser
{ {
Response<string> GetValue(IEnumerable<Claim> claims, string key, string delimiter, int index); 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.Twitter" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" 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="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.Mvc" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1" /> <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1" />
<PackageReference Include="CacheManager.Core" Version="0.9.2" /> <PackageReference Include="CacheManager.Core" Version="0.9.2" />
@ -53,7 +53,7 @@
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="0.9.2" /> <PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="0.9.2" />
<PackageReference Include="Consul" Version="0.7.2.1" /> <PackageReference Include="Consul" Version="0.7.2.1" />
<PackageReference Include="Polly" Version="5.0.3" /> <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" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="1.1.1" />
</ItemGroup> </ItemGroup>

View File

@ -22,9 +22,12 @@ namespace Ocelot.Requester
public async Task<Response<HttpResponseMessage>> GetResponse(Request.Request request) 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 try
{ {
var response = await httpClient.SendAsync(request.HttpRequestMessage); 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); var httpClient = _cacheHandlers.Get(cacheKey);
if (httpClient == null) if (httpClient == null)
{ {
httpClient = builder.Create(); httpClient = builder.Create();
@ -63,9 +65,16 @@ namespace Ocelot.Requester
return httpClient; 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}"; 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; return baseUrl;
} }
} }

View File

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

View File

@ -48,7 +48,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = _downstreamServiceHost, DownstreamHost = _downstreamServiceHost,
DownstreamScheme = _downstreamServiceScheme, DownstreamScheme = _downstreamServiceScheme,
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Post", UpstreamHttpMethod = new List<string> { "Post" },
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AllowedScopes = new List<string>(), AllowedScopes = new List<string>(),
@ -62,7 +62,7 @@ namespace Ocelot.AcceptanceTests
} }
}; };
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 => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty))
.And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning()) .And(x => _steps.GivenOcelotIsRunning())
@ -86,7 +86,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = _downstreamServiceHost, DownstreamHost = _downstreamServiceHost,
DownstreamScheme = _downstreamServiceScheme, DownstreamScheme = _downstreamServiceScheme,
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Post", UpstreamHttpMethod = new List<string> { "Post" },
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AllowedScopes = new List<string>(), AllowedScopes = new List<string>(),
@ -100,7 +100,7 @@ namespace Ocelot.AcceptanceTests
} }
}; };
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 => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty))
.And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning()) .And(x => _steps.GivenOcelotIsRunning())
@ -124,7 +124,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = _downstreamServiceHost, DownstreamHost = _downstreamServiceHost,
DownstreamScheme = _downstreamServiceScheme, DownstreamScheme = _downstreamServiceScheme,
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AllowedScopes = new List<string>(), AllowedScopes = new List<string>(),
@ -138,7 +138,7 @@ namespace Ocelot.AcceptanceTests
} }
}; };
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 => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 200, "Hello from Laura"))
.And(x => _steps.GivenIHaveAToken(_identityServerRootUrl)) .And(x => _steps.GivenIHaveAToken(_identityServerRootUrl))
.And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenThereIsAConfiguration(configuration))
@ -150,6 +150,45 @@ namespace Ocelot.AcceptanceTests
.BDDfy(); .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] [Fact]
public void should_return_201_using_identity_server_access_token() public void should_return_201_using_identity_server_access_token()
{ {
@ -164,7 +203,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = _downstreamServiceHost, DownstreamHost = _downstreamServiceHost,
DownstreamScheme = _downstreamServiceScheme, DownstreamScheme = _downstreamServiceScheme,
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Post", UpstreamHttpMethod = new List<string> { "Post" },
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
@ -179,7 +218,7 @@ namespace Ocelot.AcceptanceTests
} }
}; };
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 => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty))
.And(x => _steps.GivenIHaveAToken(_identityServerRootUrl)) .And(x => _steps.GivenIHaveAToken(_identityServerRootUrl))
.And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenThereIsAConfiguration(configuration))
@ -205,7 +244,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = _downstreamServiceHost, DownstreamHost = _downstreamServiceHost,
DownstreamScheme = _downstreamServiceScheme, DownstreamScheme = _downstreamServiceScheme,
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Post", UpstreamHttpMethod = new List<string> { "Post" },
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AllowedScopes = new List<string>(), AllowedScopes = new List<string>(),
@ -219,7 +258,7 @@ namespace Ocelot.AcceptanceTests
} }
}; };
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 => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty))
.And(x => _steps.GivenIHaveAToken(_identityServerRootUrl)) .And(x => _steps.GivenIHaveAToken(_identityServerRootUrl))
.And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenThereIsAConfiguration(configuration))
@ -252,7 +291,7 @@ namespace Ocelot.AcceptanceTests
_servicebuilder.Start(); _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() _identityServerBuilder = new WebHostBuilder()
.UseUrls(url) .UseUrls(url)
@ -276,6 +315,32 @@ namespace Ocelot.AcceptanceTests
Scopes = new List<Scope>() Scopes = new List<Scope>()
{ {
new Scope("api"), 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("openid"),
new Scope("offline_access") new Scope("offline_access")
}, },
@ -299,7 +364,7 @@ namespace Ocelot.AcceptanceTests
ClientId = "client", ClientId = "client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())}, 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, AccessTokenType = tokenType,
Enabled = true, Enabled = true,
RequireClientSecret = false RequireClientSecret = false

View File

@ -42,7 +42,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http", DownstreamScheme = "http",
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AllowedScopes = new List<string>(), AllowedScopes = new List<string>(),
@ -99,7 +99,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http", DownstreamScheme = "http",
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AllowedScopes = new List<string>(), AllowedScopes = new List<string>(),
@ -140,6 +140,84 @@ namespace Ocelot.AcceptanceTests
.BDDfy(); .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) private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
{ {
_servicebuilder = new WebHostBuilder() _servicebuilder = new WebHostBuilder()
@ -185,6 +263,7 @@ namespace Ocelot.AcceptanceTests
Scopes = new List<Scope>() Scopes = new List<Scope>()
{ {
new Scope("api"), new Scope("api"),
new Scope("api.readOnly"),
new Scope("openid"), new Scope("openid"),
new Scope("offline_access") new Scope("offline_access")
}, },
@ -209,7 +288,7 @@ namespace Ocelot.AcceptanceTests
ClientId = "client", ClientId = "client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())}, 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, AccessTokenType = tokenType,
Enabled = true, Enabled = true,
RequireClientSecret = false RequireClientSecret = false

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -50,7 +50,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http", DownstreamScheme = "http",
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
} }
} }
}; };
@ -87,8 +87,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http", DownstreamScheme = "http",
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
} }
} }
}; };
@ -125,8 +124,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http", DownstreamScheme = "http",
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
} }
} }
}; };
@ -163,7 +161,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http", DownstreamScheme = "http",
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
} }
} }
}; };
@ -200,7 +198,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http", DownstreamScheme = "http",
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
} }
} }
}; };
@ -237,7 +235,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http", DownstreamScheme = "http",
DownstreamHost = "localhost", DownstreamHost = "localhost",
UpstreamPathTemplate = "/", 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.AspNetCore.Http" Version="1.1.1" />
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.0" /> <PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.0" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="1.1.1" /> <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.Mvc" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1" /> <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" 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", DownstreamHost = "localhost",
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
QoSOptions = new FileQoSOptions QoSOptions = new FileQoSOptions
{ {
ExceptionsAllowedBeforeBreaking = 1, ExceptionsAllowedBeforeBreaking = 1,
TimeoutValue = 500, TimeoutValue = 500,
DurationOfBreak = 1000 DurationOfBreak = 1000
} },
} }
} }
}; };
@ -83,7 +84,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
QoSOptions = new FileQoSOptions QoSOptions = new FileQoSOptions
{ {
ExceptionsAllowedBeforeBreaking = 1, ExceptionsAllowedBeforeBreaking = 1,
@ -98,7 +99,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
DownstreamPort = 51880, DownstreamPort = 51880,
UpstreamPathTemplate = "working", UpstreamPathTemplate = "working",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
} }
} }
}; };

View File

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

View File

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

View File

@ -45,7 +45,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
} }
} }
}; };
@ -73,8 +73,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
} }
} }
}; };
@ -102,8 +101,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost/", DownstreamHost = "localhost/",
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
} }
} }
}; };
@ -131,8 +129,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamPathTemplate = "/products/", UpstreamPathTemplate = "/products/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
} }
} }
}; };
@ -160,7 +157,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamPathTemplate = "/products", UpstreamPathTemplate = "/products",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
} }
} }
}; };
@ -188,7 +185,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamPathTemplate = "/products/{productId}", UpstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
QoSOptions = new FileQoSOptions() QoSOptions = new FileQoSOptions()
{ {
ExceptionsAllowedBeforeBreaking = 3, ExceptionsAllowedBeforeBreaking = 3,
@ -221,7 +218,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamPathTemplate = "/products/{productId}", UpstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
} }
} }
}; };
@ -249,7 +246,7 @@ namespace Ocelot.AcceptanceTests
DownstreamPort = 51879, DownstreamPort = 51879,
DownstreamScheme = "http", DownstreamScheme = "http",
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Post", UpstreamHttpMethod = new List<string> { "Post" },
} }
} }
}; };
@ -277,7 +274,7 @@ namespace Ocelot.AcceptanceTests
DownstreamScheme = "http", DownstreamScheme = "http",
DownstreamHost = "localhost", DownstreamHost = "localhost",
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
} }
} }
}; };
@ -305,7 +302,7 @@ namespace Ocelot.AcceptanceTests
DownstreamHost = "localhost", DownstreamHost = "localhost",
DownstreamPort = 51879, DownstreamPort = 51879,
UpstreamPathTemplate = "/myApp1Name/api/{urlPath}", UpstreamPathTemplate = "/myApp1Name/api/{urlPath}",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
} }
} }
}; };
@ -319,6 +316,62 @@ namespace Ocelot.AcceptanceTests
.BDDfy(); .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) private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
{ {
_builder = new WebHostBuilder() _builder = new WebHostBuilder()

View File

@ -69,7 +69,7 @@ namespace Ocelot.AcceptanceTests
DownstreamPathTemplate = "/", DownstreamPathTemplate = "/",
DownstreamScheme = "http", DownstreamScheme = "http",
UpstreamPathTemplate = "/", UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get", UpstreamHttpMethod = new List<string> { "Get" },
ServiceName = serviceName, ServiceName = serviceName,
LoadBalancer = "LeastConnection", 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) public void GivenIHaveAnOcelotToken(string adminPath)
{ {
var tokenUrl = $"{adminPath}/connect/token"; var tokenUrl = $"{adminPath}/connect/token";

View File

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

View File

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

View File

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

View File

@ -6,7 +6,7 @@
"DownstreamHost": "localhost", "DownstreamHost": "localhost",
"DownstreamPort": 52876, "DownstreamPort": 52876,
"UpstreamPathTemplate": "/identityserverexample", "UpstreamPathTemplate": "/identityserverexample",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": [ "Get" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -51,7 +51,7 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 443, "DownstreamPort": 443,
"UpstreamPathTemplate": "/posts", "UpstreamPathTemplate": "/posts",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": [ "Get" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -64,7 +64,7 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/{postId}", "UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": [ "Get" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -77,7 +77,7 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/{postId}/comments", "UpstreamPathTemplate": "/posts/{postId}/comments",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": [ "Get" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -90,7 +90,7 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/comments", "UpstreamPathTemplate": "/comments",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": [ "Get" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -103,7 +103,7 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/posts", "UpstreamPathTemplate": "/posts",
"UpstreamHttpMethod": "Post", "UpstreamHttpMethod": [ "Post" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -116,7 +116,7 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/{postId}", "UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Put", "UpstreamHttpMethod": [ "Put" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -129,7 +129,7 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/{postId}", "UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Patch", "UpstreamHttpMethod": [ "Patch" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -142,7 +142,7 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/{postId}", "UpstreamPathTemplate": "/posts/{postId}",
"UpstreamHttpMethod": "Delete", "UpstreamHttpMethod": [ "Delete" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -155,7 +155,7 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/products", "UpstreamPathTemplate": "/products",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": [ "Get" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -169,7 +169,7 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/products/{productId}", "UpstreamPathTemplate": "/products/{productId}",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": [ "Get" ],
"FileCacheOptions": { "TtlSeconds": 15 } "FileCacheOptions": { "TtlSeconds": 15 }
}, },
{ {
@ -178,7 +178,7 @@
"DownstreamHost": "products20161126090340.azurewebsites.net", "DownstreamHost": "products20161126090340.azurewebsites.net",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/products", "UpstreamPathTemplate": "/products",
"UpstreamHttpMethod": "Post", "UpstreamHttpMethod": [ "Post" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -191,7 +191,7 @@
"DownstreamHost": "products20161126090340.azurewebsites.net", "DownstreamHost": "products20161126090340.azurewebsites.net",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/products/{productId}", "UpstreamPathTemplate": "/products/{productId}",
"UpstreamHttpMethod": "Put", "UpstreamHttpMethod": [ "Put" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -205,7 +205,7 @@
"DownstreamHost": "products20161126090340.azurewebsites.net", "DownstreamHost": "products20161126090340.azurewebsites.net",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/products/{productId}", "UpstreamPathTemplate": "/products/{productId}",
"UpstreamHttpMethod": "Delete", "UpstreamHttpMethod": [ "Delete" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -219,7 +219,7 @@
"DownstreamHost": "customers20161126090811.azurewebsites.net", "DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/customers", "UpstreamPathTemplate": "/customers",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": [ "Get" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -233,7 +233,7 @@
"DownstreamHost": "customers20161126090811.azurewebsites.net", "DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/customers/{customerId}", "UpstreamPathTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": [ "Get" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -247,7 +247,7 @@
"DownstreamHost": "customers20161126090811.azurewebsites.net", "DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/customers", "UpstreamPathTemplate": "/customers",
"UpstreamHttpMethod": "Post", "UpstreamHttpMethod": [ "Post" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -261,7 +261,7 @@
"DownstreamHost": "customers20161126090811.azurewebsites.net", "DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/customers/{customerId}", "UpstreamPathTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": "Put", "UpstreamHttpMethod": [ "Put" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -275,7 +275,7 @@
"DownstreamHost": "customers20161126090811.azurewebsites.net", "DownstreamHost": "customers20161126090811.azurewebsites.net",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/customers/{customerId}", "UpstreamPathTemplate": "/customers/{customerId}",
"UpstreamHttpMethod": "Delete", "UpstreamHttpMethod": [ "Delete" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -289,7 +289,7 @@
"DownstreamHost": "jsonplaceholder.typicode.com", "DownstreamHost": "jsonplaceholder.typicode.com",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/posts/", "UpstreamPathTemplate": "/posts/",
"UpstreamHttpMethod": "Get", "UpstreamHttpMethod": [ "Get" ],
"QoSOptions": { "QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, "ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 10, "DurationOfBreak": 10,
@ -303,7 +303,7 @@
"DownstreamHost": "www.bbc.co.uk", "DownstreamHost": "www.bbc.co.uk",
"DownstreamPort": 80, "DownstreamPort": 80,
"UpstreamPathTemplate": "/bbc/", "UpstreamPathTemplate": "/bbc/",
"UpstreamHttpMethod": "Get" "UpstreamHttpMethod": [ "Get" ],
} }
], ],

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -45,7 +45,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
new ReRouteBuilder() new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath") .WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod("Get") .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("someUpstreamPath") .WithUpstreamTemplatePattern("someUpstreamPath")
.Build() .Build()
}, string.Empty }, string.Empty
@ -58,7 +58,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
new List<UrlPathPlaceholderNameAndValue>(), new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder() new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath") .WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod("Get") .WithUpstreamHttpMethod(new List<string> { "Get" })
.Build() .Build()
))) )))
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly()) .And(x => x.ThenTheUrlMatcherIsCalledCorrectly())
@ -78,7 +78,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
new ReRouteBuilder() new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath") .WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod("Get") .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("someUpstreamPath") .WithUpstreamTemplatePattern("someUpstreamPath")
.Build() .Build()
}, string.Empty }, string.Empty
@ -90,7 +90,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder() new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath") .WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod("Get") .WithUpstreamHttpMethod(new List<string> { "Get" })
.Build() .Build()
))) )))
.And(x => x.ThenTheUrlMatcherIsNotCalled()) .And(x => x.ThenTheUrlMatcherIsNotCalled())
@ -110,13 +110,13 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
new ReRouteBuilder() new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath") .WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod("Get") .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("") .WithUpstreamTemplatePattern("")
.Build(), .Build(),
new ReRouteBuilder() new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPathForAPost") .WithDownstreamPathTemplate("someDownstreamPathForAPost")
.WithUpstreamPathTemplate("someUpstreamPath") .WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod("Post") .WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern("") .WithUpstreamTemplatePattern("")
.Build() .Build()
}, string.Empty }, string.Empty
@ -128,7 +128,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder() new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPathForAPost") .WithDownstreamPathTemplate("someDownstreamPathForAPost")
.WithUpstreamHttpMethod("Post") .WithUpstreamHttpMethod(new List<string> { "Post" })
.Build() .Build()
))) )))
.BDDfy(); .BDDfy();
@ -143,7 +143,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
new ReRouteBuilder() new ReRouteBuilder()
.WithDownstreamPathTemplate("somPath") .WithDownstreamPathTemplate("somPath")
.WithUpstreamPathTemplate("somePath") .WithUpstreamPathTemplate("somePath")
.WithUpstreamHttpMethod("Get") .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("somePath") .WithUpstreamTemplatePattern("somePath")
.Build(), .Build(),
}, string.Empty }, string.Empty
@ -157,6 +157,95 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.BDDfy(); .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) private void GivenTheTemplateVariableAndNameFinderReturns(Response<List<UrlPathPlaceholderNameAndValue>> response)
{ {
_finder _finder

View File

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

View File

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

View File

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

View File

@ -73,7 +73,7 @@ namespace Ocelot.UnitTests.LoadBalancer
{ {
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(), var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder() new ReRouteBuilder()
.WithUpstreamHttpMethod("Get") .WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()); .Build());
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123")) 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>(), var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder() new ReRouteBuilder()
.WithUpstreamHttpMethod("Get") .WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()); .Build());
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123")) 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>(), var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder() new ReRouteBuilder()
.WithUpstreamHttpMethod("Get") .WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()); .Build());
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123")) 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) new ClaimToThing("UserId", "Subject", "", 0)
}) })
.WithUpstreamHttpMethod("Get") .WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()); .Build());
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) 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>(), var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions( new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>(), false, "", "", new Ocelot.Configuration.RateLimitRule("1s", 100, 3), 429)) 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()); .Build());
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
@ -89,7 +89,7 @@ namespace Ocelot.UnitTests.RateLimit
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(), var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions( new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>() { "ocelotclient2" }, false, "", "", new RateLimitRule( "1s", 100,3),429)) 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()); .Build());
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))

View File

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

View File

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

View File

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