removed flurl and made a request creator

This commit is contained in:
TomPallister 2016-10-07 12:54:50 +01:00
parent 74a7f5d270
commit 8688c1eb6f
11 changed files with 289 additions and 591 deletions

View File

@ -1,210 +0,0 @@
namespace Ocelot.Library.Infrastructure.HttpClient
{
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
public class HttpClientWrapper : IHttpClient
{
private readonly HttpClient _httpClient;
public HttpClientWrapper(HttpClient httpClient)
{
_httpClient = httpClient;
}
public void Dispose()
{
_httpClient.Dispose();
}
public Uri BaseAddress
{
get { return _httpClient.BaseAddress; }
set { _httpClient.BaseAddress = value; }
}
public HttpRequestHeaders DefaultRequestHeaders
{
get { return _httpClient.DefaultRequestHeaders; }
}
public long MaxResponseContentBufferSize
{
get { return _httpClient.MaxResponseContentBufferSize; }
set { _httpClient.MaxResponseContentBufferSize = value; }
}
public TimeSpan Timeout
{
get { return _httpClient.Timeout; }
set { _httpClient.Timeout = value; }
}
public void CancelPendingRequests()
{
_httpClient.CancelPendingRequests();
}
public async Task<HttpResponseMessage> DeleteAsync(string requestUri)
{
return await _httpClient.DeleteAsync(requestUri);
}
public async Task<HttpResponseMessage> DeleteAsync(Uri requestUri)
{
return await _httpClient.DeleteAsync(requestUri);
}
public async Task<HttpResponseMessage> DeleteAsync(Uri requestUri, CancellationToken cancellationToken)
{
return await _httpClient.DeleteAsync(requestUri, cancellationToken);
}
public async Task<HttpResponseMessage> DeleteAsync(string requestUri, CancellationToken cancellationToken)
{
return await _httpClient.DeleteAsync(requestUri, cancellationToken);
}
public async Task<HttpResponseMessage> GetAsync(string requestUri)
{
return await _httpClient.GetAsync(requestUri);
}
public async Task<HttpResponseMessage> GetAsync(Uri requestUri)
{
return await _httpClient.GetAsync(requestUri);
}
public async Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption)
{
return await _httpClient.GetAsync(requestUri, completionOption);
}
public async Task<HttpResponseMessage> GetAsync(string requestUri, CancellationToken cancellationToken)
{
return await _httpClient.GetAsync(requestUri, cancellationToken);
}
public async Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption)
{
return await _httpClient.GetAsync(requestUri, completionOption);
}
public async Task<HttpResponseMessage> GetAsync(Uri requestUri, CancellationToken cancellationToken)
{
return await _httpClient.GetAsync(requestUri, cancellationToken);
}
public async Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken)
{
return await _httpClient.GetAsync(requestUri, completionOption, cancellationToken);
}
public async Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken)
{
return await _httpClient.GetAsync(requestUri, completionOption, cancellationToken);
}
public async Task<byte[]> GetByteArrayAsync(string requestUri)
{
return await _httpClient.GetByteArrayAsync(requestUri);
}
public async Task<byte[]> GetByteArrayAsync(Uri requestUri)
{
return await _httpClient.GetByteArrayAsync(requestUri);
}
public async Task<Stream> GetStreamAsync(string requestUri)
{
return await _httpClient.GetStreamAsync(requestUri);
}
public async Task<Stream> GetStreamAsync(Uri requestUri)
{
return await _httpClient.GetStreamAsync(requestUri);
}
public async Task<string> GetStringAsync(string requestUri)
{
return await _httpClient.GetStringAsync(requestUri);
}
public async Task<string> GetStringAsync(Uri requestUri)
{
return await _httpClient.GetStringAsync(requestUri);
}
public async Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content)
{
return await _httpClient.PostAsync(requestUri, content);
}
public async Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content)
{
return await _httpClient.PostAsync(requestUri, content);
}
public async Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content, CancellationToken cancellationToken)
{
return await _httpClient.PostAsync(requestUri, content, cancellationToken);
}
public async Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken)
{
return await _httpClient.PostAsync(requestUri, content, cancellationToken);
}
public async Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content)
{
return await _httpClient.PutAsync(requestUri, content);
}
public async Task<HttpResponseMessage> PutAsync(Uri requestUri, HttpContent content)
{
return await _httpClient.PutAsync(requestUri, content);
}
public async Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content, CancellationToken cancellationToken)
{
return await _httpClient.PutAsync(requestUri, content, cancellationToken);
}
public async Task<HttpResponseMessage> PutAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken)
{
return await _httpClient.PutAsync(requestUri, content, cancellationToken);
}
public async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)
{
return await _httpClient.SendAsync(request);
}
public async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption)
{
return await _httpClient.SendAsync(request, completionOption);
}
public async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return await _httpClient.SendAsync(request, cancellationToken);
}
public async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
{
return await _httpClient.SendAsync(request, completionOption, cancellationToken);
}
public void Dispose(bool disposing)
{
if (!disposing)
{
_httpClient.Dispose();
}
}
}
}

