mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:22:50 +08:00
Merge remote-tracking branch 'origin/develop' into feature/#128-cookie-proxying-and-auto-redirect-configuration
This commit is contained in:
commit
8bc5819f90
@ -1,6 +1,7 @@
|
|||||||
#tool "nuget:?package=GitVersion.CommandLine"
|
#tool "nuget:?package=GitVersion.CommandLine"
|
||||||
#tool "nuget:?package=GitReleaseNotes"
|
#tool "nuget:?package=GitReleaseNotes"
|
||||||
#addin "nuget:?package=Cake.Json"
|
#addin nuget:?package=Cake.Json
|
||||||
|
#addin nuget:?package=Newtonsoft.Json&version=9.0.1
|
||||||
#tool "nuget:?package=OpenCover"
|
#tool "nuget:?package=OpenCover"
|
||||||
#tool "nuget:?package=ReportGenerator"
|
#tool "nuget:?package=ReportGenerator"
|
||||||
#tool coveralls.net
|
#tool coveralls.net
|
||||||
|
117
build.ps1
117
build.ps1
@ -21,34 +21,35 @@ The build script target to run.
|
|||||||
The build configuration to use.
|
The build configuration to use.
|
||||||
.PARAMETER Verbosity
|
.PARAMETER Verbosity
|
||||||
Specifies the amount of information to be displayed.
|
Specifies the amount of information to be displayed.
|
||||||
|
.PARAMETER ShowDescription
|
||||||
|
Shows description about tasks.
|
||||||
|
.PARAMETER DryRun
|
||||||
|
Performs a dry run.
|
||||||
.PARAMETER Experimental
|
.PARAMETER Experimental
|
||||||
Tells Cake to use the latest Roslyn release.
|
Uses the nightly builds of the Roslyn script engine.
|
||||||
.PARAMETER WhatIf
|
|
||||||
Performs a dry run of the build script.
|
|
||||||
No tasks will be executed.
|
|
||||||
.PARAMETER Mono
|
.PARAMETER Mono
|
||||||
Tells Cake to use the Mono scripting engine.
|
Uses the Mono Compiler rather than the Roslyn script engine.
|
||||||
.PARAMETER SkipToolPackageRestore
|
.PARAMETER SkipToolPackageRestore
|
||||||
Skips restoring of packages.
|
Skips restoring of packages.
|
||||||
.PARAMETER ScriptArgs
|
.PARAMETER ScriptArgs
|
||||||
Remaining arguments are added here.
|
Remaining arguments are added here.
|
||||||
|
|
||||||
.LINK
|
.LINK
|
||||||
http://cakebuild.net
|
https://cakebuild.net
|
||||||
|
|
||||||
#>
|
#>
|
||||||
|
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
Param(
|
Param(
|
||||||
[string]$Script = "build.cake",
|
[string]$Script = "build.cake",
|
||||||
[string]$Target = "Default",
|
[string]$Target,
|
||||||
[ValidateSet("Release", "Debug")]
|
[string]$Configuration,
|
||||||
[string]$Configuration = "Release",
|
|
||||||
[ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
|
[ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
|
||||||
[string]$Verbosity = "Verbose",
|
[string]$Verbosity,
|
||||||
|
[switch]$ShowDescription,
|
||||||
|
[Alias("WhatIf", "Noop")]
|
||||||
|
[switch]$DryRun,
|
||||||
[switch]$Experimental,
|
[switch]$Experimental,
|
||||||
[Alias("DryRun","Noop")]
|
|
||||||
[switch]$WhatIf,
|
|
||||||
[switch]$Mono,
|
[switch]$Mono,
|
||||||
[switch]$SkipToolPackageRestore,
|
[switch]$SkipToolPackageRestore,
|
||||||
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
|
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
|
||||||
@ -80,6 +81,15 @@ function MD5HashFile([string] $filePath)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function GetProxyEnabledWebClient
|
||||||
|
{
|
||||||
|
$wc = New-Object System.Net.WebClient
|
||||||
|
$proxy = [System.Net.WebRequest]::GetSystemWebProxy()
|
||||||
|
$proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials
|
||||||
|
$wc.Proxy = $proxy
|
||||||
|
return $wc
|
||||||
|
}
|
||||||
|
|
||||||
Write-Host "Preparing to run build script..."
|
Write-Host "Preparing to run build script..."
|
||||||
|
|
||||||
if(!$PSScriptRoot){
|
if(!$PSScriptRoot){
|
||||||
@ -87,31 +97,15 @@ if(!$PSScriptRoot){
|
|||||||
}
|
}
|
||||||
|
|
||||||
$TOOLS_DIR = Join-Path $PSScriptRoot "tools"
|
$TOOLS_DIR = Join-Path $PSScriptRoot "tools"
|
||||||
|
$ADDINS_DIR = Join-Path $TOOLS_DIR "Addins"
|
||||||
|
$MODULES_DIR = Join-Path $TOOLS_DIR "Modules"
|
||||||
$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
|
$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
|
||||||
$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
|
$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
|
||||||
$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
|
$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
|
||||||
$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config"
|
$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config"
|
||||||
$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum"
|
$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum"
|
||||||
|
$ADDINS_PACKAGES_CONFIG = Join-Path $ADDINS_DIR "packages.config"
|
||||||
# Should we use mono?
|
$MODULES_PACKAGES_CONFIG = Join-Path $MODULES_DIR "packages.config"
|
||||||
$UseMono = "";
|
|
||||||
if($Mono.IsPresent) {
|
|
||||||
Write-Verbose -Message "Using the Mono based scripting engine."
|
|
||||||
$UseMono = "-mono"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Should we use the new Roslyn?
|
|
||||||
$UseExperimental = "";
|
|
||||||
if($Experimental.IsPresent -and !($Mono.IsPresent)) {
|
|
||||||
Write-Verbose -Message "Using experimental version of Roslyn."
|
|
||||||
$UseExperimental = "-experimental"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Is this a dry run?
|
|
||||||
$UseDryRun = "";
|
|
||||||
if($WhatIf.IsPresent) {
|
|
||||||
$UseDryRun = "-dryrun"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Make sure tools folder exists
|
# Make sure tools folder exists
|
||||||
if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
|
if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
|
||||||
@ -122,7 +116,9 @@ if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
|
|||||||
# Make sure that packages.config exist.
|
# Make sure that packages.config exist.
|
||||||
if (!(Test-Path $PACKAGES_CONFIG)) {
|
if (!(Test-Path $PACKAGES_CONFIG)) {
|
||||||
Write-Verbose -Message "Downloading packages.config..."
|
Write-Verbose -Message "Downloading packages.config..."
|
||||||
try { (New-Object System.Net.WebClient).DownloadFile("http://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch {
|
try {
|
||||||
|
$wc = GetProxyEnabledWebClient
|
||||||
|
$wc.DownloadFile("https://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch {
|
||||||
Throw "Could not download packages.config."
|
Throw "Could not download packages.config."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,7 +126,7 @@ if (!(Test-Path $PACKAGES_CONFIG)) {
|
|||||||
# Try find NuGet.exe in path if not exists
|
# Try find NuGet.exe in path if not exists
|
||||||
if (!(Test-Path $NUGET_EXE)) {
|
if (!(Test-Path $NUGET_EXE)) {
|
||||||
Write-Verbose -Message "Trying to find nuget.exe in PATH..."
|
Write-Verbose -Message "Trying to find nuget.exe in PATH..."
|
||||||
$existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_) }
|
$existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_ -PathType Container) }
|
||||||
$NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1
|
$NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1
|
||||||
if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) {
|
if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) {
|
||||||
Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)."
|
Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)."
|
||||||
@ -142,7 +138,8 @@ if (!(Test-Path $NUGET_EXE)) {
|
|||||||
if (!(Test-Path $NUGET_EXE)) {
|
if (!(Test-Path $NUGET_EXE)) {
|
||||||
Write-Verbose -Message "Downloading NuGet.exe..."
|
Write-Verbose -Message "Downloading NuGet.exe..."
|
||||||
try {
|
try {
|
||||||
(New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE)
|
$wc = GetProxyEnabledWebClient
|
||||||
|
$wc.DownloadFile($NUGET_URL, $NUGET_EXE)
|
||||||
} catch {
|
} catch {
|
||||||
Throw "Could not download NuGet.exe."
|
Throw "Could not download NuGet.exe."
|
||||||
}
|
}
|
||||||
@ -175,6 +172,41 @@ if(-Not $SkipToolPackageRestore.IsPresent) {
|
|||||||
$md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
|
$md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
|
||||||
}
|
}
|
||||||
Write-Verbose -Message ($NuGetOutput | out-string)
|
Write-Verbose -Message ($NuGetOutput | out-string)
|
||||||
|
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
|
|
||||||
|
# Restore addins from NuGet
|
||||||
|
if (Test-Path $ADDINS_PACKAGES_CONFIG) {
|
||||||
|
Push-Location
|
||||||
|
Set-Location $ADDINS_DIR
|
||||||
|
|
||||||
|
Write-Verbose -Message "Restoring addins from NuGet..."
|
||||||
|
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$ADDINS_DIR`""
|
||||||
|
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Throw "An error occured while restoring NuGet addins."
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Verbose -Message ($NuGetOutput | out-string)
|
||||||
|
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
|
|
||||||
|
# Restore modules from NuGet
|
||||||
|
if (Test-Path $MODULES_PACKAGES_CONFIG) {
|
||||||
|
Push-Location
|
||||||
|
Set-Location $MODULES_DIR
|
||||||
|
|
||||||
|
Write-Verbose -Message "Restoring modules from NuGet..."
|
||||||
|
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$MODULES_DIR`""
|
||||||
|
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Throw "An error occured while restoring NuGet modules."
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Verbose -Message ($NuGetOutput | out-string)
|
||||||
|
|
||||||
Pop-Location
|
Pop-Location
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +215,20 @@ if (!(Test-Path $CAKE_EXE)) {
|
|||||||
Throw "Could not find Cake.exe at $CAKE_EXE"
|
Throw "Could not find Cake.exe at $CAKE_EXE"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Build Cake arguments
|
||||||
|
$cakeArguments = @("$Script");
|
||||||
|
if ($Target) { $cakeArguments += "-target=$Target" }
|
||||||
|
if ($Configuration) { $cakeArguments += "-configuration=$Configuration" }
|
||||||
|
if ($Verbosity) { $cakeArguments += "-verbosity=$Verbosity" }
|
||||||
|
if ($ShowDescription) { $cakeArguments += "-showdescription" }
|
||||||
|
if ($DryRun) { $cakeArguments += "-dryrun" }
|
||||||
|
if ($Experimental) { $cakeArguments += "-experimental" }
|
||||||
|
if ($Mono) { $cakeArguments += "-mono" }
|
||||||
|
$cakeArguments += $ScriptArgs
|
||||||
|
|
||||||
# Start Cake
|
# Start Cake
|
||||||
Write-Host "Running build script..."
|
Write-Host "Running build script..."
|
||||||
Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs"
|
&$CAKE_EXE $cakeArguments
|
||||||
exit $LASTEXITCODE
|
exit $LASTEXITCODE
|
@ -184,7 +184,7 @@ namespace Ocelot.Configuration.Creator
|
|||||||
private string CreateReRouteKey(FileReRoute fileReRoute)
|
private string CreateReRouteKey(FileReRoute fileReRoute)
|
||||||
{
|
{
|
||||||
//note - not sure if this is the correct key, but this is probably the only unique key i can think of given my poor brain
|
//note - not sure if this is the correct key, but this is probably the only unique key i can think of given my poor brain
|
||||||
var loadBalancerKey = $"{fileReRoute.UpstreamPathTemplate}{fileReRoute.UpstreamHttpMethod}";
|
var loadBalancerKey = $"{fileReRoute.UpstreamPathTemplate}|{string.Join(",", fileReRoute.UpstreamHttpMethod)}";
|
||||||
return loadBalancerKey;
|
return loadBalancerKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ using Ocelot.Configuration.Provider;
|
|||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
using Ocelot.Errors;
|
using Ocelot.Errors;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
|
using Ocelot.Utilities;
|
||||||
|
|
||||||
namespace Ocelot.DownstreamRouteFinder.Finder
|
namespace Ocelot.DownstreamRouteFinder.Finder
|
||||||
{
|
{
|
||||||
@ -24,6 +25,8 @@ namespace Ocelot.DownstreamRouteFinder.Finder
|
|||||||
|
|
||||||
public async Task<Response<DownstreamRoute>> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod)
|
public async Task<Response<DownstreamRoute>> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod)
|
||||||
{
|
{
|
||||||
|
upstreamUrlPath = upstreamUrlPath.SetLastCharacterAs('/');
|
||||||
|
|
||||||
var configuration = await _configProvider.Get();
|
var configuration = await _configProvider.Get();
|
||||||
|
|
||||||
var applicableReRoutes = configuration.Data.ReRoutes.Where(r => r.UpstreamHttpMethod.Count == 0 || r.UpstreamHttpMethod.Select(x => x.Method.ToLower()).Contains(upstreamHttpMethod.ToLower()));
|
var applicableReRoutes = configuration.Data.ReRoutes.Where(r => r.UpstreamHttpMethod.Count == 0 || r.UpstreamHttpMethod.Select(x => x.Method.ToLower()).Contains(upstreamHttpMethod.ToLower()));
|
||||||
|
@ -30,7 +30,7 @@ namespace Ocelot.DownstreamRouteFinder.Middleware
|
|||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
var upstreamUrlPath = context.Request.Path.ToString().SetLastCharacterAs('/');
|
var upstreamUrlPath = context.Request.Path.ToString();
|
||||||
|
|
||||||
_logger.LogDebug("upstream url path is {upstreamUrlPath}", upstreamUrlPath);
|
_logger.LogDebug("upstream url path is {upstreamUrlPath}", upstreamUrlPath);
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Builder;
|
|||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Ocelot.Configuration.File;
|
using Ocelot.Configuration.File;
|
||||||
|
using Shouldly;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
@ -15,6 +16,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
private IWebHost _builder;
|
private IWebHost _builder;
|
||||||
private readonly Steps _steps;
|
private readonly Steps _steps;
|
||||||
|
private string _downstreamPath;
|
||||||
|
|
||||||
public RoutingTests()
|
public RoutingTests()
|
||||||
{
|
{
|
||||||
@ -232,6 +234,34 @@ namespace Ocelot.AcceptanceTests
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_not_add_trailing_slash_to_downstream_url()
|
||||||
|
{
|
||||||
|
var configuration = new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
DownstreamPathTemplate = "/api/products/{productId}",
|
||||||
|
DownstreamScheme = "http",
|
||||||
|
DownstreamHost = "localhost",
|
||||||
|
DownstreamPort = 51879,
|
||||||
|
UpstreamPathTemplate = "/products/{productId}",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.Given(x => GivenThereIsAServiceRunningOn("http://localhost:51879/api/products/1", 200, "Some Product"))
|
||||||
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
|
.And(x => _steps.GivenOcelotIsRunning())
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/products/1"))
|
||||||
|
.Then(x => ThenTheDownstreamUrlPathShouldBe("/api/products/1"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_response_201_with_simple_url()
|
public void should_return_response_201_with_simple_url()
|
||||||
{
|
{
|
||||||
@ -379,11 +409,11 @@ namespace Ocelot.AcceptanceTests
|
|||||||
.UseKestrel()
|
.UseKestrel()
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
.UseIISIntegration()
|
.UseIISIntegration()
|
||||||
.UseUrls(url)
|
|
||||||
.Configure(app =>
|
.Configure(app =>
|
||||||
{
|
{
|
||||||
app.Run(async context =>
|
app.Run(async context =>
|
||||||
{
|
{
|
||||||
|
_downstreamPath = context.Request.PathBase.Value;
|
||||||
context.Response.StatusCode = statusCode;
|
context.Response.StatusCode = statusCode;
|
||||||
await context.Response.WriteAsync(responseBody);
|
await context.Response.WriteAsync(responseBody);
|
||||||
});
|
});
|
||||||
@ -393,6 +423,11 @@ namespace Ocelot.AcceptanceTests
|
|||||||
_builder.Start();
|
_builder.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void ThenTheDownstreamUrlPathShouldBe(string expectedDownstreamPath)
|
||||||
|
{
|
||||||
|
_downstreamPath.ShouldBe(expectedDownstreamPath);
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_builder?.Dispose();
|
_builder?.Dispose();
|
||||||
|
@ -36,7 +36,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_route()
|
public void should_return_route()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher"))
|
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher/"))
|
||||||
.And(x =>x.GivenTheTemplateVariableAndNameFinderReturns(
|
.And(x =>x.GivenTheTemplateVariableAndNameFinderReturns(
|
||||||
new OkResponse<List<UrlPathPlaceholderNameAndValue>>(
|
new OkResponse<List<UrlPathPlaceholderNameAndValue>>(
|
||||||
new List<UrlPathPlaceholderNameAndValue>())))
|
new List<UrlPathPlaceholderNameAndValue>())))
|
||||||
@ -65,6 +65,39 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_append_slash_to_upstream_url_path()
|
||||||
|
{
|
||||||
|
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher"))
|
||||||
|
.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" })
|
||||||
|
.WithUpstreamTemplatePattern("someUpstreamPath")
|
||||||
|
.Build()
|
||||||
|
}, string.Empty
|
||||||
|
))
|
||||||
|
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
|
||||||
|
.And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
|
||||||
|
.When(x => x.WhenICallTheFinder())
|
||||||
|
.Then(
|
||||||
|
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(
|
||||||
|
new List<UrlPathPlaceholderNameAndValue>(),
|
||||||
|
new ReRouteBuilder()
|
||||||
|
.WithDownstreamPathTemplate("someDownstreamPath")
|
||||||
|
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||||
|
.Build()
|
||||||
|
)))
|
||||||
|
.And(x => x.ThenTheUrlMatcherIsCalledCorrectly("matchInUrlMatcher/"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_return_route_if_upstream_path_and_upstream_template_are_the_same()
|
public void should_return_route_if_upstream_path_and_upstream_template_are_the_same()
|
||||||
{
|
{
|
||||||
@ -137,7 +170,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void should_not_return_route()
|
public void should_not_return_route()
|
||||||
{
|
{
|
||||||
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("dontMatchPath"))
|
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("dontMatchPath/"))
|
||||||
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
|
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
|
||||||
{
|
{
|
||||||
new ReRouteBuilder()
|
new ReRouteBuilder()
|
||||||
@ -269,6 +302,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
.Verify(x => x.Match(_upstreamUrlPath, _reRoutesConfig[0].UpstreamPathTemplate.Value), Times.Once);
|
.Verify(x => x.Match(_upstreamUrlPath, _reRoutesConfig[0].UpstreamPathTemplate.Value), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ThenTheUrlMatcherIsCalledCorrectly(string expectedUpstreamUrlPath)
|
||||||
|
{
|
||||||
|
_mockMatcher
|
||||||
|
.Verify(x => x.Match(expectedUpstreamUrlPath, _reRoutesConfig[0].UpstreamPathTemplate.Value), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
private void ThenTheUrlMatcherIsNotCalled()
|
private void ThenTheUrlMatcherIsNotCalled()
|
||||||
{
|
{
|
||||||
_mockMatcher
|
_mockMatcher
|
||||||
|
124
test/Ocelot.UnitTests/Infrastructure/ScopesAuthoriserTests.cs
Normal file
124
test/Ocelot.UnitTests/Infrastructure/ScopesAuthoriserTests.cs
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
using Xunit;
|
||||||
|
using Shouldly;
|
||||||
|
using Ocelot.Authorisation;
|
||||||
|
using Ocelot.Infrastructure.Claims.Parser;
|
||||||
|
using Moq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using Ocelot.Responses;
|
||||||
|
using TestStack.BDDfy;
|
||||||
|
using Ocelot.Errors;
|
||||||
|
|
||||||
|
namespace Ocelot.UnitTests.Infrastructure
|
||||||
|
{
|
||||||
|
public class ScopesAuthoriserTests
|
||||||
|
{
|
||||||
|
private ScopesAuthoriser _authoriser;
|
||||||
|
public Mock<IClaimsParser> _parser;
|
||||||
|
private ClaimsPrincipal _principal;
|
||||||
|
private List<string> _allowedScopes;
|
||||||
|
private Response<bool> _result;
|
||||||
|
|
||||||
|
public ScopesAuthoriserTests()
|
||||||
|
{
|
||||||
|
_parser = new Mock<IClaimsParser>();
|
||||||
|
_authoriser = new ScopesAuthoriser(_parser.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_ok_if_no_allowed_scopes()
|
||||||
|
{
|
||||||
|
this.Given(_ => GivenTheFollowing(new ClaimsPrincipal()))
|
||||||
|
.And(_ => GivenTheFollowing(new List<string>()))
|
||||||
|
.When(_ => WhenIAuthorise())
|
||||||
|
.Then(_ => ThenTheFollowingIsReturned(new OkResponse<bool>(true)))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_ok_if_null_allowed_scopes()
|
||||||
|
{
|
||||||
|
this.Given(_ => GivenTheFollowing(new ClaimsPrincipal()))
|
||||||
|
.And(_ => GivenTheFollowing((List<string>)null))
|
||||||
|
.When(_ => WhenIAuthorise())
|
||||||
|
.Then(_ => ThenTheFollowingIsReturned(new OkResponse<bool>(true)))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_return_error_if_claims_parser_returns_error()
|
||||||
|
{
|
||||||
|
var fakeError = new FakeError();
|
||||||
|
this.Given(_ => GivenTheFollowing(new ClaimsPrincipal()))
|
||||||
|
.And(_ => GivenTheParserReturns(new ErrorResponse<List<string>>(fakeError)))
|
||||||
|
.And(_ => GivenTheFollowing(new List<string>(){"doesntmatter"}))
|
||||||
|
.When(_ => WhenIAuthorise())
|
||||||
|
.Then(_ => ThenTheFollowingIsReturned(new ErrorResponse<bool>(fakeError)))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_match_scopes_and_return_ok_result()
|
||||||
|
{
|
||||||
|
var claimsPrincipal = new ClaimsPrincipal();
|
||||||
|
var allowedScopes = new List<string>(){"someScope"};
|
||||||
|
|
||||||
|
this.Given(_ => GivenTheFollowing(claimsPrincipal))
|
||||||
|
.And(_ => GivenTheParserReturns(new OkResponse<List<string>>(allowedScopes)))
|
||||||
|
.And(_ => GivenTheFollowing(allowedScopes))
|
||||||
|
.When(_ => WhenIAuthorise())
|
||||||
|
.Then(_ => ThenTheFollowingIsReturned(new OkResponse<bool>(true)))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_not_match_scopes_and_return_error_result()
|
||||||
|
{
|
||||||
|
var fakeError = new FakeError();
|
||||||
|
var claimsPrincipal = new ClaimsPrincipal();
|
||||||
|
var allowedScopes = new List<string>(){"someScope"};
|
||||||
|
var userScopes = new List<string>(){"anotherScope"};
|
||||||
|
|
||||||
|
this.Given(_ => GivenTheFollowing(claimsPrincipal))
|
||||||
|
.And(_ => GivenTheParserReturns(new OkResponse<List<string>>(userScopes)))
|
||||||
|
.And(_ => GivenTheFollowing(allowedScopes))
|
||||||
|
.When(_ => WhenIAuthorise())
|
||||||
|
.Then(_ => ThenTheFollowingIsReturned(new ErrorResponse<bool>(fakeError)))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheParserReturns(Response<List<string>> response)
|
||||||
|
{
|
||||||
|
_parser.Setup(x => x.GetValuesByClaimType(It.IsAny<IEnumerable<Claim>>(), It.IsAny<string>())).Returns(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheFollowing(ClaimsPrincipal principal)
|
||||||
|
{
|
||||||
|
_principal = principal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheFollowing(List<string> allowedScopes)
|
||||||
|
{
|
||||||
|
_allowedScopes = allowedScopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WhenIAuthorise()
|
||||||
|
{
|
||||||
|
_result = _authoriser.Authorise(_principal, _allowedScopes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheFollowingIsReturned(Response<bool> expected)
|
||||||
|
{
|
||||||
|
_result.Data.ShouldBe(expected.Data);
|
||||||
|
_result.IsError.ShouldBe(expected.IsError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FakeError : Error
|
||||||
|
{
|
||||||
|
public FakeError() : base("fake error", OcelotErrorCode.CannotAddDataError)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Cake" version="0.17.0" />
|
<package id="Cake" version="0.22.2" />
|
||||||
</packages>
|
</packages>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user