diff --git a/src/Ocelot.Library/Infrastructure/HttpClient/HttpClientWrapper.cs b/src/Ocelot.Library/Infrastructure/HttpClient/HttpClientWrapper.cs deleted file mode 100644 index 9a08eb1c..00000000 --- a/src/Ocelot.Library/Infrastructure/HttpClient/HttpClientWrapper.cs +++ /dev/null @@ -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 DeleteAsync(string requestUri) - { - return await _httpClient.DeleteAsync(requestUri); - } - - public async Task DeleteAsync(Uri requestUri) - { - return await _httpClient.DeleteAsync(requestUri); - } - - public async Task DeleteAsync(Uri requestUri, CancellationToken cancellationToken) - { - return await _httpClient.DeleteAsync(requestUri, cancellationToken); - } - - public async Task DeleteAsync(string requestUri, CancellationToken cancellationToken) - { - return await _httpClient.DeleteAsync(requestUri, cancellationToken); - } - - public async Task GetAsync(string requestUri) - { - return await _httpClient.GetAsync(requestUri); - } - - public async Task GetAsync(Uri requestUri) - { - return await _httpClient.GetAsync(requestUri); - } - - public async Task GetAsync(string requestUri, HttpCompletionOption completionOption) - { - return await _httpClient.GetAsync(requestUri, completionOption); - } - - public async Task GetAsync(string requestUri, CancellationToken cancellationToken) - { - return await _httpClient.GetAsync(requestUri, cancellationToken); - } - - public async Task GetAsync(Uri requestUri, HttpCompletionOption completionOption) - { - return await _httpClient.GetAsync(requestUri, completionOption); - } - - public async Task GetAsync(Uri requestUri, CancellationToken cancellationToken) - { - return await _httpClient.GetAsync(requestUri, cancellationToken); - } - - public async Task GetAsync(string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken) - { - return await _httpClient.GetAsync(requestUri, completionOption, cancellationToken); - } - - public async Task GetAsync(Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken) - { - return await _httpClient.GetAsync(requestUri, completionOption, cancellationToken); - } - - public async Task GetByteArrayAsync(string requestUri) - { - return await _httpClient.GetByteArrayAsync(requestUri); - } - - public async Task GetByteArrayAsync(Uri requestUri) - { - return await _httpClient.GetByteArrayAsync(requestUri); - } - - public async Task GetStreamAsync(string requestUri) - { - return await _httpClient.GetStreamAsync(requestUri); - } - - public async Task GetStreamAsync(Uri requestUri) - { - return await _httpClient.GetStreamAsync(requestUri); - } - - public async Task GetStringAsync(string requestUri) - { - return await _httpClient.GetStringAsync(requestUri); - } - - public async Task GetStringAsync(Uri requestUri) - { - return await _httpClient.GetStringAsync(requestUri); - } - - public async Task PostAsync(string requestUri, HttpContent content) - { - return await _httpClient.PostAsync(requestUri, content); - } - - public async Task PostAsync(Uri requestUri, HttpContent content) - { - return await _httpClient.PostAsync(requestUri, content); - } - - public async Task PostAsync(string requestUri, HttpContent content, CancellationToken cancellationToken) - { - return await _httpClient.PostAsync(requestUri, content, cancellationToken); - } - - public async Task PostAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken) - { - return await _httpClient.PostAsync(requestUri, content, cancellationToken); - } - - public async Task PutAsync(string requestUri, HttpContent content) - { - return await _httpClient.PutAsync(requestUri, content); - } - - public async Task PutAsync(Uri requestUri, HttpContent content) - { - return await _httpClient.PutAsync(requestUri, content); - } - - public async Task PutAsync(string requestUri, HttpContent content, CancellationToken cancellationToken) - { - return await _httpClient.PutAsync(requestUri, content, cancellationToken); - } - - public async Task PutAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken) - { - return await _httpClient.PutAsync(requestUri, content, cancellationToken); - } - - public async Task SendAsync(HttpRequestMessage request) - { - return await _httpClient.SendAsync(request); - } - - public async Task SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption) - { - return await _httpClient.SendAsync(request, completionOption); - } - - public async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - return await _httpClient.SendAsync(request, cancellationToken); - } - - public async Task SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) - { - return await _httpClient.SendAsync(request, completionOption, cancellationToken); - } - - public void Dispose(bool disposing) - { - if (!disposing) - { - _httpClient.Dispose(); - } - } - } -} diff --git a/src/Ocelot.Library/Infrastructure/HttpClient/IHttpClient.cs b/src/Ocelot.Library/Infrastructure/HttpClient/IHttpClient.cs deleted file mode 100644 index b74a4246..00000000 --- a/src/Ocelot.Library/Infrastructure/HttpClient/IHttpClient.cs +++ /dev/null @@ -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 DeleteAsync(string requestUri); - Task DeleteAsync(Uri requestUri); - Task DeleteAsync(Uri requestUri, CancellationToken cancellationToken); - Task DeleteAsync(string requestUri, CancellationToken cancellationToken); - Task GetAsync(string requestUri); - Task GetAsync(Uri requestUri); - Task GetAsync(string requestUri, HttpCompletionOption completionOption); - Task GetAsync(string requestUri, CancellationToken cancellationToken); - Task GetAsync(Uri requestUri, HttpCompletionOption completionOption); - Task GetAsync(Uri requestUri, CancellationToken cancellationToken); - Task GetAsync(string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken); - Task GetAsync(Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken); - Task GetByteArrayAsync(string requestUri); - Task GetByteArrayAsync(Uri requestUri); - Task GetStreamAsync(string requestUri); - Task GetStreamAsync(Uri requestUri); - Task GetStringAsync(string requestUri); - Task GetStringAsync(Uri requestUri); - Task PostAsync(string requestUri, HttpContent content); - Task PostAsync(Uri requestUri, HttpContent content); - Task PostAsync(string requestUri, HttpContent content, CancellationToken cancellationToken); - Task PostAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken); - Task PutAsync(string requestUri, HttpContent content); - Task PutAsync(Uri requestUri, HttpContent content); - Task PutAsync(string requestUri, HttpContent content, CancellationToken cancellationToken); - Task PutAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken); - Task SendAsync(HttpRequestMessage request); - Task SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption); - Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken); - Task SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken); - void Dispose(bool disposing); - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/RequestBuilder/IRequestBuilder.cs b/src/Ocelot.Library/Infrastructure/RequestBuilder/IRequestBuilder.cs index 5bb6e27d..482bf51a 100644 --- a/src/Ocelot.Library/Infrastructure/RequestBuilder/IRequestBuilder.cs +++ b/src/Ocelot.Library/Infrastructure/RequestBuilder/IRequestBuilder.cs @@ -1,17 +1,16 @@ -namespace Ocelot.Library.Infrastructure.RequestBuilder -{ - using System.IO; - using System.Net.Http; - using Microsoft.AspNetCore.Http; +using System.IO; +using Microsoft.AspNetCore.Http; +namespace Ocelot.Library.Infrastructure.RequestBuilder +{ public interface IRequestBuilder { - HttpRequestMessage Build(string httpMethod, + Request Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers, IRequestCookieCollection cookies, - IQueryCollection queryString, + string queryString, string contentType); } } diff --git a/src/Ocelot.Library/Infrastructure/RequestBuilder/Request.cs b/src/Ocelot.Library/Infrastructure/RequestBuilder/Request.cs new file mode 100644 index 00000000..b35abf32 --- /dev/null +++ b/src/Ocelot.Library/Infrastructure/RequestBuilder/Request.cs @@ -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; } + } +} diff --git a/src/Ocelot.Library/Infrastructure/RequestBuilder/RequestBuilder.cs b/src/Ocelot.Library/Infrastructure/RequestBuilder/RequestBuilder.cs index 578b60b5..653c263a 100644 --- a/src/Ocelot.Library/Infrastructure/RequestBuilder/RequestBuilder.cs +++ b/src/Ocelot.Library/Infrastructure/RequestBuilder/RequestBuilder.cs @@ -1,24 +1,27 @@ -namespace Ocelot.Library.Infrastructure.RequestBuilder -{ - using System; - using System.IO; - using System.Net.Http; - using System.Net.Http.Headers; - using Microsoft.AspNetCore.Http; +using System; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using Microsoft.AspNetCore.Http; +namespace Ocelot.Library.Infrastructure.RequestBuilder +{ public class RequestBuilder : IRequestBuilder { - public HttpRequestMessage Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers, - IRequestCookieCollection cookies, IQueryCollection queryString, string contentType) + public Request Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers, + IRequestCookieCollection cookies, string queryString, string contentType) { 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)) { @@ -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); } } } \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/Requester/HttpClientHttpRequester.cs b/src/Ocelot.Library/Infrastructure/Requester/HttpClientHttpRequester.cs index b2a14c7e..c2b91523 100644 --- a/src/Ocelot.Library/Infrastructure/Requester/HttpClientHttpRequester.cs +++ b/src/Ocelot.Library/Infrastructure/Requester/HttpClientHttpRequester.cs @@ -1,22 +1,18 @@ using System.Net.Http; using System.Threading.Tasks; +using Ocelot.Library.Infrastructure.RequestBuilder; namespace Ocelot.Library.Infrastructure.Requester { - using HttpClient; - public class HttpClientHttpRequester : IHttpRequester { - private readonly IHttpClient _httpClient; - - public HttpClientHttpRequester(IHttpClient httpClient) + public async Task GetResponse(Request request) { - _httpClient = httpClient; - } - - public async Task GetResponse(HttpRequestMessage httpRequestMessage) - { - return await _httpClient.SendAsync(httpRequestMessage); + using (var handler = new HttpClientHandler { CookieContainer = request.CookieContainer }) + using (var httpClient = new HttpClient(handler)) + { + return await httpClient.SendAsync(request.HttpRequestMessage); + } } } } \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/Requester/IHttpRequester.cs b/src/Ocelot.Library/Infrastructure/Requester/IHttpRequester.cs index 2a426d52..e8d3d33b 100644 --- a/src/Ocelot.Library/Infrastructure/Requester/IHttpRequester.cs +++ b/src/Ocelot.Library/Infrastructure/Requester/IHttpRequester.cs @@ -1,10 +1,11 @@ using System.Net.Http; using System.Threading.Tasks; +using Ocelot.Library.Infrastructure.RequestBuilder; namespace Ocelot.Library.Infrastructure.Requester { public interface IHttpRequester { - Task GetResponse(HttpRequestMessage httpRequestMessage); + Task GetResponse(Request request); } } diff --git a/src/Ocelot.Library/Middleware/HttpRequesterMiddleware.cs b/src/Ocelot.Library/Middleware/HttpRequesterMiddleware.cs index 4521e858..ed585924 100644 --- a/src/Ocelot.Library/Middleware/HttpRequesterMiddleware.cs +++ b/src/Ocelot.Library/Middleware/HttpRequesterMiddleware.cs @@ -41,7 +41,7 @@ namespace Ocelot.Library.Middleware var request = _requestBuilder .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 .GetResponse(request); diff --git a/src/Ocelot/Startup.cs b/src/Ocelot/Startup.cs index 71d329a5..0ff6b0e2 100644 --- a/src/Ocelot/Startup.cs +++ b/src/Ocelot/Startup.cs @@ -4,21 +4,18 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Ocelot.Library.Infrastructure.Configuration; using Ocelot.Library.Infrastructure.DownstreamRouteFinder; using Ocelot.Library.Infrastructure.Repository; +using Ocelot.Library.Infrastructure.RequestBuilder; using Ocelot.Library.Infrastructure.Requester; using Ocelot.Library.Infrastructure.Responder; +using Ocelot.Library.Infrastructure.UrlMatcher; +using Ocelot.Library.Infrastructure.UrlTemplateReplacer; using Ocelot.Library.Middleware; 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 Startup(IHostingEnvironment env) @@ -47,8 +44,6 @@ namespace Ocelot services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddTransient(); - services.AddTransient(); services.AddSingleton(); // see this for why we register this as singleton http://stackoverflow.com/questions/37371264/invalidoperationexception-unable-to-resolve-service-for-type-microsoft-aspnetc diff --git a/test/Ocelot.UnitTests/Configuration/Requester/RequesterTests.cs b/test/Ocelot.UnitTests/Configuration/Requester/RequesterTests.cs deleted file mode 100644 index 46708773..00000000 --- a/test/Ocelot.UnitTests/Configuration/Requester/RequesterTests.cs +++ /dev/null @@ -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 _httpClient; - - public RequesterTests() - { - _httpClient = new Mock(); - _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 - { - { "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 - { - { "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 - { - { "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(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(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(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())) - .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); - } - } -} diff --git a/test/Ocelot.UnitTests/RequestBuilder/RequestBuilderTests.cs b/test/Ocelot.UnitTests/RequestBuilder/RequestBuilderTests.cs new file mode 100644 index 00000000..eb841306 --- /dev/null +++ b/test/Ocelot.UnitTests/RequestBuilder/RequestBuilderTests.cs @@ -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 + { + { "TheCookie","Monster" } + }))) + .When(x => x.WhenICreateARequest()) + .And(x => x.ThenTheCorrectCookiesAreUsed(new RequestCookieCollection(new Dictionary + { + { "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().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(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(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); + } + } +}