mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 15:58:16 +08:00
+semver: upgrade to net5.0 (#1390)
* breaking upgrade base build image to net5.0 * add make and build tools to image * fix code broken after net5.0 upgrade * fix warnings * fix tests and line endings * upgrade dotnet test and coverages packages * update circle build image * removed rafty and updated more packages * bring back develop * rename authorisation to authorization
This commit is contained in:
@ -1,119 +1,119 @@
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using IdentityServer4.AccessTokenValidation;
|
||||
using IdentityServer4.Models;
|
||||
using IdentityServer4.Test;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Configuration.File;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Claims;
|
||||
using TestStack.BDDfy;
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using IdentityServer4.AccessTokenValidation;
|
||||
using IdentityServer4.Models;
|
||||
using IdentityServer4.Test;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Configuration.File;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Claims;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class AuthenticationTests : IDisposable
|
||||
{
|
||||
private readonly Steps _steps;
|
||||
private IWebHost _identityServerBuilder;
|
||||
private string _identityServerRootUrl;
|
||||
private string _downstreamServicePath = "/";
|
||||
private string _downstreamServiceHost = "localhost";
|
||||
private string _downstreamServiceScheme = "http";
|
||||
private string _downstreamServiceUrl = "http://localhost:";
|
||||
private readonly Action<IdentityServerAuthenticationOptions> _options;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public AuthenticationTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
|
||||
public class AuthenticationTests : IDisposable
|
||||
{
|
||||
private readonly Steps _steps;
|
||||
private IWebHost _identityServerBuilder;
|
||||
private string _identityServerRootUrl;
|
||||
private string _downstreamServicePath = "/";
|
||||
private string _downstreamServiceHost = "localhost";
|
||||
private string _downstreamServiceScheme = "http";
|
||||
private string _downstreamServiceUrl = "http://localhost:";
|
||||
private readonly Action<IdentityServerAuthenticationOptions> _options;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public AuthenticationTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
_steps = new Steps();
|
||||
var identityServerPort = RandomPortFinder.GetRandomPort();
|
||||
_identityServerRootUrl = $"http://localhost:{identityServerPort}";
|
||||
_options = o =>
|
||||
{
|
||||
o.Authority = _identityServerRootUrl;
|
||||
o.ApiName = "api";
|
||||
o.RequireHttpsMetadata = false;
|
||||
o.SupportedTokens = SupportedTokens.Both;
|
||||
o.ApiSecret = "secret";
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_401_using_identity_server_access_token()
|
||||
{
|
||||
_identityServerRootUrl = $"http://localhost:{identityServerPort}";
|
||||
_options = o =>
|
||||
{
|
||||
o.Authority = _identityServerRootUrl;
|
||||
o.ApiName = "api";
|
||||
o.RequireHttpsMetadata = false;
|
||||
o.SupportedTokens = SupportedTokens.Both;
|
||||
o.ApiSecret = "secret";
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_401_using_identity_server_access_token()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = _downstreamServicePath,
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host =_downstreamServiceHost,
|
||||
Port = port,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = _downstreamServiceScheme,
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Post" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
|
||||
.And(x => x.GivenThereIsAServiceRunningOn($"{_downstreamServiceUrl}{port}", 201, string.Empty))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning(_options, "Test"))
|
||||
.And(x => _steps.GivenThePostHasContent("postContent"))
|
||||
.When(x => _steps.WhenIPostUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Unauthorized))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_200_using_identity_server()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = _downstreamServicePath,
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host =_downstreamServiceHost,
|
||||
Port = port,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = _downstreamServiceScheme,
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Post" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
|
||||
.And(x => x.GivenThereIsAServiceRunningOn($"{_downstreamServiceUrl}{port}", 201, string.Empty))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning(_options, "Test"))
|
||||
.And(x => _steps.GivenThePostHasContent("postContent"))
|
||||
.When(x => _steps.WhenIPostUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Unauthorized))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_200_using_identity_server()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = _downstreamServicePath,
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host =_downstreamServiceHost,
|
||||
Port = port,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = _downstreamServiceScheme,
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test"
|
||||
}
|
||||
}
|
||||
}
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = _downstreamServicePath,
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host =_downstreamServiceHost,
|
||||
Port = port,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = _downstreamServiceScheme,
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
|
||||
@ -125,38 +125,38 @@ namespace Ocelot.AcceptanceTests
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_401_using_identity_server_with_token_requested_for_other_api()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_401_using_identity_server_with_token_requested_for_other_api()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = _downstreamServicePath,
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host =_downstreamServiceHost,
|
||||
Port = port,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = _downstreamServiceScheme,
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test"
|
||||
}
|
||||
}
|
||||
}
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = _downstreamServicePath,
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host =_downstreamServiceHost,
|
||||
Port = port,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = _downstreamServiceScheme,
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
|
||||
@ -167,38 +167,38 @@ namespace Ocelot.AcceptanceTests
|
||||
.And(x => _steps.GivenIHaveAddedATokenToMyRequest())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Unauthorized))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_201_using_identity_server_access_token()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_201_using_identity_server_access_token()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = _downstreamServicePath,
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host =_downstreamServiceHost,
|
||||
Port = port,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = _downstreamServiceScheme,
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Post" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test"
|
||||
}
|
||||
}
|
||||
}
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = _downstreamServicePath,
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host =_downstreamServiceHost,
|
||||
Port = port,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = _downstreamServiceScheme,
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Post" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
|
||||
@ -210,38 +210,38 @@ namespace Ocelot.AcceptanceTests
|
||||
.And(x => _steps.GivenThePostHasContent("postContent"))
|
||||
.When(x => _steps.WhenIPostUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Created))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_201_using_identity_server_reference_token()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_201_using_identity_server_reference_token()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = _downstreamServicePath,
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host =_downstreamServiceHost,
|
||||
Port = port,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = _downstreamServiceScheme,
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Post" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test"
|
||||
}
|
||||
}
|
||||
}
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = _downstreamServicePath,
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host =_downstreamServiceHost,
|
||||
Port = port,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = _downstreamServiceScheme,
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Post" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test"
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Reference))
|
||||
@ -253,126 +253,131 @@ namespace Ocelot.AcceptanceTests
|
||||
.And(x => _steps.GivenThePostHasContent("postContent"))
|
||||
.When(x => _steps.WhenIPostUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Created))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(url, async context =>
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
}
|
||||
|
||||
private void GivenThereIsAnIdentityServerOn(string url, string apiName, string api2Name, AccessTokenType tokenType)
|
||||
{
|
||||
_identityServerBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddIdentityServer()
|
||||
.AddDeveloperSigningCredential()
|
||||
.AddInMemoryApiResources(new List<ApiResource>
|
||||
{
|
||||
new ApiResource
|
||||
{
|
||||
Name = apiName,
|
||||
Description = "My API",
|
||||
Enabled = true,
|
||||
DisplayName = "test",
|
||||
Scopes = new List<Scope>()
|
||||
{
|
||||
new Scope("api"),
|
||||
new Scope("api.readOnly"),
|
||||
new Scope("openid"),
|
||||
new Scope("offline_access")
|
||||
},
|
||||
ApiSecrets = new List<Secret>()
|
||||
{
|
||||
new Secret
|
||||
{
|
||||
Value = "secret".Sha256()
|
||||
}
|
||||
},
|
||||
UserClaims = new List<string>()
|
||||
{
|
||||
"CustomerId", "LocationId"
|
||||
}
|
||||
},
|
||||
new ApiResource
|
||||
{
|
||||
Name = api2Name,
|
||||
Description = "My second API",
|
||||
Enabled = true,
|
||||
DisplayName = "second test",
|
||||
Scopes = new List<Scope>()
|
||||
{
|
||||
new Scope("api2"),
|
||||
new Scope("api2.readOnly"),
|
||||
},
|
||||
ApiSecrets = new List<Secret>()
|
||||
{
|
||||
new Secret
|
||||
{
|
||||
Value = "secret".Sha256()
|
||||
}
|
||||
},
|
||||
UserClaims = new List<string>()
|
||||
{
|
||||
"CustomerId", "LocationId"
|
||||
}
|
||||
},
|
||||
})
|
||||
.AddInMemoryClients(new List<Client>
|
||||
{
|
||||
new Client
|
||||
{
|
||||
ClientId = "client",
|
||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
|
||||
AllowedScopes = new List<string> { apiName, api2Name, "api.readOnly", "openid", "offline_access" },
|
||||
AccessTokenType = tokenType,
|
||||
Enabled = true,
|
||||
RequireClientSecret = false
|
||||
}
|
||||
})
|
||||
.AddTestUsers(new List<TestUser>
|
||||
{
|
||||
new TestUser
|
||||
{
|
||||
Username = "test",
|
||||
Password = "test",
|
||||
SubjectId = "registered|1231231",
|
||||
Claims = new List<Claim>
|
||||
{
|
||||
new Claim("CustomerId", "123"),
|
||||
new Claim("LocationId", "321")
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseIdentityServer();
|
||||
})
|
||||
.Build();
|
||||
|
||||
_identityServerBuilder.Start();
|
||||
|
||||
_steps.VerifyIdentiryServerStarted(url);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler.Dispose();
|
||||
_steps.Dispose();
|
||||
_identityServerBuilder?.Dispose();
|
||||
}
|
||||
}
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(url, async context =>
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
}
|
||||
|
||||
private void GivenThereIsAnIdentityServerOn(string url, string apiName, string api2Name, AccessTokenType tokenType)
|
||||
{
|
||||
_identityServerBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddIdentityServer()
|
||||
.AddDeveloperSigningCredential()
|
||||
.AddInMemoryApiScopes(new List<ApiScope>
|
||||
{
|
||||
new ApiScope(apiName, "test"),
|
||||
new ApiScope(api2Name, "test"),
|
||||
})
|
||||
.AddInMemoryApiResources(new List<ApiResource>
|
||||
{
|
||||
new ApiResource
|
||||
{
|
||||
Name = apiName,
|
||||
Description = "My API",
|
||||
Enabled = true,
|
||||
DisplayName = "test",
|
||||
Scopes = new List<string>()
|
||||
{
|
||||
"api",
|
||||
"api.readOnly",
|
||||
"openid",
|
||||
"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<string>()
|
||||
{
|
||||
"api2",
|
||||
"api2.readOnly",
|
||||
},
|
||||
ApiSecrets = new List<Secret>()
|
||||
{
|
||||
new Secret
|
||||
{
|
||||
Value = "secret".Sha256(),
|
||||
},
|
||||
},
|
||||
UserClaims = new List<string>()
|
||||
{
|
||||
"CustomerId", "LocationId",
|
||||
},
|
||||
},
|
||||
})
|
||||
.AddInMemoryClients(new List<Client>
|
||||
{
|
||||
new Client
|
||||
{
|
||||
ClientId = "client",
|
||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
|
||||
AllowedScopes = new List<string> { apiName, api2Name, "api.readOnly", "openid", "offline_access" },
|
||||
AccessTokenType = tokenType,
|
||||
Enabled = true,
|
||||
RequireClientSecret = false,
|
||||
},
|
||||
})
|
||||
.AddTestUsers(new List<TestUser>
|
||||
{
|
||||
new TestUser
|
||||
{
|
||||
Username = "test",
|
||||
Password = "test",
|
||||
SubjectId = "registered|1231231",
|
||||
Claims = new List<Claim>
|
||||
{
|
||||
new Claim("CustomerId", "123"),
|
||||
new Claim("LocationId", "321"),
|
||||
},
|
||||
},
|
||||
});
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseIdentityServer();
|
||||
})
|
||||
.Build();
|
||||
|
||||
_identityServerBuilder.Start();
|
||||
|
||||
_steps.VerifyIdentiryServerStarted(url);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler.Dispose();
|
||||
_steps.Dispose();
|
||||
_identityServerBuilder?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,91 +1,91 @@
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using IdentityServer4.AccessTokenValidation;
|
||||
using IdentityServer4.Models;
|
||||
using IdentityServer4.Test;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Configuration.File;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Claims;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class AuthorisationTests : IDisposable
|
||||
{
|
||||
private IWebHost _identityServerBuilder;
|
||||
private readonly Steps _steps;
|
||||
private readonly Action<IdentityServerAuthenticationOptions> _options;
|
||||
private string _identityServerRootUrl;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public AuthorisationTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using IdentityServer4.AccessTokenValidation;
|
||||
using IdentityServer4.Models;
|
||||
using IdentityServer4.Test;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Configuration.File;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Claims;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class AuthorizationTests : IDisposable
|
||||
{
|
||||
private IWebHost _identityServerBuilder;
|
||||
private readonly Steps _steps;
|
||||
private readonly Action<IdentityServerAuthenticationOptions> _options;
|
||||
private string _identityServerRootUrl;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public AuthorizationTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
_steps = new Steps();
|
||||
var identityServerPort = RandomPortFinder.GetRandomPort();
|
||||
_identityServerRootUrl = $"http://localhost:{identityServerPort}";
|
||||
_options = o =>
|
||||
{
|
||||
o.Authority = _identityServerRootUrl;
|
||||
o.ApiName = "api";
|
||||
o.RequireHttpsMetadata = false;
|
||||
o.SupportedTokens = SupportedTokens.Both;
|
||||
o.ApiSecret = "secret";
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_200_authorising_route()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
_identityServerRootUrl = $"http://localhost:{identityServerPort}";
|
||||
_options = o =>
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test"
|
||||
},
|
||||
AddHeadersToRequest =
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"},
|
||||
{"LocationId", "Claims[LocationId] > value"},
|
||||
{"UserType", "Claims[sub] > value[0] > |"},
|
||||
{"UserId", "Claims[sub] > value[1] > |"}
|
||||
},
|
||||
AddClaimsToRequest =
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"},
|
||||
{"UserType", "Claims[sub] > value[0] > |"},
|
||||
{"UserId", "Claims[sub] > value[1] > |"}
|
||||
},
|
||||
RouteClaimsRequirement =
|
||||
{
|
||||
{"UserType", "registered"}
|
||||
}
|
||||
}
|
||||
}
|
||||
o.Authority = _identityServerRootUrl;
|
||||
o.ApiName = "api";
|
||||
o.RequireHttpsMetadata = false;
|
||||
o.SupportedTokens = SupportedTokens.Both;
|
||||
o.ApiSecret = "secret";
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_200_authorizing_route()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
},
|
||||
AddHeadersToRequest =
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"},
|
||||
{"LocationId", "Claims[LocationId] > value"},
|
||||
{"UserType", "Claims[sub] > value[0] > |"},
|
||||
{"UserId", "Claims[sub] > value[1] > |"},
|
||||
},
|
||||
AddClaimsToRequest =
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"},
|
||||
{"UserType", "Claims[sub] > value[0] > |"},
|
||||
{"UserId", "Claims[sub] > value[1] > |"},
|
||||
},
|
||||
RouteClaimsRequirement =
|
||||
{
|
||||
{"UserType", "registered"},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt))
|
||||
@ -97,54 +97,54 @@ namespace Ocelot.AcceptanceTests
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_403_authorising_route()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_403_authorizing_route()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test"
|
||||
},
|
||||
AddHeadersToRequest =
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"},
|
||||
{"LocationId", "Claims[LocationId] > value"},
|
||||
{"UserType", "Claims[sub] > value[0] > |"},
|
||||
{"UserId", "Claims[sub] > value[1] > |"}
|
||||
},
|
||||
AddClaimsToRequest =
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"},
|
||||
{"UserId", "Claims[sub] > value[1] > |"}
|
||||
},
|
||||
RouteClaimsRequirement =
|
||||
{
|
||||
{"UserType", "registered"}
|
||||
}
|
||||
}
|
||||
}
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
},
|
||||
AddHeadersToRequest =
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"},
|
||||
{"LocationId", "Claims[LocationId] > value"},
|
||||
{"UserType", "Claims[sub] > value[0] > |"},
|
||||
{"UserId", "Claims[sub] > value[1] > |"},
|
||||
},
|
||||
AddClaimsToRequest =
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"},
|
||||
{"UserId", "Claims[sub] > value[1] > |"},
|
||||
},
|
||||
RouteClaimsRequirement =
|
||||
{
|
||||
{"UserType", "registered"},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt))
|
||||
@ -155,39 +155,39 @@ namespace Ocelot.AcceptanceTests
|
||||
.And(x => _steps.GivenIHaveAddedATokenToMyRequest())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Forbidden))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_200_using_identity_server_with_allowed_scope()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_200_using_identity_server_with_allowed_scope()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
AllowedScopes = new List<string>{ "api", "api.readOnly", "openid", "offline_access" },
|
||||
},
|
||||
}
|
||||
}
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
AllowedScopes = new List<string>{ "api", "api.readOnly", "openid", "offline_access" },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt))
|
||||
@ -198,39 +198,39 @@ namespace Ocelot.AcceptanceTests
|
||||
.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()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_403_using_identity_server_with_scope_not_allowed()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
AllowedScopes = new List<string>{ "api", "openid", "offline_access" },
|
||||
},
|
||||
}
|
||||
}
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
AllowedScopes = new List<string>{ "api", "openid", "offline_access" },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt))
|
||||
@ -241,57 +241,57 @@ namespace Ocelot.AcceptanceTests
|
||||
.And(x => _steps.GivenIHaveAddedATokenToMyRequest())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Forbidden))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_fix_issue_240()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_fix_issue_240()
|
||||
{
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test"
|
||||
},
|
||||
RouteClaimsRequirement =
|
||||
{
|
||||
{"Role", "User"}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var users = new List<TestUser>
|
||||
{
|
||||
new TestUser
|
||||
{
|
||||
Username = "test",
|
||||
Password = "test",
|
||||
SubjectId = "registered|1231231",
|
||||
Claims = new List<Claim>
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
},
|
||||
RouteClaimsRequirement =
|
||||
{
|
||||
{"Role", "User"},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
var users = new List<TestUser>
|
||||
{
|
||||
new TestUser
|
||||
{
|
||||
Username = "test",
|
||||
Password = "test",
|
||||
SubjectId = "registered|1231231",
|
||||
Claims = new List<Claim>
|
||||
{
|
||||
new Claim("Role", "AdminUser"),
|
||||
new Claim("Role", "User")
|
||||
},
|
||||
}
|
||||
new Claim("Role", "User"),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt, users))
|
||||
@ -303,170 +303,181 @@ namespace Ocelot.AcceptanceTests
|
||||
.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)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(url, async context =>
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
}
|
||||
|
||||
private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType)
|
||||
{
|
||||
_identityServerBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddIdentityServer()
|
||||
.AddDeveloperSigningCredential()
|
||||
.AddInMemoryApiResources(new List<ApiResource>
|
||||
{
|
||||
new ApiResource
|
||||
{
|
||||
Name = apiName,
|
||||
Description = "My API",
|
||||
Enabled = true,
|
||||
DisplayName = "test",
|
||||
Scopes = new List<Scope>()
|
||||
{
|
||||
new Scope("api"),
|
||||
new Scope("api.readOnly"),
|
||||
new Scope("openid"),
|
||||
new Scope("offline_access")
|
||||
},
|
||||
ApiSecrets = new List<Secret>()
|
||||
{
|
||||
new Secret
|
||||
{
|
||||
Value = "secret".Sha256()
|
||||
}
|
||||
},
|
||||
UserClaims = new List<string>()
|
||||
{
|
||||
"CustomerId", "LocationId", "UserType", "UserId"
|
||||
}
|
||||
},
|
||||
})
|
||||
.AddInMemoryClients(new List<Client>
|
||||
{
|
||||
new Client
|
||||
{
|
||||
ClientId = "client",
|
||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
|
||||
AllowedScopes = new List<string> { apiName, "api.readOnly", "openid", "offline_access" },
|
||||
AccessTokenType = tokenType,
|
||||
Enabled = true,
|
||||
RequireClientSecret = false
|
||||
}
|
||||
})
|
||||
.AddTestUsers(new List<TestUser>
|
||||
{
|
||||
new TestUser
|
||||
{
|
||||
Username = "test",
|
||||
Password = "test",
|
||||
SubjectId = "registered|1231231",
|
||||
Claims = new List<Claim>
|
||||
{
|
||||
new Claim("CustomerId", "123"),
|
||||
new Claim("LocationId", "321")
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseIdentityServer();
|
||||
})
|
||||
.Build();
|
||||
|
||||
_identityServerBuilder.Start();
|
||||
|
||||
_steps.VerifyIdentiryServerStarted(url);
|
||||
}
|
||||
|
||||
private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType, List<TestUser> users)
|
||||
{
|
||||
_identityServerBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddIdentityServer()
|
||||
.AddDeveloperSigningCredential()
|
||||
.AddInMemoryApiResources(new List<ApiResource>
|
||||
{
|
||||
new ApiResource
|
||||
{
|
||||
Name = apiName,
|
||||
Description = "My API",
|
||||
Enabled = true,
|
||||
DisplayName = "test",
|
||||
Scopes = new List<Scope>()
|
||||
{
|
||||
new Scope("api"),
|
||||
new Scope("api.readOnly"),
|
||||
new Scope("openid"),
|
||||
new Scope("offline_access"),
|
||||
},
|
||||
ApiSecrets = new List<Secret>()
|
||||
{
|
||||
new Secret
|
||||
{
|
||||
Value = "secret".Sha256()
|
||||
}
|
||||
},
|
||||
UserClaims = new List<string>()
|
||||
{
|
||||
"CustomerId", "LocationId", "UserType", "UserId", "Role"
|
||||
}
|
||||
},
|
||||
})
|
||||
.AddInMemoryClients(new List<Client>
|
||||
{
|
||||
new Client
|
||||
{
|
||||
ClientId = "client",
|
||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
|
||||
AllowedScopes = new List<string> { apiName, "api.readOnly", "openid", "offline_access" },
|
||||
AccessTokenType = tokenType,
|
||||
Enabled = true,
|
||||
RequireClientSecret = false,
|
||||
}
|
||||
})
|
||||
.AddTestUsers(users);
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseIdentityServer();
|
||||
})
|
||||
.Build();
|
||||
|
||||
_identityServerBuilder.Start();
|
||||
|
||||
_steps.VerifyIdentiryServerStarted(url);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler?.Dispose();
|
||||
_steps.Dispose();
|
||||
_identityServerBuilder?.Dispose();
|
||||
}
|
||||
}
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(url, async context =>
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
}
|
||||
|
||||
private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType)
|
||||
{
|
||||
_identityServerBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddIdentityServer()
|
||||
.AddDeveloperSigningCredential()
|
||||
.AddInMemoryApiScopes(new List<ApiScope>
|
||||
{
|
||||
new ApiScope(apiName, "test"),
|
||||
new ApiScope("openid", "test"),
|
||||
new ApiScope("offline_access", "test"),
|
||||
new ApiScope("api.readOnly", "test"),
|
||||
})
|
||||
.AddInMemoryApiResources(new List<ApiResource>
|
||||
{
|
||||
new ApiResource
|
||||
{
|
||||
Name = apiName,
|
||||
Description = "My API",
|
||||
Enabled = true,
|
||||
DisplayName = "test",
|
||||
Scopes = new List<string>()
|
||||
{
|
||||
"api",
|
||||
"api.readOnly",
|
||||
"openid",
|
||||
"offline_access",
|
||||
},
|
||||
ApiSecrets = new List<Secret>()
|
||||
{
|
||||
new Secret
|
||||
{
|
||||
Value = "secret".Sha256(),
|
||||
},
|
||||
},
|
||||
UserClaims = new List<string>()
|
||||
{
|
||||
"CustomerId", "LocationId", "UserType", "UserId",
|
||||
},
|
||||
},
|
||||
})
|
||||
.AddInMemoryClients(new List<Client>
|
||||
{
|
||||
new Client
|
||||
{
|
||||
ClientId = "client",
|
||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
|
||||
AllowedScopes = new List<string> { apiName, "api.readOnly", "openid", "offline_access" },
|
||||
AccessTokenType = tokenType,
|
||||
Enabled = true,
|
||||
RequireClientSecret = false,
|
||||
},
|
||||
})
|
||||
.AddTestUsers(new List<TestUser>
|
||||
{
|
||||
new TestUser
|
||||
{
|
||||
Username = "test",
|
||||
Password = "test",
|
||||
SubjectId = "registered|1231231",
|
||||
Claims = new List<Claim>
|
||||
{
|
||||
new Claim("CustomerId", "123"),
|
||||
new Claim("LocationId", "321"),
|
||||
},
|
||||
},
|
||||
});
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseIdentityServer();
|
||||
})
|
||||
.Build();
|
||||
|
||||
_identityServerBuilder.Start();
|
||||
|
||||
_steps.VerifyIdentiryServerStarted(url);
|
||||
}
|
||||
|
||||
private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType, List<TestUser> users)
|
||||
{
|
||||
_identityServerBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddIdentityServer()
|
||||
.AddDeveloperSigningCredential()
|
||||
.AddInMemoryApiScopes(new List<ApiScope>
|
||||
{
|
||||
new ApiScope(apiName, "test"),
|
||||
})
|
||||
.AddInMemoryApiResources(new List<ApiResource>
|
||||
{
|
||||
new ApiResource
|
||||
{
|
||||
Name = apiName,
|
||||
Description = "My API",
|
||||
Enabled = true,
|
||||
DisplayName = "test",
|
||||
Scopes = new List<string>()
|
||||
{
|
||||
"api",
|
||||
"api.readOnly",
|
||||
"openid",
|
||||
"offline_access",
|
||||
},
|
||||
ApiSecrets = new List<Secret>()
|
||||
{
|
||||
new Secret
|
||||
{
|
||||
Value = "secret".Sha256(),
|
||||
},
|
||||
},
|
||||
UserClaims = new List<string>()
|
||||
{
|
||||
"CustomerId", "LocationId", "UserType", "UserId", "Role",
|
||||
},
|
||||
},
|
||||
})
|
||||
.AddInMemoryClients(new List<Client>
|
||||
{
|
||||
new Client
|
||||
{
|
||||
ClientId = "client",
|
||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
|
||||
AllowedScopes = new List<string> { apiName, "api.readOnly", "openid", "offline_access" },
|
||||
AccessTokenType = tokenType,
|
||||
Enabled = true,
|
||||
RequireClientSecret = false,
|
||||
},
|
||||
})
|
||||
.AddTestUsers(users);
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseIdentityServer();
|
||||
})
|
||||
.Build();
|
||||
|
||||
_identityServerBuilder.Start();
|
||||
|
||||
_steps.VerifyIdentiryServerStarted(url);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler?.Dispose();
|
||||
_steps.Dispose();
|
||||
_identityServerBuilder?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,10 @@
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using Butterfly.Client.AspNetCore;
|
||||
using Configuration.File;
|
||||
using Ocelot.Configuration.File;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Rafty.Infrastructure;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -1,205 +1,217 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using IdentityServer4.AccessTokenValidation;
|
||||
using IdentityServer4.Models;
|
||||
using IdentityServer4.Test;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Configuration.File;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using TestStack.BDDfy;
|
||||
|
||||
public class ClaimsToDownstreamPathTests : IDisposable
|
||||
{
|
||||
private IWebHost _servicebuilder;
|
||||
private IWebHost _identityServerBuilder;
|
||||
private readonly Steps _steps;
|
||||
private Action<IdentityServerAuthenticationOptions> _options;
|
||||
private string _identityServerRootUrl;
|
||||
private string _downstreamFinalPath;
|
||||
|
||||
public ClaimsToDownstreamPathTests()
|
||||
{
|
||||
var identityServerPort = RandomPortFinder.GetRandomPort();
|
||||
_identityServerRootUrl = $"http://localhost:{identityServerPort}";
|
||||
_steps = new Steps();
|
||||
_options = o =>
|
||||
{
|
||||
o.Authority = _identityServerRootUrl;
|
||||
o.ApiName = "api";
|
||||
o.RequireHttpsMetadata = false;
|
||||
o.SupportedTokens = SupportedTokens.Both;
|
||||
o.ApiSecret = "secret";
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_200_and_change_downstream_path()
|
||||
{
|
||||
var user = new TestUser()
|
||||
{
|
||||
Username = "test",
|
||||
Password = "test",
|
||||
SubjectId = "registered|1231231",
|
||||
};
|
||||
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/users/{userId}",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/users",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
AllowedScopes = new List<string>
|
||||
{
|
||||
"openid", "offline_access", "api",
|
||||
},
|
||||
},
|
||||
ChangeDownstreamPathTemplate =
|
||||
{
|
||||
{"userId", "Claims[sub] > value[1] > |"},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt, user))
|
||||
.And(x => x.GivenThereIsAServiceRunningOn($"http://localhost:{port}", 200))
|
||||
.And(x => _steps.GivenIHaveAToken(_identityServerRootUrl))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning(_options, "Test"))
|
||||
.And(x => _steps.GivenIHaveAddedATokenToMyRequest())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/users"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("UserId: 1231231"))
|
||||
.And(x => _downstreamFinalPath.ShouldBe("/users/1231231"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode)
|
||||
{
|
||||
_servicebuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.Configure(app =>
|
||||
{
|
||||
app.Run(async context =>
|
||||
{
|
||||
_downstreamFinalPath = context.Request.Path.Value;
|
||||
|
||||
string userId = _downstreamFinalPath.Replace("/users/", string.Empty);
|
||||
|
||||
var responseBody = $"UserId: {userId}";
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
_servicebuilder.Start();
|
||||
}
|
||||
|
||||
private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType, TestUser user)
|
||||
{
|
||||
_identityServerBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddIdentityServer()
|
||||
.AddDeveloperSigningCredential()
|
||||
.AddInMemoryApiResources(new List<ApiResource>
|
||||
{
|
||||
new ApiResource
|
||||
{
|
||||
Name = apiName,
|
||||
Description = "My API",
|
||||
Enabled = true,
|
||||
DisplayName = "test",
|
||||
Scopes = new List<Scope>()
|
||||
{
|
||||
new Scope("api"),
|
||||
new Scope("openid"),
|
||||
new Scope("offline_access")
|
||||
},
|
||||
ApiSecrets = new List<Secret>()
|
||||
{
|
||||
new Secret
|
||||
{
|
||||
Value = "secret".Sha256()
|
||||
}
|
||||
},
|
||||
UserClaims = new List<string>()
|
||||
{
|
||||
"CustomerId", "LocationId", "UserType", "UserId"
|
||||
}
|
||||
}
|
||||
})
|
||||
.AddInMemoryClients(new List<Client>
|
||||
{
|
||||
new Client
|
||||
{
|
||||
ClientId = "client",
|
||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
|
||||
AllowedScopes = new List<string> { apiName, "openid", "offline_access" },
|
||||
AccessTokenType = tokenType,
|
||||
Enabled = true,
|
||||
RequireClientSecret = false
|
||||
}
|
||||
})
|
||||
.AddTestUsers(new List<TestUser>
|
||||
{
|
||||
user
|
||||
});
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseIdentityServer();
|
||||
})
|
||||
.Build();
|
||||
|
||||
_identityServerBuilder.Start();
|
||||
|
||||
_steps.VerifyIdentiryServerStarted(url);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_servicebuilder?.Dispose();
|
||||
_steps.Dispose();
|
||||
_identityServerBuilder?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using IdentityServer4.AccessTokenValidation;
|
||||
using IdentityServer4.Models;
|
||||
using IdentityServer4.Test;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Configuration.File;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using TestStack.BDDfy;
|
||||
|
||||
public class ClaimsToDownstreamPathTests : IDisposable
|
||||
{
|
||||
private IWebHost _servicebuilder;
|
||||
private IWebHost _identityServerBuilder;
|
||||
private readonly Steps _steps;
|
||||
private Action<IdentityServerAuthenticationOptions> _options;
|
||||
private string _identityServerRootUrl;
|
||||
private string _downstreamFinalPath;
|
||||
|
||||
public ClaimsToDownstreamPathTests()
|
||||
{
|
||||
var identityServerPort = RandomPortFinder.GetRandomPort();
|
||||
_identityServerRootUrl = $"http://localhost:{identityServerPort}";
|
||||
_steps = new Steps();
|
||||
_options = o =>
|
||||
{
|
||||
o.Authority = _identityServerRootUrl;
|
||||
o.ApiName = "api";
|
||||
o.RequireHttpsMetadata = false;
|
||||
o.SupportedTokens = SupportedTokens.Both;
|
||||
o.ApiSecret = "secret";
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_200_and_change_downstream_path()
|
||||
{
|
||||
var user = new TestUser()
|
||||
{
|
||||
Username = "test",
|
||||
Password = "test",
|
||||
SubjectId = "registered|1231231",
|
||||
};
|
||||
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/users/{userId}",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/users",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
AllowedScopes = new List<string>
|
||||
{
|
||||
"openid", "offline_access", "api",
|
||||
},
|
||||
},
|
||||
ChangeDownstreamPathTemplate =
|
||||
{
|
||||
{"userId", "Claims[sub] > value[1] > |"},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt, user))
|
||||
.And(x => x.GivenThereIsAServiceRunningOn($"http://localhost:{port}", 200))
|
||||
.And(x => _steps.GivenIHaveAToken(_identityServerRootUrl))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning(_options, "Test"))
|
||||
.And(x => _steps.GivenIHaveAddedATokenToMyRequest())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/users"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("UserId: 1231231"))
|
||||
.And(x => ThenTheDownstreamPathIs("/users/1231231"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenTheDownstreamPathIs(string path)
|
||||
{
|
||||
_downstreamFinalPath.ShouldBe(path);
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode)
|
||||
{
|
||||
_servicebuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.Configure(app =>
|
||||
{
|
||||
app.Run(async context =>
|
||||
{
|
||||
_downstreamFinalPath = context.Request.Path.Value;
|
||||
|
||||
string userId = _downstreamFinalPath.Replace("/users/", string.Empty);
|
||||
|
||||
var responseBody = $"UserId: {userId}";
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
_servicebuilder.Start();
|
||||
}
|
||||
|
||||
private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType, TestUser user)
|
||||
{
|
||||
_identityServerBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddIdentityServer()
|
||||
.AddDeveloperSigningCredential()
|
||||
.AddInMemoryApiScopes(new List<ApiScope>
|
||||
{
|
||||
new ApiScope(apiName, "test"),
|
||||
new ApiScope("openid", "test"),
|
||||
new ApiScope("offline_access", "test"),
|
||||
new ApiScope("api.readOnly", "test"),
|
||||
})
|
||||
.AddInMemoryApiResources(new List<ApiResource>
|
||||
{
|
||||
new ApiResource
|
||||
{
|
||||
Name = apiName,
|
||||
Description = "My API",
|
||||
Enabled = true,
|
||||
DisplayName = "test",
|
||||
Scopes = new List<string>()
|
||||
{
|
||||
"api",
|
||||
"openid",
|
||||
"offline_access",
|
||||
},
|
||||
ApiSecrets = new List<Secret>()
|
||||
{
|
||||
new Secret
|
||||
{
|
||||
Value = "secret".Sha256(),
|
||||
},
|
||||
},
|
||||
UserClaims = new List<string>()
|
||||
{
|
||||
"CustomerId", "LocationId", "UserType", "UserId",
|
||||
},
|
||||
},
|
||||
})
|
||||
.AddInMemoryClients(new List<Client>
|
||||
{
|
||||
new Client
|
||||
{
|
||||
ClientId = "client",
|
||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
|
||||
AllowedScopes = new List<string> { apiName, "openid", "offline_access" },
|
||||
AccessTokenType = tokenType,
|
||||
Enabled = true,
|
||||
RequireClientSecret = false,
|
||||
},
|
||||
})
|
||||
.AddTestUsers(new List<TestUser>
|
||||
{
|
||||
user,
|
||||
});
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseIdentityServer();
|
||||
})
|
||||
.Build();
|
||||
|
||||
_identityServerBuilder.Start();
|
||||
|
||||
_steps.VerifyIdentiryServerStarted(url);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_servicebuilder?.Dispose();
|
||||
_steps.Dispose();
|
||||
_identityServerBuilder?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,101 +1,101 @@
|
||||
using Xunit;
|
||||
|
||||
[assembly: CollectionBehavior(DisableTestParallelization = true)]
|
||||
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using IdentityServer4.AccessTokenValidation;
|
||||
using IdentityServer4.Models;
|
||||
using IdentityServer4.Test;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Configuration.File;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Claims;
|
||||
using TestStack.BDDfy;
|
||||
|
||||
public class ClaimsToHeadersForwardingTests : IDisposable
|
||||
{
|
||||
private IWebHost _identityServerBuilder;
|
||||
private readonly Steps _steps;
|
||||
private Action<IdentityServerAuthenticationOptions> _options;
|
||||
private string _identityServerRootUrl;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public ClaimsToHeadersForwardingTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
using Xunit;
|
||||
|
||||
[assembly: CollectionBehavior(DisableTestParallelization = true)]
|
||||
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using IdentityServer4.AccessTokenValidation;
|
||||
using IdentityServer4.Models;
|
||||
using IdentityServer4.Test;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Configuration.File;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Claims;
|
||||
using TestStack.BDDfy;
|
||||
|
||||
public class ClaimsToHeadersForwardingTests : IDisposable
|
||||
{
|
||||
private IWebHost _identityServerBuilder;
|
||||
private readonly Steps _steps;
|
||||
private Action<IdentityServerAuthenticationOptions> _options;
|
||||
private string _identityServerRootUrl;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public ClaimsToHeadersForwardingTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
_steps = new Steps();
|
||||
var identityServerPort = RandomPortFinder.GetRandomPort();
|
||||
_identityServerRootUrl = $"http://localhost:{identityServerPort}";
|
||||
_options = o =>
|
||||
{
|
||||
o.Authority = _identityServerRootUrl;
|
||||
o.ApiName = "api";
|
||||
o.RequireHttpsMetadata = false;
|
||||
o.SupportedTokens = SupportedTokens.Both;
|
||||
o.ApiSecret = "secret";
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_200_and_foward_claim_as_header()
|
||||
_identityServerRootUrl = $"http://localhost:{identityServerPort}";
|
||||
_options = o =>
|
||||
{
|
||||
o.Authority = _identityServerRootUrl;
|
||||
o.ApiName = "api";
|
||||
o.RequireHttpsMetadata = false;
|
||||
o.SupportedTokens = SupportedTokens.Both;
|
||||
o.ApiSecret = "secret";
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_200_and_foward_claim_as_header()
|
||||
{
|
||||
var user = new TestUser()
|
||||
{
|
||||
Username = "test",
|
||||
Password = "test",
|
||||
SubjectId = "registered|1231231",
|
||||
Claims = new List<Claim>
|
||||
{
|
||||
new Claim("CustomerId", "123"),
|
||||
new Claim("LocationId", "1")
|
||||
}
|
||||
Claims = new List<Claim>
|
||||
{
|
||||
new Claim("CustomerId", "123"),
|
||||
new Claim("LocationId", "1"),
|
||||
},
|
||||
};
|
||||
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
AllowedScopes = new List<string>
|
||||
{
|
||||
"openid", "offline_access", "api"
|
||||
},
|
||||
},
|
||||
AddHeadersToRequest =
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"},
|
||||
{"LocationId", "Claims[LocationId] > value"},
|
||||
{"UserType", "Claims[sub] > value[0] > |"},
|
||||
{"UserId", "Claims[sub] > value[1] > |"}
|
||||
}
|
||||
}
|
||||
}
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
AllowedScopes = new List<string>
|
||||
{
|
||||
"openid", "offline_access", "api",
|
||||
},
|
||||
},
|
||||
AddHeadersToRequest =
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"},
|
||||
{"LocationId", "Claims[LocationId] > value"},
|
||||
{"UserType", "Claims[sub] > value[0] > |"},
|
||||
{"UserId", "Claims[sub] > value[1] > |"},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt, user))
|
||||
@ -107,98 +107,105 @@ namespace Ocelot.AcceptanceTests
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("CustomerId: 123 LocationId: 1 UserType: registered UserId: 1231231"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(url, async context =>
|
||||
{
|
||||
var customerId = context.Request.Headers.First(x => x.Key == "CustomerId").Value.First();
|
||||
var locationId = context.Request.Headers.First(x => x.Key == "LocationId").Value.First();
|
||||
var userType = context.Request.Headers.First(x => x.Key == "UserType").Value.First();
|
||||
var userId = context.Request.Headers.First(x => x.Key == "UserId").Value.First();
|
||||
|
||||
var responseBody = $"CustomerId: {customerId} LocationId: {locationId} UserType: {userType} UserId: {userId}";
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
}
|
||||
|
||||
private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType, TestUser user)
|
||||
{
|
||||
_identityServerBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddIdentityServer()
|
||||
.AddDeveloperSigningCredential()
|
||||
.AddInMemoryApiResources(new List<ApiResource>
|
||||
{
|
||||
new ApiResource
|
||||
{
|
||||
Name = apiName,
|
||||
Description = "My API",
|
||||
Enabled = true,
|
||||
DisplayName = "test",
|
||||
Scopes = new List<Scope>()
|
||||
{
|
||||
new Scope("api"),
|
||||
new Scope("openid"),
|
||||
new Scope("offline_access")
|
||||
},
|
||||
ApiSecrets = new List<Secret>()
|
||||
{
|
||||
new Secret
|
||||
{
|
||||
Value = "secret".Sha256()
|
||||
}
|
||||
},
|
||||
UserClaims = new List<string>()
|
||||
{
|
||||
"CustomerId", "LocationId", "UserType", "UserId"
|
||||
}
|
||||
}
|
||||
})
|
||||
.AddInMemoryClients(new List<Client>
|
||||
{
|
||||
new Client
|
||||
{
|
||||
ClientId = "client",
|
||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
|
||||
AllowedScopes = new List<string> { apiName, "openid", "offline_access" },
|
||||
AccessTokenType = tokenType,
|
||||
Enabled = true,
|
||||
RequireClientSecret = false
|
||||
}
|
||||
})
|
||||
.AddTestUsers(new List<TestUser>
|
||||
{
|
||||
user
|
||||
});
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseIdentityServer();
|
||||
})
|
||||
.Build();
|
||||
|
||||
_identityServerBuilder.Start();
|
||||
|
||||
_steps.VerifyIdentiryServerStarted(url);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler?.Dispose();
|
||||
_steps.Dispose();
|
||||
_identityServerBuilder?.Dispose();
|
||||
}
|
||||
}
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(url, async context =>
|
||||
{
|
||||
var customerId = context.Request.Headers.First(x => x.Key == "CustomerId").Value.First();
|
||||
var locationId = context.Request.Headers.First(x => x.Key == "LocationId").Value.First();
|
||||
var userType = context.Request.Headers.First(x => x.Key == "UserType").Value.First();
|
||||
var userId = context.Request.Headers.First(x => x.Key == "UserId").Value.First();
|
||||
|
||||
var responseBody = $"CustomerId: {customerId} LocationId: {locationId} UserType: {userType} UserId: {userId}";
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
}
|
||||
|
||||
private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType, TestUser user)
|
||||
{
|
||||
_identityServerBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddIdentityServer()
|
||||
.AddDeveloperSigningCredential()
|
||||
.AddInMemoryApiScopes(new List<ApiScope>
|
||||
{
|
||||
new ApiScope(apiName, "test"),
|
||||
new ApiScope("openid", "test"),
|
||||
new ApiScope("offline_access", "test"),
|
||||
new ApiScope("api.readOnly", "test"),
|
||||
})
|
||||
.AddInMemoryApiResources(new List<ApiResource>
|
||||
{
|
||||
new ApiResource
|
||||
{
|
||||
Name = apiName,
|
||||
Description = "My API",
|
||||
Enabled = true,
|
||||
DisplayName = "test",
|
||||
Scopes = new List<string>()
|
||||
{
|
||||
"api",
|
||||
"openid",
|
||||
"offline_access",
|
||||
},
|
||||
ApiSecrets = new List<Secret>()
|
||||
{
|
||||
new Secret
|
||||
{
|
||||
Value = "secret".Sha256(),
|
||||
},
|
||||
},
|
||||
UserClaims = new List<string>()
|
||||
{
|
||||
"CustomerId", "LocationId", "UserType", "UserId",
|
||||
},
|
||||
},
|
||||
})
|
||||
.AddInMemoryClients(new List<Client>
|
||||
{
|
||||
new Client
|
||||
{
|
||||
ClientId = "client",
|
||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
|
||||
AllowedScopes = new List<string> { apiName, "openid", "offline_access" },
|
||||
AccessTokenType = tokenType,
|
||||
Enabled = true,
|
||||
RequireClientSecret = false,
|
||||
},
|
||||
})
|
||||
.AddTestUsers(new List<TestUser>
|
||||
{
|
||||
user,
|
||||
});
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseIdentityServer();
|
||||
})
|
||||
.Build();
|
||||
|
||||
_identityServerBuilder.Start();
|
||||
|
||||
_steps.VerifyIdentiryServerStarted(url);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler?.Dispose();
|
||||
_steps.Dispose();
|
||||
_identityServerBuilder?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,100 +1,99 @@
|
||||
using IdentityServer4.AccessTokenValidation;
|
||||
using IdentityServer4.Models;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Ocelot.Configuration.File;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Claims;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using IdentityServer4.Test;
|
||||
using Shouldly;
|
||||
|
||||
public class ClaimsToQueryStringForwardingTests : IDisposable
|
||||
{
|
||||
private IWebHost _servicebuilder;
|
||||
private IWebHost _identityServerBuilder;
|
||||
private readonly Steps _steps;
|
||||
private Action<IdentityServerAuthenticationOptions> _options;
|
||||
private string _identityServerRootUrl;
|
||||
private string _downstreamQueryString;
|
||||
|
||||
public ClaimsToQueryStringForwardingTests()
|
||||
{
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using IdentityServer4.Test;
|
||||
using Shouldly;
|
||||
using IdentityServer4.AccessTokenValidation;
|
||||
using IdentityServer4.Models;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Ocelot.Configuration.File;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Claims;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class ClaimsToQueryStringForwardingTests : IDisposable
|
||||
{
|
||||
private IWebHost _servicebuilder;
|
||||
private IWebHost _identityServerBuilder;
|
||||
private readonly Steps _steps;
|
||||
private Action<IdentityServerAuthenticationOptions> _options;
|
||||
private string _identityServerRootUrl;
|
||||
private string _downstreamQueryString;
|
||||
|
||||
public ClaimsToQueryStringForwardingTests()
|
||||
{
|
||||
_steps = new Steps();
|
||||
var identityServerPort = RandomPortFinder.GetRandomPort();
|
||||
_identityServerRootUrl = $"http://localhost:{identityServerPort}";
|
||||
_options = o =>
|
||||
{
|
||||
o.Authority = _identityServerRootUrl;
|
||||
o.ApiName = "api";
|
||||
o.RequireHttpsMetadata = false;
|
||||
o.SupportedTokens = SupportedTokens.Both;
|
||||
o.ApiSecret = "secret";
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_200_and_foward_claim_as_query_string()
|
||||
_identityServerRootUrl = $"http://localhost:{identityServerPort}";
|
||||
_options = o =>
|
||||
{
|
||||
o.Authority = _identityServerRootUrl;
|
||||
o.ApiName = "api";
|
||||
o.RequireHttpsMetadata = false;
|
||||
o.SupportedTokens = SupportedTokens.Both;
|
||||
o.ApiSecret = "secret";
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_200_and_foward_claim_as_query_string()
|
||||
{
|
||||
var user = new TestUser()
|
||||
{
|
||||
Username = "test",
|
||||
Password = "test",
|
||||
SubjectId = "registered|1231231",
|
||||
Claims = new List<Claim>
|
||||
{
|
||||
new Claim("CustomerId", "123"),
|
||||
new Claim("LocationId", "1")
|
||||
}
|
||||
Claims = new List<Claim>
|
||||
{
|
||||
new Claim("CustomerId", "123"),
|
||||
new Claim("LocationId", "1"),
|
||||
},
|
||||
};
|
||||
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
AllowedScopes = new List<string>
|
||||
{
|
||||
"openid", "offline_access", "api"
|
||||
},
|
||||
},
|
||||
AddQueriesToRequest =
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"},
|
||||
{"LocationId", "Claims[LocationId] > value"},
|
||||
{"UserType", "Claims[sub] > value[0] > |"},
|
||||
{"UserId", "Claims[sub] > value[1] > |"}
|
||||
}
|
||||
}
|
||||
}
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
AllowedScopes = new List<string>
|
||||
{
|
||||
"openid", "offline_access", "api",
|
||||
},
|
||||
},
|
||||
AddQueriesToRequest =
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"},
|
||||
{"LocationId", "Claims[LocationId] > value"},
|
||||
{"UserType", "Claims[sub] > value[0] > |"},
|
||||
{"UserId", "Claims[sub] > value[1] > |"},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt, user))
|
||||
@ -106,61 +105,61 @@ namespace Ocelot.AcceptanceTests
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("CustomerId: 123 LocationId: 1 UserType: registered UserId: 1231231"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_200_and_foward_claim_as_query_string_and_preserve_original_string()
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_200_and_foward_claim_as_query_string_and_preserve_original_string()
|
||||
{
|
||||
var user = new TestUser()
|
||||
{
|
||||
Username = "test",
|
||||
Password = "test",
|
||||
SubjectId = "registered|1231231",
|
||||
Claims = new List<Claim>
|
||||
{
|
||||
new Claim("CustomerId", "123"),
|
||||
new Claim("LocationId", "1")
|
||||
}
|
||||
Claims = new List<Claim>
|
||||
{
|
||||
new Claim("CustomerId", "123"),
|
||||
new Claim("LocationId", "1"),
|
||||
},
|
||||
};
|
||||
|
||||
int port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
AllowedScopes = new List<string>
|
||||
{
|
||||
"openid", "offline_access", "api"
|
||||
},
|
||||
},
|
||||
AddQueriesToRequest =
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"},
|
||||
{"LocationId", "Claims[LocationId] > value"},
|
||||
{"UserType", "Claims[sub] > value[0] > |"},
|
||||
{"UserId", "Claims[sub] > value[1] > |"}
|
||||
}
|
||||
}
|
||||
}
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = port,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
AuthenticationOptions = new FileAuthenticationOptions
|
||||
{
|
||||
AuthenticationProviderKey = "Test",
|
||||
AllowedScopes = new List<string>
|
||||
{
|
||||
"openid", "offline_access", "api",
|
||||
},
|
||||
},
|
||||
AddQueriesToRequest =
|
||||
{
|
||||
{"CustomerId", "Claims[CustomerId] > value"},
|
||||
{"LocationId", "Claims[LocationId] > value"},
|
||||
{"UserType", "Claims[sub] > value[0] > |"},
|
||||
{"UserId", "Claims[sub] > value[1] > |"},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt, user))
|
||||
@ -172,120 +171,132 @@ namespace Ocelot.AcceptanceTests
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/?test=1&test=2"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("CustomerId: 123 LocationId: 1 UserType: registered UserId: 1231231"))
|
||||
.And(_ => _downstreamQueryString.ShouldBe("?test=1&test=2&CustomerId=123&LocationId=1&UserId=1231231&UserType=registered"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode)
|
||||
{
|
||||
_servicebuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.Configure(app =>
|
||||
{
|
||||
app.Run(async context =>
|
||||
{
|
||||
_downstreamQueryString = context.Request.QueryString.Value;
|
||||
|
||||
StringValues customerId;
|
||||
context.Request.Query.TryGetValue("CustomerId", out customerId);
|
||||
|
||||
StringValues locationId;
|
||||
context.Request.Query.TryGetValue("LocationId", out locationId);
|
||||
|
||||
StringValues userType;
|
||||
context.Request.Query.TryGetValue("UserType", out userType);
|
||||
|
||||
StringValues userId;
|
||||
context.Request.Query.TryGetValue("UserId", out userId);
|
||||
|
||||
var responseBody = $"CustomerId: {customerId} LocationId: {locationId} UserType: {userType} UserId: {userId}";
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
_servicebuilder.Start();
|
||||
}
|
||||
|
||||
private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType, TestUser user)
|
||||
{
|
||||
_identityServerBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddIdentityServer()
|
||||
.AddDeveloperSigningCredential()
|
||||
.AddInMemoryApiResources(new List<ApiResource>
|
||||
{
|
||||
new ApiResource
|
||||
{
|
||||
Name = apiName,
|
||||
Description = "My API",
|
||||
Enabled = true,
|
||||
DisplayName = "test",
|
||||
Scopes = new List<Scope>()
|
||||
{
|
||||
new Scope("api"),
|
||||
new Scope("openid"),
|
||||
new Scope("offline_access")
|
||||
},
|
||||
ApiSecrets = new List<Secret>()
|
||||
{
|
||||
new Secret
|
||||
{
|
||||
Value = "secret".Sha256()
|
||||
}
|
||||
},
|
||||
UserClaims = new List<string>()
|
||||
{
|
||||
"CustomerId", "LocationId", "UserType", "UserId"
|
||||
}
|
||||
}
|
||||
})
|
||||
.AddInMemoryClients(new List<Client>
|
||||
{
|
||||
new Client
|
||||
{
|
||||
ClientId = "client",
|
||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
|
||||
AllowedScopes = new List<string> { apiName, "openid", "offline_access" },
|
||||
AccessTokenType = tokenType,
|
||||
Enabled = true,
|
||||
RequireClientSecret = false
|
||||
}
|
||||
})
|
||||
.AddTestUsers(new List<TestUser>
|
||||
{
|
||||
user
|
||||
});
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseIdentityServer();
|
||||
})
|
||||
.Build();
|
||||
|
||||
_identityServerBuilder.Start();
|
||||
|
||||
_steps.VerifyIdentiryServerStarted(url);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_servicebuilder?.Dispose();
|
||||
_steps.Dispose();
|
||||
_identityServerBuilder?.Dispose();
|
||||
}
|
||||
}
|
||||
.And(_ => ThenTheQueryStringIs("?test=1&test=2&CustomerId=123&LocationId=1&UserId=1231231&UserType=registered"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenTheQueryStringIs(string queryString)
|
||||
{
|
||||
_downstreamQueryString.ShouldBe(queryString);
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode)
|
||||
{
|
||||
_servicebuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.Configure(app =>
|
||||
{
|
||||
app.Run(async context =>
|
||||
{
|
||||
_downstreamQueryString = context.Request.QueryString.Value;
|
||||
|
||||
StringValues customerId;
|
||||
context.Request.Query.TryGetValue("CustomerId", out customerId);
|
||||
|
||||
StringValues locationId;
|
||||
context.Request.Query.TryGetValue("LocationId", out locationId);
|
||||
|
||||
StringValues userType;
|
||||
context.Request.Query.TryGetValue("UserType", out userType);
|
||||
|
||||
StringValues userId;
|
||||
context.Request.Query.TryGetValue("UserId", out userId);
|
||||
|
||||
var responseBody = $"CustomerId: {customerId} LocationId: {locationId} UserType: {userType} UserId: {userId}";
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
_servicebuilder.Start();
|
||||
}
|
||||
|
||||
private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType, TestUser user)
|
||||
{
|
||||
_identityServerBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddLogging();
|
||||
services.AddIdentityServer()
|
||||
.AddDeveloperSigningCredential()
|
||||
.AddInMemoryApiScopes(new List<ApiScope>
|
||||
{
|
||||
new ApiScope(apiName, "test"),
|
||||
new ApiScope("openid", "test"),
|
||||
new ApiScope("offline_access", "test"),
|
||||
new ApiScope("api.readOnly", "test"),
|
||||
})
|
||||
.AddInMemoryApiResources(new List<ApiResource>
|
||||
{
|
||||
new ApiResource
|
||||
{
|
||||
Name = apiName,
|
||||
Description = "My API",
|
||||
Enabled = true,
|
||||
DisplayName = "test",
|
||||
Scopes = new List<string>()
|
||||
{
|
||||
"api",
|
||||
"openid",
|
||||
"offline_access",
|
||||
},
|
||||
ApiSecrets = new List<Secret>()
|
||||
{
|
||||
new Secret
|
||||
{
|
||||
Value = "secret".Sha256(),
|
||||
},
|
||||
},
|
||||
UserClaims = new List<string>()
|
||||
{
|
||||
"CustomerId", "LocationId", "UserType", "UserId",
|
||||
},
|
||||
},
|
||||
})
|
||||
.AddInMemoryClients(new List<Client>
|
||||
{
|
||||
new Client
|
||||
{
|
||||
ClientId = "client",
|
||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
|
||||
AllowedScopes = new List<string> { apiName, "openid", "offline_access" },
|
||||
AccessTokenType = tokenType,
|
||||
Enabled = true,
|
||||
RequireClientSecret = false,
|
||||
},
|
||||
})
|
||||
.AddTestUsers(new List<TestUser>
|
||||
{
|
||||
user,
|
||||
});
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseIdentityServer();
|
||||
})
|
||||
.Build();
|
||||
|
||||
_identityServerBuilder.Start();
|
||||
|
||||
_steps.VerifyIdentiryServerStarted(url);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_servicebuilder?.Dispose();
|
||||
_steps.Dispose();
|
||||
_identityServerBuilder?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
private void ThenTheContentLengthShouldBeZero()
|
||||
{
|
||||
_contentLength.ShouldBeEquivalentTo(0L);
|
||||
_contentLength.ShouldBeNull();
|
||||
}
|
||||
|
||||
private void ThenTheContentLengthIs(int expected)
|
||||
|
@ -10,7 +10,7 @@
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using Xunit;
|
||||
|
||||
public class CustomMiddlewareTests : IDisposable
|
||||
{
|
||||
@ -32,13 +32,13 @@
|
||||
{
|
||||
var configuration = new OcelotPipelineConfiguration
|
||||
{
|
||||
AuthorisationMiddleware = async (ctx, next) =>
|
||||
AuthorizationMiddleware = async (ctx, next) =>
|
||||
{
|
||||
_counter++;
|
||||
await next.Invoke();
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var fileConfiguration = new FileConfiguration
|
||||
@ -73,17 +73,17 @@
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_authorisation_middleware()
|
||||
public void should_call_authorization_middleware()
|
||||
{
|
||||
var configuration = new OcelotPipelineConfiguration
|
||||
{
|
||||
AuthorisationMiddleware = async (ctx, next) =>
|
||||
AuthorizationMiddleware = async (ctx, next) =>
|
||||
{
|
||||
_counter++;
|
||||
await next.Invoke();
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var fileConfiguration = new FileConfiguration
|
||||
@ -127,8 +127,8 @@
|
||||
_counter++;
|
||||
await next.Invoke();
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var fileConfiguration = new FileConfiguration
|
||||
@ -172,8 +172,8 @@
|
||||
_counter++;
|
||||
await next.Invoke();
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var fileConfiguration = new FileConfiguration
|
||||
@ -208,17 +208,17 @@
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_pre_authorisation_middleware()
|
||||
public void should_call_pre_authorization_middleware()
|
||||
{
|
||||
var configuration = new OcelotPipelineConfiguration
|
||||
{
|
||||
PreAuthorisationMiddleware = async (ctx, next) =>
|
||||
PreAuthorizationMiddleware = async (ctx, next) =>
|
||||
{
|
||||
_counter++;
|
||||
await next.Invoke();
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var fileConfiguration = new FileConfiguration
|
||||
@ -262,8 +262,8 @@
|
||||
_counter++;
|
||||
await next.Invoke();
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var fileConfiguration = new FileConfiguration
|
||||
@ -295,8 +295,8 @@
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => x.ThenTheCounterIs(1))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Fact(Skip = "This is just an example to show how you could hook into Ocelot pipeline with your own middleware. At the moment you must use Response.OnCompleted callback and cannot change the response :( I will see if this can be changed one day!")]
|
||||
public void should_fix_issue_237()
|
||||
{
|
||||
@ -305,14 +305,14 @@
|
||||
var httpContext = (HttpContext)state;
|
||||
|
||||
if (httpContext.Response.StatusCode > 400)
|
||||
{
|
||||
{
|
||||
Debug.WriteLine("COUNT CALLED");
|
||||
Console.WriteLine("COUNT CALLED");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var fileConfiguration = new FileConfiguration
|
||||
@ -376,8 +376,8 @@
|
||||
public class FakeMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly Func<object, Task> _callback;
|
||||
|
||||
private readonly Func<object, Task> _callback;
|
||||
|
||||
public FakeMiddleware(RequestDelegate next, Func<object, Task> callback)
|
||||
{
|
||||
_next = next;
|
||||
@ -386,10 +386,10 @@
|
||||
|
||||
public async Task Invoke(HttpContext context)
|
||||
{
|
||||
await _next(context);
|
||||
|
||||
await _next(context);
|
||||
|
||||
context.Response.OnCompleted(_callback, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using Configuration.File;
|
||||
using Ocelot.Configuration.File;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Steeltoe.Common.Discovery;
|
||||
@ -38,24 +38,24 @@
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
new FileRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
ServiceName = serviceName,
|
||||
LoadBalancerOptions = new FileLoadBalancerOptions { Type = "LeastConnection" },
|
||||
}
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
ServiceName = serviceName,
|
||||
LoadBalancerOptions = new FileLoadBalancerOptions { Type = "LeastConnection" },
|
||||
},
|
||||
},
|
||||
GlobalConfiguration = new FileGlobalConfiguration()
|
||||
{
|
||||
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider()
|
||||
{
|
||||
Type = "Eureka"
|
||||
}
|
||||
}
|
||||
Type = "Eureka",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenEurekaProductServiceOneIsRunning(downstreamServiceOneUrl))
|
||||
@ -91,42 +91,42 @@
|
||||
{
|
||||
name = serviceName,
|
||||
instance = new List<Instance>
|
||||
{
|
||||
new Instance
|
||||
{
|
||||
instanceId = $"{serviceInstance.Host}:{serviceInstance}",
|
||||
hostName = serviceInstance.Host,
|
||||
app = serviceName,
|
||||
ipAddr = "127.0.0.1",
|
||||
status = "UP",
|
||||
overriddenstatus = "UNKNOWN",
|
||||
port = new Port {value = serviceInstance.Port, enabled = "true"},
|
||||
securePort = new SecurePort {value = serviceInstance.Port, enabled = "true"},
|
||||
countryId = 1,
|
||||
dataCenterInfo = new DataCenterInfo {value = "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo", name = "MyOwn"},
|
||||
leaseInfo = new LeaseInfo
|
||||
{
|
||||
new Instance
|
||||
{
|
||||
instanceId = $"{serviceInstance.Host}:{serviceInstance}",
|
||||
hostName = serviceInstance.Host,
|
||||
app = serviceName,
|
||||
ipAddr = "127.0.0.1",
|
||||
status = "UP",
|
||||
overriddenstatus = "UNKNOWN",
|
||||
port = new Port {value = serviceInstance.Port, enabled = "true"},
|
||||
securePort = new SecurePort {value = serviceInstance.Port, enabled = "true"},
|
||||
countryId = 1,
|
||||
dataCenterInfo = new DataCenterInfo {value = "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo", name = "MyOwn"},
|
||||
leaseInfo = new LeaseInfo
|
||||
{
|
||||
renewalIntervalInSecs = 30,
|
||||
durationInSecs = 90,
|
||||
registrationTimestamp = 1457714988223,
|
||||
lastRenewalTimestamp= 1457716158319,
|
||||
evictionTimestamp = 0,
|
||||
serviceUpTimestamp = 1457714988223
|
||||
},
|
||||
metadata = new Metadata
|
||||
{
|
||||
value = "java.util.Collections$EmptyMap"
|
||||
},
|
||||
homePageUrl = $"{serviceInstance.Host}:{serviceInstance.Port}",
|
||||
statusPageUrl = $"{serviceInstance.Host}:{serviceInstance.Port}",
|
||||
healthCheckUrl = $"{serviceInstance.Host}:{serviceInstance.Port}",
|
||||
vipAddress = serviceName,
|
||||
isCoordinatingDiscoveryServer = "false",
|
||||
lastUpdatedTimestamp = "1457714988223",
|
||||
lastDirtyTimestamp = "1457714988172",
|
||||
actionType = "ADDED"
|
||||
}
|
||||
}
|
||||
renewalIntervalInSecs = 30,
|
||||
durationInSecs = 90,
|
||||
registrationTimestamp = 1457714988223,
|
||||
lastRenewalTimestamp= 1457716158319,
|
||||
evictionTimestamp = 0,
|
||||
serviceUpTimestamp = 1457714988223,
|
||||
},
|
||||
metadata = new Metadata
|
||||
{
|
||||
value = "java.util.Collections$EmptyMap",
|
||||
},
|
||||
homePageUrl = $"{serviceInstance.Host}:{serviceInstance.Port}",
|
||||
statusPageUrl = $"{serviceInstance.Host}:{serviceInstance.Port}",
|
||||
healthCheckUrl = $"{serviceInstance.Host}:{serviceInstance.Port}",
|
||||
vipAddress = serviceName,
|
||||
isCoordinatingDiscoveryServer = "false",
|
||||
lastUpdatedTimestamp = "1457714988223",
|
||||
lastDirtyTimestamp = "1457714988172",
|
||||
actionType = "ADDED",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
apps.Add(a);
|
||||
@ -138,8 +138,8 @@
|
||||
{
|
||||
application = apps,
|
||||
apps__hashcode = "UP_1_",
|
||||
versions__delta = "1"
|
||||
}
|
||||
versions__delta = "1",
|
||||
},
|
||||
};
|
||||
|
||||
var json = JsonConvert.SerializeObject(applications);
|
||||
|
@ -24,8 +24,8 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
[Fact]
|
||||
public void should_transform_upstream_header()
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
@ -65,8 +65,8 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
[Fact]
|
||||
public void should_transform_downstream_header()
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
@ -105,8 +105,8 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
[Fact]
|
||||
public void should_fix_issue_190()
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
@ -149,8 +149,8 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
[Fact]
|
||||
public void should_fix_issue_205()
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
@ -193,8 +193,8 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
[Fact]
|
||||
public void should_fix_issue_417()
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
@ -241,8 +241,8 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
[Fact]
|
||||
public void request_should_reuse_cookies_with_cookie_container()
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
@ -284,8 +284,8 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
[Fact]
|
||||
public void request_should_have_own_cookies_no_cookie_container()
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
@ -327,8 +327,8 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
[Fact]
|
||||
public void issue_474_should_not_put_spaces_in_header()
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
@ -364,8 +364,8 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
[Fact]
|
||||
public void issue_474_should_put_spaces_in_header()
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
{
|
||||
var port = RandomPortFinder.GetRandomPort();
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
@ -413,9 +413,18 @@ namespace Ocelot.AcceptanceTests
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
if (context.Request.Cookies.TryGetValue("test", out var cookieValue) || context.Request.Headers.TryGetValue("Set-Cookie", out var headerValue))
|
||||
if (context.Request.Cookies.TryGetValue("test", out var cookieValue))
|
||||
{
|
||||
if (cookieValue == "0" || headerValue == "test=1; path=/")
|
||||
if (cookieValue == "0")
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
if (context.Request.Headers.TryGetValue("Set-Cookie", out var headerValue))
|
||||
{
|
||||
if (headerValue == "test=1; path=/")
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
return Task.CompletedTask;
|
||||
|
@ -62,7 +62,7 @@ namespace Ocelot.AcceptanceTests
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.And(x => cache.Count.ShouldBe(1))
|
||||
.And(x => ThenTheCountShouldBe(cache, 1))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
@ -122,10 +122,15 @@ namespace Ocelot.AcceptanceTests
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.And(x => cache.Count.ShouldBe(2))
|
||||
.And(x => ThenTheCountShouldBe(cache, 2))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenTheCountShouldBe(FakeHttpClientCache cache, int count)
|
||||
{
|
||||
cache.Count.ShouldBe(count);
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string baseUrl, int statusCode, string responseBody)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, async context =>
|
||||
|
@ -1,77 +1,76 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<AssemblyName>Ocelot.AcceptanceTests</AssemblyName>
|
||||
<OutputType>Exe</OutputType>
|
||||
<PackageId>Ocelot.AcceptanceTests</PackageId>
|
||||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||
<RuntimeIdentifiers>osx.10.11-x64;osx.10.12-x64;win7-x64;win10-x64</RuntimeIdentifiers>
|
||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
|
||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="appsettings.product.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="idsrv3test.pfx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Ocelot.Tracing.Butterfly\Ocelot.Tracing.Butterfly.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Tracing.OpenTracing\Ocelot.Tracing.OpenTracing.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Cache.CacheManager\Ocelot.Cache.CacheManager.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Consul\Ocelot.Provider.Consul.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Eureka\Ocelot.Provider.Eureka.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Polly\Ocelot.Provider.Polly.csproj" />
|
||||
<ProjectReference Include="..\Ocelot.ManualTest\Ocelot.ManualTest.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||
<PackageReference Include="Moq" Version="4.13.1" />
|
||||
<PackageReference Include="OpenTracing" Version="0.12.1" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
||||
<PackageReference Include="Shouldly" Version="4.0.0-beta0002" />
|
||||
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
|
||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
|
||||
<PackageReference Include="IdentityServer4" Version="3.1.1" />
|
||||
<PackageReference Include="Consul" Version="0.7.2.6" />
|
||||
<PackageReference Include="Rafty" Version="0.4.4" />
|
||||
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="2.0.0-beta-1629" />
|
||||
<PackageReference Include="CacheManager.Serialization.Json" Version="2.0.0-beta-1629" />
|
||||
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="2.4.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AssemblyName>Ocelot.AcceptanceTests</AssemblyName>
|
||||
<OutputType>Exe</OutputType>
|
||||
<PackageId>Ocelot.AcceptanceTests</PackageId>
|
||||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||
<RuntimeIdentifiers>osx.10.11-x64;osx.10.12-x64;win7-x64;win10-x64</RuntimeIdentifiers>
|
||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
|
||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="appsettings.product.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="idsrv3test.pfx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Ocelot.Tracing.Butterfly\Ocelot.Tracing.Butterfly.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Tracing.OpenTracing\Ocelot.Tracing.OpenTracing.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Cache.CacheManager\Ocelot.Cache.CacheManager.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Consul\Ocelot.Provider.Consul.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Eureka\Ocelot.Provider.Eureka.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Polly\Ocelot.Provider.Polly.csproj" />
|
||||
<ProjectReference Include="..\Ocelot.ManualTest\Ocelot.ManualTest.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
|
||||
<PackageReference Include="Moq" Version="4.15.2" />
|
||||
<PackageReference Include="OpenTracing" Version="0.12.1" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
||||
<PackageReference Include="Shouldly" Version="4.0.1" />
|
||||
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
|
||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
|
||||
<PackageReference Include="IdentityServer4" Version="4.1.1" />
|
||||
<PackageReference Include="Consul" Version="1.6.1.1" />
|
||||
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="2.0.0-beta-1629" />
|
||||
<PackageReference Include="CacheManager.Serialization.Json" Version="2.0.0-beta-1629" />
|
||||
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="3.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -8,7 +8,6 @@ namespace Ocelot.AcceptanceTests
|
||||
using OpenTracing;
|
||||
using OpenTracing.Propagation;
|
||||
using OpenTracing.Tag;
|
||||
using Rafty.Infrastructure;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -17,6 +16,8 @@ namespace Ocelot.AcceptanceTests
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class OpenTracingTests : IDisposable
|
||||
{
|
||||
@ -513,4 +514,70 @@ namespace Ocelot.AcceptanceTests
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class Wait
|
||||
{
|
||||
public static Waiter WaitFor(int milliSeconds)
|
||||
{
|
||||
return new Waiter(milliSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
public class Waiter
|
||||
{
|
||||
private readonly int _milliSeconds;
|
||||
|
||||
public Waiter(int milliSeconds)
|
||||
{
|
||||
_milliSeconds = milliSeconds;
|
||||
}
|
||||
|
||||
public bool Until(Func<bool> condition)
|
||||
{
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
var passed = false;
|
||||
while (stopwatch.ElapsedMilliseconds < _milliSeconds)
|
||||
{
|
||||
if (condition.Invoke())
|
||||
{
|
||||
passed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return passed;
|
||||
}
|
||||
|
||||
public async Task<bool> Until(Func<Task<bool>> condition)
|
||||
{
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
var passed = false;
|
||||
while (stopwatch.ElapsedMilliseconds < _milliSeconds)
|
||||
{
|
||||
if (await condition.Invoke())
|
||||
{
|
||||
passed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return passed;
|
||||
}
|
||||
|
||||
public bool Until<T>(Func<bool> condition)
|
||||
{
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
var passed = false;
|
||||
while (stopwatch.ElapsedMilliseconds < _milliSeconds)
|
||||
{
|
||||
if (condition.Invoke())
|
||||
{
|
||||
passed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return passed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -322,7 +322,7 @@
|
||||
.When(_ => _steps.WhenIGetUrlOnTheApiGateway("/home"))
|
||||
.Then(_ => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(_ => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.And(_ => _receivedToken.ShouldBe(token))
|
||||
.And(_ => ThenTheTokenIs(token))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
@ -462,6 +462,11 @@
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenTheTokenIs(string token)
|
||||
{
|
||||
_receivedToken.ShouldBe(token);
|
||||
}
|
||||
|
||||
private void WhenIAddAServiceBackIn(ServiceEntry serviceEntryTwo)
|
||||
|
@ -814,7 +814,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new KeyValuePair<string, string>("scope", "api"),
|
||||
new KeyValuePair<string, string>("username", "test"),
|
||||
new KeyValuePair<string, string>("password", "test"),
|
||||
new KeyValuePair<string, string>("grant_type", "password")
|
||||
new KeyValuePair<string, string>("grant_type", "password"),
|
||||
};
|
||||
var content = new FormUrlEncodedContent(formData);
|
||||
|
||||
@ -837,7 +837,7 @@ namespace Ocelot.AcceptanceTests
|
||||
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")
|
||||
new KeyValuePair<string, string>("grant_type", "password"),
|
||||
};
|
||||
var content = new FormUrlEncodedContent(formData);
|
||||
|
||||
|
@ -57,7 +57,7 @@ namespace Ocelot.AcceptanceTests
|
||||
.And(_ => _steps.StartFakeOcelotWithWebSockets())
|
||||
.And(_ => StartFakeDownstreamService($"http://{downstreamHost}:{downstreamPort}", "/ws"))
|
||||
.When(_ => StartClient("ws://localhost:5000/"))
|
||||
.Then(_ => _firstRecieved.Count.ShouldBe(10))
|
||||
.Then(_ => ThenTheReceivedCountIs(10))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
@ -323,8 +323,12 @@ namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void ThenTheReceivedCountIs(int count)
|
||||
{
|
||||
_firstRecieved.Count.ShouldBe(count);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler?.Dispose();
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AssemblyName>Ocelot.Benchmarks</AssemblyName>
|
||||
<OutputType>Exe</OutputType>
|
||||
<PackageId>Ocelot.Benchmarks</PackageId>
|
||||
@ -18,7 +18,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.12.0" />
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
@ -27,4 +27,4 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,61 +1,60 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<AssemblyName>Ocelot.IntegrationTests</AssemblyName>
|
||||
<OutputType>Exe</OutputType>
|
||||
<PackageId>Ocelot.IntegrationTests</PackageId>
|
||||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||
<RuntimeIdentifiers>win10-x64;osx.10.11-x64;osx.10.12-x64;win7-x64</RuntimeIdentifiers>
|
||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
|
||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Update="peers.json;appsettings.json;idsrv3test.pfx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Administration\Ocelot.Administration.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Cache.CacheManager\Ocelot.Cache.CacheManager.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Consul\Ocelot.Provider.Consul.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Eureka\Ocelot.Provider.Eureka.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Polly\Ocelot.Provider.Polly.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Rafty\Ocelot.Provider.Rafty.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||
<PackageReference Include="Microsoft.Data.SQLite" Version="3.1.1" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="Shouldly" Version="4.0.0-beta0002" />
|
||||
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
||||
<PackageReference Include="Microsoft.Data.SQLite" Version="3.1.1" />
|
||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
|
||||
<PackageReference Include="IdentityServer4" Version="3.1.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AssemblyName>Ocelot.IntegrationTests</AssemblyName>
|
||||
<OutputType>Exe</OutputType>
|
||||
<PackageId>Ocelot.IntegrationTests</PackageId>
|
||||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||
<RuntimeIdentifiers>win10-x64;osx.10.11-x64;osx.10.12-x64;win7-x64</RuntimeIdentifiers>
|
||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
|
||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Update="peers.json;appsettings.json;idsrv3test.pfx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Administration\Ocelot.Administration.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Cache.CacheManager\Ocelot.Cache.CacheManager.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Consul\Ocelot.Provider.Consul.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Eureka\Ocelot.Provider.Eureka.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Polly\Ocelot.Provider.Polly.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
|
||||
<PackageReference Include="Microsoft.Data.SQLite" Version="3.1.1" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="Shouldly" Version="4.0.1" />
|
||||
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
||||
<PackageReference Include="Microsoft.Data.SQLite" Version="5.0.0" />
|
||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
|
||||
<PackageReference Include="IdentityServer4" Version="4.1.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -1,513 +0,0 @@
|
||||
namespace Ocelot.IntegrationTests
|
||||
{
|
||||
using Administration;
|
||||
using Configuration.File;
|
||||
using DependencyInjection;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Middleware;
|
||||
using Newtonsoft.Json;
|
||||
using Ocelot.Provider.Rafty;
|
||||
using Rafty.Infrastructure;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using Wait = Rafty.Infrastructure.Wait;
|
||||
|
||||
public class RaftTests : IDisposable
|
||||
{
|
||||
private readonly List<IWebHost> _builders;
|
||||
private readonly List<IWebHostBuilder> _webHostBuilders;
|
||||
private readonly List<Thread> _threads;
|
||||
private FilePeers _peers;
|
||||
private HttpClient _httpClient;
|
||||
private readonly HttpClient _httpClientForAssertions;
|
||||
private BearerToken _token;
|
||||
private HttpResponseMessage _response;
|
||||
private static readonly object _lock = new object();
|
||||
private ITestOutputHelper _output;
|
||||
|
||||
public RaftTests(ITestOutputHelper output)
|
||||
{
|
||||
_output = output;
|
||||
_httpClientForAssertions = new HttpClient();
|
||||
_webHostBuilders = new List<IWebHostBuilder>();
|
||||
_builders = new List<IWebHost>();
|
||||
_threads = new List<Thread>();
|
||||
}
|
||||
|
||||
[Fact(Skip = "Still not stable, more work required in rafty..")]
|
||||
public async Task should_persist_command_to_five_servers()
|
||||
{
|
||||
var peers = new List<FilePeer>
|
||||
{
|
||||
new FilePeer {HostAndPort = "http://localhost:5000"},
|
||||
|
||||
new FilePeer {HostAndPort = "http://localhost:5001"},
|
||||
|
||||
new FilePeer {HostAndPort = "http://localhost:5002"},
|
||||
|
||||
new FilePeer {HostAndPort = "http://localhost:5003"},
|
||||
|
||||
new FilePeer {HostAndPort = "http://localhost:5004"}
|
||||
};
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
GlobalConfiguration = new FileGlobalConfiguration
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
var updatedConfiguration = new FileConfiguration
|
||||
{
|
||||
GlobalConfiguration = new FileGlobalConfiguration
|
||||
{
|
||||
},
|
||||
Routes = new List<FileRoute>()
|
||||
{
|
||||
new FileRoute()
|
||||
{
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "127.0.0.1",
|
||||
Port = 80,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
DownstreamPathTemplate = "/geoffrey",
|
||||
UpstreamHttpMethod = new List<string> { "get" },
|
||||
UpstreamPathTemplate = "/"
|
||||
},
|
||||
new FileRoute()
|
||||
{
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "123.123.123",
|
||||
Port = 443,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "https",
|
||||
DownstreamPathTemplate = "/blooper/{productId}",
|
||||
UpstreamHttpMethod = new List<string> { "post" },
|
||||
UpstreamPathTemplate = "/test"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var command = new UpdateFileConfiguration(updatedConfiguration);
|
||||
GivenThePeersAre(peers);
|
||||
GivenThereIsAConfiguration(configuration);
|
||||
GivenFiveServersAreRunning();
|
||||
await GivenIHaveAnOcelotToken("/administration");
|
||||
await WhenISendACommandIntoTheCluster(command);
|
||||
Thread.Sleep(5000);
|
||||
await ThenTheCommandIsReplicatedToAllStateMachines(command);
|
||||
}
|
||||
|
||||
[Fact(Skip = "Still not stable, more work required in rafty..")]
|
||||
public async Task should_persist_command_to_five_servers_when_using_administration_api()
|
||||
{
|
||||
var peers = new List<FilePeer>
|
||||
{
|
||||
new FilePeer {HostAndPort = "http://localhost:5005"},
|
||||
|
||||
new FilePeer {HostAndPort = "http://localhost:5006"},
|
||||
|
||||
new FilePeer {HostAndPort = "http://localhost:5007"},
|
||||
|
||||
new FilePeer {HostAndPort = "http://localhost:5008"},
|
||||
|
||||
new FilePeer {HostAndPort = "http://localhost:5009"}
|
||||
};
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
};
|
||||
|
||||
var updatedConfiguration = new FileConfiguration
|
||||
{
|
||||
Routes = new List<FileRoute>()
|
||||
{
|
||||
new FileRoute()
|
||||
{
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "127.0.0.1",
|
||||
Port = 80,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
DownstreamPathTemplate = "/geoffrey",
|
||||
UpstreamHttpMethod = new List<string> { "get" },
|
||||
UpstreamPathTemplate = "/"
|
||||
},
|
||||
new FileRoute()
|
||||
{
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "123.123.123",
|
||||
Port = 443,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "https",
|
||||
DownstreamPathTemplate = "/blooper/{productId}",
|
||||
UpstreamHttpMethod = new List<string> { "post" },
|
||||
UpstreamPathTemplate = "/test"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var command = new UpdateFileConfiguration(updatedConfiguration);
|
||||
GivenThePeersAre(peers);
|
||||
GivenThereIsAConfiguration(configuration);
|
||||
GivenFiveServersAreRunning();
|
||||
await GivenIHaveAnOcelotToken("/administration");
|
||||
GivenIHaveAddedATokenToMyRequest();
|
||||
await WhenIPostOnTheApiGateway("/administration/configuration", updatedConfiguration);
|
||||
await ThenTheCommandIsReplicatedToAllStateMachines(command);
|
||||
}
|
||||
|
||||
private void GivenThePeersAre(List<FilePeer> peers)
|
||||
{
|
||||
FilePeers filePeers = new FilePeers();
|
||||
filePeers.Peers.AddRange(peers);
|
||||
var json = JsonConvert.SerializeObject(filePeers);
|
||||
File.WriteAllText("peers.json", json);
|
||||
_httpClient = new HttpClient();
|
||||
var ocelotBaseUrl = peers[0].HostAndPort;
|
||||
_httpClient.BaseAddress = new Uri(ocelotBaseUrl);
|
||||
}
|
||||
|
||||
private async Task WhenISendACommandIntoTheCluster(UpdateFileConfiguration command)
|
||||
{
|
||||
async Task<bool> SendCommand()
|
||||
{
|
||||
try
|
||||
{
|
||||
var p = _peers.Peers.First();
|
||||
var json = JsonConvert.SerializeObject(command, new JsonSerializerSettings()
|
||||
{
|
||||
TypeNameHandling = TypeNameHandling.All
|
||||
});
|
||||
var httpContent = new StringContent(json);
|
||||
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
||||
using (var httpClient = new HttpClient())
|
||||
{
|
||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token.AccessToken);
|
||||
var response = await httpClient.PostAsync($"{p.HostAndPort}/administration/raft/command", httpContent);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
|
||||
var errorResult = JsonConvert.DeserializeObject<ErrorResponse<UpdateFileConfiguration>>(content);
|
||||
|
||||
if (!string.IsNullOrEmpty(errorResult.Error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var okResult = JsonConvert.DeserializeObject<OkResponse<UpdateFileConfiguration>>(content);
|
||||
|
||||
if (okResult.Command.Configuration.Routes.Count == 2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var commandSent = await Wait.WaitFor(40000).Until(async () =>
|
||||
{
|
||||
var result = await SendCommand();
|
||||
Thread.Sleep(1000);
|
||||
return result;
|
||||
});
|
||||
|
||||
commandSent.ShouldBeTrue();
|
||||
}
|
||||
|
||||
private async Task ThenTheCommandIsReplicatedToAllStateMachines(UpdateFileConfiguration expecteds)
|
||||
{
|
||||
async Task<bool> CommandCalledOnAllStateMachines()
|
||||
{
|
||||
try
|
||||
{
|
||||
var passed = 0;
|
||||
foreach (var peer in _peers.Peers)
|
||||
{
|
||||
var path = $"{peer.HostAndPort.Replace("/", "").Replace(":", "")}.db";
|
||||
using (var connection = new SqliteConnection($"Data Source={path};"))
|
||||
{
|
||||
connection.Open();
|
||||
var sql = @"select count(id) from logs";
|
||||
using (var command = new SqliteCommand(sql, connection))
|
||||
{
|
||||
var index = Convert.ToInt32(command.ExecuteScalar());
|
||||
index.ShouldBe(1);
|
||||
}
|
||||
}
|
||||
|
||||
_httpClientForAssertions.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token.AccessToken);
|
||||
var result = await _httpClientForAssertions.GetAsync($"{peer.HostAndPort}/administration/configuration");
|
||||
var json = await result.Content.ReadAsStringAsync();
|
||||
var response = JsonConvert.DeserializeObject<FileConfiguration>(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });
|
||||
response.GlobalConfiguration.RequestIdKey.ShouldBe(expecteds.Configuration.GlobalConfiguration.RequestIdKey);
|
||||
response.GlobalConfiguration.ServiceDiscoveryProvider.Host.ShouldBe(expecteds.Configuration.GlobalConfiguration.ServiceDiscoveryProvider.Host);
|
||||
response.GlobalConfiguration.ServiceDiscoveryProvider.Port.ShouldBe(expecteds.Configuration.GlobalConfiguration.ServiceDiscoveryProvider.Port);
|
||||
|
||||
for (var i = 0; i < response.Routes.Count; i++)
|
||||
{
|
||||
for (var j = 0; j < response.Routes[i].DownstreamHostAndPorts.Count; j++)
|
||||
{
|
||||
var res = response.Routes[i].DownstreamHostAndPorts[j];
|
||||
var expected = expecteds.Configuration.Routes[i].DownstreamHostAndPorts[j];
|
||||
res.Host.ShouldBe(expected.Host);
|
||||
res.Port.ShouldBe(expected.Port);
|
||||
}
|
||||
|
||||
response.Routes[i].DownstreamPathTemplate.ShouldBe(expecteds.Configuration.Routes[i].DownstreamPathTemplate);
|
||||
response.Routes[i].DownstreamScheme.ShouldBe(expecteds.Configuration.Routes[i].DownstreamScheme);
|
||||
response.Routes[i].UpstreamPathTemplate.ShouldBe(expecteds.Configuration.Routes[i].UpstreamPathTemplate);
|
||||
response.Routes[i].UpstreamHttpMethod.ShouldBe(expecteds.Configuration.Routes[i].UpstreamHttpMethod);
|
||||
}
|
||||
|
||||
passed++;
|
||||
}
|
||||
|
||||
return passed == 5;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//_output.WriteLine($"{e.Message}, {e.StackTrace}");
|
||||
Console.WriteLine(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var commandOnAllStateMachines = await Wait.WaitFor(40000).Until(async () =>
|
||||
{
|
||||
var result = await CommandCalledOnAllStateMachines();
|
||||
Thread.Sleep(1000);
|
||||
return result;
|
||||
});
|
||||
|
||||
commandOnAllStateMachines.ShouldBeTrue();
|
||||
}
|
||||
|
||||
private async Task WhenIPostOnTheApiGateway(string url, FileConfiguration updatedConfiguration)
|
||||
{
|
||||
async Task<bool> SendCommand()
|
||||
{
|
||||
var json = JsonConvert.SerializeObject(updatedConfiguration);
|
||||
|
||||
var content = new StringContent(json);
|
||||
|
||||
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
||||
|
||||
_response = await _httpClient.PostAsync(url, content);
|
||||
|
||||
var responseContent = await _response.Content.ReadAsStringAsync();
|
||||
|
||||
if (responseContent == "There was a problem. This error message sucks raise an issue in GitHub.")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(responseContent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _response.IsSuccessStatusCode;
|
||||
}
|
||||
|
||||
var commandSent = await Wait.WaitFor(40000).Until(async () =>
|
||||
{
|
||||
var result = await SendCommand();
|
||||
Thread.Sleep(1000);
|
||||
return result;
|
||||
});
|
||||
|
||||
commandSent.ShouldBeTrue();
|
||||
}
|
||||
|
||||
private void GivenIHaveAddedATokenToMyRequest()
|
||||
{
|
||||
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token.AccessToken);
|
||||
}
|
||||
|
||||
private async Task GivenIHaveAnOcelotToken(string adminPath)
|
||||
{
|
||||
async Task<bool> AddToken()
|
||||
{
|
||||
try
|
||||
{
|
||||
var tokenUrl = $"{adminPath}/connect/token";
|
||||
var formData = new List<KeyValuePair<string, string>>
|
||||
{
|
||||
new KeyValuePair<string, string>("client_id", "admin"),
|
||||
new KeyValuePair<string, string>("client_secret", "secret"),
|
||||
new KeyValuePair<string, string>("scope", "admin"),
|
||||
new KeyValuePair<string, string>("grant_type", "client_credentials")
|
||||
};
|
||||
var content = new FormUrlEncodedContent(formData);
|
||||
|
||||
var response = await _httpClient.PostAsync(tokenUrl, content);
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
|
||||
var configPath = $"{adminPath}/.well-known/openid-configuration";
|
||||
response = await _httpClient.GetAsync(configPath);
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var addToken = await Wait.WaitFor(40000).Until(async () =>
|
||||
{
|
||||
var result = await AddToken();
|
||||
Thread.Sleep(1000);
|
||||
return result;
|
||||
});
|
||||
|
||||
addToken.ShouldBeTrue();
|
||||
}
|
||||
|
||||
private void GivenThereIsAConfiguration(FileConfiguration fileConfiguration)
|
||||
{
|
||||
var configurationPath = $"{Directory.GetCurrentDirectory()}/ocelot.json";
|
||||
|
||||
var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
|
||||
|
||||
if (File.Exists(configurationPath))
|
||||
{
|
||||
File.Delete(configurationPath);
|
||||
}
|
||||
|
||||
File.WriteAllText(configurationPath, jsonConfiguration);
|
||||
|
||||
var text = File.ReadAllText(configurationPath);
|
||||
|
||||
configurationPath = $"{AppContext.BaseDirectory}/ocelot.json";
|
||||
|
||||
if (File.Exists(configurationPath))
|
||||
{
|
||||
File.Delete(configurationPath);
|
||||
}
|
||||
|
||||
File.WriteAllText(configurationPath, jsonConfiguration);
|
||||
|
||||
text = File.ReadAllText(configurationPath);
|
||||
}
|
||||
|
||||
private void GivenAServerIsRunning(string url)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
IWebHostBuilder webHostBuilder = new WebHostBuilder();
|
||||
webHostBuilder.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||
{
|
||||
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
|
||||
var env = hostingContext.HostingEnvironment;
|
||||
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
|
||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: false);
|
||||
config.AddJsonFile("ocelot.json", false, false);
|
||||
config.AddJsonFile("peers.json", optional: true, reloadOnChange: false);
|
||||
#pragma warning disable CS0618
|
||||
config.AddOcelotBaseUrl(url);
|
||||
#pragma warning restore CS0618
|
||||
config.AddEnvironmentVariables();
|
||||
})
|
||||
.ConfigureServices(x =>
|
||||
{
|
||||
x.AddSingleton(new NodeId(url));
|
||||
x
|
||||
.AddOcelot()
|
||||
.AddAdministration("/administration", "secret")
|
||||
.AddRafty();
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseOcelot().Wait();
|
||||
});
|
||||
|
||||
var builder = webHostBuilder.Build();
|
||||
builder.Start();
|
||||
|
||||
_webHostBuilders.Add(webHostBuilder);
|
||||
_builders.Add(builder);
|
||||
}
|
||||
}
|
||||
|
||||
private void GivenFiveServersAreRunning()
|
||||
{
|
||||
var bytes = File.ReadAllText("peers.json");
|
||||
_peers = JsonConvert.DeserializeObject<FilePeers>(bytes);
|
||||
|
||||
foreach (var peer in _peers.Peers)
|
||||
{
|
||||
File.Delete(peer.HostAndPort.Replace("/", "").Replace(":", ""));
|
||||
File.Delete($"{peer.HostAndPort.Replace("/", "").Replace(":", "")}.db");
|
||||
var thread = new Thread(() => GivenAServerIsRunning(peer.HostAndPort));
|
||||
thread.Start();
|
||||
_threads.Add(thread);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var builder in _builders)
|
||||
{
|
||||
builder?.Dispose();
|
||||
}
|
||||
|
||||
foreach (var peer in _peers.Peers)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(peer.HostAndPort.Replace("/", "").Replace(":", ""));
|
||||
File.Delete($"{peer.HostAndPort.Replace("/", "").Replace(":", "")}.db");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
<AssemblyName>Ocelot.ManualTest</AssemblyName>
|
||||
<OutputType>Exe</OutputType>
|
||||
@ -28,13 +28,13 @@
|
||||
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
@ -42,4 +42,4 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -1,101 +1,102 @@
|
||||
namespace Ocelot.UnitTests.Administration
|
||||
{
|
||||
namespace Ocelot.UnitTests.Administration
|
||||
{
|
||||
using IdentityServer4.AccessTokenValidation;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Moq;
|
||||
using Ocelot.Administration;
|
||||
using Ocelot.DependencyInjection;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class OcelotAdministrationBuilderTests
|
||||
{
|
||||
private readonly IServiceCollection _services;
|
||||
private IServiceProvider _serviceProvider;
|
||||
private readonly IConfiguration _configRoot;
|
||||
private IOcelotBuilder _ocelotBuilder;
|
||||
private Exception _ex;
|
||||
|
||||
public OcelotAdministrationBuilderTests()
|
||||
{
|
||||
_configRoot = new ConfigurationRoot(new List<IConfigurationProvider>());
|
||||
_services = new ServiceCollection();
|
||||
_services.AddSingleton<IWebHostEnvironment>(GetHostingEnvironment());
|
||||
_services.AddSingleton(_configRoot);
|
||||
}
|
||||
|
||||
private IWebHostEnvironment GetHostingEnvironment()
|
||||
{
|
||||
var environment = new Mock<IWebHostEnvironment>();
|
||||
environment
|
||||
.Setup(e => e.ApplicationName)
|
||||
.Returns(typeof(OcelotAdministrationBuilderTests).GetTypeInfo().Assembly.GetName().Name);
|
||||
|
||||
return environment.Object;
|
||||
}
|
||||
|
||||
//keep
|
||||
[Fact]
|
||||
public void should_set_up_administration_with_identity_server_options()
|
||||
{
|
||||
Action<IdentityServerAuthenticationOptions> options = o => { };
|
||||
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => WhenISetUpAdministration(options))
|
||||
.Then(x => ThenAnExceptionIsntThrown())
|
||||
.Then(x => ThenTheCorrectAdminPathIsRegitered())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
//keep
|
||||
[Fact]
|
||||
public void should_set_up_administration()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => WhenISetUpAdministration())
|
||||
.Then(x => ThenAnExceptionIsntThrown())
|
||||
.Then(x => ThenTheCorrectAdminPathIsRegitered())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenISetUpAdministration()
|
||||
{
|
||||
_ocelotBuilder.AddAdministration("/administration", "secret");
|
||||
}
|
||||
|
||||
private void WhenISetUpAdministration(Action<IdentityServerAuthenticationOptions> options)
|
||||
{
|
||||
_ocelotBuilder.AddAdministration("/administration", options);
|
||||
}
|
||||
|
||||
private void ThenTheCorrectAdminPathIsRegitered()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var path = _serviceProvider.GetService<IAdministrationPath>();
|
||||
path.Path.ShouldBe("/administration");
|
||||
}
|
||||
|
||||
private void WhenISetUpOcelotServices()
|
||||
{
|
||||
try
|
||||
{
|
||||
_ocelotBuilder = _services.AddOcelot(_configRoot);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_ex = e;
|
||||
}
|
||||
}
|
||||
|
||||
private void ThenAnExceptionIsntThrown()
|
||||
{
|
||||
_ex.ShouldBeNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Moq;
|
||||
using Ocelot.Administration;
|
||||
using Ocelot.DependencyInjection;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class OcelotAdministrationBuilderTests
|
||||
{
|
||||
private readonly IServiceCollection _services;
|
||||
private IServiceProvider _serviceProvider;
|
||||
private readonly IConfiguration _configRoot;
|
||||
private IOcelotBuilder _ocelotBuilder;
|
||||
private Exception _ex;
|
||||
|
||||
public OcelotAdministrationBuilderTests()
|
||||
{
|
||||
_configRoot = new ConfigurationRoot(new List<IConfigurationProvider>());
|
||||
_services = new ServiceCollection();
|
||||
_services.AddSingleton<IWebHostEnvironment>(GetHostingEnvironment());
|
||||
_services.AddSingleton(_configRoot);
|
||||
}
|
||||
|
||||
private IWebHostEnvironment GetHostingEnvironment()
|
||||
{
|
||||
var environment = new Mock<IWebHostEnvironment>();
|
||||
environment
|
||||
.Setup(e => e.ApplicationName)
|
||||
.Returns(typeof(OcelotAdministrationBuilderTests).GetTypeInfo().Assembly.GetName().Name);
|
||||
|
||||
return environment.Object;
|
||||
}
|
||||
|
||||
//keep
|
||||
[Fact]
|
||||
public void should_set_up_administration_with_identity_server_options()
|
||||
{
|
||||
Action<JwtBearerOptions> options = o => { };
|
||||
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => WhenISetUpAdministration(options))
|
||||
.Then(x => ThenAnExceptionIsntThrown())
|
||||
.Then(x => ThenTheCorrectAdminPathIsRegitered())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
//keep
|
||||
[Fact]
|
||||
public void should_set_up_administration()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => WhenISetUpAdministration())
|
||||
.Then(x => ThenAnExceptionIsntThrown())
|
||||
.Then(x => ThenTheCorrectAdminPathIsRegitered())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenISetUpAdministration()
|
||||
{
|
||||
_ocelotBuilder.AddAdministration("/administration", "secret");
|
||||
}
|
||||
|
||||
private void WhenISetUpAdministration(Action<JwtBearerOptions> options)
|
||||
{
|
||||
_ocelotBuilder.AddAdministration("/administration", options);
|
||||
}
|
||||
|
||||
private void ThenTheCorrectAdminPathIsRegitered()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var path = _serviceProvider.GetService<IAdministrationPath>();
|
||||
path.Path.ShouldBe("/administration");
|
||||
}
|
||||
|
||||
private void WhenISetUpOcelotServices()
|
||||
{
|
||||
try
|
||||
{
|
||||
_ocelotBuilder = _services.AddOcelot(_configRoot);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_ex = e;
|
||||
}
|
||||
}
|
||||
|
||||
private void ThenAnExceptionIsntThrown()
|
||||
{
|
||||
_ex.ShouldBeNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ namespace Ocelot.UnitTests.Authorization
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Authorisation;
|
||||
using Ocelot.Authorisation.Middleware;
|
||||
using Ocelot.Authorization;
|
||||
using Ocelot.Authorization.Middleware;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
@ -18,35 +18,35 @@ namespace Ocelot.UnitTests.Authorization
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class AuthorisationMiddlewareTests
|
||||
public class AuthorizationMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IClaimsAuthoriser> _authService;
|
||||
private readonly Mock<IScopesAuthoriser> _authScopesService;
|
||||
private readonly Mock<IClaimsAuthorizer> _authService;
|
||||
private readonly Mock<IScopesAuthorizer> _authScopesService;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly AuthorisationMiddleware _middleware;
|
||||
private readonly AuthorizationMiddleware _middleware;
|
||||
private RequestDelegate _next;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public AuthorisationMiddlewareTests()
|
||||
public AuthorizationMiddlewareTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_authService = new Mock<IClaimsAuthoriser>();
|
||||
_authScopesService = new Mock<IScopesAuthoriser>();
|
||||
_authService = new Mock<IClaimsAuthorizer>();
|
||||
_authScopesService = new Mock<IScopesAuthorizer>();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<AuthorisationMiddleware>()).Returns(_logger.Object);
|
||||
_loggerFactory.Setup(x => x.CreateLogger<AuthorizationMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_middleware = new AuthorisationMiddleware(_next, _authService.Object, _authScopesService.Object, _loggerFactory.Object);
|
||||
_middleware = new AuthorizationMiddleware(_next, _authService.Object, _authScopesService.Object, _loggerFactory.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_authorisation_service()
|
||||
public void should_call_authorization_service()
|
||||
{
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(new List<PlaceholderNameAndValue>(),
|
||||
new DownstreamRouteBuilder()
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().Build())
|
||||
.WithIsAuthorised(true)
|
||||
.WithIsAuthorized(true)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build()))
|
||||
.And(x => x.GivenTheAuthServiceReturns(new OkResponse<bool>(true)))
|
||||
@ -69,7 +69,7 @@ namespace Ocelot.UnitTests.Authorization
|
||||
private void GivenTheAuthServiceReturns(Response<bool> expected)
|
||||
{
|
||||
_authService
|
||||
.Setup(x => x.Authorise(
|
||||
.Setup(x => x.Authorize(
|
||||
It.IsAny<ClaimsPrincipal>(),
|
||||
It.IsAny<Dictionary<string, string>>(),
|
||||
It.IsAny<List<PlaceholderNameAndValue>>()))
|
||||
@ -79,7 +79,7 @@ namespace Ocelot.UnitTests.Authorization
|
||||
private void ThenTheAuthServiceIsCalledCorrectly()
|
||||
{
|
||||
_authService
|
||||
.Verify(x => x.Authorise(
|
||||
.Verify(x => x.Authorize(
|
||||
It.IsAny<ClaimsPrincipal>(),
|
||||
It.IsAny<Dictionary<string, string>>(),
|
||||
It.IsAny<List<PlaceholderNameAndValue>>())
|
@ -1,4 +1,4 @@
|
||||
using Ocelot.Authorisation;
|
||||
using Ocelot.Authorization;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
@ -11,21 +11,21 @@ namespace Ocelot.UnitTests.Authorization
|
||||
{
|
||||
using Ocelot.Infrastructure.Claims.Parser;
|
||||
|
||||
public class ClaimsAuthoriserTests
|
||||
public class ClaimsAuthorizerTests
|
||||
{
|
||||
private readonly ClaimsAuthoriser _claimsAuthoriser;
|
||||
private readonly ClaimsAuthorizer _claimsAuthorizer;
|
||||
private ClaimsPrincipal _claimsPrincipal;
|
||||
private Dictionary<string, string> _requirement;
|
||||
private List<PlaceholderNameAndValue> _urlPathPlaceholderNameAndValues;
|
||||
private Response<bool> _result;
|
||||
|
||||
public ClaimsAuthoriserTests()
|
||||
public ClaimsAuthorizerTests()
|
||||
{
|
||||
_claimsAuthoriser = new ClaimsAuthoriser(new ClaimsParser());
|
||||
_claimsAuthorizer = new ClaimsAuthorizer(new ClaimsParser());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_authorise_user()
|
||||
public void should_authorize_user()
|
||||
{
|
||||
this.Given(x => x.GivenAClaimsPrincipal(new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
|
||||
{
|
||||
@ -35,8 +35,8 @@ namespace Ocelot.UnitTests.Authorization
|
||||
{
|
||||
{"UserType", "registered"}
|
||||
}))
|
||||
.When(x => x.WhenICallTheAuthoriser())
|
||||
.Then(x => x.ThenTheUserIsAuthorised())
|
||||
.When(x => x.WhenICallTheAuthorizer())
|
||||
.Then(x => x.ThenTheUserIsAuthorized())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
@ -55,8 +55,8 @@ namespace Ocelot.UnitTests.Authorization
|
||||
{
|
||||
new PlaceholderNameAndValue("{userId}", "14")
|
||||
}))
|
||||
.When(x => x.WhenICallTheAuthoriser())
|
||||
.Then(x => x.ThenTheUserIsAuthorised())
|
||||
.When(x => x.WhenICallTheAuthorizer())
|
||||
.Then(x => x.ThenTheUserIsAuthorized())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
@ -75,13 +75,13 @@ namespace Ocelot.UnitTests.Authorization
|
||||
{
|
||||
new PlaceholderNameAndValue("{userId}", "14")
|
||||
}))
|
||||
.When(x => x.WhenICallTheAuthoriser())
|
||||
.Then(x => x.ThenTheUserIsntAuthorised())
|
||||
.When(x => x.WhenICallTheAuthorizer())
|
||||
.Then(x => x.ThenTheUserIsntAuthorized())
|
||||
.BDDfy();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_authorise_user_multiple_claims_of_same_type()
|
||||
public void should_authorize_user_multiple_claims_of_same_type()
|
||||
{
|
||||
this.Given(x => x.GivenAClaimsPrincipal(new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
|
||||
{
|
||||
@ -92,21 +92,21 @@ namespace Ocelot.UnitTests.Authorization
|
||||
{
|
||||
{"UserType", "registered"}
|
||||
}))
|
||||
.When(x => x.WhenICallTheAuthoriser())
|
||||
.Then(x => x.ThenTheUserIsAuthorised())
|
||||
.When(x => x.WhenICallTheAuthorizer())
|
||||
.Then(x => x.ThenTheUserIsAuthorized())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_authorise_user()
|
||||
public void should_not_authorize_user()
|
||||
{
|
||||
this.Given(x => x.GivenAClaimsPrincipal(new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()))))
|
||||
.And(x => x.GivenARouteClaimsRequirement(new Dictionary<string, string>
|
||||
{
|
||||
{ "UserType", "registered" }
|
||||
}))
|
||||
.When(x => x.WhenICallTheAuthoriser())
|
||||
.Then(x => x.ThenTheUserIsntAuthorised())
|
||||
.When(x => x.WhenICallTheAuthorizer())
|
||||
.Then(x => x.ThenTheUserIsntAuthorized())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
@ -125,19 +125,19 @@ namespace Ocelot.UnitTests.Authorization
|
||||
_urlPathPlaceholderNameAndValues = urlPathPlaceholderNameAndValues;
|
||||
}
|
||||
|
||||
private void WhenICallTheAuthoriser()
|
||||
private void WhenICallTheAuthorizer()
|
||||
{
|
||||
_result = _claimsAuthoriser.Authorise(_claimsPrincipal, _requirement, _urlPathPlaceholderNameAndValues);
|
||||
_result = _claimsAuthorizer.Authorize(_claimsPrincipal, _requirement, _urlPathPlaceholderNameAndValues);
|
||||
}
|
||||
|
||||
private void ThenTheUserIsAuthorised()
|
||||
private void ThenTheUserIsAuthorized()
|
||||
{
|
||||
_result.Data.ShouldBe(true);
|
||||
}
|
||||
|
||||
private void ThenTheUserIsntAuthorised()
|
||||
private void ThenTheUserIsntAuthorized()
|
||||
{
|
||||
_result.Data.ShouldBe(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -46,7 +46,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
|
||||
var expected = new RouteOptionsBuilder()
|
||||
.WithIsAuthenticated(true)
|
||||
.WithIsAuthorised(true)
|
||||
.WithIsAuthorized(true)
|
||||
.WithIsCached(true)
|
||||
.WithRateLimiting(true)
|
||||
.WithUseServiceDiscovery(true)
|
||||
@ -71,7 +71,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
private void ThenTheFollowingIsReturned(RouteOptions expected)
|
||||
{
|
||||
_result.IsAuthenticated.ShouldBe(expected.IsAuthenticated);
|
||||
_result.IsAuthorised.ShouldBe(expected.IsAuthorised);
|
||||
_result.IsAuthorized.ShouldBe(expected.IsAuthorized);
|
||||
_result.IsCached.ShouldBe(expected.IsCached);
|
||||
_result.EnableRateLimiting.ShouldBe(expected.EnableRateLimiting);
|
||||
_result.UseServiceDiscovery.ShouldBe(expected.UseServiceDiscovery);
|
||||
|
@ -218,7 +218,7 @@
|
||||
{
|
||||
_result[routeIndex].DownstreamRoute[0].DownstreamHttpVersion.ShouldBe(_expectedVersion);
|
||||
_result[routeIndex].DownstreamRoute[0].IsAuthenticated.ShouldBe(_rro.IsAuthenticated);
|
||||
_result[routeIndex].DownstreamRoute[0].IsAuthorised.ShouldBe(_rro.IsAuthorised);
|
||||
_result[routeIndex].DownstreamRoute[0].IsAuthorized.ShouldBe(_rro.IsAuthorized);
|
||||
_result[routeIndex].DownstreamRoute[0].IsCached.ShouldBe(_rro.IsCached);
|
||||
_result[routeIndex].DownstreamRoute[0].EnableEndpointEndpointRateLimiting.ShouldBe(_rro.EnableRateLimiting);
|
||||
_result[routeIndex].DownstreamRoute[0].RequestIdKey.ShouldBe(_requestId);
|
||||
|
@ -87,7 +87,7 @@
|
||||
Address = "localhost",
|
||||
Port = 50881,
|
||||
ID = Guid.NewGuid().ToString(),
|
||||
Tags = new string[0]
|
||||
Tags = new string[0],
|
||||
},
|
||||
};
|
||||
|
||||
@ -95,7 +95,7 @@
|
||||
.And(_ => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne))
|
||||
.When(_ => WhenIGetTheServices())
|
||||
.Then(_ => ThenTheCountIs(1))
|
||||
.And(_ => _receivedToken.ShouldBe(token))
|
||||
.And(_ => ThenTheTokenIs(token))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
@ -253,6 +253,11 @@
|
||||
_services = _provider.Get().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void ThenTheTokenIs(string token)
|
||||
{
|
||||
_receivedToken.ShouldBe(token);
|
||||
}
|
||||
|
||||
private void GivenTheServicesAreRegisteredWithConsul(params ServiceEntry[] serviceEntries)
|
||||
{
|
||||
foreach (var serviceEntry in serviceEntries)
|
||||
|
@ -6,10 +6,10 @@
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.Repository;
|
||||
using Provider.Eureka;
|
||||
using Responses;
|
||||
using Ocelot.Provider.Eureka;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using Steeltoe.Common.Discovery;
|
||||
using Steeltoe.Discovery;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
services.AddSingleton<IInternalConfigurationRepository>(configRepo.Object);
|
||||
var sp = services.BuildServiceProvider();
|
||||
var provider = EurekaMiddlewareConfigurationProvider.Get(new ApplicationBuilder(sp));
|
||||
provider.ShouldBeOfType<Task>();
|
||||
provider.Status.ShouldBe(TaskStatus.RanToCompletion);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -41,7 +41,7 @@
|
||||
services.AddSingleton<IDiscoveryClient>(client.Object);
|
||||
var sp = services.BuildServiceProvider();
|
||||
var provider = EurekaMiddlewareConfigurationProvider.Get(new ApplicationBuilder(sp));
|
||||
provider.ShouldBeOfType<Task>();
|
||||
provider.Status.ShouldBe(TaskStatus.RanToCompletion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Provider.Eureka;
|
||||
using Shouldly;
|
||||
using Steeltoe.Common.Discovery;
|
||||
using Steeltoe.Discovery;
|
||||
using Xunit;
|
||||
|
||||
public class EurekaProviderFactoryTests
|
||||
|
@ -1,117 +1,118 @@
|
||||
namespace Ocelot.UnitTests.Eureka
|
||||
{
|
||||
using Moq;
|
||||
using Provider.Eureka;
|
||||
using Shouldly;
|
||||
namespace Ocelot.UnitTests.Eureka
|
||||
{
|
||||
using Moq;
|
||||
using Ocelot.Provider.Eureka;
|
||||
using Shouldly;
|
||||
using Steeltoe.Common.Discovery;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Values;
|
||||
using Xunit;
|
||||
|
||||
public class EurekaServiceDiscoveryProviderTests
|
||||
{
|
||||
private readonly Eureka _provider;
|
||||
private readonly Mock<IDiscoveryClient> _client;
|
||||
private readonly string _serviceId;
|
||||
private List<IServiceInstance> _instances;
|
||||
private List<Service> _result;
|
||||
|
||||
public EurekaServiceDiscoveryProviderTests()
|
||||
{
|
||||
_serviceId = "Laura";
|
||||
_client = new Mock<IDiscoveryClient>();
|
||||
_provider = new Eureka(_serviceId, _client.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_empty_services()
|
||||
{
|
||||
this.When(_ => WhenIGet())
|
||||
.Then(_ => ThenTheCountIs(0))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_service_from_client()
|
||||
{
|
||||
var instances = new List<IServiceInstance>
|
||||
{
|
||||
new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>())
|
||||
};
|
||||
|
||||
this.Given(_ => GivenThe(instances))
|
||||
.When(_ => WhenIGet())
|
||||
.Then(_ => ThenTheCountIs(1))
|
||||
.And(_ => ThenTheClientIsCalledCorrectly())
|
||||
.And(_ => ThenTheServiceIsMapped())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_services_from_client()
|
||||
{
|
||||
var instances = new List<IServiceInstance>
|
||||
{
|
||||
new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>()),
|
||||
new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>())
|
||||
};
|
||||
|
||||
this.Given(_ => GivenThe(instances))
|
||||
.When(_ => WhenIGet())
|
||||
.Then(_ => ThenTheCountIs(2))
|
||||
.And(_ => ThenTheClientIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenTheServiceIsMapped()
|
||||
{
|
||||
_result[0].HostAndPort.DownstreamHost.ShouldBe("somehost");
|
||||
_result[0].HostAndPort.DownstreamPort.ShouldBe(801);
|
||||
_result[0].Name.ShouldBe(_serviceId);
|
||||
}
|
||||
|
||||
private void ThenTheCountIs(int expected)
|
||||
{
|
||||
_result.Count.ShouldBe(expected);
|
||||
}
|
||||
|
||||
private void ThenTheClientIsCalledCorrectly()
|
||||
{
|
||||
_client.Verify(x => x.GetInstances(_serviceId), Times.Once);
|
||||
}
|
||||
|
||||
private async Task WhenIGet()
|
||||
{
|
||||
_result = await _provider.Get();
|
||||
}
|
||||
|
||||
private void GivenThe(List<IServiceInstance> instances)
|
||||
{
|
||||
_instances = instances;
|
||||
_client.Setup(x => x.GetInstances(It.IsAny<string>())).Returns(instances);
|
||||
}
|
||||
}
|
||||
|
||||
public class EurekaService : IServiceInstance
|
||||
{
|
||||
public EurekaService(string serviceId, string host, int port, bool isSecure, Uri uri, IDictionary<string, string> metadata)
|
||||
{
|
||||
ServiceId = serviceId;
|
||||
Host = host;
|
||||
Port = port;
|
||||
IsSecure = isSecure;
|
||||
Uri = uri;
|
||||
Metadata = metadata;
|
||||
}
|
||||
|
||||
public string ServiceId { get; }
|
||||
public string Host { get; }
|
||||
public int Port { get; }
|
||||
public bool IsSecure { get; }
|
||||
public Uri Uri { get; }
|
||||
public IDictionary<string, string> Metadata { get; }
|
||||
}
|
||||
}
|
||||
using Steeltoe.Discovery;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Ocelot.Values;
|
||||
using Xunit;
|
||||
|
||||
public class EurekaServiceDiscoveryProviderTests
|
||||
{
|
||||
private readonly Eureka _provider;
|
||||
private readonly Mock<IDiscoveryClient> _client;
|
||||
private readonly string _serviceId;
|
||||
private List<IServiceInstance> _instances;
|
||||
private List<Service> _result;
|
||||
|
||||
public EurekaServiceDiscoveryProviderTests()
|
||||
{
|
||||
_serviceId = "Laura";
|
||||
_client = new Mock<IDiscoveryClient>();
|
||||
_provider = new Eureka(_serviceId, _client.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_empty_services()
|
||||
{
|
||||
this.When(_ => WhenIGet())
|
||||
.Then(_ => ThenTheCountIs(0))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_service_from_client()
|
||||
{
|
||||
var instances = new List<IServiceInstance>
|
||||
{
|
||||
new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>())
|
||||
};
|
||||
|
||||
this.Given(_ => GivenThe(instances))
|
||||
.When(_ => WhenIGet())
|
||||
.Then(_ => ThenTheCountIs(1))
|
||||
.And(_ => ThenTheClientIsCalledCorrectly())
|
||||
.And(_ => ThenTheServiceIsMapped())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_services_from_client()
|
||||
{
|
||||
var instances = new List<IServiceInstance>
|
||||
{
|
||||
new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>()),
|
||||
new EurekaService(_serviceId, "somehost", 801, false, new Uri("http://somehost:801"), new Dictionary<string, string>())
|
||||
};
|
||||
|
||||
this.Given(_ => GivenThe(instances))
|
||||
.When(_ => WhenIGet())
|
||||
.Then(_ => ThenTheCountIs(2))
|
||||
.And(_ => ThenTheClientIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenTheServiceIsMapped()
|
||||
{
|
||||
_result[0].HostAndPort.DownstreamHost.ShouldBe("somehost");
|
||||
_result[0].HostAndPort.DownstreamPort.ShouldBe(801);
|
||||
_result[0].Name.ShouldBe(_serviceId);
|
||||
}
|
||||
|
||||
private void ThenTheCountIs(int expected)
|
||||
{
|
||||
_result.Count.ShouldBe(expected);
|
||||
}
|
||||
|
||||
private void ThenTheClientIsCalledCorrectly()
|
||||
{
|
||||
_client.Verify(x => x.GetInstances(_serviceId), Times.Once);
|
||||
}
|
||||
|
||||
private async Task WhenIGet()
|
||||
{
|
||||
_result = await _provider.Get();
|
||||
}
|
||||
|
||||
private void GivenThe(List<IServiceInstance> instances)
|
||||
{
|
||||
_instances = instances;
|
||||
_client.Setup(x => x.GetInstances(It.IsAny<string>())).Returns(instances);
|
||||
}
|
||||
}
|
||||
|
||||
public class EurekaService : IServiceInstance
|
||||
{
|
||||
public EurekaService(string serviceId, string host, int port, bool isSecure, Uri uri, IDictionary<string, string> metadata)
|
||||
{
|
||||
ServiceId = serviceId;
|
||||
Host = host;
|
||||
Port = port;
|
||||
IsSecure = isSecure;
|
||||
Uri = uri;
|
||||
Metadata = metadata;
|
||||
}
|
||||
|
||||
public string ServiceId { get; }
|
||||
public string Host { get; }
|
||||
public int Port { get; }
|
||||
public bool IsSecure { get; }
|
||||
public Uri Uri { get; }
|
||||
public IDictionary<string, string> Metadata { get; }
|
||||
}
|
||||
}
|
||||
|
@ -1,128 +1,129 @@
|
||||
namespace Ocelot.UnitTests.Headers
|
||||
{
|
||||
namespace Ocelot.UnitTests.Headers
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration.Creator;
|
||||
using Ocelot.Headers;
|
||||
using Ocelot.Infrastructure;
|
||||
using Ocelot.Infrastructure.Claims.Parser;
|
||||
using Ocelot.Logging;
|
||||
using Responder;
|
||||
using Responses;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class AddHeadersToRequestPlainTests
|
||||
{
|
||||
private readonly AddHeadersToRequest _addHeadersToRequest;
|
||||
private HttpContext _context;
|
||||
private AddHeader _addedHeader;
|
||||
private readonly Mock<IPlaceholders> _placeholders;
|
||||
private Mock<IOcelotLoggerFactory> _factory;
|
||||
private readonly Mock<IOcelotLogger> _logger;
|
||||
|
||||
public AddHeadersToRequestPlainTests()
|
||||
{
|
||||
_placeholders = new Mock<IPlaceholders>();
|
||||
_factory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_factory.Setup(x => x.CreateLogger<AddHeadersToRequest>()).Returns(_logger.Object);
|
||||
_addHeadersToRequest = new AddHeadersToRequest(Mock.Of<IClaimsParser>(), _placeholders.Object, _factory.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_log_error_if_cannot_find_placeholder()
|
||||
{
|
||||
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new ErrorResponse<string>(new AnyError()));
|
||||
|
||||
this.Given(_ => GivenHttpRequestWithoutHeaders())
|
||||
.When(_ => WhenAddingHeader("X-Forwarded-For", "{RemoteIdAddress}"))
|
||||
.Then(_ => ThenAnErrorIsLogged("X-Forwarded-For", "{RemoteIdAddress}"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_placeholder_to_downstream_request()
|
||||
{
|
||||
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new OkResponse<string>("replaced"));
|
||||
|
||||
this.Given(_ => GivenHttpRequestWithoutHeaders())
|
||||
.When(_ => WhenAddingHeader("X-Forwarded-For", "{RemoteIdAddress}"))
|
||||
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders("replaced"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_plain_text_header_to_downstream_request()
|
||||
{
|
||||
this.Given(_ => GivenHttpRequestWithoutHeaders())
|
||||
.When(_ => WhenAddingHeader("X-Custom-Header", "PlainValue"))
|
||||
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_overwrite_existing_header_with_added_header()
|
||||
{
|
||||
this.Given(_ => GivenHttpRequestWithHeader("X-Custom-Header", "This should get overwritten"))
|
||||
.When(_ => WhenAddingHeader("X-Custom-Header", "PlainValue"))
|
||||
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenAnErrorIsLogged(string key, string value)
|
||||
{
|
||||
_logger.Verify(x => x.LogWarning($"Unable to add header to response {key}: {value}"), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenHttpRequestWithoutHeaders()
|
||||
{
|
||||
_context = new DefaultHttpContext
|
||||
{
|
||||
Request =
|
||||
{
|
||||
Headers =
|
||||
{
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void GivenHttpRequestWithHeader(string headerKey, string headerValue)
|
||||
{
|
||||
_context = new DefaultHttpContext
|
||||
{
|
||||
Request =
|
||||
{
|
||||
Headers =
|
||||
{
|
||||
{ headerKey, headerValue }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void WhenAddingHeader(string headerKey, string headerValue)
|
||||
{
|
||||
_addedHeader = new AddHeader(headerKey, headerValue);
|
||||
_addHeadersToRequest.SetHeadersOnDownstreamRequest(new[] { _addedHeader }, _context);
|
||||
}
|
||||
|
||||
private void ThenTheHeaderGetsTakenOverToTheRequestHeaders()
|
||||
{
|
||||
var requestHeaders = _context.Request.Headers;
|
||||
requestHeaders.ContainsKey(_addedHeader.Key).ShouldBeTrue($"Header {_addedHeader.Key} was expected but not there.");
|
||||
var value = requestHeaders[_addedHeader.Key];
|
||||
value.ShouldNotBeNull($"Value of header {_addedHeader.Key} was expected to not be null.");
|
||||
value.ToString().ShouldBe(_addedHeader.Value);
|
||||
}
|
||||
|
||||
private void ThenTheHeaderGetsTakenOverToTheRequestHeaders(string expected)
|
||||
{
|
||||
var requestHeaders = _context.Request.Headers;
|
||||
var value = requestHeaders[_addedHeader.Key];
|
||||
value.ToString().ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Moq;
|
||||
using Ocelot.Configuration.Creator;
|
||||
using Ocelot.Headers;
|
||||
using Ocelot.Infrastructure;
|
||||
using Ocelot.Infrastructure.Claims.Parser;
|
||||
using Ocelot.Logging;
|
||||
using Responder;
|
||||
using Responses;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class AddHeadersToRequestPlainTests
|
||||
{
|
||||
private readonly AddHeadersToRequest _addHeadersToRequest;
|
||||
private HttpContext _context;
|
||||
private AddHeader _addedHeader;
|
||||
private readonly Mock<IPlaceholders> _placeholders;
|
||||
private Mock<IOcelotLoggerFactory> _factory;
|
||||
private readonly Mock<IOcelotLogger> _logger;
|
||||
|
||||
public AddHeadersToRequestPlainTests()
|
||||
{
|
||||
_placeholders = new Mock<IPlaceholders>();
|
||||
_factory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_factory.Setup(x => x.CreateLogger<AddHeadersToRequest>()).Returns(_logger.Object);
|
||||
_addHeadersToRequest = new AddHeadersToRequest(Mock.Of<IClaimsParser>(), _placeholders.Object, _factory.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_log_error_if_cannot_find_placeholder()
|
||||
{
|
||||
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new ErrorResponse<string>(new AnyError()));
|
||||
|
||||
this.Given(_ => GivenHttpRequestWithoutHeaders())
|
||||
.When(_ => WhenAddingHeader("X-Forwarded-For", "{RemoteIdAddress}"))
|
||||
.Then(_ => ThenAnErrorIsLogged("X-Forwarded-For", "{RemoteIdAddress}"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_placeholder_to_downstream_request()
|
||||
{
|
||||
_placeholders.Setup(x => x.Get(It.IsAny<string>())).Returns(new OkResponse<string>("replaced"));
|
||||
|
||||
this.Given(_ => GivenHttpRequestWithoutHeaders())
|
||||
.When(_ => WhenAddingHeader("X-Forwarded-For", "{RemoteIdAddress}"))
|
||||
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders("replaced"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_plain_text_header_to_downstream_request()
|
||||
{
|
||||
this.Given(_ => GivenHttpRequestWithoutHeaders())
|
||||
.When(_ => WhenAddingHeader("X-Custom-Header", "PlainValue"))
|
||||
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_overwrite_existing_header_with_added_header()
|
||||
{
|
||||
this.Given(_ => GivenHttpRequestWithHeader("X-Custom-Header", "This should get overwritten"))
|
||||
.When(_ => WhenAddingHeader("X-Custom-Header", "PlainValue"))
|
||||
.Then(_ => ThenTheHeaderGetsTakenOverToTheRequestHeaders())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenAnErrorIsLogged(string key, string value)
|
||||
{
|
||||
_logger.Verify(x => x.LogWarning($"Unable to add header to response {key}: {value}"), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenHttpRequestWithoutHeaders()
|
||||
{
|
||||
_context = new DefaultHttpContext
|
||||
{
|
||||
Request =
|
||||
{
|
||||
Headers =
|
||||
{
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void GivenHttpRequestWithHeader(string headerKey, string headerValue)
|
||||
{
|
||||
_context = new DefaultHttpContext
|
||||
{
|
||||
Request =
|
||||
{
|
||||
Headers =
|
||||
{
|
||||
{ headerKey, headerValue }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void WhenAddingHeader(string headerKey, string headerValue)
|
||||
{
|
||||
_addedHeader = new AddHeader(headerKey, headerValue);
|
||||
_addHeadersToRequest.SetHeadersOnDownstreamRequest(new[] { _addedHeader }, _context);
|
||||
}
|
||||
|
||||
private void ThenTheHeaderGetsTakenOverToTheRequestHeaders()
|
||||
{
|
||||
var requestHeaders = _context.Request.Headers;
|
||||
requestHeaders.ContainsKey(_addedHeader.Key).ShouldBeTrue($"Header {_addedHeader.Key} was expected but not there.");
|
||||
var value = requestHeaders[_addedHeader.Key];
|
||||
value.ShouldNotBe(default(StringValues), $"Value of header {_addedHeader.Key} was expected to not be null.");
|
||||
value.ToString().ShouldBe(_addedHeader.Value);
|
||||
}
|
||||
|
||||
private void ThenTheHeaderGetsTakenOverToTheRequestHeaders(string expected)
|
||||
{
|
||||
var requestHeaders = _context.Request.Headers;
|
||||
var value = requestHeaders[_addedHeader.Key];
|
||||
value.ToString().ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ namespace Ocelot.UnitTests.Headers
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Authorisation.Middleware;
|
||||
using Ocelot.Authorization.Middleware;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
@ -38,7 +38,7 @@ namespace Ocelot.UnitTests.Headers
|
||||
_postReplacer = new Mock<IHttpResponseHeaderReplacer>();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<AuthorisationMiddleware>()).Returns(_logger.Object);
|
||||
_loggerFactory.Setup(x => x.CreateLogger<AuthorizationMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_addHeadersToResponse = new Mock<IAddHeadersToResponse>();
|
||||
_addHeadersToRequest = new Mock<IAddHeadersToRequest>();
|
||||
|
@ -1,88 +1,88 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Infrastructure
|
||||
{
|
||||
public class HttpDataRepositoryTests
|
||||
{
|
||||
private readonly HttpContext _httpContext;
|
||||
private IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly HttpDataRepository _httpDataRepository;
|
||||
private object _result;
|
||||
|
||||
public HttpDataRepositoryTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_httpContextAccessor = new HttpContextAccessor { HttpContext = _httpContext };
|
||||
_httpDataRepository = new HttpDataRepository(_httpContextAccessor);
|
||||
}
|
||||
|
||||
/*
|
||||
TODO - Additional tests -> Type mistmatch aka Add string, request int
|
||||
TODO - Additional tests -> HttpContent null. This should never happen
|
||||
*/
|
||||
|
||||
[Fact]
|
||||
public void get_returns_correct_key_from_http_context()
|
||||
{
|
||||
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
||||
.When(x => x.GetIsCalledWithKey<string>("key"))
|
||||
.Then(x => x.ThenTheResultIsAnOkResponse<string>("string"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void get_returns_error_response_if_the_key_is_not_found() //Therefore does not return null
|
||||
{
|
||||
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
||||
.When(x => x.GetIsCalledWithKey<string>("keyDoesNotExist"))
|
||||
.Then(x => x.ThenTheResultIsAnErrorReposnse<string>("string1"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_update()
|
||||
{
|
||||
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
||||
.And(x => x.UpdateIsCalledWith<string>("key", "new string"))
|
||||
.When(x => x.GetIsCalledWithKey<string>("key"))
|
||||
.Then(x => x.ThenTheResultIsAnOkResponse<string>("new string"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void UpdateIsCalledWith<T>(string key, string value)
|
||||
{
|
||||
_httpDataRepository.Update(key, value);
|
||||
}
|
||||
|
||||
private void GivenAHttpContextContaining(string key, object o)
|
||||
{
|
||||
_httpContext.Items.Add(key, o);
|
||||
}
|
||||
|
||||
private void GetIsCalledWithKey<T>(string key)
|
||||
{
|
||||
_result = _httpDataRepository.Get<T>(key);
|
||||
}
|
||||
|
||||
private void ThenTheResultIsAnErrorReposnse<T>(object resultValue)
|
||||
{
|
||||
_result.ShouldBeOfType<ErrorResponse<T>>();
|
||||
((ErrorResponse<T>)_result).Data.ShouldBeNull();
|
||||
((ErrorResponse<T>)_result).IsError.ShouldBe(true);
|
||||
((ErrorResponse<T>)_result).Errors.ShouldHaveSingleItem()
|
||||
.ShouldBeOfType<CannotFindDataError>()
|
||||
.Message.ShouldStartWith("Unable to find data for key: ");
|
||||
}
|
||||
|
||||
private void ThenTheResultIsAnOkResponse<T>(object resultValue)
|
||||
{
|
||||
_result.ShouldBeOfType<OkResponse<T>>();
|
||||
((OkResponse<T>)_result).Data.ShouldBe(resultValue);
|
||||
}
|
||||
}
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Infrastructure
|
||||
{
|
||||
public class HttpDataRepositoryTests
|
||||
{
|
||||
private readonly HttpContext _httpContext;
|
||||
private IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly HttpDataRepository _httpDataRepository;
|
||||
private object _result;
|
||||
|
||||
public HttpDataRepositoryTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_httpContextAccessor = new HttpContextAccessor { HttpContext = _httpContext };
|
||||
_httpDataRepository = new HttpDataRepository(_httpContextAccessor);
|
||||
}
|
||||
|
||||
/*
|
||||
TODO - Additional tests -> Type mistmatch aka Add string, request int
|
||||
TODO - Additional tests -> HttpContent null. This should never happen
|
||||
*/
|
||||
|
||||
[Fact]
|
||||
public void get_returns_correct_key_from_http_context()
|
||||
{
|
||||
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
||||
.When(x => x.GetIsCalledWithKey<string>("key"))
|
||||
.Then(x => x.ThenTheResultIsAnOkResponse<string>("string"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void get_returns_error_response_if_the_key_is_not_found() //Therefore does not return null
|
||||
{
|
||||
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
||||
.When(x => x.GetIsCalledWithKey<string>("keyDoesNotExist"))
|
||||
.Then(x => x.ThenTheResultIsAnErrorReposnse<string>("string1"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_update()
|
||||
{
|
||||
this.Given(x => x.GivenAHttpContextContaining("key", "string"))
|
||||
.And(x => x.UpdateIsCalledWith<string>("key", "new string"))
|
||||
.When(x => x.GetIsCalledWithKey<string>("key"))
|
||||
.Then(x => x.ThenTheResultIsAnOkResponse<string>("new string"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void UpdateIsCalledWith<T>(string key, string value)
|
||||
{
|
||||
_httpDataRepository.Update(key, value);
|
||||
}
|
||||
|
||||
private void GivenAHttpContextContaining(string key, object o)
|
||||
{
|
||||
_httpContext.Items.Add(key, o);
|
||||
}
|
||||
|
||||
private void GetIsCalledWithKey<T>(string key)
|
||||
{
|
||||
_result = _httpDataRepository.Get<T>(key);
|
||||
}
|
||||
|
||||
private void ThenTheResultIsAnErrorReposnse<T>(object resultValue)
|
||||
{
|
||||
_result.ShouldBeOfType<ErrorResponse<T>>();
|
||||
((ErrorResponse<T>)_result).Data.ShouldBe(default(T));
|
||||
((ErrorResponse<T>)_result).IsError.ShouldBe(true);
|
||||
((ErrorResponse<T>)_result).Errors.ShouldHaveSingleItem()
|
||||
.ShouldBeOfType<CannotFindDataError>()
|
||||
.Message.ShouldStartWith("Unable to find data for key: ");
|
||||
}
|
||||
|
||||
private void ThenTheResultIsAnOkResponse<T>(object resultValue)
|
||||
{
|
||||
_result.ShouldBeOfType<OkResponse<T>>();
|
||||
((OkResponse<T>)_result).Data.ShouldBe(resultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
using Moq;
|
||||
using Ocelot.Authorisation;
|
||||
using Ocelot.Authorization;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Infrastructure.Claims.Parser;
|
||||
using Ocelot.Responses;
|
||||
@ -11,18 +11,18 @@ using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Infrastructure
|
||||
{
|
||||
public class ScopesAuthoriserTests
|
||||
public class ScopesAuthorizerTests
|
||||
{
|
||||
private ScopesAuthoriser _authoriser;
|
||||
private ScopesAuthorizer _authorizer;
|
||||
public Mock<IClaimsParser> _parser;
|
||||
private ClaimsPrincipal _principal;
|
||||
private List<string> _allowedScopes;
|
||||
private Response<bool> _result;
|
||||
|
||||
public ScopesAuthoriserTests()
|
||||
public ScopesAuthorizerTests()
|
||||
{
|
||||
_parser = new Mock<IClaimsParser>();
|
||||
_authoriser = new ScopesAuthoriser(_parser.Object);
|
||||
_authorizer = new ScopesAuthorizer(_parser.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -30,7 +30,7 @@ namespace Ocelot.UnitTests.Infrastructure
|
||||
{
|
||||
this.Given(_ => GivenTheFollowing(new ClaimsPrincipal()))
|
||||
.And(_ => GivenTheFollowing(new List<string>()))
|
||||
.When(_ => WhenIAuthorise())
|
||||
.When(_ => WhenIAuthorize())
|
||||
.Then(_ => ThenTheFollowingIsReturned(new OkResponse<bool>(true)))
|
||||
.BDDfy();
|
||||
}
|
||||
@ -40,7 +40,7 @@ namespace Ocelot.UnitTests.Infrastructure
|
||||
{
|
||||
this.Given(_ => GivenTheFollowing(new ClaimsPrincipal()))
|
||||
.And(_ => GivenTheFollowing((List<string>)null))
|
||||
.When(_ => WhenIAuthorise())
|
||||
.When(_ => WhenIAuthorize())
|
||||
.Then(_ => ThenTheFollowingIsReturned(new OkResponse<bool>(true)))
|
||||
.BDDfy();
|
||||
}
|
||||
@ -52,7 +52,7 @@ namespace Ocelot.UnitTests.Infrastructure
|
||||
this.Given(_ => GivenTheFollowing(new ClaimsPrincipal()))
|
||||
.And(_ => GivenTheParserReturns(new ErrorResponse<List<string>>(fakeError)))
|
||||
.And(_ => GivenTheFollowing(new List<string>() { "doesntmatter" }))
|
||||
.When(_ => WhenIAuthorise())
|
||||
.When(_ => WhenIAuthorize())
|
||||
.Then(_ => ThenTheFollowingIsReturned(new ErrorResponse<bool>(fakeError)))
|
||||
.BDDfy();
|
||||
}
|
||||
@ -66,7 +66,7 @@ namespace Ocelot.UnitTests.Infrastructure
|
||||
this.Given(_ => GivenTheFollowing(claimsPrincipal))
|
||||
.And(_ => GivenTheParserReturns(new OkResponse<List<string>>(allowedScopes)))
|
||||
.And(_ => GivenTheFollowing(allowedScopes))
|
||||
.When(_ => WhenIAuthorise())
|
||||
.When(_ => WhenIAuthorize())
|
||||
.Then(_ => ThenTheFollowingIsReturned(new OkResponse<bool>(true)))
|
||||
.BDDfy();
|
||||
}
|
||||
@ -82,7 +82,7 @@ namespace Ocelot.UnitTests.Infrastructure
|
||||
this.Given(_ => GivenTheFollowing(claimsPrincipal))
|
||||
.And(_ => GivenTheParserReturns(new OkResponse<List<string>>(userScopes)))
|
||||
.And(_ => GivenTheFollowing(allowedScopes))
|
||||
.When(_ => WhenIAuthorise())
|
||||
.When(_ => WhenIAuthorize())
|
||||
.Then(_ => ThenTheFollowingIsReturned(new ErrorResponse<bool>(fakeError)))
|
||||
.BDDfy();
|
||||
}
|
||||
@ -102,9 +102,9 @@ namespace Ocelot.UnitTests.Infrastructure
|
||||
_allowedScopes = allowedScopes;
|
||||
}
|
||||
|
||||
private void WhenIAuthorise()
|
||||
private void WhenIAuthorize()
|
||||
{
|
||||
_result = _authoriser.Authorise(_principal, _allowedScopes);
|
||||
_result = _authorizer.Authorize(_principal, _allowedScopes);
|
||||
}
|
||||
|
||||
private void ThenTheFollowingIsReturned(Response<bool> expected)
|
@ -1,149 +1,154 @@
|
||||
using KubeClient;
|
||||
using KubeClient.Models;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Provider.Kubernetes;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Kubernetes
|
||||
{
|
||||
public class KubeServiceDiscoveryProviderTests : IDisposable
|
||||
{
|
||||
private IWebHost _fakeKubeBuilder;
|
||||
private readonly KubernetesServiceDiscoveryProvider _provider;
|
||||
private EndpointsV1 _endpointEntries;
|
||||
private readonly string _serviceName;
|
||||
private readonly string _namespaces;
|
||||
private readonly int _port;
|
||||
private readonly string _kubeHost;
|
||||
private readonly string _fakekubeServiceDiscoveryUrl;
|
||||
private List<Service> _services;
|
||||
private readonly Mock<IOcelotLoggerFactory> _factory;
|
||||
private readonly Mock<IOcelotLogger> _logger;
|
||||
private string _receivedToken;
|
||||
private readonly IKubeApiClient _clientFactory;
|
||||
|
||||
public KubeServiceDiscoveryProviderTests()
|
||||
{
|
||||
_serviceName = "test";
|
||||
_namespaces = "dev";
|
||||
_port = 86;
|
||||
_kubeHost = "localhost";
|
||||
_fakekubeServiceDiscoveryUrl = $"http://{_kubeHost}:{_port}";
|
||||
_endpointEntries = new EndpointsV1();
|
||||
_factory = new Mock<IOcelotLoggerFactory>();
|
||||
|
||||
var option = new KubeClientOptions
|
||||
{
|
||||
ApiEndPoint = new Uri(_fakekubeServiceDiscoveryUrl),
|
||||
AccessToken = "txpc696iUhbVoudg164r93CxDTrKRVWG",
|
||||
AuthStrategy = KubeClient.KubeAuthStrategy.BearerToken,
|
||||
AllowInsecure = true,
|
||||
};
|
||||
|
||||
_clientFactory = KubeApiClient.Create(option);
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_factory.Setup(x => x.CreateLogger<KubernetesServiceDiscoveryProvider>()).Returns(_logger.Object);
|
||||
var config = new KubeRegistryConfiguration()
|
||||
{
|
||||
KeyOfServiceInK8s = _serviceName,
|
||||
KubeNamespace = _namespaces,
|
||||
};
|
||||
_provider = new KubernetesServiceDiscoveryProvider(config, _factory.Object, _clientFactory);
|
||||
using KubeClient;
|
||||
using KubeClient.Models;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Provider.Kubernetes;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Kubernetes
|
||||
{
|
||||
public class KubeServiceDiscoveryProviderTests : IDisposable
|
||||
{
|
||||
private IWebHost _fakeKubeBuilder;
|
||||
private readonly KubernetesServiceDiscoveryProvider _provider;
|
||||
private EndpointsV1 _endpointEntries;
|
||||
private readonly string _serviceName;
|
||||
private readonly string _namespaces;
|
||||
private readonly int _port;
|
||||
private readonly string _kubeHost;
|
||||
private readonly string _fakekubeServiceDiscoveryUrl;
|
||||
private List<Service> _services;
|
||||
private readonly Mock<IOcelotLoggerFactory> _factory;
|
||||
private readonly Mock<IOcelotLogger> _logger;
|
||||
private string _receivedToken;
|
||||
private readonly IKubeApiClient _clientFactory;
|
||||
|
||||
public KubeServiceDiscoveryProviderTests()
|
||||
{
|
||||
_serviceName = "test";
|
||||
_namespaces = "dev";
|
||||
_port = 86;
|
||||
_kubeHost = "localhost";
|
||||
_fakekubeServiceDiscoveryUrl = $"http://{_kubeHost}:{_port}";
|
||||
_endpointEntries = new EndpointsV1();
|
||||
_factory = new Mock<IOcelotLoggerFactory>();
|
||||
|
||||
var option = new KubeClientOptions
|
||||
{
|
||||
ApiEndPoint = new Uri(_fakekubeServiceDiscoveryUrl),
|
||||
AccessToken = "txpc696iUhbVoudg164r93CxDTrKRVWG",
|
||||
AuthStrategy = KubeClient.KubeAuthStrategy.BearerToken,
|
||||
AllowInsecure = true,
|
||||
};
|
||||
|
||||
_clientFactory = KubeApiClient.Create(option);
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_factory.Setup(x => x.CreateLogger<KubernetesServiceDiscoveryProvider>()).Returns(_logger.Object);
|
||||
var config = new KubeRegistryConfiguration()
|
||||
{
|
||||
KeyOfServiceInK8s = _serviceName,
|
||||
KubeNamespace = _namespaces,
|
||||
};
|
||||
_provider = new KubernetesServiceDiscoveryProvider(config, _factory.Object, _clientFactory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_service_from_k8s()
|
||||
{
|
||||
var token = "Bearer txpc696iUhbVoudg164r93CxDTrKRVWG";
|
||||
var endPointEntryOne = new EndpointsV1
|
||||
{
|
||||
Kind = "endpoint",
|
||||
ApiVersion = "1.0",
|
||||
Metadata = new ObjectMetaV1()
|
||||
{
|
||||
Namespace = "dev",
|
||||
},
|
||||
};
|
||||
var endpointSubsetV1 = new EndpointSubsetV1();
|
||||
endpointSubsetV1.Addresses.Add(new EndpointAddressV1()
|
||||
{
|
||||
Ip = "127.0.0.1",
|
||||
Hostname = "localhost",
|
||||
});
|
||||
endpointSubsetV1.Ports.Add(new EndpointPortV1()
|
||||
{
|
||||
Port = 80,
|
||||
});
|
||||
endPointEntryOne.Subsets.Add(endpointSubsetV1);
|
||||
|
||||
this.Given(x => GivenThereIsAFakeKubeServiceDiscoveryProvider(_fakekubeServiceDiscoveryUrl, _serviceName, _namespaces))
|
||||
.And(x => GivenTheServicesAreRegisteredWithKube(endPointEntryOne))
|
||||
.When(x => WhenIGetTheServices())
|
||||
.Then(x => ThenTheCountIs(1))
|
||||
.And(_ => ThenTheTokenIs(token))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_service_from_k8s()
|
||||
private void ThenTheTokenIs(string token)
|
||||
{
|
||||
var token = "Bearer txpc696iUhbVoudg164r93CxDTrKRVWG";
|
||||
var endPointEntryOne = new EndpointsV1
|
||||
{
|
||||
Kind = "endpoint",
|
||||
ApiVersion = "1.0",
|
||||
Metadata = new ObjectMetaV1()
|
||||
{
|
||||
Namespace = "dev",
|
||||
},
|
||||
};
|
||||
var endpointSubsetV1 = new EndpointSubsetV1();
|
||||
endpointSubsetV1.Addresses.Add(new EndpointAddressV1()
|
||||
{
|
||||
Ip = "127.0.0.1",
|
||||
Hostname = "localhost",
|
||||
});
|
||||
endpointSubsetV1.Ports.Add(new EndpointPortV1()
|
||||
{
|
||||
Port = 80,
|
||||
});
|
||||
endPointEntryOne.Subsets.Add(endpointSubsetV1);
|
||||
|
||||
this.Given(x => GivenThereIsAFakeKubeServiceDiscoveryProvider(_fakekubeServiceDiscoveryUrl, _serviceName, _namespaces))
|
||||
.And(x => GivenTheServicesAreRegisteredWithKube(endPointEntryOne))
|
||||
.When(x => WhenIGetTheServices())
|
||||
.Then(x => ThenTheCountIs(1))
|
||||
.And(_ => _receivedToken.ShouldBe(token))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenTheCountIs(int count)
|
||||
{
|
||||
_services.Count.ShouldBe(count);
|
||||
}
|
||||
|
||||
private void WhenIGetTheServices()
|
||||
{
|
||||
_services = _provider.Get().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheServicesAreRegisteredWithKube(EndpointsV1 endpointEntries)
|
||||
{
|
||||
_endpointEntries = endpointEntries;
|
||||
}
|
||||
|
||||
private void GivenThereIsAFakeKubeServiceDiscoveryProvider(string url, string serviceName, string namespaces)
|
||||
{
|
||||
_fakeKubeBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.Configure(app =>
|
||||
{
|
||||
app.Run(async context =>
|
||||
{
|
||||
if (context.Request.Path.Value == $"/api/v1/namespaces/{namespaces}/endpoints/{serviceName}")
|
||||
{
|
||||
if (context.Request.Headers.TryGetValue("Authorization", out var values))
|
||||
{
|
||||
_receivedToken = values.First();
|
||||
}
|
||||
|
||||
var json = JsonConvert.SerializeObject(_endpointEntries);
|
||||
context.Response.Headers.Add("Content-Type", "application/json");
|
||||
await context.Response.WriteAsync(json);
|
||||
}
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
_fakeKubeBuilder.Start();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_fakeKubeBuilder?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
_receivedToken.ShouldBe(token);
|
||||
}
|
||||
|
||||
private void ThenTheCountIs(int count)
|
||||
{
|
||||
_services.Count.ShouldBe(count);
|
||||
}
|
||||
|
||||
private void WhenIGetTheServices()
|
||||
{
|
||||
_services = _provider.Get().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheServicesAreRegisteredWithKube(EndpointsV1 endpointEntries)
|
||||
{
|
||||
_endpointEntries = endpointEntries;
|
||||
}
|
||||
|
||||
private void GivenThereIsAFakeKubeServiceDiscoveryProvider(string url, string serviceName, string namespaces)
|
||||
{
|
||||
_fakeKubeBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.Configure(app =>
|
||||
{
|
||||
app.Run(async context =>
|
||||
{
|
||||
if (context.Request.Path.Value == $"/api/v1/namespaces/{namespaces}/endpoints/{serviceName}")
|
||||
{
|
||||
if (context.Request.Headers.TryGetValue("Authorization", out var values))
|
||||
{
|
||||
_receivedToken = values.First();
|
||||
}
|
||||
|
||||
var json = JsonConvert.SerializeObject(_endpointEntries);
|
||||
context.Response.Headers.Add("Content-Type", "application/json");
|
||||
await context.Response.WriteAsync(json);
|
||||
}
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
_fakeKubeBuilder.Start();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_fakeKubeBuilder?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,97 +1,95 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<AssemblyName>Ocelot.UnitTests</AssemblyName>
|
||||
<PackageId>Ocelot.UnitTests</PackageId>
|
||||
<OutputType>Exe</OutputType>
|
||||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||
<RuntimeIdentifiers>osx.10.11-x64;osx.10.12-x64;win7-x64;win10-x64</RuntimeIdentifiers>
|
||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
|
||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DebugType>full</DebugType>
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Kubernetes\KubeProviderFactoryTests.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Kubernetes\Ocelot.Provider.Kubernetes.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Administration\Ocelot.Administration.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Cache.CacheManager\Ocelot.Cache.CacheManager.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Consul\Ocelot.Provider.Consul.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Eureka\Ocelot.Provider.Eureka.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Polly\Ocelot.Provider.Polly.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Rafty\Ocelot.Provider.Rafty.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Tracing.Butterfly\Ocelot.Tracing.Butterfly.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="idsrv3test.pfx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.1" />
|
||||
<PackageReference Include="Moq" Version="4.13.1" />
|
||||
<PackageReference Include="Shouldly" Version="4.0.0-beta0002" />
|
||||
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
|
||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
|
||||
<PackageReference Include="IdentityServer4" Version="3.1.1" />
|
||||
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="2.4.2" />
|
||||
<PackageReference Include="Consul" Version="0.7.2.6" />
|
||||
<PackageReference Include="CacheManager.Core" Version="2.0.0-beta-1629" />
|
||||
<PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="2.0.0-beta-1629" />
|
||||
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="2.0.0-beta-1629" />
|
||||
<PackageReference Include="Polly" Version="7.2.0" />
|
||||
<PackageReference Include="Rafty" Version="0.4.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="WebSockets\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.2.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AssemblyName>Ocelot.UnitTests</AssemblyName>
|
||||
<PackageId>Ocelot.UnitTests</PackageId>
|
||||
<OutputType>Exe</OutputType>
|
||||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||
<RuntimeIdentifiers>osx.10.11-x64;osx.10.12-x64;win7-x64;win10-x64</RuntimeIdentifiers>
|
||||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
|
||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DebugType>full</DebugType>
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Kubernetes\KubeProviderFactoryTests.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Kubernetes\Ocelot.Provider.Kubernetes.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Administration\Ocelot.Administration.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Cache.CacheManager\Ocelot.Cache.CacheManager.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Consul\Ocelot.Provider.Consul.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Eureka\Ocelot.Provider.Eureka.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Polly\Ocelot.Provider.Polly.csproj" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Tracing.Butterfly\Ocelot.Tracing.Butterfly.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="idsrv3test.pfx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
||||
<PackageReference Include="Moq" Version="4.15.2" />
|
||||
<PackageReference Include="Shouldly" Version="4.0.1" />
|
||||
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
|
||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
|
||||
<PackageReference Include="IdentityServer4" Version="4.1.1" />
|
||||
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="3.0.1" />
|
||||
<PackageReference Include="Consul" Version="1.6.1.1" />
|
||||
<PackageReference Include="CacheManager.Core" Version="2.0.0-beta-1629" />
|
||||
<PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="2.0.0-beta-1629" />
|
||||
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="2.0.0-beta-1629" />
|
||||
<PackageReference Include="Polly" Version="7.2.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="WebSockets\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -1,89 +0,0 @@
|
||||
namespace Ocelot.UnitTests.Rafty
|
||||
{
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Moq;
|
||||
using Ocelot.Administration;
|
||||
using Ocelot.DependencyInjection;
|
||||
using Provider.Rafty;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class OcelotAdministrationBuilderExtensionsTests
|
||||
{
|
||||
private readonly IServiceCollection _services;
|
||||
private IServiceProvider _serviceProvider;
|
||||
private readonly IConfiguration _configRoot;
|
||||
private IOcelotBuilder _ocelotBuilder;
|
||||
private Exception _ex;
|
||||
|
||||
public OcelotAdministrationBuilderExtensionsTests()
|
||||
{
|
||||
_configRoot = new ConfigurationRoot(new List<IConfigurationProvider>());
|
||||
_services = new ServiceCollection();
|
||||
_services.AddSingleton<IWebHostEnvironment>(GetHostingEnvironment());
|
||||
_services.AddSingleton(_configRoot);
|
||||
}
|
||||
|
||||
private IWebHostEnvironment GetHostingEnvironment()
|
||||
{
|
||||
var environment = new Mock<IWebHostEnvironment>();
|
||||
environment
|
||||
.Setup(e => e.ApplicationName)
|
||||
.Returns(typeof(OcelotAdministrationBuilderExtensionsTests).GetTypeInfo().Assembly.GetName().Name);
|
||||
|
||||
return environment.Object;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_up_rafty()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => WhenISetUpRafty())
|
||||
.Then(x => ThenAnExceptionIsntThrown())
|
||||
.Then(x => ThenTheCorrectAdminPathIsRegitered())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenISetUpRafty()
|
||||
{
|
||||
try
|
||||
{
|
||||
_ocelotBuilder.AddAdministration("/administration", "secret").AddRafty();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_ex = e;
|
||||
}
|
||||
}
|
||||
|
||||
private void WhenISetUpOcelotServices()
|
||||
{
|
||||
try
|
||||
{
|
||||
_ocelotBuilder = _services.AddOcelot(_configRoot);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_ex = e;
|
||||
}
|
||||
}
|
||||
|
||||
private void ThenAnExceptionIsntThrown()
|
||||
{
|
||||
_ex.ShouldBeNull();
|
||||
}
|
||||
|
||||
private void ThenTheCorrectAdminPathIsRegitered()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var path = _serviceProvider.GetService<IAdministrationPath>();
|
||||
path.Path.ShouldBe("/administration");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
namespace Ocelot.UnitTests.Rafty
|
||||
{
|
||||
using Moq;
|
||||
using Ocelot.Configuration.Setter;
|
||||
using Provider.Rafty;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class OcelotFiniteStateMachineTests
|
||||
{
|
||||
private UpdateFileConfiguration _command;
|
||||
private readonly OcelotFiniteStateMachine _fsm;
|
||||
private readonly Mock<IFileConfigurationSetter> _setter;
|
||||
|
||||
public OcelotFiniteStateMachineTests()
|
||||
{
|
||||
_setter = new Mock<IFileConfigurationSetter>();
|
||||
_fsm = new OcelotFiniteStateMachine(_setter.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_handle_update_file_configuration_command()
|
||||
{
|
||||
this.Given(x => GivenACommand(new UpdateFileConfiguration(new Ocelot.Configuration.File.FileConfiguration())))
|
||||
.When(x => WhenTheCommandIsHandled())
|
||||
.Then(x => ThenTheStateIsUpdated())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenACommand(UpdateFileConfiguration command)
|
||||
{
|
||||
_command = command;
|
||||
}
|
||||
|
||||
private void WhenTheCommandIsHandled()
|
||||
{
|
||||
_fsm.Handle(new global::Rafty.Log.LogEntry(_command, _command.GetType(), 0)).Wait();
|
||||
}
|
||||
|
||||
private void ThenTheStateIsUpdated()
|
||||
{
|
||||
_setter.Verify(x => x.Set(_command.Configuration), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
namespace Ocelot.UnitTests.Rafty
|
||||
{
|
||||
using global::Rafty.Concensus.Node;
|
||||
using global::Rafty.Infrastructure;
|
||||
using Moq;
|
||||
using Ocelot.Configuration.File;
|
||||
using Provider.Rafty;
|
||||
using Shouldly;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
public class RaftyFileConfigurationSetterTests
|
||||
{
|
||||
private readonly RaftyFileConfigurationSetter _setter;
|
||||
private readonly Mock<INode> _node;
|
||||
|
||||
public RaftyFileConfigurationSetterTests()
|
||||
{
|
||||
_node = new Mock<INode>();
|
||||
_setter = new RaftyFileConfigurationSetter(_node.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task should_return_ok()
|
||||
{
|
||||
var fileConfig = new FileConfiguration();
|
||||
|
||||
var response = new OkResponse<UpdateFileConfiguration>(new UpdateFileConfiguration(fileConfig));
|
||||
|
||||
_node.Setup(x => x.Accept(It.IsAny<UpdateFileConfiguration>()))
|
||||
.ReturnsAsync(response);
|
||||
|
||||
var result = await _setter.Set(fileConfig);
|
||||
result.IsError.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task should_return_not_ok()
|
||||
{
|
||||
var fileConfig = new FileConfiguration();
|
||||
|
||||
var response = new ErrorResponse<UpdateFileConfiguration>("error", new UpdateFileConfiguration(fileConfig));
|
||||
|
||||
_node.Setup(x => x.Accept(It.IsAny<UpdateFileConfiguration>()))
|
||||
.ReturnsAsync(response);
|
||||
|
||||
var result = await _setter.Set(fileConfig);
|
||||
|
||||
result.IsError.ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
}
|
@ -452,7 +452,7 @@
|
||||
foreach (var header in _mappedRequest.Data.Headers)
|
||||
{
|
||||
var inputHeader = _inputHeaders.First(h => h.Key == header.Key);
|
||||
inputHeader.ShouldNotBeNull();
|
||||
inputHeader.ShouldNotBe(default(KeyValuePair<string, StringValues>));
|
||||
inputHeader.Value.Count().ShouldBe(header.Value.Count());
|
||||
foreach (var inputHeaderValue in inputHeader.Value)
|
||||
{
|
||||
|
@ -29,10 +29,10 @@ namespace Ocelot.UnitTests.Responder
|
||||
|
||||
[Theory]
|
||||
[InlineData(OcelotErrorCode.CannotFindClaimError)]
|
||||
[InlineData(OcelotErrorCode.ClaimValueNotAuthorisedError)]
|
||||
[InlineData(OcelotErrorCode.ScopeNotAuthorisedError)]
|
||||
[InlineData(OcelotErrorCode.ClaimValueNotAuthorizedError)]
|
||||
[InlineData(OcelotErrorCode.ScopeNotAuthorizedError)]
|
||||
[InlineData(OcelotErrorCode.UnauthorizedError)]
|
||||
[InlineData(OcelotErrorCode.UserDoesNotHaveClaimError)]
|
||||
[InlineData(OcelotErrorCode.UserDoesNotHaveClaimError)]
|
||||
public void should_return_forbidden(OcelotErrorCode errorCode)
|
||||
{
|
||||
ShouldMapErrorToStatusCode(errorCode, HttpStatusCode.Forbidden);
|
||||
@ -52,8 +52,8 @@ namespace Ocelot.UnitTests.Responder
|
||||
public void should_return_internal_server_error(OcelotErrorCode errorCode)
|
||||
{
|
||||
ShouldMapErrorToStatusCode(errorCode, HttpStatusCode.InternalServerError);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(OcelotErrorCode.ConnectionToDownstreamServiceError)]
|
||||
public void should_return_bad_gateway_error(OcelotErrorCode errorCode)
|
||||
@ -104,7 +104,7 @@ namespace Ocelot.UnitTests.Responder
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AuthorisationErrorsHaveSecondHighestPriority()
|
||||
public void AuthorizationErrorsHaveSecondHighestPriority()
|
||||
{
|
||||
var errors = new List<OcelotErrorCode>
|
||||
{
|
||||
@ -177,4 +177,4 @@ namespace Ocelot.UnitTests.Responder
|
||||
_result.ShouldBe((int)expectedCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<RunSettings>
|
||||
<DataCollectionRunSettings>
|
||||
<DataCollectors>
|
||||
<DataCollector friendlyName="XPlat code coverage">
|
||||
<Configuration>
|
||||
<Format>opencover</Format>
|
||||
<SingleHit>false</SingleHit>
|
||||
<UseSourceLink>true</UseSourceLink>
|
||||
</Configuration>
|
||||
</DataCollector>
|
||||
</DataCollectors>
|
||||
</DataCollectionRunSettings>
|
||||
<!-- This is a workaround for an issue with Coverlet.Collector > 1.0.0 (see https://github.com/microsoft/vstest/issues/2205)-->
|
||||
<InProcDataCollectionRunSettings>
|
||||
<InProcDataCollectors>
|
||||
<InProcDataCollector assemblyQualifiedName="Coverlet.Collector.DataCollection.CoverletInProcDataCollector, coverlet.collector, Version=1.1.0.0, Culture=neutral, PublicKeyToken=null"
|
||||
friendlyName="XPlat Code Coverage"
|
||||
enabled="True"
|
||||
codebase="coverlet.collector.dll" />
|
||||
</InProcDataCollectors>
|
||||
</InProcDataCollectionRunSettings>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<RunSettings>
|
||||
<DataCollectionRunSettings>
|
||||
<DataCollectors>
|
||||
<DataCollector friendlyName="XPlat code coverage">
|
||||
<Configuration>
|
||||
<Format>opencover</Format>
|
||||
<SingleHit>false</SingleHit>
|
||||
<UseSourceLink>true</UseSourceLink>
|
||||
</Configuration>
|
||||
</DataCollector>
|
||||
</DataCollectors>
|
||||
</DataCollectionRunSettings>
|
||||
<!-- This is a workaround for an issue with Coverlet.Collector > 1.0.0 (see https://github.com/microsoft/vstest/issues/2205)-->
|
||||
<InProcDataCollectionRunSettings>
|
||||
<InProcDataCollectors>
|
||||
<InProcDataCollector assemblyQualifiedName="Coverlet.Collector.DataCollection.CoverletInProcDataCollector, coverlet.collector, Version=1.1.0.0, Culture=neutral, PublicKeyToken=null"
|
||||
friendlyName="XPlat Code Coverage"
|
||||
enabled="True"
|
||||
codebase="coverlet.collector.dll" />
|
||||
</InProcDataCollectors>
|
||||
</InProcDataCollectionRunSettings>
|
||||
</RunSettings>
|
Reference in New Issue
Block a user