Feature/proxy reason phrase (#618)

* #599 started work to proxy reason phrase

* #599 test for aggregator
This commit is contained in:
Tom Pallister 2018-09-12 19:48:56 +01:00 committed by GitHub
parent 0b9ff92549
commit 669ece07b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 446 additions and 335 deletions

View File

@ -9,14 +9,15 @@ namespace Ocelot.Cache
HttpStatusCode statusCode, HttpStatusCode statusCode,
Dictionary<string, IEnumerable<string>> headers, Dictionary<string, IEnumerable<string>> headers,
string body, string body,
Dictionary<string, IEnumerable<string>> contentHeaders Dictionary<string, IEnumerable<string>> contentHeaders,
string reasonPhrase
) )
{ {
StatusCode = statusCode; StatusCode = statusCode;
Headers = headers ?? new Dictionary<string, IEnumerable<string>>(); Headers = headers ?? new Dictionary<string, IEnumerable<string>>();
ContentHeaders = contentHeaders ?? new Dictionary<string, IEnumerable<string>>(); ContentHeaders = contentHeaders ?? new Dictionary<string, IEnumerable<string>>();
Body = body ?? ""; Body = body ?? "";
ReasonPhrase = reasonPhrase;
} }
public HttpStatusCode StatusCode { get; private set; } public HttpStatusCode StatusCode { get; private set; }
@ -26,5 +27,7 @@ namespace Ocelot.Cache
public Dictionary<string, IEnumerable<string>> ContentHeaders { get; private set; } public Dictionary<string, IEnumerable<string>> ContentHeaders { get; private set; }
public string Body { get; private set; } public string Body { get; private set; }
public string ReasonPhrase { get; private set; }
} }
} }

View File

@ -87,7 +87,7 @@
streamContent.Headers.TryAddWithoutValidation(header.Key, header.Value); streamContent.Headers.TryAddWithoutValidation(header.Key, header.Value);
} }
return new DownstreamResponse(streamContent, cached.StatusCode, cached.Headers.ToList()); return new DownstreamResponse(streamContent, cached.StatusCode, cached.Headers.ToList(), cached.ReasonPhrase);
} }
internal async Task<CachedResponse> CreateCachedResponse(DownstreamResponse response) internal async Task<CachedResponse> CreateCachedResponse(DownstreamResponse response)
@ -109,7 +109,7 @@
var contentHeaders = response?.Content?.Headers.ToDictionary(v => v.Key, v => v.Value); var contentHeaders = response?.Content?.Headers.ToDictionary(v => v.Key, v => v.Value);
var cached = new CachedResponse(statusCode, headers, body, contentHeaders); var cached = new CachedResponse(statusCode, headers, body, contentHeaders, response.ReasonPhrase);
return cached; return cached;
} }
} }

View File

@ -7,25 +7,27 @@ namespace Ocelot.Middleware
{ {
public class DownstreamResponse public class DownstreamResponse
{ {
public DownstreamResponse(HttpContent content, HttpStatusCode statusCode, List<Header> headers) public DownstreamResponse(HttpContent content, HttpStatusCode statusCode, List<Header> headers, string reasonPhrase)
{ {
Content = content; Content = content;
StatusCode = statusCode; StatusCode = statusCode;
Headers = headers ?? new List<Header>(); Headers = headers ?? new List<Header>();
ReasonPhrase = reasonPhrase;
} }
public DownstreamResponse(HttpResponseMessage response) public DownstreamResponse(HttpResponseMessage response)
:this(response.Content, response.StatusCode, response.Headers.Select(x => new Header(x.Key, x.Value)).ToList()) :this(response.Content, response.StatusCode, response.Headers.Select(x => new Header(x.Key, x.Value)).ToList(), response.ReasonPhrase)
{ {
} }
public DownstreamResponse(HttpContent content, HttpStatusCode statusCode, IEnumerable<KeyValuePair<string, IEnumerable<string>>> headers) public DownstreamResponse(HttpContent content, HttpStatusCode statusCode, IEnumerable<KeyValuePair<string, IEnumerable<string>>> headers, string reasonPhrase)
:this(content, statusCode, headers.Select(x => new Header(x.Key, x.Value)).ToList()) :this(content, statusCode, headers.Select(x => new Header(x.Key, x.Value)).ToList(), reasonPhrase)
{ {
} }
public HttpContent Content { get; } public HttpContent Content { get; }
public HttpStatusCode StatusCode { get; } public HttpStatusCode StatusCode { get; }
public List<Header> Headers { get; } public List<Header> Headers { get; }
public string ReasonPhrase {get;}
} }
} }

