+semver: breaking PRs merged from Develop, Eureka honour scheme, don't crash on dispose and validate duplicate placeholders in UpstreamPathTemplate

* initial commit for new feature #1077

allow to limit the number of concurrent tcp connection to a downstream service

* protect code against value not in accurate range

add unit test

* Do not crash host on Dispose

* Add test

* Pin GitVersion.CommandLine package version

* #683 validate if there are duplicated placeholders in UpstreamPathTemplate

* Use registered scheme from Eureka (#1087)

* extra test

* very brief mention MaxConnectionsPerServer in docs

* build develop like a PR

* more docs

Co-authored-by: jlukawska <56401969+jlukawska@users.noreply.github.com>
Co-authored-by: buretjph <58700930+buretjph@users.noreply.github.com>
Co-authored-by: Jonathan Mezach <jonathanmezach@gmail.com>
Co-authored-by: 彭伟 <pengweiqhca@sina.com>
This commit is contained in:
Tom Pallister 2020-01-19 15:00:21 +00:00 committed by GitHub
parent 664c6ef626
commit 65710f4a94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 792 additions and 560 deletions

View File

@ -27,4 +27,3 @@ workflows:
branches: branches:
ignore: ignore:
- master - master
- develop

View File

@ -1,500 +1,500 @@
#tool "nuget:?package=GitVersion.CommandLine&version=5.0.1" #tool "nuget:?package=GitVersion.CommandLine&version=5.0.1"
#tool "nuget:?package=GitReleaseNotes" #tool "nuget:?package=GitReleaseNotes"
#addin nuget:?package=Cake.Json #addin nuget:?package=Cake.Json
#addin nuget:?package=Newtonsoft.Json #addin nuget:?package=Newtonsoft.Json
#addin nuget:?package=System.Net.Http #addin nuget:?package=System.Net.Http
#tool "nuget:?package=ReportGenerator" #tool "nuget:?package=ReportGenerator"
#tool "nuget:?package=coveralls.net&version=0.7.0" #tool "nuget:?package=coveralls.net&version=0.7.0"
#addin Cake.Coveralls&version=0.10.1 #addin Cake.Coveralls&version=0.10.1
// compile // compile
var compileConfig = Argument("configuration", "Release"); var compileConfig = Argument("configuration", "Release");
var slnFile = "./Ocelot.sln"; var slnFile = "./Ocelot.sln";
// build artifacts // build artifacts
var artifactsDir = Directory("artifacts"); var artifactsDir = Directory("artifacts");
// unit testing // unit testing
var artifactsForUnitTestsDir = artifactsDir + Directory("UnitTests"); var artifactsForUnitTestsDir = artifactsDir + Directory("UnitTests");
var unitTestAssemblies = @"./test/Ocelot.UnitTests/Ocelot.UnitTests.csproj"; var unitTestAssemblies = @"./test/Ocelot.UnitTests/Ocelot.UnitTests.csproj";
var minCodeCoverage = 80d; var minCodeCoverage = 80d;
var coverallsRepoToken = "OCELOT_COVERALLS_TOKEN"; var coverallsRepoToken = "OCELOT_COVERALLS_TOKEN";
var coverallsRepo = "https://coveralls.io/github/ThreeMammals/Ocelot"; var coverallsRepo = "https://coveralls.io/github/ThreeMammals/Ocelot";
// acceptance testing // acceptance testing
var artifactsForAcceptanceTestsDir = artifactsDir + Directory("AcceptanceTests"); var artifactsForAcceptanceTestsDir = artifactsDir + Directory("AcceptanceTests");
var acceptanceTestAssemblies = @"./test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj"; var acceptanceTestAssemblies = @"./test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj";
// integration testing // integration testing
var artifactsForIntegrationTestsDir = artifactsDir + Directory("IntegrationTests"); var artifactsForIntegrationTestsDir = artifactsDir + Directory("IntegrationTests");
var integrationTestAssemblies = @"./test/Ocelot.IntegrationTests/Ocelot.IntegrationTests.csproj"; var integrationTestAssemblies = @"./test/Ocelot.IntegrationTests/Ocelot.IntegrationTests.csproj";
// benchmark testing // benchmark testing
var artifactsForBenchmarkTestsDir = artifactsDir + Directory("BenchmarkTests"); var artifactsForBenchmarkTestsDir = artifactsDir + Directory("BenchmarkTests");
var benchmarkTestAssemblies = @"./test/Ocelot.Benchmarks"; var benchmarkTestAssemblies = @"./test/Ocelot.Benchmarks";
// packaging // packaging
var packagesDir = artifactsDir + Directory("Packages"); var packagesDir = artifactsDir + Directory("Packages");
var releaseNotesFile = packagesDir + File("releasenotes.md"); var releaseNotesFile = packagesDir + File("releasenotes.md");
var artifactsFile = packagesDir + File("artifacts.txt"); var artifactsFile = packagesDir + File("artifacts.txt");
// stable releases // stable releases
var tagsUrl = "https://api.github.com/repos/ThreeMammals/ocelot/releases/tags/"; var tagsUrl = "https://api.github.com/repos/ThreeMammals/ocelot/releases/tags/";
var nugetFeedStableKey = EnvironmentVariable("OCELOT_NUTGET_API_KEY"); var nugetFeedStableKey = EnvironmentVariable("OCELOT_NUTGET_API_KEY");
var nugetFeedStableUploadUrl = "https://www.nuget.org/api/v2/package"; var nugetFeedStableUploadUrl = "https://www.nuget.org/api/v2/package";
var nugetFeedStableSymbolsUploadUrl = "https://www.nuget.org/api/v2/package"; var nugetFeedStableSymbolsUploadUrl = "https://www.nuget.org/api/v2/package";
// internal build variables - don't change these. // internal build variables - don't change these.
string committedVersion = "0.0.0-dev"; string committedVersion = "0.0.0-dev";
GitVersion versioning = null; GitVersion versioning = null;
int releaseId = 0; int releaseId = 0;
string gitHubUsername = "TomPallister"; string gitHubUsername = "TomPallister";
string gitHubPassword = Environment.GetEnvironmentVariable("OCELOT_GITHUB_API_KEY"); string gitHubPassword = Environment.GetEnvironmentVariable("OCELOT_GITHUB_API_KEY");
var target = Argument("target", "Default"); var target = Argument("target", "Default");
Information("target is " + target); Information("target is " + target);
Information("Build configuration is " + compileConfig); Information("Build configuration is " + compileConfig);
Task("Default") Task("Default")
.IsDependentOn("Build"); .IsDependentOn("Build");
Task("Build") Task("Build")
.IsDependentOn("RunTests"); .IsDependentOn("RunTests");
Task("RunTests") Task("RunTests")
.IsDependentOn("RunUnitTests") .IsDependentOn("RunUnitTests")
.IsDependentOn("RunAcceptanceTests") .IsDependentOn("RunAcceptanceTests")
.IsDependentOn("RunIntegrationTests"); .IsDependentOn("RunIntegrationTests");
Task("Release") Task("Release")
.IsDependentOn("Build") .IsDependentOn("Build")
.IsDependentOn("CreateArtifacts") .IsDependentOn("CreateArtifacts")
.IsDependentOn("PublishGitHubRelease") .IsDependentOn("PublishGitHubRelease")
.IsDependentOn("PublishToNuget"); .IsDependentOn("PublishToNuget");
Task("Compile") Task("Compile")
.IsDependentOn("Clean") .IsDependentOn("Clean")
.IsDependentOn("Version") .IsDependentOn("Version")
.Does(() => .Does(() =>
{ {
var settings = new DotNetCoreBuildSettings var settings = new DotNetCoreBuildSettings
{ {
Configuration = compileConfig, Configuration = compileConfig,
}; };
DotNetCoreBuild(slnFile, settings); DotNetCoreBuild(slnFile, settings);
}); });
Task("Clean") Task("Clean")
.Does(() => .Does(() =>
{ {
if (DirectoryExists(artifactsDir)) if (DirectoryExists(artifactsDir))
{ {
DeleteDirectory(artifactsDir, recursive:true); DeleteDirectory(artifactsDir, recursive:true);
} }
CreateDirectory(artifactsDir); CreateDirectory(artifactsDir);
}); });
Task("Version") Task("Version")
.Does(() => .Does(() =>
{ {
versioning = GetNuGetVersionForCommit(); versioning = GetNuGetVersionForCommit();
var nugetVersion = versioning.NuGetVersion; var nugetVersion = versioning.NuGetVersion;
Information("SemVer version number: " + nugetVersion); Information("SemVer version number: " + nugetVersion);
if (IsRunningOnCircleCI()) if (IsRunningOnCircleCI())
{ {
Information("Persisting version number..."); Information("Persisting version number...");
PersistVersion(committedVersion, nugetVersion); PersistVersion(committedVersion, nugetVersion);
} }
else else
{ {
Information("We are not running on build server, so we won't persist the version number."); Information("We are not running on build server, so we won't persist the version number.");
} }
}); });
Task("RunUnitTests") Task("RunUnitTests")
.IsDependentOn("Compile") .IsDependentOn("Compile")
.Does(() => .Does(() =>
{ {
var testSettings = new DotNetCoreTestSettings var testSettings = new DotNetCoreTestSettings
{ {
Configuration = compileConfig, Configuration = compileConfig,
ResultsDirectory = artifactsForUnitTestsDir, ResultsDirectory = artifactsForUnitTestsDir,
ArgumentCustomization = args => args ArgumentCustomization = args => args
// this create the code coverage report // this create the code coverage report
.Append("--settings test/Ocelot.UnitTests/UnitTests.runsettings") .Append("--settings test/Ocelot.UnitTests/UnitTests.runsettings")
}; };
EnsureDirectoryExists(artifactsForUnitTestsDir); EnsureDirectoryExists(artifactsForUnitTestsDir);
DotNetCoreTest(unitTestAssemblies, testSettings); DotNetCoreTest(unitTestAssemblies, testSettings);
var coverageSummaryFile = GetSubDirectories(artifactsForUnitTestsDir).First().CombineWithFilePath(File("coverage.opencover.xml")); var coverageSummaryFile = GetSubDirectories(artifactsForUnitTestsDir).First().CombineWithFilePath(File("coverage.opencover.xml"));
Information(coverageSummaryFile); Information(coverageSummaryFile);
Information(artifactsForUnitTestsDir); Information(artifactsForUnitTestsDir);
// todo bring back report generator to get a friendly report // todo bring back report generator to get a friendly report
// ReportGenerator(coverageSummaryFile, artifactsForUnitTestsDir); // ReportGenerator(coverageSummaryFile, artifactsForUnitTestsDir);
// https://github.com/danielpalme/ReportGenerator // https://github.com/danielpalme/ReportGenerator
if (IsRunningOnCircleCI()) if (IsRunningOnCircleCI())
{ {
var repoToken = EnvironmentVariable(coverallsRepoToken); var repoToken = EnvironmentVariable(coverallsRepoToken);
if (string.IsNullOrEmpty(repoToken)) if (string.IsNullOrEmpty(repoToken))
{ {
throw new Exception(string.Format("Coveralls repo token not found. Set environment variable '{0}'", coverallsRepoToken)); throw new Exception(string.Format("Coveralls repo token not found. Set environment variable '{0}'", coverallsRepoToken));
} }
Information(string.Format("Uploading test coverage to {0}", coverallsRepo)); Information(string.Format("Uploading test coverage to {0}", coverallsRepo));
CoverallsNet(coverageSummaryFile, CoverallsNetReportType.OpenCover, new CoverallsNetSettings() CoverallsNet(coverageSummaryFile, CoverallsNetReportType.OpenCover, new CoverallsNetSettings()
{ {
RepoToken = repoToken RepoToken = repoToken
}); });
} }
else else
{ {
Information("We are not running on the build server so we won't publish the coverage report to coveralls.io"); Information("We are not running on the build server so we won't publish the coverage report to coveralls.io");
} }
var sequenceCoverage = XmlPeek(coverageSummaryFile, "//CoverageSession/Summary/@sequenceCoverage"); var sequenceCoverage = XmlPeek(coverageSummaryFile, "//CoverageSession/Summary/@sequenceCoverage");
var branchCoverage = XmlPeek(coverageSummaryFile, "//CoverageSession/Summary/@branchCoverage"); var branchCoverage = XmlPeek(coverageSummaryFile, "//CoverageSession/Summary/@branchCoverage");
Information("Sequence Coverage: " + sequenceCoverage); Information("Sequence Coverage: " + sequenceCoverage);
if(double.Parse(sequenceCoverage) < minCodeCoverage) if(double.Parse(sequenceCoverage) < minCodeCoverage)
{ {
var whereToCheck = !IsRunningOnCircleCI() ? coverallsRepo : artifactsForUnitTestsDir; var whereToCheck = !IsRunningOnCircleCI() ? coverallsRepo : artifactsForUnitTestsDir;
throw new Exception(string.Format("Code coverage fell below the threshold of {0}%. You can find the code coverage report at {1}", minCodeCoverage, whereToCheck)); throw new Exception(string.Format("Code coverage fell below the threshold of {0}%. You can find the code coverage report at {1}", minCodeCoverage, whereToCheck));
}; };
}); });
Task("RunAcceptanceTests") Task("RunAcceptanceTests")
.IsDependentOn("Compile") .IsDependentOn("Compile")
.Does(() => .Does(() =>
{ {
var settings = new DotNetCoreTestSettings var settings = new DotNetCoreTestSettings
{ {
Configuration = compileConfig, Configuration = compileConfig,
ArgumentCustomization = args => args ArgumentCustomization = args => args
.Append("--no-restore") .Append("--no-restore")
.Append("--no-build") .Append("--no-build")
}; };
EnsureDirectoryExists(artifactsForAcceptanceTestsDir); EnsureDirectoryExists(artifactsForAcceptanceTestsDir);
DotNetCoreTest(acceptanceTestAssemblies, settings); DotNetCoreTest(acceptanceTestAssemblies, settings);
}); });
Task("RunIntegrationTests") Task("RunIntegrationTests")
.IsDependentOn("Compile") .IsDependentOn("Compile")
.Does(() => .Does(() =>
{ {
var settings = new DotNetCoreTestSettings var settings = new DotNetCoreTestSettings
{ {
Configuration = compileConfig, Configuration = compileConfig,
ArgumentCustomization = args => args ArgumentCustomization = args => args
.Append("--no-restore") .Append("--no-restore")
.Append("--no-build") .Append("--no-build")
}; };
EnsureDirectoryExists(artifactsForIntegrationTestsDir); EnsureDirectoryExists(artifactsForIntegrationTestsDir);
DotNetCoreTest(integrationTestAssemblies, settings); DotNetCoreTest(integrationTestAssemblies, settings);
}); });
Task("CreateArtifacts") Task("CreateArtifacts")
.IsDependentOn("Compile") .IsDependentOn("Compile")
.Does(() => .Does(() =>
{ {
EnsureDirectoryExists(packagesDir); EnsureDirectoryExists(packagesDir);
CopyFiles("./src/**/Release/Ocelot.*.nupkg", packagesDir); CopyFiles("./src/**/Release/Ocelot.*.nupkg", packagesDir);
// todo fix this for docker build // todo fix this for docker build
//GenerateReleaseNotes(releaseNotesFile); //GenerateReleaseNotes(releaseNotesFile);
var projectFiles = GetFiles("./src/**/Release/Ocelot.*.nupkg"); var projectFiles = GetFiles("./src/**/Release/Ocelot.*.nupkg");
foreach(var projectFile in projectFiles) foreach(var projectFile in projectFiles)
{ {
System.IO.File.AppendAllLines(artifactsFile, new[]{ System.IO.File.AppendAllLines(artifactsFile, new[]{
projectFile.GetFilename().FullPath, projectFile.GetFilename().FullPath,
// todo fix this for docker build // todo fix this for docker build
//"releaseNotes:releasenotes.md" //"releaseNotes:releasenotes.md"
}); });
} }
var artifacts = System.IO.File var artifacts = System.IO.File
.ReadAllLines(artifactsFile) .ReadAllLines(artifactsFile)
.Distinct(); .Distinct();
foreach(var artifact in artifacts) foreach(var artifact in artifacts)
{ {
var codePackage = packagesDir + File(artifact); var codePackage = packagesDir + File(artifact);
Information("Created package " + codePackage); Information("Created package " + codePackage);
} }
}); });
Task("PublishGitHubRelease") Task("PublishGitHubRelease")
.IsDependentOn("CreateArtifacts") .IsDependentOn("CreateArtifacts")
.Does(() => .Does(() =>
{ {
if (IsRunningOnCircleCI()) if (IsRunningOnCircleCI())
{ {
var path = packagesDir.ToString() + @"/**/*"; var path = packagesDir.ToString() + @"/**/*";
CreateGitHubRelease(); CreateGitHubRelease();
foreach (var file in GetFiles(path)) foreach (var file in GetFiles(path))
{ {
UploadFileToGitHubRelease(file); UploadFileToGitHubRelease(file);
} }
CompleteGitHubRelease(); CompleteGitHubRelease();
} }
}); });
Task("EnsureStableReleaseRequirements") Task("EnsureStableReleaseRequirements")
.Does(() => .Does(() =>
{ {
Information("Check if stable release..."); Information("Check if stable release...");
if (!IsRunningOnCircleCI()) if (!IsRunningOnCircleCI())
{ {
throw new Exception("Stable release should happen via circleci"); throw new Exception("Stable release should happen via circleci");
} }
Information("Release is stable..."); Information("Release is stable...");
}); });
Task("DownloadGitHubReleaseArtifacts") Task("DownloadGitHubReleaseArtifacts")
.Does(() => .Does(() =>
{ {
try try
{ {
EnsureDirectoryExists(packagesDir); EnsureDirectoryExists(packagesDir);
var releaseUrl = tagsUrl + versioning.NuGetVersion; var releaseUrl = tagsUrl + versioning.NuGetVersion;
var assets_url = Newtonsoft.Json.Linq.JObject.Parse(GetResource(releaseUrl)) var assets_url = Newtonsoft.Json.Linq.JObject.Parse(GetResource(releaseUrl))
.Value<string>("assets_url"); .Value<string>("assets_url");
var assets = GetResource(assets_url); var assets = GetResource(assets_url);
foreach(var asset in Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JArray>(assets)) foreach(var asset in Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JArray>(assets))
{ {
var file = packagesDir + File(asset.Value<string>("name")); var file = packagesDir + File(asset.Value<string>("name"));
DownloadFile(asset.Value<string>("browser_download_url"), file); DownloadFile(asset.Value<string>("browser_download_url"), file);
} }
} }
catch(Exception exception) catch(Exception exception)
{ {
Information("There was an exception " + exception); Information("There was an exception " + exception);
throw; throw;
} }
}); });
Task("PublishToNuget") Task("PublishToNuget")
.IsDependentOn("DownloadGitHubReleaseArtifacts") .IsDependentOn("DownloadGitHubReleaseArtifacts")
.Does(() => .Does(() =>
{ {
if (IsRunningOnCircleCI()) if (IsRunningOnCircleCI())
{ {
PublishPackages(packagesDir, artifactsFile, nugetFeedStableKey, nugetFeedStableUploadUrl, nugetFeedStableSymbolsUploadUrl); PublishPackages(packagesDir, artifactsFile, nugetFeedStableKey, nugetFeedStableUploadUrl, nugetFeedStableSymbolsUploadUrl);
} }
}); });
RunTarget(target); RunTarget(target);
/// Gets nuique nuget version for this commit /// Gets nuique nuget version for this commit
private GitVersion GetNuGetVersionForCommit() private GitVersion GetNuGetVersionForCommit()
{ {
GitVersion(new GitVersionSettings{ GitVersion(new GitVersionSettings{
UpdateAssemblyInfo = false, UpdateAssemblyInfo = false,
OutputType = GitVersionOutput.BuildServer OutputType = GitVersionOutput.BuildServer
}); });
return GitVersion(new GitVersionSettings{ OutputType = GitVersionOutput.Json }); return GitVersion(new GitVersionSettings{ OutputType = GitVersionOutput.Json });
} }
/// Updates project version in all of our projects /// Updates project version in all of our projects
private void PersistVersion(string committedVersion, string newVersion) private void PersistVersion(string committedVersion, string newVersion)
{ {
Information(string.Format("We'll search all csproj files for {0} and replace with {1}...", committedVersion, newVersion)); Information(string.Format("We'll search all csproj files for {0} and replace with {1}...", committedVersion, newVersion));
var projectFiles = GetFiles("./**/*.csproj"); var projectFiles = GetFiles("./**/*.csproj");
foreach(var projectFile in projectFiles) foreach(var projectFile in projectFiles)
{ {
var file = projectFile.ToString(); var file = projectFile.ToString();
Information(string.Format("Updating {0}...", file)); Information(string.Format("Updating {0}...", file));
var updatedProjectFile = System.IO.File.ReadAllText(file) var updatedProjectFile = System.IO.File.ReadAllText(file)
.Replace(committedVersion, newVersion); .Replace(committedVersion, newVersion);
System.IO.File.WriteAllText(file, updatedProjectFile); System.IO.File.WriteAllText(file, updatedProjectFile);
} }
} }
/// generates release notes based on issues closed in GitHub since the last release /// generates release notes based on issues closed in GitHub since the last release
private void GenerateReleaseNotes(ConvertableFilePath file) private void GenerateReleaseNotes(ConvertableFilePath file)
{ {
if(!IsRunningOnWindows()) if(!IsRunningOnWindows())
{ {
Warning("We are not running on Windows so we cannot generate release notes."); Warning("We are not running on Windows so we cannot generate release notes.");
return; return;
} }
Information("Generating release notes at " + file); Information("Generating release notes at " + file);
var releaseNotesExitCode = StartProcess( var releaseNotesExitCode = StartProcess(
@"tools/GitReleaseNotes/tools/gitreleasenotes.exe", @"tools/GitReleaseNotes/tools/gitreleasenotes.exe",
new ProcessSettings { Arguments = ". /o " + file }); new ProcessSettings { Arguments = ". /o " + file });
if (string.IsNullOrEmpty(System.IO.File.ReadAllText(file))) if (string.IsNullOrEmpty(System.IO.File.ReadAllText(file)))
{ {
System.IO.File.WriteAllText(file, "No issues closed since last release"); System.IO.File.WriteAllText(file, "No issues closed since last release");
} }
if (releaseNotesExitCode != 0) if (releaseNotesExitCode != 0)
{ {
throw new Exception("Failed to generate release notes"); throw new Exception("Failed to generate release notes");
} }
} }
/// Publishes code and symbols packages to nuget feed, based on contents of artifacts file /// Publishes code and symbols packages to nuget feed, based on contents of artifacts file
private void PublishPackages(ConvertableDirectoryPath packagesDir, ConvertableFilePath artifactsFile, string feedApiKey, string codeFeedUrl, string symbolFeedUrl) private void PublishPackages(ConvertableDirectoryPath packagesDir, ConvertableFilePath artifactsFile, string feedApiKey, string codeFeedUrl, string symbolFeedUrl)
{ {
Information("PublishPackages"); Information("PublishPackages");
var artifacts = System.IO.File var artifacts = System.IO.File
.ReadAllLines(artifactsFile) .ReadAllLines(artifactsFile)
.Distinct(); .Distinct();
foreach(var artifact in artifacts) foreach(var artifact in artifacts)
{ {
var codePackage = packagesDir + File(artifact); var codePackage = packagesDir + File(artifact);
Information("Pushing package " + codePackage); Information("Pushing package " + codePackage);
Information("Calling NuGetPush"); Information("Calling NuGetPush");
NuGetPush( NuGetPush(
codePackage, codePackage,
new NuGetPushSettings { new NuGetPushSettings {
ApiKey = feedApiKey, ApiKey = feedApiKey,
Source = codeFeedUrl Source = codeFeedUrl
}); });
} }
} }
private void CreateGitHubRelease() private void CreateGitHubRelease()
{ {
var json = $"{{ \"tag_name\": \"{versioning.NuGetVersion}\", \"target_commitish\": \"master\", \"name\": \"{versioning.NuGetVersion}\", \"body\": \"todo: notes coming\", \"draft\": true, \"prerelease\": true }}"; var json = $"{{ \"tag_name\": \"{versioning.NuGetVersion}\", \"target_commitish\": \"master\", \"name\": \"{versioning.NuGetVersion}\", \"body\": \"todo: notes coming\", \"draft\": true, \"prerelease\": true }}";
var content = new System.Net.Http.StringContent(json, System.Text.Encoding.UTF8, "application/json"); var content = new System.Net.Http.StringContent(json, System.Text.Encoding.UTF8, "application/json");
using(var client = new System.Net.Http.HttpClient()) using(var client = new System.Net.Http.HttpClient())
{ {
client.DefaultRequestHeaders.Authorization = client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue( new System.Net.Http.Headers.AuthenticationHeaderValue(
"Basic", Convert.ToBase64String( "Basic", Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes( System.Text.ASCIIEncoding.ASCII.GetBytes(
$"{gitHubUsername}:{gitHubPassword}"))); $"{gitHubUsername}:{gitHubPassword}")));
client.DefaultRequestHeaders.Add("User-Agent", "Ocelot Release"); client.DefaultRequestHeaders.Add("User-Agent", "Ocelot Release");
var result = client.PostAsync("https://api.github.com/repos/ThreeMammals/Ocelot/releases", content).Result; var result = client.PostAsync("https://api.github.com/repos/ThreeMammals/Ocelot/releases", content).Result;
if(result.StatusCode != System.Net.HttpStatusCode.Created) if(result.StatusCode != System.Net.HttpStatusCode.Created)
{ {
throw new Exception("CreateGitHubRelease result.StatusCode = " + result.StatusCode); throw new Exception("CreateGitHubRelease result.StatusCode = " + result.StatusCode);
} }
var returnValue = result.Content.ReadAsStringAsync().Result; var returnValue = result.Content.ReadAsStringAsync().Result;
dynamic test = Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(returnValue); dynamic test = Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(returnValue);
releaseId = test.id; releaseId = test.id;
} }
} }
private void UploadFileToGitHubRelease(FilePath file) private void UploadFileToGitHubRelease(FilePath file)
{ {
var data = System.IO.File.ReadAllBytes(file.FullPath); var data = System.IO.File.ReadAllBytes(file.FullPath);
var content = new System.Net.Http.ByteArrayContent(data); var content = new System.Net.Http.ByteArrayContent(data);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream"); content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
using(var client = new System.Net.Http.HttpClient()) using(var client = new System.Net.Http.HttpClient())
{ {
client.DefaultRequestHeaders.Authorization = client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue( new System.Net.Http.Headers.AuthenticationHeaderValue(
"Basic", Convert.ToBase64String( "Basic", Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes( System.Text.ASCIIEncoding.ASCII.GetBytes(
$"{gitHubUsername}:{gitHubPassword}"))); $"{gitHubUsername}:{gitHubPassword}")));
client.DefaultRequestHeaders.Add("User-Agent", "Ocelot Release"); client.DefaultRequestHeaders.Add("User-Agent", "Ocelot Release");
var result = client.PostAsync($"https://uploads.github.com/repos/ThreeMammals/Ocelot/releases/{releaseId}/assets?name={file.GetFilename()}", content).Result; var result = client.PostAsync($"https://uploads.github.com/repos/ThreeMammals/Ocelot/releases/{releaseId}/assets?name={file.GetFilename()}", content).Result;
if(result.StatusCode != System.Net.HttpStatusCode.Created) if(result.StatusCode != System.Net.HttpStatusCode.Created)
{ {
throw new Exception("UploadFileToGitHubRelease result.StatusCode = " + result.StatusCode); throw new Exception("UploadFileToGitHubRelease result.StatusCode = " + result.StatusCode);
} }
} }
} }
private void CompleteGitHubRelease() private void CompleteGitHubRelease()
{ {
var json = $"{{ \"tag_name\": \"{versioning.NuGetVersion}\", \"target_commitish\": \"master\", \"name\": \"{versioning.NuGetVersion}\", \"body\": \"todo: notes coming\", \"draft\": false, \"prerelease\": false }}"; var json = $"{{ \"tag_name\": \"{versioning.NuGetVersion}\", \"target_commitish\": \"master\", \"name\": \"{versioning.NuGetVersion}\", \"body\": \"todo: notes coming\", \"draft\": false, \"prerelease\": false }}";
var request = new System.Net.Http.HttpRequestMessage(new System.Net.Http.HttpMethod("Patch"), $"https://api.github.com/repos/ThreeMammals/Ocelot/releases/{releaseId}"); var request = new System.Net.Http.HttpRequestMessage(new System.Net.Http.HttpMethod("Patch"), $"https://api.github.com/repos/ThreeMammals/Ocelot/releases/{releaseId}");
request.Content = new System.Net.Http.StringContent(json, System.Text.Encoding.UTF8, "application/json"); request.Content = new System.Net.Http.StringContent(json, System.Text.Encoding.UTF8, "application/json");
using(var client = new System.Net.Http.HttpClient()) using(var client = new System.Net.Http.HttpClient())
{ {
client.DefaultRequestHeaders.Authorization = client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue( new System.Net.Http.Headers.AuthenticationHeaderValue(
"Basic", Convert.ToBase64String( "Basic", Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes( System.Text.ASCIIEncoding.ASCII.GetBytes(
$"{gitHubUsername}:{gitHubPassword}"))); $"{gitHubUsername}:{gitHubPassword}")));
client.DefaultRequestHeaders.Add("User-Agent", "Ocelot Release"); client.DefaultRequestHeaders.Add("User-Agent", "Ocelot Release");
var result = client.SendAsync(request).Result; var result = client.SendAsync(request).Result;
if(result.StatusCode != System.Net.HttpStatusCode.OK) if(result.StatusCode != System.Net.HttpStatusCode.OK)
{ {
throw new Exception("CompleteGitHubRelease result.StatusCode = " + result.StatusCode); throw new Exception("CompleteGitHubRelease result.StatusCode = " + result.StatusCode);
} }
} }
} }
/// gets the resource from the specified url /// gets the resource from the specified url
private string GetResource(string url) private string GetResource(string url)
{ {
try try
{ {
Information("Getting resource from " + url); Information("Getting resource from " + url);
var assetsRequest = System.Net.WebRequest.CreateHttp(url); var assetsRequest = System.Net.WebRequest.CreateHttp(url);
assetsRequest.Method = "GET"; assetsRequest.Method = "GET";
assetsRequest.Accept = "application/vnd.github.v3+json"; assetsRequest.Accept = "application/vnd.github.v3+json";
assetsRequest.UserAgent = "BuildScript"; assetsRequest.UserAgent = "BuildScript";
using (var assetsResponse = assetsRequest.GetResponse()) using (var assetsResponse = assetsRequest.GetResponse())
{ {
var assetsStream = assetsResponse.GetResponseStream(); var assetsStream = assetsResponse.GetResponseStream();
var assetsReader = new StreamReader(assetsStream); var assetsReader = new StreamReader(assetsStream);
var response = assetsReader.ReadToEnd(); var response = assetsReader.ReadToEnd();
Information("Response is " + response); Information("Response is " + response);
return response; return response;
} }
} }
catch(Exception exception) catch(Exception exception)
{ {
Information("There was an exception " + exception); Information("There was an exception " + exception);
throw; throw;
} }
} }
private bool IsRunningOnCircleCI() private bool IsRunningOnCircleCI()
{ {
return !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("CIRCLECI")); return !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("CIRCLECI"));
} }

