failing pesky test

This commit is contained in:
TomPallister 2016-09-14 21:18:25 +01:00
parent 0627e9399b
commit f3128cffe0
5 changed files with 203 additions and 6 deletions

View File

@ -1,17 +1,39 @@
using System.IO; using System.IO;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Flurl;
using Flurl.Http; using Flurl.Http;
using Microsoft.AspNetCore.Http;
namespace Ocelot.Library.Infrastructure.Requester namespace Ocelot.Library.Infrastructure.Requester
{ {
public class HttpClientHttpRequester : IHttpRequester public class HttpClientHttpRequester : IHttpRequester
{ {
public async Task<HttpResponseMessage> GetResponse(string httpMethod, string downstreamUrl, Stream content = null) public async Task<HttpResponseMessage> GetResponse(
string httpMethod,
string downstreamUrl,
Stream content,
IHeaderDictionary headers,
IRequestCookieCollection cookies,
IQueryCollection queryString)
{ {
var method = new HttpMethod(httpMethod); var method = new HttpMethod(httpMethod);
var streamContent = new StreamContent(content);
return await downstreamUrl.SendAsync(method, new StreamContent(content)); if (content.Length > 0)
{
return await downstreamUrl
.SetQueryParams(queryString)
.WithCookies(cookies)
.WithHeaders(streamContent.Headers)
.SendAsync(method, streamContent);
}
return await downstreamUrl
.SetQueryParams(queryString)
.WithHeaders(headers)
.WithCookies(cookies)
.SendAsync(method, streamContent);
} }
} }
} }

View File

@ -2,11 +2,18 @@
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Flurl.Http; using Flurl.Http;
using Microsoft.AspNetCore.Http;
namespace Ocelot.Library.Infrastructure.Requester namespace Ocelot.Library.Infrastructure.Requester
{ {
public interface IHttpRequester public interface IHttpRequester
{ {
Task<HttpResponseMessage> GetResponse(string httpMethod, string downstreamUrl, Stream content = null); Task<HttpResponseMessage> GetResponse(
string httpMethod,
string downstreamUrl,
Stream content,
IHeaderDictionary headers,
IRequestCookieCollection cookies,
IQueryCollection queryString);
} }
} }

View File

@ -47,7 +47,9 @@ namespace Ocelot.Library.Middleware
var downstreamUrl = _urlReplacer.ReplaceTemplateVariables(downstreamRoute.Data); var downstreamUrl = _urlReplacer.ReplaceTemplateVariables(downstreamRoute.Data);
var response = await _requester.GetResponse(context.Request.Method, downstreamUrl, context.Request.Body); var response = await _requester
.GetResponse(context.Request.Method, downstreamUrl, context.Request.Body,
context.Request.Headers, context.Request.Cookies, context.Request.Query);
await _responder.CreateResponse(context, response); await _responder.CreateResponse(context, response);

View File

@ -21,6 +21,7 @@ namespace Ocelot.AcceptanceTests
private HttpClient _client; private HttpClient _client;
private HttpResponseMessage _response; private HttpResponseMessage _response;
private readonly string _configurationPath; private readonly string _configurationPath;
private string _postContent;
public OcelotTests() public OcelotTests()
{ {
@ -76,11 +77,17 @@ namespace Ocelot.AcceptanceTests
} }
})) }))
.And(x => x.GivenTheApiGatewayIsRunning()) .And(x => x.GivenTheApiGatewayIsRunning())
.And(x => x.GivenThePostHasContent("postContent"))
.When(x => x.WhenIPostUrlOnTheApiGateway("/")) .When(x => x.WhenIPostUrlOnTheApiGateway("/"))
.Then(x => x.ThenTheStatusCodeShouldBe(HttpStatusCode.Created)) .Then(x => x.ThenTheStatusCodeShouldBe(HttpStatusCode.Created))
.BDDfy(); .BDDfy();
} }
private void GivenThePostHasContent(string postcontent)
{
_postContent = postcontent;
}
/// <summary> /// <summary>
/// This is annoying cos it should be in the constructor but we need to set up the yaml 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 yaml file before calling startup so its a step.
/// </summary> /// </summary>
@ -119,7 +126,8 @@ namespace Ocelot.AcceptanceTests
private void WhenIPostUrlOnTheApiGateway(string url) private void WhenIPostUrlOnTheApiGateway(string url)
{ {
_response = _client.PostAsync(url, new StringContent(string.Empty)).Result; var content = new StringContent(_postContent);
_response = _client.PostAsync(url, content).Result;
} }
private void ThenTheStatusCodeShouldBe(HttpStatusCode expectedHttpStatusCode) private void ThenTheStatusCodeShouldBe(HttpStatusCode expectedHttpStatusCode)

View File