View File

@ -1,49 +0,0 @@
namespace Ocelot.Library.Infrastructure.HttpClient
{
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
public interface IHttpClient
{
Uri BaseAddress { get; set; }
HttpRequestHeaders DefaultRequestHeaders { get; }
long MaxResponseContentBufferSize { get; set; }
TimeSpan Timeout { get; set; }
void CancelPendingRequests();
Task<HttpResponseMessage> DeleteAsync(string requestUri);
Task<HttpResponseMessage> DeleteAsync(Uri requestUri);
Task<HttpResponseMessage> DeleteAsync(Uri requestUri, CancellationToken cancellationToken);
Task<HttpResponseMessage> DeleteAsync(string requestUri, CancellationToken cancellationToken);
Task<HttpResponseMessage> GetAsync(string requestUri);
Task<HttpResponseMessage> GetAsync(Uri requestUri);
Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption);
Task<HttpResponseMessage> GetAsync(string requestUri, CancellationToken cancellationToken);
Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption);
Task<HttpResponseMessage> GetAsync(Uri requestUri, CancellationToken cancellationToken);
Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken);
Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken);
Task<byte[]> GetByteArrayAsync(string requestUri);
Task<byte[]> GetByteArrayAsync(Uri requestUri);
Task<Stream> GetStreamAsync(string requestUri);
Task<Stream> GetStreamAsync(Uri requestUri);
Task<string> GetStringAsync(string requestUri);
Task<string> GetStringAsync(Uri requestUri);
Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content);
Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content);
Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content, CancellationToken cancellationToken);
Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken);
Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content);
Task<HttpResponseMessage> PutAsync(Uri requestUri, HttpContent content);
Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content, CancellationToken cancellationToken);
Task<HttpResponseMessage> PutAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken);
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request);
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption);
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken);
void Dispose(bool disposing);
}
}

View File

@ -1,17 +1,16 @@
namespace Ocelot.Library.Infrastructure.RequestBuilder using System.IO;
{ using Microsoft.AspNetCore.Http;
using System.IO;
using System.Net.Http;
using Microsoft.AspNetCore.Http;
namespace Ocelot.Library.Infrastructure.RequestBuilder
{
public interface IRequestBuilder public interface IRequestBuilder
{ {
HttpRequestMessage Build(string httpMethod, Request Build(string httpMethod,
string downstreamUrl, string downstreamUrl,
Stream content, Stream content,
IHeaderDictionary headers, IHeaderDictionary headers,
IRequestCookieCollection cookies, IRequestCookieCollection cookies,
IQueryCollection queryString, string queryString,
string contentType); string contentType);
} }
} }

View File