View File

@ -62,7 +62,8 @@ Here is an example ReRoute configuration, You don't need to set all of these thi
"HttpHandlerOptions": { "HttpHandlerOptions": {
"AllowAutoRedirect": true, "AllowAutoRedirect": true,
"UseCookieContainer": true, "UseCookieContainer": true,
"UseTracing": true "UseTracing": true,
"MaxConnectionsPerServer": 100
}, },
"DangerousAcceptAnyServerCertificateValidator": false "DangerousAcceptAnyServerCertificateValidator": false
} }
@ -222,3 +223,8 @@ If you want to ignore SSL warnings / errors set the following in your ReRoute co
"DangerousAcceptAnyServerCertificateValidator": true "DangerousAcceptAnyServerCertificateValidator": true
I don't recommend doing this, I suggest creating your own certificate and then getting it trusted by your local / remote machine if you can. I don't recommend doing this, I suggest creating your own certificate and then getting it trusted by your local / remote machine if you can.
MaxConnectionsPerServer
^^^^^^^^^^^^^^^^^^^^^^^
This controls how many connections the internal HttpClient will open. This can be set at ReRoute or global level.

View File

@ -155,6 +155,8 @@ Eureka. One of the services polls Eureka every 30 seconds (default) and gets the
When Ocelot asks for a given service it is retrieved from memory so performance is not a big problem. Please note that this code When Ocelot asks for a given service it is retrieved from memory so performance is not a big problem. Please note that this code
is provided by the Pivotal.Discovery.Client NuGet package so big thanks to them for all the hard work. is provided by the Pivotal.Discovery.Client NuGet package so big thanks to them for all the hard work.
Ocelot will use the scheme (http/https) set in Eureka if these values are not provided in ocelot.json
Dynamic Routing Dynamic Routing
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^