@ -1,9 +1,14 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Flurl.Http.Testing; using Flurl.Http.Testing;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Internal;
using Microsoft.Extensions.Primitives;
using Ocelot.Library.Infrastructure.Requester; using Ocelot.Library.Infrastructure.Requester;
using Shouldly; using Shouldly;
using TestStack.BDDfy; using TestStack.BDDfy;
@ -19,6 +24,9 @@ namespace Ocelot.UnitTests.Requester
private string _downstreamUrl; private string _downstreamUrl;
private HttpResponseMessage _result; private HttpResponseMessage _result;
private HttpContent _content; private HttpContent _content;
private IHeaderDictionary _headers;
private IRequestCookieCollection _cookies;
private IQueryCollection _query;
public RequesterTests() public RequesterTests()
{ {
@ -66,6 +74,153 @@ namespace Ocelot.UnitTests.Requester
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_forward_http_content_headers()
{
this.Given(x => x.GivenIHaveHttpMethod("POST"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenIHaveTheHttpContent(new StringContent("Hi from Tom")
{
Headers =
{
{"Boom", "TickTick"}
}
}))
.And(x => x.GivenTheDownstreamServerReturns(HttpStatusCode.Created))
.When(x => x.WhenIMakeARequest())
.Then(x => x.ThenTheFollowingIsReturned(HttpStatusCode.Created))
.And(x => x.ThenTheDownstreamServerIsCalledCorrectly())
.And(x => x.ThenTheCorrectHttpMethodIsUsed(HttpMethod.Post))
.And(x => x.ThenTheCorrectContentIsUsed(new StringContent("Hi from Tom")
{
Headers =
{
{ "Boom", "TickTick" }
}
}))
.And(x => x.ThenTheCorrectContentHeadersAreUsed(new HeaderDictionary
{
{
"Boom", "TickTick"
}
}))
.BDDfy();
}
[Fact]
public void should_forward_headers()
{
this.Given(x => x.GivenIHaveHttpMethod("GET"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenTheHttpHeadersAre(new HeaderDictionary
{
{"ChopSticks", "Bubbles" }
}))
.And(x => x.GivenTheDownstreamServerReturns(HttpStatusCode.OK))
.When(x => x.WhenIMakeARequest())
.Then(x => x.ThenTheFollowingIsReturned(HttpStatusCode.OK))
.And(x => x.ThenTheDownstreamServerIsCalledCorrectly())
.And(x => x.ThenTheCorrectHeadersAreUsed(new HeaderDictionary
{
{"ChopSticks", "Bubbles" }
}))
.BDDfy();
}
[Fact]
public void should_forward_cookies()
{
this.Given(x => x.GivenIHaveHttpMethod("GET"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenTheCookiesAre(new RequestCookieCollection(new Dictionary<string, string>
{
{ "TheCookie","Monster" }
})))
.And(x => x.GivenTheDownstreamServerReturns(HttpStatusCode.OK))
.When(x => x.WhenIMakeARequest())
.Then(x => x.ThenTheFollowingIsReturned(HttpStatusCode.OK))
.And(x => x.ThenTheDownstreamServerIsCalledCorrectly())
.And(x => x.ThenTheCorrectCookiesAreUsed(new RequestCookieCollection(new Dictionary<string, string>
{
{ "TheCookie","Monster" }
})))
.BDDfy();
}
[Fact]
public void should_forward_query_string()
{
this.Given(x => x.GivenIHaveHttpMethod("POST"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenTheQueryStringIs(new QueryCollection(new Dictionary<string, StringValues>
{
{ "jeff", "1" },
{ "geoff", "2" }
})))
.And(x => x.GivenTheDownstreamServerReturns(HttpStatusCode.Created))
.When(x => x.WhenIMakeARequest())
.Then(x => x.ThenTheFollowingIsReturned(HttpStatusCode.Created))
.And(x => x.ThenTheDownstreamServerIsCalledCorrectly())
.And(x => x.ThenTheCorrectQueryStringIsUsed("?jeff=1&geoff=2"))
.BDDfy();
}
private void ThenTheCorrectQueryStringIsUsed(string expected)
{
_httpTest.CallLog[0].Request.RequestUri.Query.ShouldBe(expected);
}
private void GivenTheQueryStringIs(IQueryCollection query)
{
_query = query;
}
private void ThenTheCorrectCookiesAreUsed(IRequestCookieCollection cookies)
{
var expectedCookies = cookies.Select(x => new KeyValuePair<string, string>(x.Key, x.Value));
foreach (var expectedCookie in expectedCookies)
{
_httpTest
.CallLog[0]
.Request
.Headers
.ShouldContain(x => x.Key == "Cookie" && x.Value.First() == string.Format("{0}={1}", expectedCookie.Key, expectedCookie.Value));
}
}
private void GivenTheCookiesAre(IRequestCookieCollection cookies)
{
_cookies = cookies;
}
private void ThenTheCorrectHeadersAreUsed(IHeaderDictionary headers)
{
var expectedHeaders = headers.Select(x => new KeyValuePair<string, string[]>(x.Key, x.Value));
foreach (var expectedHeader in expectedHeaders)
{
_httpTest.CallLog[0].Request.Headers.ShouldContain(x => x.Key == expectedHeader.Key && x.Value.First() == expectedHeader.Value[0]);
}
}
private void ThenTheCorrectContentHeadersAreUsed(IHeaderDictionary headers)
{
var expectedHeaders = headers.Select(x => new KeyValuePair<string, string[]>(x.Key, x.Value));
foreach (var expectedHeader in expectedHeaders)
{
_httpTest.CallLog[0].Request.Content.Headers.ShouldContain(x => x.Key == expectedHeader.Key
//&& x.Value.First() == expectedHeader.Value[0]
);
}
}
private void GivenTheHttpHeadersAre(IHeaderDictionary headers)
{
_headers = headers;
}
private void GivenIHaveTheHttpContent(HttpContent content) private void GivenIHaveTheHttpContent(HttpContent content)
{ {
_content = content; _content = content;
@ -88,7 +243,10 @@ namespace Ocelot.UnitTests.Requester
private void WhenIMakeARequest() private void WhenIMakeARequest()
{ {
_result = _httpRequester.GetResponse(_httpMethod, _downstreamUrl, _content != null ? _content.ReadAsStreamAsync().Result : Stream.Null).Result; _result = _httpRequester
.GetResponse(_httpMethod, _downstreamUrl,
_content != null ? _content.ReadAsStreamAsync().Result : Stream.Null,
_headers, _cookies, _query).Result;
} }
private void ThenTheFollowingIsReturned(HttpStatusCode expected) private void ThenTheFollowingIsReturned(HttpStatusCode expected)