@ -0,0 +1,17 @@
using System.Net;
using System.Net.Http;
namespace Ocelot.Library.Infrastructure.RequestBuilder
{
public class Request
{
public Request(HttpRequestMessage httpRequestMessage, CookieContainer cookieContainer)
{
HttpRequestMessage = httpRequestMessage;
CookieContainer = cookieContainer;
}
public HttpRequestMessage HttpRequestMessage { get; private set; }
public CookieContainer CookieContainer { get; private set; }
}
}

View File

@ -1,24 +1,27 @@
namespace Ocelot.Library.Infrastructure.RequestBuilder using System;
{ using System.IO;
using System; using System.Net;
using System.IO; using System.Net.Http;
using System.Net.Http; using System.Net.Http.Headers;
using System.Net.Http.Headers; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http;
namespace Ocelot.Library.Infrastructure.RequestBuilder
{
public class RequestBuilder : IRequestBuilder public class RequestBuilder : IRequestBuilder
{ {
public HttpRequestMessage Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers, public Request Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers,
IRequestCookieCollection cookies, IQueryCollection queryString, string contentType) IRequestCookieCollection cookies, string queryString, string contentType)
{ {
var method = new HttpMethod(httpMethod); var method = new HttpMethod(httpMethod);
var uri = new Uri(downstreamUrl + queryString); var uri = new Uri(string.Format("{0}{1}", downstreamUrl, queryString));
var httpRequestMessage = new HttpRequestMessage(method, uri) var httpRequestMessage = new HttpRequestMessage(method, uri);
if (content != null)
{ {
Content = new StreamContent(content), httpRequestMessage.Content = new StreamContent(content);
}; }
if (!string.IsNullOrEmpty(contentType)) if (!string.IsNullOrEmpty(contentType))
{ {
@ -42,8 +45,19 @@
} }
} }
return httpRequestMessage; var cookieContainer = new CookieContainer();
//todo get rid of if
if (cookies != null)
{
foreach (var cookie in cookies)
{
cookieContainer.Add(uri, new Cookie(cookie.Key, cookie.Value));
}
}
return new Request(httpRequestMessage, cookieContainer);
} }
} }
} }

View File

@ -1,22 +1,18 @@
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ocelot.Library.Infrastructure.RequestBuilder;
namespace Ocelot.Library.Infrastructure.Requester namespace Ocelot.Library.Infrastructure.Requester
{ {
using HttpClient;
public class HttpClientHttpRequester : IHttpRequester public class HttpClientHttpRequester : IHttpRequester
{ {
private readonly IHttpClient _httpClient; public async Task<HttpResponseMessage> GetResponse(Request request)
public HttpClientHttpRequester(IHttpClient httpClient)
{ {
_httpClient = httpClient; using (var handler = new HttpClientHandler { CookieContainer = request.CookieContainer })
} using (var httpClient = new HttpClient(handler))
{
public async Task<HttpResponseMessage> GetResponse(HttpRequestMessage httpRequestMessage) return await httpClient.SendAsync(request.HttpRequestMessage);
{ }
return await _httpClient.SendAsync(httpRequestMessage);
} }
} }
} }

View File

@ -1,10 +1,11 @@
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ocelot.Library.Infrastructure.RequestBuilder;
namespace Ocelot.Library.Infrastructure.Requester namespace Ocelot.Library.Infrastructure.Requester
{ {
public interface IHttpRequester public interface IHttpRequester
{ {
Task<HttpResponseMessage> GetResponse(HttpRequestMessage httpRequestMessage); Task<HttpResponseMessage> GetResponse(Request request);
} }
} }

View File

@ -41,7 +41,7 @@ namespace Ocelot.Library.Middleware
var request = _requestBuilder var request = _requestBuilder
.Build(context.Request.Method, downstreamUrl.Data, context.Request.Body, .Build(context.Request.Method, downstreamUrl.Data, context.Request.Body,
context.Request.Headers, context.Request.Cookies, context.Request.Query, context.Request.ContentType); context.Request.Headers, context.Request.Cookies, context.Request.QueryString.Value, context.Request.ContentType);
var response = await _requester var response = await _requester
.GetResponse(request); .GetResponse(request);

View File