View File

@ -26,7 +26,7 @@
if (instances != null && instances.Any()) if (instances != null && instances.Any())
{ {
services.AddRange(instances.Select(i => new Service(i.ServiceId, new ServiceHostAndPort(i.Host, i.Port), "", "", new List<string>()))); services.AddRange(instances.Select(i => new Service(i.ServiceId, new ServiceHostAndPort(i.Host, i.Port, i.Uri.Scheme), "", "", new List<string>())));
} }
return Task.FromResult(services); return Task.FromResult(services);

View File

@ -18,8 +18,11 @@
{ {
var useTracing = _tracer != null && options.UseTracing; var useTracing = _tracer != null && options.UseTracing;
//be sure that maxConnectionPerServer is in correct range of values
int maxConnectionPerServer = (options.MaxConnectionsPerServer > 0) ? maxConnectionPerServer = options.MaxConnectionsPerServer : maxConnectionPerServer = int.MaxValue;
return new HttpHandlerOptions(options.AllowAutoRedirect, return new HttpHandlerOptions(options.AllowAutoRedirect,
options.UseCookieContainer, useTracing, options.UseProxy); options.UseCookieContainer, useTracing, options.UseProxy, maxConnectionPerServer);
} }
} }
} }

View File

@ -6,7 +6,8 @@
{ {
AllowAutoRedirect = false; AllowAutoRedirect = false;
UseCookieContainer = false; UseCookieContainer = false;
UseProxy = true; UseProxy = true;
MaxConnectionsPerServer = int.MaxValue;
} }
public bool AllowAutoRedirect { get; set; } public bool AllowAutoRedirect { get; set; }
@ -15,6 +16,8 @@
public bool UseTracing { get; set; } public bool UseTracing { get; set; }
public bool UseProxy { get; set; } public bool UseProxy { get; set; }
public int MaxConnectionsPerServer { get; set; }
} }
} }