View File

@ -46,7 +46,7 @@ namespace Ocelot.Middleware.Multiplexer
Headers = {ContentType = new MediaTypeHeaderValue("application/json")} Headers = {ContentType = new MediaTypeHeaderValue("application/json")}
}; };
originalContext.DownstreamResponse = new DownstreamResponse(stringContent, HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>()); originalContext.DownstreamResponse = new DownstreamResponse(stringContent, HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "cannot return from aggregate..which reason phrase would you use?");
} }
private static void MapAggregateError(DownstreamContext originalContext, List<DownstreamContext> downstreamContexts, int i) private static void MapAggregateError(DownstreamContext originalContext, List<DownstreamContext> downstreamContexts, int i)

View File

@ -3,6 +3,7 @@ using System.Linq;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
using Ocelot.Headers; using Ocelot.Headers;
using Ocelot.Middleware; using Ocelot.Middleware;
@ -45,6 +46,8 @@ namespace Ocelot.Responder
context.Response.StatusCode = (int)response.StatusCode; context.Response.StatusCode = (int)response.StatusCode;
context.Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = response.ReasonPhrase;
using(content) using(content)
{ {
if (response.StatusCode != HttpStatusCode.NotModified && context.Response.ContentLength != 0) if (response.StatusCode != HttpStatusCode.NotModified && context.Response.ContentLength != 0)

View File

@ -559,7 +559,7 @@ namespace Ocelot.AcceptanceTests
var merge = $"{one}, {two}"; var merge = $"{one}, {two}";
merge = merge.Replace("Hello", "Bye").Replace("{", "").Replace("}", ""); merge = merge.Replace("Hello", "Bye").Replace("{", "").Replace("}", "");
var headers = responses.SelectMany(x => x.Headers).ToList(); var headers = responses.SelectMany(x => x.Headers).ToList();
return new DownstreamResponse(new StringContent(merge), HttpStatusCode.OK, headers); return new DownstreamResponse(new StringContent(merge), HttpStatusCode.OK, headers, "some reason");
} }
} }
} }

View File

@ -0,0 +1,76 @@
namespace Ocelot.AcceptanceTests
{
using System;
using System.Collections.Generic;
using System.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Ocelot.Configuration.File;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
public class ReasonPhraseTests : IDisposable
{
private readonly Steps _steps;
private string _contentType;
private long? _contentLength;
private bool _contentTypeHeaderExists;
private readonly ServiceHandler _serviceHandler;
public ReasonPhraseTests()
{
_serviceHandler = new ServiceHandler();
_steps = new Steps();
}
[Fact]
public void should_return_reason_phrase()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51339,
}
},
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" },
}
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51339", "/", "some reason"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.And(_ => _steps.ThenTheReasonPhraseIs("some reason"))
.BDDfy();
}
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, string reasonPhrase)
{
_serviceHandler.GivenThereIsAServiceRunningOn(baseUrl, basePath, async context =>
{
context.Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = reasonPhrase;
await context.Response.WriteAsync("YOYO!");
});
}
public void Dispose()
{
_serviceHandler?.Dispose();
_steps.Dispose();
}
}
}

View File

@ -452,6 +452,11 @@
header.First().ShouldBe(value); header.First().ShouldBe(value);
} }
public void ThenTheReasonPhraseIs(string expected)
{
_response.ReasonPhrase.ShouldBe(expected);
}
/// <summary> /// <summary>
/// This is annoying cos it should be in the constructor but we need to set up the file before calling startup so its a step. /// This is annoying cos it should be in the constructor but we need to set up the file before calling startup so its a step.
/// </summary> /// </summary>

View File

@ -53,7 +53,7 @@
{ "content-type", new List<string> { "application/json" } } { "content-type", new List<string> { "application/json" } }
}; };
var cachedResponse = new CachedResponse(HttpStatusCode.OK, headers, "", contentHeaders); var cachedResponse = new CachedResponse(HttpStatusCode.OK, headers, "", contentHeaders, "some reason");
this.Given(x => x.GivenThereIsACachedResponse(cachedResponse)) this.Given(x => x.GivenThereIsACachedResponse(cachedResponse))
.And(x => x.GivenTheDownstreamRouteIs()) .And(x => x.GivenTheDownstreamRouteIs())
.When(x => x.WhenICallTheMiddleware()) .When(x => x.WhenICallTheMiddleware())
@ -69,7 +69,7 @@
{ "Expires", new List<string> { "-1" } } { "Expires", new List<string> { "-1" } }
}; };
var cachedResponse = new CachedResponse(HttpStatusCode.OK, new Dictionary<string, IEnumerable<string>>(), "", contentHeaders); var cachedResponse = new CachedResponse(HttpStatusCode.OK, new Dictionary<string, IEnumerable<string>>(), "", contentHeaders, "some reason");
this.Given(x => x.GivenThereIsACachedResponse(cachedResponse)) this.Given(x => x.GivenThereIsACachedResponse(cachedResponse))
.And(x => x.GivenTheDownstreamRouteIs()) .And(x => x.GivenTheDownstreamRouteIs())
.When(x => x.WhenICallTheMiddleware()) .When(x => x.WhenICallTheMiddleware())