@ -4,21 +4,18 @@ using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ocelot.Library.Infrastructure.Configuration;
using Ocelot.Library.Infrastructure.DownstreamRouteFinder; using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
using Ocelot.Library.Infrastructure.Repository; using Ocelot.Library.Infrastructure.Repository;
using Ocelot.Library.Infrastructure.RequestBuilder;
using Ocelot.Library.Infrastructure.Requester; using Ocelot.Library.Infrastructure.Requester;
using Ocelot.Library.Infrastructure.Responder; using Ocelot.Library.Infrastructure.Responder;
using Ocelot.Library.Infrastructure.UrlMatcher;
using Ocelot.Library.Infrastructure.UrlTemplateReplacer;
using Ocelot.Library.Middleware; using Ocelot.Library.Middleware;
namespace Ocelot namespace Ocelot
{ {
using System.Net.Http;
using Library.Infrastructure.Configuration;
using Library.Infrastructure.HttpClient;
using Library.Infrastructure.RequestBuilder;
using Library.Infrastructure.UrlMatcher;
using Library.Infrastructure.UrlTemplateReplacer;
public class Startup public class Startup
{ {
public Startup(IHostingEnvironment env) public Startup(IHostingEnvironment env)
@ -47,8 +44,6 @@ namespace Ocelot
services.AddSingleton<IDownstreamRouteFinder, DownstreamRouteFinder>(); services.AddSingleton<IDownstreamRouteFinder, DownstreamRouteFinder>();
services.AddSingleton<IHttpRequester, HttpClientHttpRequester>(); services.AddSingleton<IHttpRequester, HttpClientHttpRequester>();
services.AddSingleton<IHttpResponder, HttpContextResponder>(); services.AddSingleton<IHttpResponder, HttpContextResponder>();
services.AddTransient<HttpClient>();
services.AddTransient<IHttpClient, HttpClientWrapper>();
services.AddSingleton<IRequestBuilder, RequestBuilder>(); services.AddSingleton<IRequestBuilder, RequestBuilder>();
// see this for why we register this as singleton http://stackoverflow.com/questions/37371264/invalidoperationexception-unable-to-resolve-service-for-type-microsoft-aspnetc // see this for why we register this as singleton http://stackoverflow.com/questions/37371264/invalidoperationexception-unable-to-resolve-service-for-type-microsoft-aspnetc

View File

@ -1,289 +0,0 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Internal;
using Microsoft.Extensions.Primitives;
using Ocelot.Library.Infrastructure.Requester;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
namespace Ocelot.UnitTests.Requester
{
using System;
using Library.Infrastructure.HttpClient;
using Moq;
public class RequesterTests
{
private readonly IHttpRequester _httpRequester;
private string _httpMethod;
private string _downstreamUrl;
private HttpResponseMessage _result;
private HttpContent _content;
private IHeaderDictionary _headers;
private IRequestCookieCollection _cookies;
private IQueryCollection _query;
private string _contentType;
private Mock<IHttpClient> _httpClient;
public RequesterTests()
{
_httpClient = new Mock<IHttpClient>();
_httpRequester = new HttpClientHttpRequester(_httpClient.Object);
}
[Fact]
public void should_call_downstream_url_correctly()
{
this.Given(x => x.GivenIHaveHttpMethod("GET"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenTheDownstreamServerReturns(HttpStatusCode.OK))
.When(x => x.WhenIMakeARequest())
.Then(x => x.ThenTheFollowingIsReturned(HttpStatusCode.OK))
.And(x => x.ThenTheDownstreamServerIsCalledCorrectly())
.BDDfy();
}
[Fact]
public void should_obey_http_method()
{
this.Given(x => x.GivenIHaveHttpMethod("POST"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.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))
.BDDfy();
}
[Fact]
public void should_forward_http_content()
{
this.Given(x => x.GivenIHaveHttpMethod("POST"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenIHaveTheHttpContent(new StringContent("Hi from Tom")))
.And(x => x.GivenTheContentTypeIs("application/json"))
.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")))
.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")))
.And(x => x.GivenTheContentTypeIs("application/json"))
.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")))
.And(x => x.ThenTheCorrectContentHeadersAreUsed(new HeaderDictionary
{
{
"Content-Type", "application/json"
}
}))
.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 GivenTheContentTypeIs(string contentType)
{
_contentType = contentType;
}
private void ThenTheCorrectQueryStringIsUsed(string expected)
{
throw new NotImplementedException();
//_httpTest.CallLog[0].Request.RequestUri.Query.ShouldBe(expected);
}
private void GivenTheQueryStringIs(IQueryCollection query)
{
_query = query;
}
private void ThenTheCorrectCookiesAreUsed(IRequestCookieCollection cookies)
{
throw new NotImplementedException();
/* 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)
{
throw new NotImplementedException();
/*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)
{
throw new NotImplementedException();
/*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)
{
_content = content;
}
private void GivenIHaveHttpMethod(string httpMethod)
{
_httpMethod = httpMethod;
}
private void GivenIHaveDownstreamUrl(string downstreamUrl)
{
_downstreamUrl = downstreamUrl;
}
private void GivenTheDownstreamServerReturns(HttpStatusCode statusCode)
{
_httpClient
.Setup(x => x.SendAsync(It.IsAny<HttpRequestMessage>()))
.ReturnsAsync(new HttpResponseMessage()
{
StatusCode = statusCode,
Content = _content != null ? _content : null
});
/* _httpTest
.RespondWith(_content != null ? _content.ReadAsStringAsync().Result : string.Empty, (int)statusCode);*/
}
private void WhenIMakeARequest()
{
_result = _httpRequester
.GetResponse(new HttpRequestMessage()).Result;
}
private void ThenTheFollowingIsReturned(HttpStatusCode expected)
{
_result.StatusCode.ShouldBe(expected);
}
private void ThenTheDownstreamServerIsCalledCorrectly()
{
throw new NotImplementedException();
//_httpTest.ShouldHaveCalled(_downstreamUrl);
}
private void ThenTheCorrectHttpMethodIsUsed(HttpMethod expected)
{
throw new NotImplementedException();
//_httpTest.CallLog[0].Request.Method.ShouldBe(expected);
}
private void ThenTheCorrectContentIsUsed(HttpContent content)
{
throw new NotImplementedException();
//_httpTest.CallLog[0].Response.Content.ReadAsStringAsync().Result.ShouldBe(content.ReadAsStringAsync().Result);
}
}
}

View File

@ -0,0 +1,224 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Internal;
using Ocelot.Library.Infrastructure.RequestBuilder;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
namespace Ocelot.UnitTests.RequestBuilder
{
public class RequestBuilderTests
{
private string _httpMethod;
private string _downstreamUrl;
private HttpContent _content;
private IHeaderDictionary _headers;
private IRequestCookieCollection _cookies;
private string _query;
private string _contentType;
private readonly IRequestBuilder _requestBuilder;
private Request _result;
public RequestBuilderTests()
{
_content = new StringContent(string.Empty);
_requestBuilder = new Library.Infrastructure.RequestBuilder.RequestBuilder();
}
[Fact]
public void should_user_downstream_url()
{
this.Given(x => x.GivenIHaveHttpMethod("GET"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectDownstreamUrlIsUsed("http://www.bbc.co.uk/"))
.BDDfy();
}
[Fact]
public void should_use_http_method()
{
this.Given(x => x.GivenIHaveHttpMethod("POST"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectHttpMethodIsUsed(HttpMethod.Post))
.BDDfy();
}
[Fact]
public void should_use_http_content()
{
this.Given(x => x.GivenIHaveHttpMethod("POST"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenIHaveTheHttpContent(new StringContent("Hi from Tom")))
.And(x => x.GivenTheContentTypeIs("application/json"))
.When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectContentIsUsed(new StringContent("Hi from Tom")))
.BDDfy();
}
[Fact]
public void should_use_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")))
.And(x => x.GivenTheContentTypeIs("application/json"))
.When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectContentIsUsed(new StringContent("Hi from Tom")))
.And(x => x.ThenTheCorrectContentHeadersAreUsed(new HeaderDictionary
{
{
"Content-Type", "application/json"
}
}))
.BDDfy();
}
[Fact]
public void should_use_headers()
{
this.Given(x => x.GivenIHaveHttpMethod("GET"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenTheHttpHeadersAre(new HeaderDictionary
{
{"ChopSticks", "Bubbles" }
}))
.When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectHeadersAreUsed(new HeaderDictionary
{
{"ChopSticks", "Bubbles" }
}))
.BDDfy();
}
[Fact]
public void should_use_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" }
})))
.When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectCookiesAreUsed(new RequestCookieCollection(new Dictionary<string, string>
{
{ "TheCookie","Monster" }
})))
.BDDfy();
}
[Fact]
public void should_user_query_string()
{
this.Given(x => x.GivenIHaveHttpMethod("POST"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenTheQueryStringIs("?jeff=1&geoff=2"))
.When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectQueryStringIsUsed("?jeff=1&geoff=2"))
.BDDfy();
}
private void GivenTheContentTypeIs(string contentType)
{
_contentType = contentType;
}
private void ThenTheCorrectQueryStringIsUsed(string expected)
{
_result.HttpRequestMessage.RequestUri.Query.ShouldBe(expected);
}
private void GivenTheQueryStringIs(string query)
{
_query = query;
}
private void ThenTheCorrectCookiesAreUsed(IRequestCookieCollection expected)
{
var resultCookies = _result.CookieContainer.GetCookies(new Uri(_downstreamUrl + _query));
var resultDictionary = resultCookies.Cast<Cookie>().ToDictionary(cook => cook.Name, cook => cook.Value);
foreach (var expectedCookie in expected)
{
var resultCookie = resultDictionary[expectedCookie.Key];
resultCookie.ShouldBe(expectedCookie.Value);
}
}
private void GivenTheCookiesAre(IRequestCookieCollection cookies)
{
_cookies = cookies;
}
private void ThenTheCorrectHeadersAreUsed(IHeaderDictionary expected)
{
var expectedHeaders = expected.Select(x => new KeyValuePair<string, string[]>(x.Key, x.Value));
foreach (var expectedHeader in expectedHeaders)
{
_result.HttpRequestMessage.Headers.ShouldContain(x => x.Key == expectedHeader.Key && x.Value.First() == expectedHeader.Value[0]);
}
}
private void ThenTheCorrectContentHeadersAreUsed(IHeaderDictionary expected)
{
var expectedHeaders = expected.Select(x => new KeyValuePair<string, string[]>(x.Key, x.Value));
foreach (var expectedHeader in expectedHeaders)
{
_result.HttpRequestMessage.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)
{
_content = content;
}
private void GivenIHaveHttpMethod(string httpMethod)
{
_httpMethod = httpMethod;
}
private void GivenIHaveDownstreamUrl(string downstreamUrl)
{
_downstreamUrl = downstreamUrl;
}
private void WhenICreateARequest()
{
_result = _requestBuilder.Build(_httpMethod, _downstreamUrl, _content?.ReadAsStreamAsync().Result, _headers,
_cookies, _query, _contentType);
}
private void ThenTheCorrectDownstreamUrlIsUsed(string expected)
{
_result.HttpRequestMessage.RequestUri.AbsoluteUri.ShouldBe(expected);
}
private void ThenTheCorrectHttpMethodIsUsed(HttpMethod expected)
{
_result.HttpRequestMessage.Method.Method.ShouldBe(expected.Method);
}
private void ThenTheCorrectContentIsUsed(HttpContent expected)
{
_result.HttpRequestMessage.Content.ReadAsStringAsync().Result.ShouldBe(expected.ReadAsStringAsync().Result);
}
}
}