View File

@ -6,32 +6,44 @@
/// </summary> /// </summary>
public class HttpHandlerOptions public class HttpHandlerOptions
{ {
public HttpHandlerOptions(bool allowAutoRedirect, bool useCookieContainer, bool useTracing, bool useProxy) public HttpHandlerOptions(bool allowAutoRedirect, bool useCookieContainer, bool useTracing, bool useProxy, int maxConnectionsPerServer)
{ {
AllowAutoRedirect = allowAutoRedirect; AllowAutoRedirect = allowAutoRedirect;
UseCookieContainer = useCookieContainer; UseCookieContainer = useCookieContainer;
UseTracing = useTracing; UseTracing = useTracing;
UseProxy = useProxy; UseProxy = useProxy;
MaxConnectionsPerServer = maxConnectionsPerServer;
} }
/// <summary> /// <summary>
/// Specify if auto redirect is enabled /// Specify if auto redirect is enabled
/// </summary> /// </summary>
public bool AllowAutoRedirect { get; private set; } /// <value>AllowAutoRedirect</value>
public bool AllowAutoRedirect { get; private set; }
/// <summary> /// <summary>
/// Specify is handler has to use a cookie container /// Specify is handler has to use a cookie container
/// </summary> /// </summary>
/// <value>UseCookieContainer</value>
public bool UseCookieContainer { get; private set; } public bool UseCookieContainer { get; private set; }
/// <summary> /// <summary>
/// Specify is handler has to use a opentracing /// Specify is handler has to use a opentracing
/// </summary> /// </summary>
/// <value>UseTracing</value>
public bool UseTracing { get; private set; } public bool UseTracing { get; private set; }
/// <summary> /// <summary>
/// Specify if handler has to use a proxy /// Specify if handler has to use a proxy
/// </summary> /// </summary>
public bool UseProxy { get; private set; } /// <value>UseProxy</value>
public bool UseProxy { get; private set; }
/// <summary>
/// Specify the maximum of concurrent connection to a network endpoint
/// </summary>
/// <value>MaxConnectionsPerServer</value>
public int MaxConnectionsPerServer { get; private set; }
} }
} }

