mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 16:18:14 +08:00
Merge remote-tracking branch 'origin/develop' into feature/603-bad-gateway
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -1,225 +1,225 @@
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using Configuration.File;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class CachingTests : IDisposable
|
||||
{
|
||||
private readonly Steps _steps;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public CachingTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
_steps = new Steps();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_cached_response()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51899,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
FileCacheOptions = new FileCacheOptions
|
||||
{
|
||||
TtlSeconds = 100
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51899", 200, "Hello from Laura", null, null))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.Given(x => x.GivenTheServiceNowReturns("http://localhost:51899", 200, "Hello from Tom"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.And(x => _steps.ThenTheContentLengthIs(16))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_cached_response_with_expires_header()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 52839,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
FileCacheOptions = new FileCacheOptions
|
||||
{
|
||||
TtlSeconds = 100
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:52839", 200, "Hello from Laura", "Expires", "-1"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.Given(x => x.GivenTheServiceNowReturns("http://localhost:52839", 200, "Hello from Tom"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.And(x => _steps.ThenTheContentLengthIs(16))
|
||||
.And(x => _steps.ThenTheResponseBodyHeaderIs("Expires", "-1"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_cached_response_when_using_jsonserialized_cache()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51899,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
FileCacheOptions = new FileCacheOptions
|
||||
{
|
||||
TtlSeconds = 100
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51899", 200, "Hello from Laura", null, null))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunningUsingJsonSerializedCache())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.Given(x => x.GivenTheServiceNowReturns("http://localhost:51899", 200, "Hello from Tom"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_return_cached_response_as_ttl_expires()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51899,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
FileCacheOptions = new FileCacheOptions
|
||||
{
|
||||
TtlSeconds = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51899", 200, "Hello from Laura", null, null))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.Given(x => x.GivenTheServiceNowReturns("http://localhost:51899", 200, "Hello from Tom"))
|
||||
.And(x => x.GivenTheCacheExpires())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Tom"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheCacheExpires()
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
private void GivenTheServiceNowReturns(string url, int statusCode, string responseBody)
|
||||
{
|
||||
_serviceHandler.Dispose();
|
||||
GivenThereIsAServiceRunningOn(url, statusCode, responseBody, null, null);
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody, string key, string value)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(url, async context =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(key))
|
||||
{
|
||||
context.Response.Headers.Add(key, value);
|
||||
}
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler?.Dispose();
|
||||
_steps.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using Configuration.File;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class CachingTests : IDisposable
|
||||
{
|
||||
private readonly Steps _steps;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public CachingTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
_steps = new Steps();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_cached_response()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 57899,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
FileCacheOptions = new FileCacheOptions
|
||||
{
|
||||
TtlSeconds = 100
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:57899", 200, "Hello from Laura", null, null))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.Given(x => x.GivenTheServiceNowReturns("http://localhost:57899", 200, "Hello from Tom"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.And(x => _steps.ThenTheContentLengthIs(16))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_cached_response_with_expires_header()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 52839,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
FileCacheOptions = new FileCacheOptions
|
||||
{
|
||||
TtlSeconds = 100
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:52839", 200, "Hello from Laura", "Expires", "-1"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.Given(x => x.GivenTheServiceNowReturns("http://localhost:52839", 200, "Hello from Tom"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.And(x => _steps.ThenTheContentLengthIs(16))
|
||||
.And(x => _steps.ThenTheResponseBodyHeaderIs("Expires", "-1"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_cached_response_when_using_jsonserialized_cache()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 57879,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
FileCacheOptions = new FileCacheOptions
|
||||
{
|
||||
TtlSeconds = 100
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:57879", 200, "Hello from Laura", null, null))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunningUsingJsonSerializedCache())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.Given(x => x.GivenTheServiceNowReturns("http://localhost:57879", 200, "Hello from Tom"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_return_cached_response_as_ttl_expires()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 57873,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
FileCacheOptions = new FileCacheOptions
|
||||
{
|
||||
TtlSeconds = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:57873", 200, "Hello from Laura", null, null))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.Given(x => x.GivenTheServiceNowReturns("http://localhost:57873", 200, "Hello from Tom"))
|
||||
.And(x => x.GivenTheCacheExpires())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Tom"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheCacheExpires()
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
private void GivenTheServiceNowReturns(string url, int statusCode, string responseBody)
|
||||
{
|
||||
_serviceHandler.Dispose();
|
||||
GivenThereIsAServiceRunningOn(url, statusCode, responseBody, null, null);
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody, string key, string value)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(url, async context =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(key))
|
||||
{
|
||||
context.Response.Headers.Add(key, value);
|
||||
}
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler?.Dispose();
|
||||
_steps.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 51179,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
@ -50,7 +50,7 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
var input = "people";
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Hello from Laura", "\"people\""))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51179", "/", 200, "Hello from Laura", "\"people\""))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.And(x => _steps.GivenThePostHasGzipContent(input))
|
||||
|
@ -1,446 +1,446 @@
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Configuration.File;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class HeaderTests : IDisposable
|
||||
{
|
||||
private int _count;
|
||||
private readonly Steps _steps;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public HeaderTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
_steps = new Steps();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_transform_upstream_header()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51871,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
UpstreamHeaderTransform = new Dictionary<string,string>
|
||||
{
|
||||
{"Laz", "D, GP"}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51871", "/", 200, "Laz"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.And(x => _steps.GivenIAddAHeader("Laz", "D"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("GP"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_transform_downstream_header()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51871,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
DownstreamHeaderTransform = new Dictionary<string,string>
|
||||
{
|
||||
{"Location", "http://www.bbc.co.uk/, http://ocelot.com/"}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51871", "/", 200, "Location", "http://www.bbc.co.uk/"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseHeaderIs("Location", "http://ocelot.com/"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_fix_issue_190()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 6773,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
DownstreamHeaderTransform = new Dictionary<string,string>
|
||||
{
|
||||
{"Location", "http://localhost:6773, {BaseUrl}"}
|
||||
},
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions
|
||||
{
|
||||
AllowAutoRedirect = false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:6773", "/", 302, "Location", "http://localhost:6773/pay/Receive"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Redirect))
|
||||
.And(x => _steps.ThenTheResponseHeaderIs("Location", "http://localhost:5000/pay/Receive"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_fix_issue_205()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 6773,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
DownstreamHeaderTransform = new Dictionary<string,string>
|
||||
{
|
||||
{"Location", "{DownstreamBaseUrl}, {BaseUrl}"}
|
||||
},
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions
|
||||
{
|
||||
AllowAutoRedirect = false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:6773", "/", 302, "Location", "http://localhost:6773/pay/Receive"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Redirect))
|
||||
.And(x => _steps.ThenTheResponseHeaderIs("Location", "http://localhost:5000/pay/Receive"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_fix_issue_417()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 6773,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
DownstreamHeaderTransform = new Dictionary<string,string>
|
||||
{
|
||||
{"Location", "{DownstreamBaseUrl}, {BaseUrl}"}
|
||||
},
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions
|
||||
{
|
||||
AllowAutoRedirect = false
|
||||
}
|
||||
}
|
||||
},
|
||||
GlobalConfiguration = new FileGlobalConfiguration
|
||||
{
|
||||
BaseUrl = "http://anotherapp.azurewebsites.net"
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:6773", "/", 302, "Location", "http://localhost:6773/pay/Receive"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Redirect))
|
||||
.And(x => _steps.ThenTheResponseHeaderIs("Location", "http://anotherapp.azurewebsites.net/pay/Receive"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void request_should_reuse_cookies_with_cookie_container()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/sso/{everything}",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 6774,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/sso/{everything}",
|
||||
UpstreamHttpMethod = new List<string> { "Get", "Post", "Options" },
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions
|
||||
{
|
||||
UseCookieContainer = true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:6774", "/sso/test", 200))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/sso/test"))
|
||||
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseHeaderIs("Set-Cookie", "test=0; path=/"))
|
||||
.And(x => _steps.GivenIAddCookieToMyRequest("test=1; path=/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/sso/test"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void request_should_have_own_cookies_no_cookie_container()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/sso/{everything}",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 6775,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/sso/{everything}",
|
||||
UpstreamHttpMethod = new List<string> { "Get", "Post", "Options" },
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions
|
||||
{
|
||||
UseCookieContainer = false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:6775", "/sso/test", 200))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/sso/test"))
|
||||
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseHeaderIs("Set-Cookie", "test=0; path=/"))
|
||||
.And(x => _steps.GivenIAddCookieToMyRequest("test=1; path=/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/sso/test"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void issue_474_should_not_put_spaces_in_header()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Accept"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.And(x => _steps.GivenIAddAHeader("Accept", "text/html,application/xhtml+xml,application/xml;"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("text/html,application/xhtml+xml,application/xml;"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void issue_474_should_put_spaces_in_header()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Accept"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.And(x => _steps.GivenIAddAHeader("Accept", "text/html"))
|
||||
.And(x => _steps.GivenIAddAHeader("Accept", "application/xhtml+xml"))
|
||||
.And(x => _steps.GivenIAddAHeader("Accept", "application/xml"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("text/html, application/xhtml+xml, application/xml"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, basePath, context =>
|
||||
{
|
||||
if (_count == 0)
|
||||
{
|
||||
context.Response.Cookies.Append("test", "0");
|
||||
_count++;
|
||||
context.Response.StatusCode = statusCode;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
if (context.Request.Cookies.TryGetValue("test", out var cookieValue) || context.Request.Headers.TryGetValue("Set-Cookie", out var headerValue))
|
||||
{
|
||||
if (cookieValue == "0" || headerValue == "test=1; path=/")
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
context.Response.StatusCode = 500;
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode, string headerKey)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, basePath, async context =>
|
||||
{
|
||||
if (context.Request.Headers.TryGetValue(headerKey, out var values))
|
||||
{
|
||||
var result = values.First();
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode, string headerKey, string headerValue)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, basePath, context =>
|
||||
{
|
||||
context.Response.OnStarting(() =>
|
||||
{
|
||||
context.Response.Headers.Add(headerKey, headerValue);
|
||||
context.Response.StatusCode = statusCode;
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler?.Dispose();
|
||||
_steps.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Configuration.File;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class HeaderTests : IDisposable
|
||||
{
|
||||
private int _count;
|
||||
private readonly Steps _steps;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public HeaderTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
_steps = new Steps();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_transform_upstream_header()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51871,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
UpstreamHeaderTransform = new Dictionary<string,string>
|
||||
{
|
||||
{"Laz", "D, GP"}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51871", "/", 200, "Laz"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.And(x => _steps.GivenIAddAHeader("Laz", "D"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("GP"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_transform_downstream_header()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51871,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
DownstreamHeaderTransform = new Dictionary<string,string>
|
||||
{
|
||||
{"Location", "http://www.bbc.co.uk/, http://ocelot.com/"}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51871", "/", 200, "Location", "http://www.bbc.co.uk/"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseHeaderIs("Location", "http://ocelot.com/"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_fix_issue_190()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 6773,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
DownstreamHeaderTransform = new Dictionary<string,string>
|
||||
{
|
||||
{"Location", "http://localhost:6773, {BaseUrl}"}
|
||||
},
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions
|
||||
{
|
||||
AllowAutoRedirect = false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:6773", "/", 302, "Location", "http://localhost:6773/pay/Receive"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Redirect))
|
||||
.And(x => _steps.ThenTheResponseHeaderIs("Location", "http://localhost:5000/pay/Receive"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_fix_issue_205()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 6773,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
DownstreamHeaderTransform = new Dictionary<string,string>
|
||||
{
|
||||
{"Location", "{DownstreamBaseUrl}, {BaseUrl}"}
|
||||
},
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions
|
||||
{
|
||||
AllowAutoRedirect = false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:6773", "/", 302, "Location", "http://localhost:6773/pay/Receive"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Redirect))
|
||||
.And(x => _steps.ThenTheResponseHeaderIs("Location", "http://localhost:5000/pay/Receive"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_fix_issue_417()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 6773,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
DownstreamHeaderTransform = new Dictionary<string,string>
|
||||
{
|
||||
{"Location", "{DownstreamBaseUrl}, {BaseUrl}"}
|
||||
},
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions
|
||||
{
|
||||
AllowAutoRedirect = false
|
||||
}
|
||||
}
|
||||
},
|
||||
GlobalConfiguration = new FileGlobalConfiguration
|
||||
{
|
||||
BaseUrl = "http://anotherapp.azurewebsites.net"
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:6773", "/", 302, "Location", "http://localhost:6773/pay/Receive"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Redirect))
|
||||
.And(x => _steps.ThenTheResponseHeaderIs("Location", "http://anotherapp.azurewebsites.net/pay/Receive"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void request_should_reuse_cookies_with_cookie_container()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/sso/{everything}",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 6774,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/sso/{everything}",
|
||||
UpstreamHttpMethod = new List<string> { "Get", "Post", "Options" },
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions
|
||||
{
|
||||
UseCookieContainer = true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:6774", "/sso/test", 200))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/sso/test"))
|
||||
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseHeaderIs("Set-Cookie", "test=0; path=/"))
|
||||
.And(x => _steps.GivenIAddCookieToMyRequest("test=1; path=/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/sso/test"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void request_should_have_own_cookies_no_cookie_container()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/sso/{everything}",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 6775,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/sso/{everything}",
|
||||
UpstreamHttpMethod = new List<string> { "Get", "Post", "Options" },
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions
|
||||
{
|
||||
UseCookieContainer = false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:6775", "/sso/test", 200))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/sso/test"))
|
||||
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseHeaderIs("Set-Cookie", "test=0; path=/"))
|
||||
.And(x => _steps.GivenIAddCookieToMyRequest("test=1; path=/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/sso/test"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void issue_474_should_not_put_spaces_in_header()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 52866,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:52866", "/", 200, "Accept"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.And(x => _steps.GivenIAddAHeader("Accept", "text/html,application/xhtml+xml,application/xml;"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("text/html,application/xhtml+xml,application/xml;"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void issue_474_should_put_spaces_in_header()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51874,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51874", "/", 200, "Accept"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.And(x => _steps.GivenIAddAHeader("Accept", "text/html"))
|
||||
.And(x => _steps.GivenIAddAHeader("Accept", "application/xhtml+xml"))
|
||||
.And(x => _steps.GivenIAddAHeader("Accept", "application/xml"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("text/html, application/xhtml+xml, application/xml"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, basePath, context =>
|
||||
{
|
||||
if (_count == 0)
|
||||
{
|
||||
context.Response.Cookies.Append("test", "0");
|
||||
_count++;
|
||||
context.Response.StatusCode = statusCode;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
if (context.Request.Cookies.TryGetValue("test", out var cookieValue) || context.Request.Headers.TryGetValue("Set-Cookie", out var headerValue))
|
||||
{
|
||||
if (cookieValue == "0" || headerValue == "test=1; path=/")
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
context.Response.StatusCode = 500;
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode, string headerKey)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, basePath, async context =>
|
||||
{
|
||||
if (context.Request.Headers.TryGetValue(headerKey, out var values))
|
||||
{
|
||||
var result = values.First();
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode, string headerKey, string headerValue)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, basePath, context =>
|
||||
{
|
||||
context.Response.OnStarting(() =>
|
||||
{
|
||||
context.Response.Headers.Add(headerKey, headerValue);
|
||||
context.Response.StatusCode = statusCode;
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler?.Dispose();
|
||||
_steps.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,163 +1,163 @@
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using Configuration;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Configuration.File;
|
||||
using Requester;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class HttpClientCachingTests : IDisposable
|
||||
{
|
||||
private readonly Steps _steps;
|
||||
private string _downstreamPath;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public HttpClientCachingTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
_steps = new Steps();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_cache_one_http_client_same_re_route()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var cache = new FakeHttpClientCache();
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunningWithFakeHttpClientCache(cache))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.And(x => cache.Count.ShouldBe(1))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_cache_two_http_client_different_re_route()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
},
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/two",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/two",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var cache = new FakeHttpClientCache();
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunningWithFakeHttpClientCache(cache))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/two"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/two"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/two"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.And(x => cache.Count.ShouldBe(2))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string baseUrl, int statusCode, string responseBody)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, async context =>
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler.Dispose();
|
||||
_steps.Dispose();
|
||||
}
|
||||
|
||||
public class FakeHttpClientCache : IHttpClientCache
|
||||
{
|
||||
private readonly ConcurrentDictionary<DownstreamReRoute, IHttpClient> _httpClientsCache;
|
||||
|
||||
public FakeHttpClientCache()
|
||||
{
|
||||
_httpClientsCache = new ConcurrentDictionary<DownstreamReRoute, IHttpClient>();
|
||||
}
|
||||
|
||||
public void Set(DownstreamReRoute key, IHttpClient client, TimeSpan expirationTime)
|
||||
{
|
||||
_httpClientsCache.AddOrUpdate(key, client, (k, oldValue) => client);
|
||||
}
|
||||
|
||||
public IHttpClient Get(DownstreamReRoute key)
|
||||
{
|
||||
//todo handle error?
|
||||
return _httpClientsCache.TryGetValue(key, out var client) ? client : null;
|
||||
}
|
||||
|
||||
public int Count => _httpClientsCache.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using Configuration;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Configuration.File;
|
||||
using Requester;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class HttpClientCachingTests : IDisposable
|
||||
{
|
||||
private readonly Steps _steps;
|
||||
private string _downstreamPath;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public HttpClientCachingTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
_steps = new Steps();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_cache_one_http_client_same_re_route()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 58814,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var cache = new FakeHttpClientCache();
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:58814", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunningWithFakeHttpClientCache(cache))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.And(x => cache.Count.ShouldBe(1))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_cache_two_http_client_different_re_route()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 58817,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
},
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/two",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 58817,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/two",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var cache = new FakeHttpClientCache();
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:58817", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunningWithFakeHttpClientCache(cache))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/two"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/two"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/two"))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.And(x => cache.Count.ShouldBe(2))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string baseUrl, int statusCode, string responseBody)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, async context =>
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler.Dispose();
|
||||
_steps.Dispose();
|
||||
}
|
||||
|
||||
public class FakeHttpClientCache : IHttpClientCache
|
||||
{
|
||||
private readonly ConcurrentDictionary<DownstreamReRoute, IHttpClient> _httpClientsCache;
|
||||
|
||||
public FakeHttpClientCache()
|
||||
{
|
||||
_httpClientsCache = new ConcurrentDictionary<DownstreamReRoute, IHttpClient>();
|
||||
}
|
||||
|
||||
public void Set(DownstreamReRoute key, IHttpClient client, TimeSpan expirationTime)
|
||||
{
|
||||
_httpClientsCache.AddOrUpdate(key, client, (k, oldValue) => client);
|
||||
}
|
||||
|
||||
public IHttpClient Get(DownstreamReRoute key)
|
||||
{
|
||||
//todo handle error?
|
||||
return _httpClientsCache.TryGetValue(key, out var client) ? client : null;
|
||||
}
|
||||
|
||||
public int Count => _httpClientsCache.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<AssemblyName>Ocelot.AcceptanceTests</AssemblyName>
|
||||
<OutputType>Exe</OutputType>
|
||||
<PackageId>Ocelot.AcceptanceTests</PackageId>
|
||||
@ -40,6 +40,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
|
||||
<PackageReference Include="Moq" Version="4.13.0" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.66">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
@ -69,6 +70,6 @@
|
||||
<PackageReference Include="Pivotal.Discovery.ClientCore" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-19367-01" />
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,274 +1,274 @@
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using Configuration.File;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class PollyQoSTests : IDisposable
|
||||
{
|
||||
private readonly Steps _steps;
|
||||
private int _requestCount;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public PollyQoSTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
_steps = new Steps();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_timeout()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51569,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Post" },
|
||||
QoSOptions = new FileQoSOptions
|
||||
{
|
||||
TimeoutValue = 1000,
|
||||
ExceptionsAllowedBeforeBreaking = 10
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51569", 200, string.Empty, 10))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunningWithPolly())
|
||||
.And(x => _steps.GivenThePostHasContent("postContent"))
|
||||
.When(x => _steps.WhenIPostUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_timeout()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51579,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Post" },
|
||||
QoSOptions = new FileQoSOptions
|
||||
{
|
||||
TimeoutValue = 10,
|
||||
ExceptionsAllowedBeforeBreaking = 10
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51579", 201, string.Empty, 1000))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunningWithPolly())
|
||||
.And(x => _steps.GivenThePostHasContent("postContent"))
|
||||
.When(x => _steps.WhenIPostUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_open_circuit_breaker_then_close()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51892,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
QoSOptions = new FileQoSOptions
|
||||
{
|
||||
ExceptionsAllowedBeforeBreaking = 1,
|
||||
TimeoutValue = 500,
|
||||
DurationOfBreak = 1000
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAPossiblyBrokenServiceRunningOn("http://localhost:51892", "Hello from Laura"))
|
||||
.Given(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.Given(x => _steps.GivenOcelotIsRunningWithPolly())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.Given(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Given(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
|
||||
.Given(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Given(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
|
||||
.Given(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Given(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
|
||||
.Given(x => x.GivenIWaitMilliseconds(3000))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void open_circuit_should_not_effect_different_reRoute()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51872,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
QoSOptions = new FileQoSOptions
|
||||
{
|
||||
ExceptionsAllowedBeforeBreaking = 1,
|
||||
TimeoutValue = 500,
|
||||
DurationOfBreak = 1000
|
||||
}
|
||||
},
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51880,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/working",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAPossiblyBrokenServiceRunningOn("http://localhost:51872", "Hello from Laura"))
|
||||
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51880/", 200, "Hello from Tom", 0))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunningWithPolly())
|
||||
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
|
||||
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/working"))
|
||||
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Tom"))
|
||||
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
|
||||
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
|
||||
.And(x => x.GivenIWaitMilliseconds(3000))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenIWaitMilliseconds(int ms)
|
||||
{
|
||||
Thread.Sleep(ms);
|
||||
}
|
||||
|
||||
private void GivenThereIsAPossiblyBrokenServiceRunningOn(string url, string responseBody)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(url, async context =>
|
||||
{
|
||||
//circuit starts closed
|
||||
if (_requestCount == 0)
|
||||
{
|
||||
_requestCount++;
|
||||
context.Response.StatusCode = 200;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
return;
|
||||
}
|
||||
|
||||
//request one times out and polly throws exception, circuit opens
|
||||
if (_requestCount == 1)
|
||||
{
|
||||
_requestCount++;
|
||||
await Task.Delay(1000);
|
||||
context.Response.StatusCode = 200;
|
||||
return;
|
||||
}
|
||||
|
||||
//after break closes we return 200 OK
|
||||
if (_requestCount == 2)
|
||||
{
|
||||
context.Response.StatusCode = 200;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody, int timeout)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(url, async context =>
|
||||
{
|
||||
Thread.Sleep(timeout);
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler?.Dispose();
|
||||
_steps.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using Configuration.File;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class PollyQoSTests : IDisposable
|
||||
{
|
||||
private readonly Steps _steps;
|
||||
private int _requestCount;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public PollyQoSTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
_steps = new Steps();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_timeout()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51569,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Post" },
|
||||
QoSOptions = new FileQoSOptions
|
||||
{
|
||||
TimeoutValue = 1000,
|
||||
ExceptionsAllowedBeforeBreaking = 10
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51569", 200, string.Empty, 10))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunningWithPolly())
|
||||
.And(x => _steps.GivenThePostHasContent("postContent"))
|
||||
.When(x => _steps.WhenIPostUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_timeout()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51579,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Post" },
|
||||
QoSOptions = new FileQoSOptions
|
||||
{
|
||||
TimeoutValue = 10,
|
||||
ExceptionsAllowedBeforeBreaking = 10
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51579", 201, string.Empty, 1000))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunningWithPolly())
|
||||
.And(x => _steps.GivenThePostHasContent("postContent"))
|
||||
.When(x => _steps.WhenIPostUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_open_circuit_breaker_then_close()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51892,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
QoSOptions = new FileQoSOptions
|
||||
{
|
||||
ExceptionsAllowedBeforeBreaking = 1,
|
||||
TimeoutValue = 500,
|
||||
DurationOfBreak = 1000
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAPossiblyBrokenServiceRunningOn("http://localhost:51892", "Hello from Laura"))
|
||||
.Given(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.Given(x => _steps.GivenOcelotIsRunningWithPolly())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.Given(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Given(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
|
||||
.Given(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Given(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
|
||||
.Given(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Given(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
|
||||
.Given(x => x.GivenIWaitMilliseconds(3000))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void open_circuit_should_not_effect_different_reRoute()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51870,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
QoSOptions = new FileQoSOptions
|
||||
{
|
||||
ExceptionsAllowedBeforeBreaking = 1,
|
||||
TimeoutValue = 500,
|
||||
DurationOfBreak = 1000
|
||||
}
|
||||
},
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51880,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/working",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAPossiblyBrokenServiceRunningOn("http://localhost:51870", "Hello from Laura"))
|
||||
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51880/", 200, "Hello from Tom", 0))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunningWithPolly())
|
||||
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
|
||||
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/working"))
|
||||
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Tom"))
|
||||
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
|
||||
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.ServiceUnavailable))
|
||||
.And(x => x.GivenIWaitMilliseconds(3000))
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenIWaitMilliseconds(int ms)
|
||||
{
|
||||
Thread.Sleep(ms);
|
||||
}
|
||||
|
||||
private void GivenThereIsAPossiblyBrokenServiceRunningOn(string url, string responseBody)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(url, async context =>
|
||||
{
|
||||
//circuit starts closed
|
||||
if (_requestCount == 0)
|
||||
{
|
||||
_requestCount++;
|
||||
context.Response.StatusCode = 200;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
return;
|
||||
}
|
||||
|
||||
//request one times out and polly throws exception, circuit opens
|
||||
if (_requestCount == 1)
|
||||
{
|
||||
_requestCount++;
|
||||
await Task.Delay(1000);
|
||||
context.Response.StatusCode = 200;
|
||||
return;
|
||||
}
|
||||
|
||||
//after break closes we return 200 OK
|
||||
if (_requestCount == 2)
|
||||
{
|
||||
context.Response.StatusCode = 200;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody, int timeout)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(url, async context =>
|
||||
{
|
||||
Thread.Sleep(timeout);
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(responseBody);
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler?.Dispose();
|
||||
_steps.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,68 +1,68 @@
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using Ocelot.Configuration.File;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class ResponseCodeTests : IDisposable
|
||||
{
|
||||
private readonly Steps _steps;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public ResponseCodeTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
_steps = new Steps();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_304_when_service_returns_304()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/{everything}",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/{everything}",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/inline.132.bundle.js", 304))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/inline.132.bundle.js"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.NotModified))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, basePath, async context =>
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler?.Dispose();
|
||||
_steps.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
using Ocelot.Configuration.File;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class ResponseCodeTests : IDisposable
|
||||
{
|
||||
private readonly Steps _steps;
|
||||
private readonly ServiceHandler _serviceHandler;
|
||||
|
||||
public ResponseCodeTests()
|
||||
{
|
||||
_serviceHandler = new ServiceHandler();
|
||||
_steps = new Steps();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_response_304_when_service_returns_304()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/{everything}",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51092,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/{everything}",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51092", "/inline.132.bundle.js", 304))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/inline.132.bundle.js"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.NotModified))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode)
|
||||
{
|
||||
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, basePath, async context =>
|
||||
{
|
||||
context.Response.StatusCode = statusCode;
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_serviceHandler?.Dispose();
|
||||
_steps.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,8 @@
|
||||
|
||||
[Fact]
|
||||
public void should_return_internal_server_error_if_downstream_service_returns_internal_server_error()
|
||||
{
|
||||
{
|
||||
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
@ -81,6 +82,39 @@
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.InternalServerError))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_log_warning_if_downstream_service_returns_internal_server_error()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 53876,
|
||||
},
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:53876"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunningWithLogger())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => _steps.ThenWarningShouldBeLogged())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url)
|
||||
|
@ -84,14 +84,14 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 57873,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879/", "/", 200, "Hello from Laura"))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:57873/", "/", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
@ -131,7 +131,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 50810,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
@ -180,7 +180,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 50810,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
@ -189,7 +189,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879/", "/", 200, "Hello from Laura"))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:50810/", "/", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
@ -263,7 +263,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 51005,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/{url}",
|
||||
@ -272,7 +272,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Hello from Laura"))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51005", "/", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway(""))
|
||||
@ -297,7 +297,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 58589,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
@ -306,7 +306,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Hello from Laura"))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:58589", "/", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
@ -382,7 +382,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 51206,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
@ -391,7 +391,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/products", 200, "Hello from Laura"))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51206", "/api/products", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
@ -416,7 +416,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 51990,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
@ -425,7 +425,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/products", 200, "Hello from Laura"))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51990", "/api/products", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
@ -450,7 +450,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 58804,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/products/",
|
||||
@ -459,7 +459,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/products", 200, "Hello from Laura"))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:58804", "/products", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/products"))
|
||||
@ -484,7 +484,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 54015,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/products",
|
||||
@ -493,7 +493,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/products", 200, "Hello from Laura"))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:54015", "/products", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/products/"))
|
||||
@ -517,7 +517,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 54072,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/products/{productId}",
|
||||
@ -526,7 +526,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/products", 200, "Hello from Laura"))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:54072", "/products", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/products/"))
|
||||
@ -550,7 +550,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 55961,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/products/{productId}",
|
||||
@ -559,7 +559,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/products/1", 200, "Some Product"))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:55961", "/api/products/1", 200, "Some Product"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/products/1"))
|
||||
@ -584,7 +584,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 51116,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/{variantId}/products/{productId}",
|
||||
@ -593,7 +593,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/23/products/1", 200, "Some Product"))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51116", "/api/23/products/1", 200, "Some Product"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("23/products/1"))
|
||||
@ -618,7 +618,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 51809,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/products/{productId}",
|
||||
@ -627,7 +627,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/products/1", 200, "Some Product"))
|
||||
this.Given(x => GivenThereIsAServiceRunningOn("http://localhost:51809", "/api/products/1", 200, "Some Product"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/products/1"))
|
||||
@ -650,7 +650,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 56615,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
@ -660,7 +660,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 201, string.Empty))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:56615", "/", 201, string.Empty))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.And(x => _steps.GivenThePostHasContent("postContent"))
|
||||
@ -686,7 +686,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 57771,
|
||||
}
|
||||
},
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
@ -694,7 +694,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/newThing", 200, "Hello from Laura"))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:57771", "/newThing", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/newThing?DeviceType=IphoneApp&Browser=moonpigIphone&BrowserString=-&CountryCode=123&DeviceName=iPhone 5 (GSM+CDMA)&OperatingSystem=iPhone OS 7.1.2&BrowserVersion=3708AdHoc&ipAddress=-"))
|
||||
@ -719,7 +719,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 55609,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/myApp1Name/api/{urlPath}",
|
||||
@ -728,7 +728,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/products/1", 200, "Some Product"))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:55609", "/api/products/1", 200, "Some Product"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/myApp1Name/api/products/1"))
|
||||
@ -752,7 +752,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 59911,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
@ -762,7 +762,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "", 201, string.Empty))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:59911", "", 201, string.Empty))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.And(x => _steps.GivenThePostHasContent("postContent"))
|
||||
@ -786,7 +786,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 59187,
|
||||
}
|
||||
},
|
||||
DownstreamScheme = "http",
|
||||
@ -796,7 +796,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Hello from Laura"))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:59187", "/", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||
@ -821,7 +821,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 54079,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/vacancy/",
|
||||
@ -837,7 +837,7 @@ namespace Ocelot.AcceptanceTests
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
Port = 54079,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/vacancy/{vacancyId}",
|
||||
@ -847,7 +847,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/v1/vacancy/1", 200, "Hello from Laura"))
|
||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:54079", "/api/v1/vacancy/1", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunning())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("api/vacancy/1"))
|
||||
|
@ -10,12 +10,14 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using Ocelot.Cache.CacheManager;
|
||||
using Ocelot.Configuration.Creator;
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.DependencyInjection;
|
||||
using Ocelot.Infrastructure;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Middleware.Multiplexer;
|
||||
using Ocelot.Provider.Consul;
|
||||
@ -1120,5 +1122,60 @@
|
||||
|
||||
_ocelotClient = _ocelotServer.CreateClient();
|
||||
}
|
||||
|
||||
public void GivenOcelotIsRunningWithLogger()
|
||||
{
|
||||
_webHostBuilder = new WebHostBuilder();
|
||||
|
||||
_webHostBuilder
|
||||
.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.AddEnvironmentVariables();
|
||||
})
|
||||
.ConfigureServices(s =>
|
||||
{
|
||||
s.AddOcelot();
|
||||
s.AddSingleton<IOcelotLoggerFactory, MockLoggerFactory>();
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseOcelot().Wait();
|
||||
});
|
||||
|
||||
_ocelotServer = new TestServer(_webHostBuilder);
|
||||
|
||||
_ocelotClient = _ocelotServer.CreateClient();
|
||||
}
|
||||
|
||||
public void ThenWarningShouldBeLogged()
|
||||
{
|
||||
MockLoggerFactory loggerFactory = (MockLoggerFactory)_ocelotServer.Host.Services.GetService<IOcelotLoggerFactory>();
|
||||
loggerFactory.Verify();
|
||||
}
|
||||
|
||||
internal class MockLoggerFactory : IOcelotLoggerFactory
|
||||
{
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
|
||||
public IOcelotLogger CreateLogger<T>()
|
||||
{
|
||||
if (_logger == null)
|
||||
{
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_logger.Setup(x => x.LogWarning(It.IsAny<string>())).Verifiable();
|
||||
}
|
||||
return _logger.Object;
|
||||
}
|
||||
|
||||
public void Verify()
|
||||
{
|
||||
_logger.Verify(x => x.LogWarning(It.IsAny<string>()), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<AssemblyName>Ocelot.Benchmarks</AssemblyName>
|
||||
<OutputType>Exe</OutputType>
|
||||
<PackageId>Ocelot.Benchmarks</PackageId>
|
||||
@ -25,6 +25,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-19367-01" />
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
File diff suppressed because it is too large
Load Diff
@ -1,199 +1,199 @@
|
||||
using Xunit;
|
||||
|
||||
[assembly: CollectionBehavior(DisableTestParallelization = true)]
|
||||
|
||||
namespace Ocelot.IntegrationTests
|
||||
{
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.DependencyInjection;
|
||||
using Ocelot.Middleware;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
|
||||
public class HeaderTests : IDisposable
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private IWebHost _builder;
|
||||
private IWebHostBuilder _webHostBuilder;
|
||||
private readonly string _ocelotBaseUrl;
|
||||
private IWebHost _downstreamBuilder;
|
||||
private HttpResponseMessage _response;
|
||||
|
||||
public HeaderTests()
|
||||
{
|
||||
_httpClient = new HttpClient();
|
||||
_ocelotBaseUrl = "http://localhost:5005";
|
||||
_httpClient.BaseAddress = new Uri(_ocelotBaseUrl);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_pass_remote_ip_address_if_as_x_forwarded_for_header()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 6773,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
UpstreamHeaderTransform = new Dictionary<string,string>
|
||||
{
|
||||
{"X-Forwarded-For", "{RemoteIpAddress}"}
|
||||
},
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions
|
||||
{
|
||||
AllowAutoRedirect = false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => GivenThereIsAServiceRunningOn("http://localhost:6773", 200, "X-Forwarded-For"))
|
||||
.And(x => GivenThereIsAConfiguration(configuration))
|
||||
.And(x => GivenOcelotIsRunning())
|
||||
.When(x => WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => ThenXForwardedForIsSet())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string headerKey)
|
||||
{
|
||||
_downstreamBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.Configure(app =>
|
||||
{
|
||||
app.Run(async context =>
|
||||
{
|
||||
if (context.Request.Headers.TryGetValue(headerKey, out var values))
|
||||
{
|
||||
var result = values.First();
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(result);
|
||||
}
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
_downstreamBuilder.Start();
|
||||
}
|
||||
|
||||
private void GivenOcelotIsRunning()
|
||||
{
|
||||
_webHostBuilder = new WebHostBuilder()
|
||||
.UseUrls(_ocelotBaseUrl)
|
||||
.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.AddEnvironmentVariables();
|
||||
})
|
||||
.ConfigureServices(x =>
|
||||
{
|
||||
x.AddOcelot();
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseOcelot().Wait();
|
||||
});
|
||||
|
||||
_builder = _webHostBuilder.Build();
|
||||
|
||||
_builder.Start();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public async Task WhenIGetUrlOnTheApiGateway(string url)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
_response = await _httpClient.SendAsync(request);
|
||||
}
|
||||
|
||||
private void ThenTheStatusCodeShouldBe(HttpStatusCode code)
|
||||
{
|
||||
_response.StatusCode.ShouldBe(code);
|
||||
}
|
||||
|
||||
private void ThenXForwardedForIsSet()
|
||||
{
|
||||
var windowsOrMac = "::1";
|
||||
var linux = "127.0.0.1";
|
||||
|
||||
var header = _response.Content.ReadAsStringAsync().Result;
|
||||
|
||||
bool passed = false;
|
||||
|
||||
if (header == windowsOrMac || header == linux)
|
||||
{
|
||||
passed = true;
|
||||
}
|
||||
|
||||
passed.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_builder?.Dispose();
|
||||
_httpClient?.Dispose();
|
||||
_downstreamBuilder?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
using Xunit;
|
||||
|
||||
[assembly: CollectionBehavior(DisableTestParallelization = true)]
|
||||
|
||||
namespace Ocelot.IntegrationTests
|
||||
{
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.DependencyInjection;
|
||||
using Ocelot.Middleware;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
|
||||
public class HeaderTests : IDisposable
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private IWebHost _builder;
|
||||
private IWebHostBuilder _webHostBuilder;
|
||||
private readonly string _ocelotBaseUrl;
|
||||
private IWebHost _downstreamBuilder;
|
||||
private HttpResponseMessage _response;
|
||||
|
||||
public HeaderTests()
|
||||
{
|
||||
_httpClient = new HttpClient();
|
||||
_ocelotBaseUrl = "http://localhost:5010";
|
||||
_httpClient.BaseAddress = new Uri(_ocelotBaseUrl);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_pass_remote_ip_address_if_as_x_forwarded_for_header()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 6773,
|
||||
}
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
UpstreamHeaderTransform = new Dictionary<string,string>
|
||||
{
|
||||
{"X-Forwarded-For", "{RemoteIpAddress}"}
|
||||
},
|
||||
HttpHandlerOptions = new FileHttpHandlerOptions
|
||||
{
|
||||
AllowAutoRedirect = false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => GivenThereIsAServiceRunningOn("http://localhost:6773", 200, "X-Forwarded-For"))
|
||||
.And(x => GivenThereIsAConfiguration(configuration))
|
||||
.And(x => GivenOcelotIsRunning())
|
||||
.When(x => WhenIGetUrlOnTheApiGateway("/"))
|
||||
.Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => ThenXForwardedForIsSet())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string headerKey)
|
||||
{
|
||||
_downstreamBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.Configure(app =>
|
||||
{
|
||||
app.Run(async context =>
|
||||
{
|
||||
if (context.Request.Headers.TryGetValue(headerKey, out var values))
|
||||
{
|
||||
var result = values.First();
|
||||
context.Response.StatusCode = statusCode;
|
||||
await context.Response.WriteAsync(result);
|
||||
}
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
_downstreamBuilder.Start();
|
||||
}
|
||||
|
||||
private void GivenOcelotIsRunning()
|
||||
{
|
||||
_webHostBuilder = new WebHostBuilder()
|
||||
.UseUrls(_ocelotBaseUrl)
|
||||
.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.AddEnvironmentVariables();
|
||||
})
|
||||
.ConfigureServices(x =>
|
||||
{
|
||||
x.AddOcelot();
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseOcelot().Wait();
|
||||
});
|
||||
|
||||
_builder = _webHostBuilder.Build();
|
||||
|
||||
_builder.Start();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public async Task WhenIGetUrlOnTheApiGateway(string url)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
_response = await _httpClient.SendAsync(request);
|
||||
}
|
||||
|
||||
private void ThenTheStatusCodeShouldBe(HttpStatusCode code)
|
||||
{
|
||||
_response.StatusCode.ShouldBe(code);
|
||||
}
|
||||
|
||||
private void ThenXForwardedForIsSet()
|
||||
{
|
||||
var windowsOrMac = "::1";
|
||||
var linux = "127.0.0.1";
|
||||
|
||||
var header = _response.Content.ReadAsStringAsync().Result;
|
||||
|
||||
bool passed = false;
|
||||
|
||||
if (header == windowsOrMac || header == linux)
|
||||
{
|
||||
passed = true;
|
||||
}
|
||||
|
||||
passed.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_builder?.Dispose();
|
||||
_httpClient?.Dispose();
|
||||
_downstreamBuilder?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +1,61 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||
<TargetFramework>netcoreapp3.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" />
|
||||
<ProjectReference Include="..\..\src\Ocelot.Provider.Rafty\Ocelot.Provider.Rafty.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
|
||||
<PackageReference Include="Microsoft.Data.SQLite" Version="3.0.0" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.66">
|
||||
<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.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.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.0-beta0002" />
|
||||
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
||||
<PackageReference Include="Microsoft.Data.SQLite" Version="3.0.0" />
|
||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
|
||||
<PackageReference Include="IdentityServer4" Version="3.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-19367-01" />
|
||||
</ItemGroup>
|
||||
<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.3.0" />
|
||||
<PackageReference Include="Microsoft.Data.SQLite" Version="3.0.0" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.66">
|
||||
<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.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.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.0-beta0002" />
|
||||
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
|
||||
<PackageReference Include="Microsoft.Data.SQLite" Version="3.0.0" />
|
||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
|
||||
<PackageReference Include="IdentityServer4" Version="3.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,204 +1,204 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.DependencyInjection;
|
||||
using Ocelot.Middleware;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.IntegrationTests
|
||||
{
|
||||
public class ThreadSafeHeadersTests : IDisposable
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private IWebHost _builder;
|
||||
private IWebHostBuilder _webHostBuilder;
|
||||
private readonly string _ocelotBaseUrl;
|
||||
private IWebHost _downstreamBuilder;
|
||||
private readonly Random _random;
|
||||
private readonly ConcurrentBag<ThreadSafeHeadersTestResult> _results;
|
||||
|
||||
public ThreadSafeHeadersTests()
|
||||
{
|
||||
_results = new ConcurrentBag<ThreadSafeHeadersTestResult>();
|
||||
_random = new Random();
|
||||
_httpClient = new HttpClient();
|
||||
_ocelotBaseUrl = "http://localhost:5001";
|
||||
_httpClient.BaseAddress = new Uri(_ocelotBaseUrl);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_same_response_for_each_different_header_under_load_to_downsteam_service()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51879,
|
||||
},
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => GivenThereIsAConfiguration(configuration))
|
||||
.And(x => GivenThereIsAServiceRunningOn("http://localhost:51879"))
|
||||
.And(x => GivenOcelotIsRunning())
|
||||
.When(x => WhenIGetUrlOnTheApiGatewayMultipleTimesWithDifferentHeaderValues("/", 300))
|
||||
.Then(x => ThenTheSameHeaderValuesAreReturnedByTheDownstreamService())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url)
|
||||
{
|
||||
_downstreamBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.Configure(app =>
|
||||
{
|
||||
app.Run(async context =>
|
||||
{
|
||||
var header = context.Request.Headers["ThreadSafeHeadersTest"];
|
||||
|
||||
context.Response.StatusCode = 200;
|
||||
await context.Response.WriteAsync(header[0]);
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
_downstreamBuilder.Start();
|
||||
}
|
||||
|
||||
private void GivenOcelotIsRunning()
|
||||
{
|
||||
_webHostBuilder = new WebHostBuilder()
|
||||
.UseUrls(_ocelotBaseUrl)
|
||||
.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.AddEnvironmentVariables();
|
||||
})
|
||||
.ConfigureServices(x =>
|
||||
{
|
||||
x.AddOcelot();
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseOcelot().Wait();
|
||||
});
|
||||
|
||||
_builder = _webHostBuilder.Build();
|
||||
|
||||
_builder.Start();
|
||||
}
|
||||
|
||||
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 WhenIGetUrlOnTheApiGatewayMultipleTimesWithDifferentHeaderValues(string url, int times)
|
||||
{
|
||||
var tasks = new Task[times];
|
||||
|
||||
for (int i = 0; i < times; i++)
|
||||
{
|
||||
var urlCopy = url;
|
||||
var random = _random.Next(0, 50);
|
||||
tasks[i] = GetForThreadSafeHeadersTest(urlCopy, random);
|
||||
}
|
||||
|
||||
Task.WaitAll(tasks);
|
||||
}
|
||||
|
||||
private async Task GetForThreadSafeHeadersTest(string url, int random)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
request.Headers.Add("ThreadSafeHeadersTest", new List<string> { random.ToString() });
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
int result = int.Parse(content);
|
||||
var tshtr = new ThreadSafeHeadersTestResult(result, random);
|
||||
_results.Add(tshtr);
|
||||
}
|
||||
|
||||
private void ThenTheSameHeaderValuesAreReturnedByTheDownstreamService()
|
||||
{
|
||||
foreach (var result in _results)
|
||||
{
|
||||
result.Result.ShouldBe(result.Random);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_builder?.Dispose();
|
||||
_httpClient?.Dispose();
|
||||
_downstreamBuilder?.Dispose();
|
||||
}
|
||||
|
||||
private class ThreadSafeHeadersTestResult
|
||||
{
|
||||
public ThreadSafeHeadersTestResult(int result, int random)
|
||||
{
|
||||
Result = result;
|
||||
Random = random;
|
||||
}
|
||||
|
||||
public int Result { get; private set; }
|
||||
public int Random { get; private set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.DependencyInjection;
|
||||
using Ocelot.Middleware;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.IntegrationTests
|
||||
{
|
||||
public class ThreadSafeHeadersTests : IDisposable
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private IWebHost _builder;
|
||||
private IWebHostBuilder _webHostBuilder;
|
||||
private readonly string _ocelotBaseUrl;
|
||||
private IWebHost _downstreamBuilder;
|
||||
private readonly Random _random;
|
||||
private readonly ConcurrentBag<ThreadSafeHeadersTestResult> _results;
|
||||
|
||||
public ThreadSafeHeadersTests()
|
||||
{
|
||||
_results = new ConcurrentBag<ThreadSafeHeadersTestResult>();
|
||||
_random = new Random();
|
||||
_httpClient = new HttpClient();
|
||||
_ocelotBaseUrl = "http://localhost:5001";
|
||||
_httpClient.BaseAddress = new Uri(_ocelotBaseUrl);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_same_response_for_each_different_header_under_load_to_downsteam_service()
|
||||
{
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||
{
|
||||
new FileHostAndPort
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = 51611,
|
||||
},
|
||||
},
|
||||
UpstreamPathTemplate = "/",
|
||||
UpstreamHttpMethod = new List<string> { "Get" },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.Given(x => GivenThereIsAConfiguration(configuration))
|
||||
.And(x => GivenThereIsAServiceRunningOn("http://localhost:51611"))
|
||||
.And(x => GivenOcelotIsRunning())
|
||||
.When(x => WhenIGetUrlOnTheApiGatewayMultipleTimesWithDifferentHeaderValues("/", 300))
|
||||
.Then(x => ThenTheSameHeaderValuesAreReturnedByTheDownstreamService())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url)
|
||||
{
|
||||
_downstreamBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls(url)
|
||||
.Configure(app =>
|
||||
{
|
||||
app.Run(async context =>
|
||||
{
|
||||
var header = context.Request.Headers["ThreadSafeHeadersTest"];
|
||||
|
||||
context.Response.StatusCode = 200;
|
||||
await context.Response.WriteAsync(header[0]);
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
_downstreamBuilder.Start();
|
||||
}
|
||||
|
||||
private void GivenOcelotIsRunning()
|
||||
{
|
||||
_webHostBuilder = new WebHostBuilder()
|
||||
.UseUrls(_ocelotBaseUrl)
|
||||
.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.AddEnvironmentVariables();
|
||||
})
|
||||
.ConfigureServices(x =>
|
||||
{
|
||||
x.AddOcelot();
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseOcelot().Wait();
|
||||
});
|
||||
|
||||
_builder = _webHostBuilder.Build();
|
||||
|
||||
_builder.Start();
|
||||
}
|
||||
|
||||
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 WhenIGetUrlOnTheApiGatewayMultipleTimesWithDifferentHeaderValues(string url, int times)
|
||||
{
|
||||
var tasks = new Task[times];
|
||||
|
||||
for (int i = 0; i < times; i++)
|
||||
{
|
||||
var urlCopy = url;
|
||||
var random = _random.Next(0, 50);
|
||||
tasks[i] = GetForThreadSafeHeadersTest(urlCopy, random);
|
||||
}
|
||||
|
||||
Task.WaitAll(tasks);
|
||||
}
|
||||
|
||||
private async Task GetForThreadSafeHeadersTest(string url, int random)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||
request.Headers.Add("ThreadSafeHeadersTest", new List<string> { random.ToString() });
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
int result = int.Parse(content);
|
||||
var tshtr = new ThreadSafeHeadersTestResult(result, random);
|
||||
_results.Add(tshtr);
|
||||
}
|
||||
|
||||
private void ThenTheSameHeaderValuesAreReturnedByTheDownstreamService()
|
||||
{
|
||||
foreach (var result in _results)
|
||||
{
|
||||
result.Result.ShouldBe(result.Random);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_builder?.Dispose();
|
||||
_httpClient?.Dispose();
|
||||
_downstreamBuilder?.Dispose();
|
||||
}
|
||||
|
||||
private class ThreadSafeHeadersTestResult
|
||||
{
|
||||
public ThreadSafeHeadersTestResult(int result, int random)
|
||||
{
|
||||
Result = result;
|
||||
Random = random;
|
||||
}
|
||||
|
||||
public int Result { get; private set; }
|
||||
public int Random { get; private set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,45 +1,45 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
<AssemblyName>Ocelot.ManualTest</AssemblyName>
|
||||
<OutputType>Exe</OutputType>
|
||||
<PackageId>Ocelot.ManualTest</PackageId>
|
||||
<RuntimeIdentifiers>osx.10.11-x64;osx.10.12-x64;win7-x64;win10-x64</RuntimeIdentifiers>
|
||||
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Views;Areas\**\Views">
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="ocelot.json">
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="ocelot.json;appsettings.json;idsrv3test.pfx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.0.0" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.66">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-19367-01" />
|
||||
</ItemGroup>
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
<AssemblyName>Ocelot.ManualTest</AssemblyName>
|
||||
<OutputType>Exe</OutputType>
|
||||
<PackageId>Ocelot.ManualTest</PackageId>
|
||||
<RuntimeIdentifiers>osx.10.11-x64;osx.10.12-x64;win7-x64;win10-x64</RuntimeIdentifiers>
|
||||
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Views;Areas\**\Views">
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="ocelot.json">
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="ocelot.json;appsettings.json;idsrv3test.pfx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.0.0" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.66">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -41,14 +41,14 @@ namespace Ocelot.UnitTests.Configuration
|
||||
_internalConfigCreator = new Mock<IInternalConfigurationCreator>();
|
||||
_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.StartAsync(new CancellationToken());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_start()
|
||||
{
|
||||
this.Given(x => ThenTheSetterIsCalled(_fileConfig, 1))
|
||||
.BDDfy();
|
||||
this.Given(x => GivenPollerHasStarted())
|
||||
.Given(x => ThenTheSetterIsCalled(_fileConfig, 1))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[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))
|
||||
.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))
|
||||
.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))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_dispose_cleanly_without_starting()
|
||||
{
|
||||
this.When(x => WhenPollerIsDisposed())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenPollerHasStarted()
|
||||
{
|
||||
_poller.StartAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
private void WhenProviderErrors()
|
||||
{
|
||||
_repo
|
||||
@ -141,6 +156,11 @@ namespace Ocelot.UnitTests.Configuration
|
||||
.ReturnsAsync(new OkResponse<FileConfiguration>(newConfig));
|
||||
}
|
||||
|
||||
private void WhenPollerIsDisposed()
|
||||
{
|
||||
_poller.Dispose();
|
||||
}
|
||||
|
||||
private void ThenTheSetterIsCalled(FileConfiguration fileConfig, int times)
|
||||
{
|
||||
var result = WaitFor(4000).Until(() =>
|
||||
|
@ -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))
|
||||
.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))
|
||||
.And(x => GivenARealTracer())
|
||||
@ -73,7 +73,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
public void should_create_options_with_useCookie_false_and_allowAutoRedirect_true_as_default()
|
||||
{
|
||||
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))
|
||||
.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))
|
||||
.When(x => WhenICreateHttpHandlerOptions())
|
||||
@ -110,7 +110,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
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))
|
||||
.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))
|
||||
.When(x => WhenICreateHttpHandlerOptions())
|
||||
@ -154,6 +211,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
_httpHandlerOptions.UseCookieContainer.ShouldBe(expected.UseCookieContainer);
|
||||
_httpHandlerOptions.UseTracing.ShouldBe(expected.UseTracing);
|
||||
_httpHandlerOptions.UseProxy.ShouldBe(expected.UseProxy);
|
||||
_httpHandlerOptions.MaxConnectionsPerServer.ShouldBe(expected.MaxConnectionsPerServer);
|
||||
}
|
||||
|
||||
private void GivenARealTracer()
|
||||
|
@ -50,7 +50,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
};
|
||||
var expected = new RateLimitOptionsBuilder()
|
||||
.WithClientIdHeader("ClientIdHeader")
|
||||
.WithClientWhiteList(fileReRoute.RateLimitOptions.ClientWhitelist)
|
||||
.WithClientWhiteList(() => fileReRoute.RateLimitOptions.ClientWhitelist)
|
||||
.WithDisableRateLimitHeaders(true)
|
||||
.WithEnableRateLimiting(true)
|
||||
.WithHttpStatusCode(200)
|
||||
|
@ -1341,6 +1341,32 @@
|
||||
.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)
|
||||
{
|
||||
_fileConfiguration = fileConfiguration;
|
||||
|
@ -350,6 +350,36 @@
|
||||
.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)
|
||||
{
|
||||
var configuration = new InternalConfiguration(null, null, config, null, null, null, null, null);
|
||||
|
@ -1,3 +1,5 @@
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using Ocelot.Middleware;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
@ -108,6 +110,26 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
.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()
|
||||
{
|
||||
_middleware = new LoadBalancingMiddleware(_next, _loggerFactory.Object, _loadBalancerHouse.Object);
|
||||
@ -135,6 +157,13 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
.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()
|
||||
{
|
||||
_hostAndPort = new ServiceHostAndPort("127.0.0.1", 80);
|
||||
@ -186,6 +215,13 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
_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)
|
||||
{
|
||||
_downstreamContext.DownstreamRequest.ToHttpRequestMessage().RequestUri.OriginalString.ShouldBe(expectedUri);
|
||||
|
@ -1,97 +1,97 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||
<TargetFramework>netcoreapp3.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.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.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.66">
|
||||
<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.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.0.0" />
|
||||
<PackageReference Include="Moq" Version="4.13.0" />
|
||||
<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.0.1" />
|
||||
<PackageReference Include="Pivotal.Discovery.ClientCore" Version="2.2.0" />
|
||||
<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.1.1" />
|
||||
<PackageReference Include="Rafty" Version="0.4.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="WebSockets\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-19367-01" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.1.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<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.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.66">
|
||||
<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.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.0.0" />
|
||||
<PackageReference Include="Moq" Version="4.13.0" />
|
||||
<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.0.1" />
|
||||
<PackageReference Include="Pivotal.Discovery.ClientCore" Version="2.2.0" />
|
||||
<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.1.1" />
|
||||
<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.1.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -49,15 +49,15 @@ namespace Ocelot.UnitTests.RateLimit
|
||||
|
||||
[Fact]
|
||||
public void should_call_middleware_and_ratelimiting()
|
||||
{
|
||||
var upstreamTemplate = new UpstreamPathTemplateBuilder().Build();
|
||||
{
|
||||
var upstreamTemplate = new UpstreamPathTemplateBuilder().Build();
|
||||
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithEnableRateLimiting(true)
|
||||
.WithRateLimitOptions(new RateLimitOptions(true, "ClientId", new List<string>(), false, "", "", new RateLimitRule("1s", 100, 3), 429))
|
||||
.WithRateLimitOptions(new RateLimitOptions(true, "ClientId", () => new List<string>(), false, "", "", new RateLimitRule("1s", 100, 3), 429))
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.WithUpstreamPathTemplate(upstreamTemplate)
|
||||
.Build();
|
||||
.Build();
|
||||
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
@ -82,7 +82,7 @@ namespace Ocelot.UnitTests.RateLimit
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithEnableRateLimiting(true)
|
||||
.WithRateLimitOptions(
|
||||
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>() { "ocelotclient2" }, false, "", "", new RateLimitRule("1s", 100, 3), 429))
|
||||
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", () => new List<string>() { "ocelotclient2" }, false, "", "", new RateLimitRule("1s", 100, 3), 429))
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
@ -102,8 +102,8 @@ namespace Ocelot.UnitTests.RateLimit
|
||||
|
||||
private void WhenICallTheMiddlewareMultipleTime(int times)
|
||||
{
|
||||
var clientId = "ocelotclient1";
|
||||
|
||||
var clientId = "ocelotclient1";
|
||||
|
||||
for (int i = 0; i < times; i++)
|
||||
{
|
||||
var request = new HttpRequestMessage(new HttpMethod("GET"), _url);
|
||||
@ -117,8 +117,8 @@ namespace Ocelot.UnitTests.RateLimit
|
||||
|
||||
private void WhenICallTheMiddlewareWithWhiteClient()
|
||||
{
|
||||
var clientId = "ocelotclient2";
|
||||
|
||||
var clientId = "ocelotclient2";
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var request = new HttpRequestMessage(new HttpMethod("GET"), _url);
|
||||
@ -127,10 +127,10 @@ namespace Ocelot.UnitTests.RateLimit
|
||||
_downstreamContext.HttpContext.Request.Headers.TryAdd("ClientId", clientId);
|
||||
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
_responseStatusCode = (int)_downstreamContext.HttpContext.Response.StatusCode;
|
||||
}
|
||||
}
|
||||
|
||||
_responseStatusCode = (int)_downstreamContext.HttpContext.Response.StatusCode;
|
||||
}
|
||||
}
|
||||
|
||||
private void ThenresponseStatusCodeIs429()
|
||||
{
|
||||
_responseStatusCode.ShouldBe(429);
|
||||
@ -145,7 +145,7 @@ namespace Ocelot.UnitTests.RateLimit
|
||||
internal class FakeStream : Stream
|
||||
{
|
||||
public override void Flush()
|
||||
{
|
||||
{
|
||||
//do nothing
|
||||
//throw new System.NotImplementedException();
|
||||
}
|
||||
@ -176,4 +176,4 @@ namespace Ocelot.UnitTests.RateLimit
|
||||
public override long Length { get; }
|
||||
public override long Position { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true, int.MaxValue))
|
||||
.WithDelegatingHandlers(new List<string>
|
||||
{
|
||||
"FakeDelegatingHandler",
|
||||
@ -88,7 +88,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true, int.MaxValue))
|
||||
.WithDelegatingHandlers(new List<string>
|
||||
{
|
||||
"FakeDelegatingHandlerTwo",
|
||||
@ -125,7 +125,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true, int.MaxValue))
|
||||
.WithDelegatingHandlers(new List<string>
|
||||
{
|
||||
"FakeDelegatingHandlerTwo",
|
||||
@ -161,7 +161,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true, int.MaxValue))
|
||||
.WithDelegatingHandlers(new List<string>
|
||||
{
|
||||
"FakeDelegatingHandler",
|
||||
@ -195,7 +195,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.Build();
|
||||
|
||||
@ -221,7 +221,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false, true, int.MaxValue))
|
||||
.WithDelegatingHandlers(new List<string>
|
||||
{
|
||||
"FakeDelegatingHandler",
|
||||
@ -249,7 +249,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.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))
|
||||
.And(x => GivenTheQosFactoryReturns(new FakeQoSHandler()))
|
||||
@ -269,7 +269,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.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))
|
||||
.And(x => GivenTheServiceProviderReturnsNothing())
|
||||
@ -289,7 +289,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.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))
|
||||
.And(x => GivenTheQosFactoryReturns(new FakeQoSHandler()))
|
||||
@ -309,7 +309,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.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))
|
||||
.And(x => GivenTheQosFactoryReturns(new FakeQoSHandler()))
|
||||
@ -331,7 +331,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.Build();
|
||||
|
||||
@ -361,7 +361,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.Build();
|
||||
|
||||
|
@ -52,7 +52,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
@ -73,7 +73,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
@ -99,7 +99,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
@ -126,7 +126,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRouteA = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithContainsQueryString(true).WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
@ -134,7 +134,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRouteB = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithContainsQueryString(true).WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
@ -161,7 +161,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
@ -184,7 +184,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
@ -216,7 +216,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, true, false, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, true, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
@ -252,7 +252,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
|
@ -57,7 +57,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(upstreamTemplate)
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
@ -86,7 +86,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(upstreamTemplate)
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
@ -114,7 +114,7 @@ namespace Ocelot.UnitTests.Requester
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true))
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(upstreamTemplate)
|
||||
.WithQosOptions(new QoSOptionsBuilder().WithTimeoutValue(1).Build())
|
||||
|
@ -38,6 +38,14 @@
|
||||
error.ShouldBeOfType<RequestCanceledError>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_request_canceled_for_subtype()
|
||||
{
|
||||
var error = _mapper.Map(new SomeException());
|
||||
|
||||
error.ShouldBeOfType<RequestCanceledError>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error_from_mapper()
|
||||
{
|
||||
@ -56,5 +64,8 @@
|
||||
|
||||
error.ShouldBeOfType<AnyError>();
|
||||
}
|
||||
|
||||
private class SomeException : OperationCanceledException
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
@ -41,9 +41,10 @@ namespace Ocelot.UnitTests.Requester
|
||||
public void should_call_services_correctly()
|
||||
{
|
||||
this.Given(x => x.GivenTheRequestIs())
|
||||
.And(x => x.GivenTheRequesterReturns(new OkResponse<HttpResponseMessage>(new HttpResponseMessage())))
|
||||
.And(x => x.GivenTheRequesterReturns(new OkResponse<HttpResponseMessage>(new HttpResponseMessage(System.Net.HttpStatusCode.OK))))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamResponseIsSet())
|
||||
.Then(x => InformationIsLogged())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
@ -57,6 +58,17 @@ namespace Ocelot.UnitTests.Requester
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_log_downstream_internal_server_error()
|
||||
{
|
||||
this.Given(x => x.GivenTheRequestIs())
|
||||
.And(x => x.GivenTheRequesterReturns(
|
||||
new OkResponse<HttpResponseMessage>(new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError))))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.WarningIsLogged())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenTheErrorIsSet()
|
||||
{
|
||||
_downstreamContext.IsError.ShouldBeTrue();
|
||||
@ -98,5 +110,23 @@ namespace Ocelot.UnitTests.Requester
|
||||
_downstreamContext.DownstreamResponse.Content.ShouldBe(_response.Data.Content);
|
||||
_downstreamContext.DownstreamResponse.StatusCode.ShouldBe(_response.Data.StatusCode);
|
||||
}
|
||||
|
||||
private void WarningIsLogged()
|
||||
{
|
||||
_logger.Verify(
|
||||
x => x.LogWarning(
|
||||
It.IsAny<string>()
|
||||
),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
private void InformationIsLogged()
|
||||
{
|
||||
_logger.Verify(
|
||||
x => x.LogInformation(
|
||||
It.IsAny<string>()
|
||||
),
|
||||
Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user