View File

@ -43,7 +43,7 @@ namespace Ocelot.UnitTests.Headers
new List<KeyValuePair<string, IEnumerable<string>>>() new List<KeyValuePair<string, IEnumerable<string>>>()
{ {
new KeyValuePair<string, IEnumerable<string>>("test", new List<string> {"test"}) new KeyValuePair<string, IEnumerable<string>>("test", new List<string> {"test"})
}); }, "");
var fAndRs = new List<HeaderFindAndReplace> {new HeaderFindAndReplace("test", "test", "chiken", 0)}; var fAndRs = new List<HeaderFindAndReplace> {new HeaderFindAndReplace("test", "test", "chiken", 0)};
@ -61,7 +61,7 @@ namespace Ocelot.UnitTests.Headers
new List<KeyValuePair<string, IEnumerable<string>>>() new List<KeyValuePair<string, IEnumerable<string>>>()
{ {
new KeyValuePair<string, IEnumerable<string>>("test", new List<string> {"test"}) new KeyValuePair<string, IEnumerable<string>>("test", new List<string> {"test"})
}); }, "");
var fAndRs = new List<HeaderFindAndReplace>(); var fAndRs = new List<HeaderFindAndReplace>();
@ -84,7 +84,7 @@ namespace Ocelot.UnitTests.Headers
new List<KeyValuePair<string, IEnumerable<string>>>() new List<KeyValuePair<string, IEnumerable<string>>>()
{ {
new KeyValuePair<string, IEnumerable<string>>("Location", new List<string> {downstreamUrl}) new KeyValuePair<string, IEnumerable<string>>("Location", new List<string> {downstreamUrl})
}); }, "");
var fAndRs = new List<HeaderFindAndReplace> var fAndRs = new List<HeaderFindAndReplace>
{ {
@ -111,7 +111,7 @@ namespace Ocelot.UnitTests.Headers
new List<KeyValuePair<string, IEnumerable<string>>>() new List<KeyValuePair<string, IEnumerable<string>>>()
{ {
new KeyValuePair<string, IEnumerable<string>>("Location", new List<string> {downstreamUrl}) new KeyValuePair<string, IEnumerable<string>>("Location", new List<string> {downstreamUrl})
}); }, "");
var fAndRs = new List<HeaderFindAndReplace> var fAndRs = new List<HeaderFindAndReplace>
{ {
@ -138,7 +138,7 @@ namespace Ocelot.UnitTests.Headers
new List<KeyValuePair<string, IEnumerable<string>>>() new List<KeyValuePair<string, IEnumerable<string>>>()
{ {
new KeyValuePair<string, IEnumerable<string>>("Location", new List<string> {downstreamUrl}) new KeyValuePair<string, IEnumerable<string>>("Location", new List<string> {downstreamUrl})
}); }, "");
var fAndRs = new List<HeaderFindAndReplace> var fAndRs = new List<HeaderFindAndReplace>
{ {
@ -165,7 +165,7 @@ namespace Ocelot.UnitTests.Headers
new List<KeyValuePair<string, IEnumerable<string>>>() new List<KeyValuePair<string, IEnumerable<string>>>()
{ {
new KeyValuePair<string, IEnumerable<string>>("Location", new List<string> {downstreamUrl}) new KeyValuePair<string, IEnumerable<string>>("Location", new List<string> {downstreamUrl})
}); }, "");
var fAndRs = new List<HeaderFindAndReplace> var fAndRs = new List<HeaderFindAndReplace>
{ {
@ -192,7 +192,7 @@ namespace Ocelot.UnitTests.Headers
new List<KeyValuePair<string, IEnumerable<string>>>() new List<KeyValuePair<string, IEnumerable<string>>>()
{ {
new KeyValuePair<string, IEnumerable<string>>("Location", new List<string> {downstreamUrl}) new KeyValuePair<string, IEnumerable<string>>("Location", new List<string> {downstreamUrl})
}); }, "");
var fAndRs = new List<HeaderFindAndReplace> var fAndRs = new List<HeaderFindAndReplace>
{ {
@ -219,7 +219,7 @@ namespace Ocelot.UnitTests.Headers
new List<KeyValuePair<string, IEnumerable<string>>>() new List<KeyValuePair<string, IEnumerable<string>>>()
{ {
new KeyValuePair<string, IEnumerable<string>>("Location", new List<string> {downstreamUrl}) new KeyValuePair<string, IEnumerable<string>>("Location", new List<string> {downstreamUrl})
}); }, "");
var fAndRs = new List<HeaderFindAndReplace> var fAndRs = new List<HeaderFindAndReplace>
{ {

View File

@ -49,13 +49,13 @@ namespace Ocelot.UnitTests.Middleware
var billDownstreamContext = new DownstreamContext(new DefaultHttpContext()) var billDownstreamContext = new DownstreamContext(new DefaultHttpContext())
{ {
DownstreamResponse = new DownstreamResponse(new StringContent("Bill says hi"), HttpStatusCode.OK, new EditableList<KeyValuePair<string, IEnumerable<string>>>()), DownstreamResponse = new DownstreamResponse(new StringContent("Bill says hi"), HttpStatusCode.OK, new EditableList<KeyValuePair<string, IEnumerable<string>>>(), "some reason"),
DownstreamReRoute = billDownstreamReRoute DownstreamReRoute = billDownstreamReRoute
}; };
var georgeDownstreamContext = new DownstreamContext(new DefaultHttpContext()) var georgeDownstreamContext = new DownstreamContext(new DefaultHttpContext())
{ {
DownstreamResponse = new DownstreamResponse(new StringContent("George says hi"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>()), DownstreamResponse = new DownstreamResponse(new StringContent("George says hi"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason"),
DownstreamReRoute = georgeDownstreamReRoute DownstreamReRoute = georgeDownstreamReRoute
}; };
@ -69,6 +69,7 @@ namespace Ocelot.UnitTests.Middleware
.When(x => WhenIAggregate()) .When(x => WhenIAggregate())
.Then(x => ThenTheContentIs(expected)) .Then(x => ThenTheContentIs(expected))
.And(x => ThenTheContentTypeIs("application/json")) .And(x => ThenTheContentTypeIs("application/json"))
.And(x => ThenTheReasonPhraseIs("cannot return from aggregate..which reason phrase would you use?"))
.BDDfy(); .BDDfy();
} }
@ -91,13 +92,13 @@ namespace Ocelot.UnitTests.Middleware
var billDownstreamContext = new DownstreamContext(new DefaultHttpContext()) var billDownstreamContext = new DownstreamContext(new DefaultHttpContext())
{ {
DownstreamResponse = new DownstreamResponse(new StringContent("Bill says hi"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>()), DownstreamResponse = new DownstreamResponse(new StringContent("Bill says hi"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason"),
DownstreamReRoute = billDownstreamReRoute DownstreamReRoute = billDownstreamReRoute
}; };
var georgeDownstreamContext = new DownstreamContext(new DefaultHttpContext()) var georgeDownstreamContext = new DownstreamContext(new DefaultHttpContext())
{ {
DownstreamResponse = new DownstreamResponse(new StringContent("Error"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>()), DownstreamResponse = new DownstreamResponse(new StringContent("Error"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason"),
DownstreamReRoute = georgeDownstreamReRoute, DownstreamReRoute = georgeDownstreamReRoute,
}; };
@ -116,6 +117,11 @@ namespace Ocelot.UnitTests.Middleware
.BDDfy(); .BDDfy();
} }
private void ThenTheReasonPhraseIs(string expected)
{
_upstreamContext.DownstreamResponse.ReasonPhrase.ShouldBe(expected);
}
private void ThenTheErrorIsMapped() private void ThenTheErrorIsMapped()
{ {
_upstreamContext.Errors.ShouldBe(_downstreamContexts[1].Errors); _upstreamContext.Errors.ShouldBe(_downstreamContexts[1].Errors);

View File

@ -43,11 +43,11 @@ namespace Ocelot.UnitTests.Middleware
{ {
new DownstreamContext(new DefaultHttpContext()) new DownstreamContext(new DefaultHttpContext())
{ {
DownstreamResponse = new DownstreamResponse(new StringContent("Tom"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>()) DownstreamResponse = new DownstreamResponse(new StringContent("Tom"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason")
}, },
new DownstreamContext(new DefaultHttpContext()) new DownstreamContext(new DefaultHttpContext())
{ {
DownstreamResponse = new DownstreamResponse(new StringContent("Laura"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>()) DownstreamResponse = new DownstreamResponse(new StringContent("Laura"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason")
} }
}; };
@ -72,11 +72,11 @@ namespace Ocelot.UnitTests.Middleware
{ {
new DownstreamContext(new DefaultHttpContext()) new DownstreamContext(new DefaultHttpContext())
{ {
DownstreamResponse = new DownstreamResponse(new StringContent("Tom"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>()) DownstreamResponse = new DownstreamResponse(new StringContent("Tom"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason")
}, },
new DownstreamContext(new DefaultHttpContext()) new DownstreamContext(new DefaultHttpContext())
{ {
DownstreamResponse = new DownstreamResponse(new StringContent("Laura"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>()) DownstreamResponse = new DownstreamResponse(new StringContent("Laura"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason")
} }
}; };
@ -146,7 +146,7 @@ namespace Ocelot.UnitTests.Middleware
var laura = await responses[1].Content.ReadAsStringAsync(); var laura = await responses[1].Content.ReadAsStringAsync();
var content = $"{tom}, {laura}"; var content = $"{tom}, {laura}";
var headers = responses.SelectMany(x => x.Headers).ToList(); var headers = responses.SelectMany(x => x.Headers).ToList();
return new DownstreamResponse(new StringContent(content), HttpStatusCode.OK, headers); return new DownstreamResponse(new StringContent(content), HttpStatusCode.OK, headers, "some reason");
} }
} }
} }

View File

@ -3,6 +3,7 @@ using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Ocelot.Headers; using Ocelot.Headers;
using Ocelot.Middleware; using Ocelot.Middleware;
using Ocelot.Middleware.Multiplexer; using Ocelot.Middleware.Multiplexer;
@ -31,7 +32,7 @@ namespace Ocelot.UnitTests.Responder
new List<KeyValuePair<string, IEnumerable<string>>> new List<KeyValuePair<string, IEnumerable<string>>>
{ {
new KeyValuePair<string, IEnumerable<string>>("Transfer-Encoding", new List<string> {"woop"}) new KeyValuePair<string, IEnumerable<string>>("Transfer-Encoding", new List<string> {"woop"})
}); }, "some reason");
_responder.SetResponseOnHttpContext(httpContext, response).GetAwaiter().GetResult(); _responder.SetResponseOnHttpContext(httpContext, response).GetAwaiter().GetResult();
var header = httpContext.Response.Headers["Transfer-Encoding"]; var header = httpContext.Response.Headers["Transfer-Encoding"];
@ -43,7 +44,7 @@ namespace Ocelot.UnitTests.Responder
{ {
var httpContext = new DefaultHttpContext(); var httpContext = new DefaultHttpContext();
var response = new DownstreamResponse(new StringContent("test"), HttpStatusCode.OK, var response = new DownstreamResponse(new StringContent("test"), HttpStatusCode.OK,
new List<KeyValuePair<string, IEnumerable<string>>>()); new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason");
_responder.SetResponseOnHttpContext(httpContext, response).GetAwaiter().GetResult(); _responder.SetResponseOnHttpContext(httpContext, response).GetAwaiter().GetResult();
var header = httpContext.Response.Headers["Content-Length"]; var header = httpContext.Response.Headers["Content-Length"];
@ -58,13 +59,28 @@ namespace Ocelot.UnitTests.Responder
new List<KeyValuePair<string, IEnumerable<string>>> new List<KeyValuePair<string, IEnumerable<string>>>
{ {
new KeyValuePair<string, IEnumerable<string>>("test", new List<string> {"test"}) new KeyValuePair<string, IEnumerable<string>>("test", new List<string> {"test"})
}); }, "some reason");
_responder.SetResponseOnHttpContext(httpContext, response).GetAwaiter().GetResult(); _responder.SetResponseOnHttpContext(httpContext, response).GetAwaiter().GetResult();
var header = httpContext.Response.Headers["test"]; var header = httpContext.Response.Headers["test"];
header.First().ShouldBe("test"); header.First().ShouldBe("test");
} }
[Fact]
public void should_add_reason_phrase()
{
var httpContext = new DefaultHttpContext();
var response = new DownstreamResponse(new StringContent(""), HttpStatusCode.OK,
new List<KeyValuePair<string, IEnumerable<string>>>
{
new KeyValuePair<string, IEnumerable<string>>("test", new List<string> {"test"})
}, "some reason");
_responder.SetResponseOnHttpContext(httpContext, response).GetAwaiter().GetResult();
httpContext.Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase.ShouldBe(response.ReasonPhrase);
}
[Fact] [Fact]
public void should_call_without_exception() public void should_call_without_exception()
{ {