View File

@ -6,6 +6,7 @@
private bool _useCookieContainer; private bool _useCookieContainer;
private bool _useTracing; private bool _useTracing;
private bool _useProxy; private bool _useProxy;
private int _maxConnectionPerServer;
public HttpHandlerOptionsBuilder WithAllowAutoRedirect(bool input) public HttpHandlerOptionsBuilder WithAllowAutoRedirect(bool input)
{ {
@ -30,10 +31,16 @@
_useProxy = useProxy; _useProxy = useProxy;
return this; return this;
} }
public HttpHandlerOptionsBuilder WithUseMaxConnectionPerServer(int maxConnectionPerServer)
{
_maxConnectionPerServer = maxConnectionPerServer;
return this;
}
public HttpHandlerOptions Build() public HttpHandlerOptions Build()
{ {
return new HttpHandlerOptions(_allowAutoRedirect, _useCookieContainer, _useTracing, _useProxy); return new HttpHandlerOptions(_allowAutoRedirect, _useCookieContainer, _useTracing, _useProxy, _maxConnectionPerServer);
} }
} }
} }

View File

@ -105,7 +105,8 @@ namespace Ocelot.Configuration.Repository
public void Dispose() public void Dispose()
{ {
_timer.Dispose(); _timer?.Dispose();
_timer = null;
} }
} }
} }

View File

@ -9,6 +9,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
public class FileConfigurationFluentValidator : AbstractValidator<FileConfiguration>, IConfigurationValidator public class FileConfigurationFluentValidator : AbstractValidator<FileConfiguration>, IConfigurationValidator
@ -35,6 +36,10 @@
.Must((config, reRoute) => HaveServiceDiscoveryProviderRegistered(reRoute, config.GlobalConfiguration.ServiceDiscoveryProvider)) .Must((config, reRoute) => HaveServiceDiscoveryProviderRegistered(reRoute, config.GlobalConfiguration.ServiceDiscoveryProvider))
.WithMessage((config, reRoute) => $"Unable to start Ocelot, errors are: Unable to start Ocelot because either a ReRoute or GlobalConfiguration are using ServiceDiscoveryOptions but no ServiceDiscoveryFinderDelegate has been registered in dependency injection container. Are you missing a package like Ocelot.Provider.Consul and services.AddConsul() or Ocelot.Provider.Eureka and services.AddEureka()?"); .WithMessage((config, reRoute) => $"Unable to start Ocelot, errors are: Unable to start Ocelot because either a ReRoute or GlobalConfiguration are using ServiceDiscoveryOptions but no ServiceDiscoveryFinderDelegate has been registered in dependency injection container. Are you missing a package like Ocelot.Provider.Consul and services.AddConsul() or Ocelot.Provider.Eureka and services.AddEureka()?");
RuleForEach(configuration => configuration.ReRoutes)
.Must((config, reRoute) => IsPlaceholderNotDuplicatedIn(reRoute.UpstreamPathTemplate))
.WithMessage((config, reRoute) => $"{nameof(reRoute)} {reRoute.UpstreamPathTemplate} has duplicated placeholder");
RuleFor(configuration => configuration.GlobalConfiguration.ServiceDiscoveryProvider) RuleFor(configuration => configuration.GlobalConfiguration.ServiceDiscoveryProvider)
.Must(HaveServiceDiscoveryProviderRegistered) .Must(HaveServiceDiscoveryProviderRegistered)
.WithMessage((config, reRoute) => $"Unable to start Ocelot, errors are: Unable to start Ocelot because either a ReRoute or GlobalConfiguration are using ServiceDiscoveryOptions but no ServiceDiscoveryFinderDelegate has been registered in dependency injection container. Are you missing a package like Ocelot.Provider.Consul and services.AddConsul() or Ocelot.Provider.Eureka and services.AddEureka()?"); .WithMessage((config, reRoute) => $"Unable to start Ocelot, errors are: Unable to start Ocelot because either a ReRoute or GlobalConfiguration are using ServiceDiscoveryOptions but no ServiceDiscoveryFinderDelegate has been registered in dependency injection container. Are you missing a package like Ocelot.Provider.Consul and services.AddConsul() or Ocelot.Provider.Eureka and services.AddEureka()?");
@ -109,6 +114,14 @@
return reRoutesForAggregate.Count() == fileAggregateReRoute.ReRouteKeys.Count; return reRoutesForAggregate.Count() == fileAggregateReRoute.ReRouteKeys.Count;
} }
private bool IsPlaceholderNotDuplicatedIn(string upstreamPathTemplate)
{
Regex regExPlaceholder = new Regex("{[^}]+}");
var matches = regExPlaceholder.Matches(upstreamPathTemplate);
var upstreamPathPlaceholders = matches.Select(m => m.Value);
return upstreamPathPlaceholders.Count() == upstreamPathPlaceholders.Distinct().Count();
}
private static bool DoesNotContainReRoutesWithSpecificRequestIdKeys(FileAggregateReRoute fileAggregateReRoute, private static bool DoesNotContainReRoutesWithSpecificRequestIdKeys(FileAggregateReRoute fileAggregateReRoute,
List<FileReRoute> reRoutes) List<FileReRoute> reRoutes)
{ {

View File

@ -37,7 +37,10 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
return; return;
} }
context.DownstreamRequest.Scheme = context.DownstreamReRoute.DownstreamScheme; if (!string.IsNullOrEmpty(context.DownstreamReRoute.DownstreamScheme))
{
context.DownstreamRequest.Scheme = context.DownstreamReRoute.DownstreamScheme;
}
if (ServiceFabricRequest(context)) if (ServiceFabricRequest(context))
{ {

View File

@ -45,6 +45,11 @@ namespace Ocelot.LoadBalancer.Middleware
context.DownstreamRequest.Port = hostAndPort.Data.DownstreamPort; context.DownstreamRequest.Port = hostAndPort.Data.DownstreamPort;
} }
if (!string.IsNullOrEmpty(hostAndPort.Data.Scheme))
{
context.DownstreamRequest.Scheme = hostAndPort.Data.Scheme;
}
try try
{ {
await _next.Invoke(context); await _next.Invoke(context);

View File

@ -90,7 +90,9 @@ namespace Ocelot.Requester
{ {
AllowAutoRedirect = context.DownstreamReRoute.HttpHandlerOptions.AllowAutoRedirect, AllowAutoRedirect = context.DownstreamReRoute.HttpHandlerOptions.AllowAutoRedirect,
UseCookies = context.DownstreamReRoute.HttpHandlerOptions.UseCookieContainer, UseCookies = context.DownstreamReRoute.HttpHandlerOptions.UseCookieContainer,
UseProxy = context.DownstreamReRoute.HttpHandlerOptions.UseProxy UseProxy = context.DownstreamReRoute.HttpHandlerOptions.UseProxy,
MaxConnectionsPerServer = context.DownstreamReRoute.HttpHandlerOptions.MaxConnectionsPerServer
}; };
} }
@ -101,6 +103,7 @@ namespace Ocelot.Requester
AllowAutoRedirect = context.DownstreamReRoute.HttpHandlerOptions.AllowAutoRedirect, AllowAutoRedirect = context.DownstreamReRoute.HttpHandlerOptions.AllowAutoRedirect,
UseCookies = context.DownstreamReRoute.HttpHandlerOptions.UseCookieContainer, UseCookies = context.DownstreamReRoute.HttpHandlerOptions.UseCookieContainer,
UseProxy = context.DownstreamReRoute.HttpHandlerOptions.UseProxy, UseProxy = context.DownstreamReRoute.HttpHandlerOptions.UseProxy,
MaxConnectionsPerServer = context.DownstreamReRoute.HttpHandlerOptions.MaxConnectionsPerServer,
CookieContainer = new CookieContainer() CookieContainer = new CookieContainer()
}; };
} }

