Feature/dont validate cached content headers (#406)

* #372 use period timespan to decide when client can make requests again

* #400 dont validate cached body headers
This commit is contained in:
Tom Pallister 2018-06-15 20:30:25 +01:00 committed by GitHub
parent 9979f8a4b8
commit 8e1a5ce827
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 505 additions and 435 deletions

View File

@ -88,7 +88,7 @@ namespace Ocelot.Cache.Middleware
foreach (var header in cached.ContentHeaders)
{
streamContent.Headers.Add(header.Key, header.Value);
streamContent.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
return new DownstreamResponse(streamContent, cached.StatusCode, cached.Headers.ToList());

View File

@ -51,7 +51,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51899", 200, "Hello from Laura"))
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("/"))
@ -65,6 +65,50 @@ namespace Ocelot.AcceptanceTests
.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()
{
@ -94,7 +138,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51899", 200, "Hello from Laura"))
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("/"))
@ -136,7 +180,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51899", 200, "Hello from Laura"))
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("/"))
@ -158,10 +202,10 @@ namespace Ocelot.AcceptanceTests
private void GivenTheServiceNowReturns(string url, int statusCode, string responseBody)
{
_builder.Dispose();
GivenThereIsAServiceRunningOn(url, statusCode, responseBody);
GivenThereIsAServiceRunningOn(url, statusCode, responseBody, null, null);
}
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody, string key, string value)
{
_builder = new WebHostBuilder()
.UseUrls(url)
@ -173,6 +217,10 @@ namespace Ocelot.AcceptanceTests
{
app.Run(async context =>
{
if(!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(key))
{
context.Response.Headers.Add(key, value);
}
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync(responseBody);
});

View File

@ -392,6 +392,12 @@ namespace Ocelot.AcceptanceTests
header.First().ShouldBe(value);
}
public void ThenTheResponseBodyHeaderIs(string key, string value)
{
var header = _response.Content.Headers.GetValues(key);
header.First().ShouldBe(value);
}
public void ThenTheTraceHeaderIsSet(string key)
{
var header = _response.Headers.GetValues(key);

View File

@ -63,10 +63,26 @@
.BDDfy();
}
[Fact]
public void should_returned_cached_item_when_it_is_in_cache_expires_header()
{
var contentHeaders = new Dictionary<string, IEnumerable<string>>
{
{ "Expires", new List<string> { "-1" } }
};
var cachedResponse = new CachedResponse(HttpStatusCode.OK, new Dictionary<string, IEnumerable<string>>(), "", contentHeaders);
this.Given(x => x.GivenThereIsACachedResponse(cachedResponse))
.And(x => x.GivenTheDownstreamRouteIs())
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheCacheGetIsCalledCorrectly())
.BDDfy();
}
[Fact]
public void should_continue_with_pipeline_and_cache_response()
{
this.Given(x => x.GivenResponseIsNotCached())
this.Given(x => x.GivenResponseIsNotCached(new HttpResponseMessage()))
.And(x => x.GivenTheDownstreamRouteIs())
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheCacheAddIsCalledCorrectly())
@ -87,9 +103,9 @@
.Returns(_response);
}
private void GivenResponseIsNotCached()
private void GivenResponseIsNotCached(HttpResponseMessage responseMessage)
{
_downstreamContext.DownstreamResponse = new DownstreamResponse(new HttpResponseMessage());
_downstreamContext.DownstreamResponse = new DownstreamResponse(responseMessage);
}
private void GivenTheDownstreamRouteIs()