View File

@ -34,7 +34,7 @@ namespace Ocelot.ServiceDiscovery
foreach (var downstreamAddress in reRoute.DownstreamAddresses) foreach (var downstreamAddress in reRoute.DownstreamAddresses)
{ {
var service = new Service(reRoute.ServiceName, new ServiceHostAndPort(downstreamAddress.Host, downstreamAddress.Port), string.Empty, string.Empty, new string[0]); var service = new Service(reRoute.ServiceName, new ServiceHostAndPort(downstreamAddress.Host, downstreamAddress.Port, reRoute.DownstreamScheme), string.Empty, string.Empty, new string[0]);
services.Add(service); services.Add(service);
} }

View File

@ -8,8 +8,13 @@
DownstreamPort = downstreamPort; DownstreamPort = downstreamPort;
} }
public ServiceHostAndPort(string downstreamHost, int downstreamPort, string scheme)
: this(downstreamHost, downstreamPort) => Scheme = scheme;
public string DownstreamHost { get; } public string DownstreamHost { get; }
public int DownstreamPort { get; } public int DownstreamPort { get; }
public string Scheme { get; }
} }
} }

View File

@ -41,14 +41,14 @@ namespace Ocelot.UnitTests.Configuration
_internalConfigCreator = new Mock<IInternalConfigurationCreator>(); _internalConfigCreator = new Mock<IInternalConfigurationCreator>();
_internalConfigCreator.Setup(x => x.Create(It.IsAny<FileConfiguration>())).ReturnsAsync(new OkResponse<IInternalConfiguration>(_internalConfig)); _internalConfigCreator.Setup(x => x.Create(It.IsAny<FileConfiguration>())).ReturnsAsync(new OkResponse<IInternalConfiguration>(_internalConfig));
_poller = new FileConfigurationPoller(_factory.Object, _repo.Object, _config.Object, _internalConfigRepo.Object, _internalConfigCreator.Object); _poller = new FileConfigurationPoller(_factory.Object, _repo.Object, _config.Object, _internalConfigRepo.Object, _internalConfigCreator.Object);
_poller.StartAsync(new CancellationToken());
} }
[Fact] [Fact]
public void should_start() public void should_start()
{ {
this.Given(x => ThenTheSetterIsCalled(_fileConfig, 1)) this.Given(x => GivenPollerHasStarted())
.BDDfy(); .Given(x => ThenTheSetterIsCalled(_fileConfig, 1))
.BDDfy();
} }
[Fact] [Fact]
@ -71,7 +71,8 @@ namespace Ocelot.UnitTests.Configuration
} }
}; };
this.Given(x => WhenTheConfigIsChanged(newConfig, 0)) this.Given(x => GivenPollerHasStarted())
.Given(x => WhenTheConfigIsChanged(newConfig, 0))
.Then(x => ThenTheSetterIsCalledAtLeast(newConfig, 1)) .Then(x => ThenTheSetterIsCalledAtLeast(newConfig, 1))
.BDDfy(); .BDDfy();
} }
@ -96,7 +97,8 @@ namespace Ocelot.UnitTests.Configuration
} }
}; };
this.Given(x => WhenTheConfigIsChanged(newConfig, 10)) this.Given(x => GivenPollerHasStarted())
.Given(x => WhenTheConfigIsChanged(newConfig, 10))
.Then(x => ThenTheSetterIsCalled(newConfig, 1)) .Then(x => ThenTheSetterIsCalled(newConfig, 1))
.BDDfy(); .BDDfy();
} }
@ -121,11 +123,24 @@ namespace Ocelot.UnitTests.Configuration
} }
}; };
this.Given(x => WhenProviderErrors()) this.Given(x => GivenPollerHasStarted())
.Given(x => WhenProviderErrors())
.Then(x => ThenTheSetterIsCalled(newConfig, 0)) .Then(x => ThenTheSetterIsCalled(newConfig, 0))
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_dispose_cleanly_without_starting()
{
this.When(x => WhenPollerIsDisposed())
.BDDfy();
}
private void GivenPollerHasStarted()
{
_poller.StartAsync(CancellationToken.None);
}
private void WhenProviderErrors() private void WhenProviderErrors()
{ {
_repo _repo
@ -141,6 +156,11 @@ namespace Ocelot.UnitTests.Configuration
.ReturnsAsync(new OkResponse<FileConfiguration>(newConfig)); .ReturnsAsync(new OkResponse<FileConfiguration>(newConfig));
} }
private void WhenPollerIsDisposed()
{
_poller.Dispose();
}
private void ThenTheSetterIsCalled(FileConfiguration fileConfig, int times) private void ThenTheSetterIsCalled(FileConfiguration fileConfig, int times)
{ {
var result = WaitFor(4000).Until(() => var result = WaitFor(4000).Until(() =>

View File

@ -41,7 +41,7 @@ namespace Ocelot.UnitTests.Configuration
} }
}; };
var expectedOptions = new HttpHandlerOptions(false, false, false, true); var expectedOptions = new HttpHandlerOptions(false, false, false, true, int.MaxValue);
this.Given(x => GivenTheFollowing(fileReRoute)) this.Given(x => GivenTheFollowing(fileReRoute))
.When(x => WhenICreateHttpHandlerOptions()) .When(x => WhenICreateHttpHandlerOptions())
@ -60,7 +60,7 @@ namespace Ocelot.UnitTests.Configuration
} }
}; };
var expectedOptions = new HttpHandlerOptions(false, false, true, true); var expectedOptions = new HttpHandlerOptions(false, false, true, true, int.MaxValue);
this.Given(x => GivenTheFollowing(fileReRoute)) this.Given(x => GivenTheFollowing(fileReRoute))
.And(x => GivenARealTracer()) .And(x => GivenARealTracer())
@ -73,7 +73,7 @@ namespace Ocelot.UnitTests.Configuration
public void should_create_options_with_useCookie_false_and_allowAutoRedirect_true_as_default() public void should_create_options_with_useCookie_false_and_allowAutoRedirect_true_as_default()
{ {
var fileReRoute = new FileReRoute(); var fileReRoute = new FileReRoute();
var expectedOptions = new HttpHandlerOptions(false, false, false, true); var expectedOptions = new HttpHandlerOptions(false, false, false, true, int.MaxValue);
this.Given(x => GivenTheFollowing(fileReRoute)) this.Given(x => GivenTheFollowing(fileReRoute))
.When(x => WhenICreateHttpHandlerOptions()) .When(x => WhenICreateHttpHandlerOptions())
@ -94,7 +94,7 @@ namespace Ocelot.UnitTests.Configuration
} }
}; };
var expectedOptions = new HttpHandlerOptions(false, false, false, true); var expectedOptions = new HttpHandlerOptions(false, false, false, true, int.MaxValue);
this.Given(x => GivenTheFollowing(fileReRoute)) this.Given(x => GivenTheFollowing(fileReRoute))
.When(x => WhenICreateHttpHandlerOptions()) .When(x => WhenICreateHttpHandlerOptions())
@ -110,7 +110,7 @@ namespace Ocelot.UnitTests.Configuration
HttpHandlerOptions = new FileHttpHandlerOptions() HttpHandlerOptions = new FileHttpHandlerOptions()
}; };
var expectedOptions = new HttpHandlerOptions(false, false, false, true); var expectedOptions = new HttpHandlerOptions(false, false, false, true, int.MaxValue);
this.Given(x => GivenTheFollowing(fileReRoute)) this.Given(x => GivenTheFollowing(fileReRoute))
.When(x => WhenICreateHttpHandlerOptions()) .When(x => WhenICreateHttpHandlerOptions())
@ -129,7 +129,64 @@ namespace Ocelot.UnitTests.Configuration
} }
}; };
var expectedOptions = new HttpHandlerOptions(false, false, false, false); var expectedOptions = new HttpHandlerOptions(false, false, false, false, int.MaxValue);
this.Given(x => GivenTheFollowing(fileReRoute))
.When(x => WhenICreateHttpHandlerOptions())
.Then(x => ThenTheFollowingOptionsReturned(expectedOptions))
.BDDfy();
}
[Fact]
public void should_create_options_with_specified_MaxConnectionsPerServer()
{
var fileReRoute = new FileReRoute
{
HttpHandlerOptions = new FileHttpHandlerOptions
{
MaxConnectionsPerServer = 10
}
};
var expectedOptions = new HttpHandlerOptions(false, false, false, true, 10);
this.Given(x => GivenTheFollowing(fileReRoute))
.When(x => WhenICreateHttpHandlerOptions())
.Then(x => ThenTheFollowingOptionsReturned(expectedOptions))
.BDDfy();
}
[Fact]
public void should_create_options_fixing_specified_MaxConnectionsPerServer_range()
{
var fileReRoute = new FileReRoute
{
HttpHandlerOptions = new FileHttpHandlerOptions
{
MaxConnectionsPerServer = -1
}
};
var expectedOptions = new HttpHandlerOptions(false, false, false, true, int.MaxValue);
this.Given(x => GivenTheFollowing(fileReRoute))
.When(x => WhenICreateHttpHandlerOptions())
.Then(x => ThenTheFollowingOptionsReturned(expectedOptions))
.BDDfy();
}
[Fact]
public void should_create_options_fixing_specified_MaxConnectionsPerServer_range_when_zero()
{
var fileReRoute = new FileReRoute
{
HttpHandlerOptions = new FileHttpHandlerOptions
{
MaxConnectionsPerServer = 0
}
};
var expectedOptions = new HttpHandlerOptions(false, false, false, true, int.MaxValue);
this.Given(x => GivenTheFollowing(fileReRoute)) this.Given(x => GivenTheFollowing(fileReRoute))
.When(x => WhenICreateHttpHandlerOptions()) .When(x => WhenICreateHttpHandlerOptions())
@ -154,6 +211,7 @@ namespace Ocelot.UnitTests.Configuration
_httpHandlerOptions.UseCookieContainer.ShouldBe(expected.UseCookieContainer); _httpHandlerOptions.UseCookieContainer.ShouldBe(expected.UseCookieContainer);
_httpHandlerOptions.UseTracing.ShouldBe(expected.UseTracing); _httpHandlerOptions.UseTracing.ShouldBe(expected.UseTracing);
_httpHandlerOptions.UseProxy.ShouldBe(expected.UseProxy); _httpHandlerOptions.UseProxy.ShouldBe(expected.UseProxy);
_httpHandlerOptions.MaxConnectionsPerServer.ShouldBe(expected.MaxConnectionsPerServer);
} }
private void GivenARealTracer() private void GivenARealTracer()

View File

@ -1341,6 +1341,32 @@
.BDDfy(); .BDDfy();
} }
[Fact]
public void configuration_is_invalid_when_placeholder_is_used_twice_in_upstream_path_template()
{
this.Given(x => x.GivenAConfiguration(new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/bar/{everything}",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort() { Host = "a.b.cd" },
},
UpstreamPathTemplate = "/foo/bar/{everything}/{everything}",
UpstreamHttpMethod = new List<string> { "Get" },
},
},
}))
.When(x => x.WhenIValidateTheConfiguration())
.Then(x => x.ThenTheResultIsNotValid())
.And(x => x.ThenTheErrorMessageAtPositionIs(0, "reRoute /foo/bar/{everything}/{everything} has duplicated placeholder"))
.BDDfy();
}
private void GivenAConfiguration(FileConfiguration fileConfiguration) private void GivenAConfiguration(FileConfiguration fileConfiguration)
{ {
_fileConfiguration = fileConfiguration; _fileConfiguration = fileConfiguration;

View File

@ -350,6 +350,36 @@
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_not_replace_by_empty_scheme()
{
var downstreamReRoute = new DownstreamReRouteBuilder()
.WithDownstreamScheme("")
.WithServiceName("Ocelot/OcelotApp")
.WithUseServiceDiscovery(true)
.Build();
var downstreamRoute = new DownstreamRoute(
new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamReRoute(downstreamReRoute)
.Build());
var config = new ServiceProviderConfigurationBuilder()
.WithType("ServiceFabric")
.WithHost("localhost")
.WithPort(19081)
.Build();
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
.And(x => GivenTheServiceProviderConfigIs(config))
.And(x => x.GivenTheDownstreamRequestUriIs("https://localhost:19081?PartitionKind=test&PartitionKey=1"))
.And(x => x.GivenTheUrlReplacerWillReturnSequence("/api/products/1", "Ocelot/OcelotApp"))
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheDownstreamRequestUriIs("https://localhost:19081/Ocelot/OcelotApp/api/products/1?PartitionKind=test&PartitionKey=1"))
.BDDfy();
}
private void GivenTheServiceProviderConfigIs(ServiceProviderConfiguration config) private void GivenTheServiceProviderConfigIs(ServiceProviderConfiguration config)
{ {
var configuration = new InternalConfiguration(null, null, config, null, null, null, null, null); var configuration = new InternalConfiguration(null, null, config, null, null, null, null, null);

View File

@ -1,3 +1,5 @@
using System;
using System.Linq.Expressions;
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.UnitTests.LoadBalancer namespace Ocelot.UnitTests.LoadBalancer
@ -108,6 +110,26 @@ namespace Ocelot.UnitTests.LoadBalancer
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_set_scheme()
{
var downstreamRoute = new DownstreamReRouteBuilder()
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build();
var serviceProviderConfig = new ServiceProviderConfigurationBuilder()
.Build();
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123"))
.And(x => GivenTheConfigurationIs(serviceProviderConfig))
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute, new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>()))
.And(x => x.GivenTheLoadBalancerHouseReturns())
.And(x => x.GivenTheLoadBalancerReturnsOk())
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenAnHostAndPortIsSetOnPipeline())
.BDDfy();
}
private void WhenICallTheMiddleware() private void WhenICallTheMiddleware()
{ {
_middleware = new LoadBalancingMiddleware(_next, _loggerFactory.Object, _loadBalancerHouse.Object); _middleware = new LoadBalancingMiddleware(_next, _loggerFactory.Object, _loadBalancerHouse.Object);
@ -135,6 +157,13 @@ namespace Ocelot.UnitTests.LoadBalancer
.ReturnsAsync(_getHostAndPortError); .ReturnsAsync(_getHostAndPortError);
} }
private void GivenTheLoadBalancerReturnsOk()
{
_loadBalancer
.Setup(x => x.Lease(It.IsAny<DownstreamContext>()))
.ReturnsAsync(new OkResponse<ServiceHostAndPort>(new ServiceHostAndPort("abc", 123, "https")));
}
private void GivenTheLoadBalancerReturns() private void GivenTheLoadBalancerReturns()
{ {
_hostAndPort = new ServiceHostAndPort("127.0.0.1", 80); _hostAndPort = new ServiceHostAndPort("127.0.0.1", 80);
@ -186,6 +215,13 @@ namespace Ocelot.UnitTests.LoadBalancer
_downstreamContext.Errors.ShouldBe(_getHostAndPortError.Errors); _downstreamContext.Errors.ShouldBe(_getHostAndPortError.Errors);
} }
private void ThenAnHostAndPortIsSetOnPipeline()
{
_downstreamContext.DownstreamRequest.Host.ShouldBeEquivalentTo("abc");
_downstreamContext.DownstreamRequest.Port.ShouldBeEquivalentTo(123);
_downstreamContext.DownstreamRequest.Scheme.ShouldBeEquivalentTo("https");
}
private void ThenTheDownstreamUrlIsReplacedWith(string expectedUri) private void ThenTheDownstreamUrlIsReplacedWith(string expectedUri)
{ {
_downstreamContext.DownstreamRequest.ToHttpRequestMessage().RequestUri.OriginalString.ShouldBe(expectedUri); _downstreamContext.DownstreamRequest.ToHttpRequestMessage().RequestUri.OriginalString.ShouldBe(expectedUri);

View File

@ -52,7 +52,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true, int.MaxValue))
.WithDelegatingHandlers(new List<string> .WithDelegatingHandlers(new List<string>
{ {
"FakeDelegatingHandler", "FakeDelegatingHandler",
@ -88,7 +88,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true, int.MaxValue))
.WithDelegatingHandlers(new List<string> .WithDelegatingHandlers(new List<string>
{ {
"FakeDelegatingHandlerTwo", "FakeDelegatingHandlerTwo",
@ -125,7 +125,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true, int.MaxValue))
.WithDelegatingHandlers(new List<string> .WithDelegatingHandlers(new List<string>
{ {
"FakeDelegatingHandlerTwo", "FakeDelegatingHandlerTwo",
@ -161,7 +161,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true, int.MaxValue))
.WithDelegatingHandlers(new List<string> .WithDelegatingHandlers(new List<string>
{ {
"FakeDelegatingHandler", "FakeDelegatingHandler",
@ -195,7 +195,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true, int.MaxValue))
.WithLoadBalancerKey("") .WithLoadBalancerKey("")
.Build(); .Build();
@ -221,7 +221,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false, true, int.MaxValue))
.WithDelegatingHandlers(new List<string> .WithDelegatingHandlers(new List<string>
{ {
"FakeDelegatingHandler", "FakeDelegatingHandler",
@ -249,7 +249,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false, true)).WithLoadBalancerKey("").Build(); .WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false, true, int.MaxValue)).WithLoadBalancerKey("").Build();
this.Given(x => GivenTheFollowingRequest(reRoute)) this.Given(x => GivenTheFollowingRequest(reRoute))
.And(x => GivenTheQosFactoryReturns(new FakeQoSHandler())) .And(x => GivenTheQosFactoryReturns(new FakeQoSHandler()))
@ -269,7 +269,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false, true)).WithLoadBalancerKey("").Build(); .WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false, true, int.MaxValue)).WithLoadBalancerKey("").Build();
this.Given(x => GivenTheFollowingRequest(reRoute)) this.Given(x => GivenTheFollowingRequest(reRoute))
.And(x => GivenTheServiceProviderReturnsNothing()) .And(x => GivenTheServiceProviderReturnsNothing())
@ -289,7 +289,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false, true)).WithLoadBalancerKey("").Build(); .WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false, true, int.MaxValue)).WithLoadBalancerKey("").Build();
this.Given(x => GivenTheFollowingRequest(reRoute)) this.Given(x => GivenTheFollowingRequest(reRoute))
.And(x => GivenTheQosFactoryReturns(new FakeQoSHandler())) .And(x => GivenTheQosFactoryReturns(new FakeQoSHandler()))
@ -309,7 +309,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false, true)).WithLoadBalancerKey("").Build(); .WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false, true, int.MaxValue)).WithLoadBalancerKey("").Build();
this.Given(x => GivenTheFollowingRequest(reRoute)) this.Given(x => GivenTheFollowingRequest(reRoute))
.And(x => GivenTheQosFactoryReturns(new FakeQoSHandler())) .And(x => GivenTheQosFactoryReturns(new FakeQoSHandler()))
@ -331,7 +331,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true, int.MaxValue))
.WithLoadBalancerKey("") .WithLoadBalancerKey("")
.Build(); .Build();
@ -361,7 +361,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true, int.MaxValue))
.WithLoadBalancerKey("") .WithLoadBalancerKey("")
.Build(); .Build();

View File

@ -52,7 +52,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
.WithLoadBalancerKey("") .WithLoadBalancerKey("")
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build()) .WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
.WithQosOptions(new QoSOptionsBuilder().Build()) .WithQosOptions(new QoSOptionsBuilder().Build())
@ -73,7 +73,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
.WithLoadBalancerKey("") .WithLoadBalancerKey("")
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build()) .WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
.WithQosOptions(new QoSOptionsBuilder().Build()) .WithQosOptions(new QoSOptionsBuilder().Build())
@ -99,7 +99,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
.WithLoadBalancerKey("") .WithLoadBalancerKey("")
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build()) .WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
.WithQosOptions(new QoSOptionsBuilder().Build()) .WithQosOptions(new QoSOptionsBuilder().Build())
@ -126,7 +126,7 @@ namespace Ocelot.UnitTests.Requester
var reRouteA = new DownstreamReRouteBuilder() var reRouteA = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
.WithLoadBalancerKey("") .WithLoadBalancerKey("")
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithContainsQueryString(true).WithOriginalValue("").Build()) .WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithContainsQueryString(true).WithOriginalValue("").Build())
.WithQosOptions(new QoSOptionsBuilder().Build()) .WithQosOptions(new QoSOptionsBuilder().Build())
@ -134,7 +134,7 @@ namespace Ocelot.UnitTests.Requester
var reRouteB = new DownstreamReRouteBuilder() var reRouteB = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
.WithLoadBalancerKey("") .WithLoadBalancerKey("")
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithContainsQueryString(true).WithOriginalValue("").Build()) .WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithContainsQueryString(true).WithOriginalValue("").Build())
.WithQosOptions(new QoSOptionsBuilder().Build()) .WithQosOptions(new QoSOptionsBuilder().Build())
@ -161,7 +161,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
.WithLoadBalancerKey("") .WithLoadBalancerKey("")
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build()) .WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
.WithQosOptions(new QoSOptionsBuilder().Build()) .WithQosOptions(new QoSOptionsBuilder().Build())
@ -184,7 +184,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
.WithLoadBalancerKey("") .WithLoadBalancerKey("")
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build()) .WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
.WithQosOptions(new QoSOptionsBuilder().Build()) .WithQosOptions(new QoSOptionsBuilder().Build())
@ -216,7 +216,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, true, false, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(false, true, false, true, int.MaxValue))
.WithLoadBalancerKey("") .WithLoadBalancerKey("")
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build()) .WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
.WithQosOptions(new QoSOptionsBuilder().Build()) .WithQosOptions(new QoSOptionsBuilder().Build())
@ -252,7 +252,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
.WithLoadBalancerKey("") .WithLoadBalancerKey("")
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build()) .WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
.WithQosOptions(new QoSOptionsBuilder().Build()) .WithQosOptions(new QoSOptionsBuilder().Build())

View File

@ -57,7 +57,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
.WithLoadBalancerKey("") .WithLoadBalancerKey("")
.WithUpstreamPathTemplate(upstreamTemplate) .WithUpstreamPathTemplate(upstreamTemplate)
.WithQosOptions(new QoSOptionsBuilder().Build()) .WithQosOptions(new QoSOptionsBuilder().Build())
@ -86,7 +86,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
.WithLoadBalancerKey("") .WithLoadBalancerKey("")
.WithUpstreamPathTemplate(upstreamTemplate) .WithUpstreamPathTemplate(upstreamTemplate)
.WithQosOptions(new QoSOptionsBuilder().Build()) .WithQosOptions(new QoSOptionsBuilder().Build())
@ -114,7 +114,7 @@ namespace Ocelot.UnitTests.Requester
var reRoute = new DownstreamReRouteBuilder() var reRoute = new DownstreamReRouteBuilder()
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true)) .WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
.WithLoadBalancerKey("") .WithLoadBalancerKey("")
.WithUpstreamPathTemplate(upstreamTemplate) .WithUpstreamPathTemplate(upstreamTemplate)
.WithQosOptions(new QoSOptionsBuilder().WithTimeoutValue(1).Build()) .WithQosOptions(new QoSOptionsBuilder().WithTimeoutValue(1).Build())