fixed a bug where getting invalid parameter error if sending a steam content with no stream, now we try convert to byte array which the c# http client is happy to take if empty...or this error is caused because we are trying to use a stream when we shouldnt.

This commit is contained in:
TomPallister 2016-10-28 22:50:00 +01:00
parent 6be3c1cf73
commit 3a1dd1f9bc
7 changed files with 49 additions and 18 deletions

View File

@ -12,17 +12,18 @@ namespace Ocelot.RequestBuilder.Builder
public class HttpRequestBuilder : IRequestBuilder public class HttpRequestBuilder : IRequestBuilder
{ {
public async Task<Response<Request>> Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers, public async Task<Response<Request>> Build(string httpMethod, string downstreamUrl, Stream content, IHeaderDictionary headers,
IRequestCookieCollection cookies, string queryString, string contentType) IRequestCookieCollection cookies, QueryString queryString, string contentType)
{ {
var method = new HttpMethod(httpMethod); var method = new HttpMethod(httpMethod);
var uri = new Uri(string.Format("{0}{1}", downstreamUrl, queryString)); var uri = new Uri(string.Format("{0}{1}", downstreamUrl, queryString.ToUriComponent()));
var httpRequestMessage = new HttpRequestMessage(method, uri); var httpRequestMessage = new HttpRequestMessage(method, uri);
if (content != null) if (content != null)
{ {
httpRequestMessage.Content = new StreamContent(content); httpRequestMessage.Content = new ByteArrayContent(ToByteArray(content));
} }
if (!string.IsNullOrEmpty(contentType)) if (!string.IsNullOrEmpty(contentType))
@ -35,11 +36,7 @@ namespace Ocelot.RequestBuilder.Builder
if (headers != null) if (headers != null)
{ {
headers.Remove("Content-Type"); headers.Remove("Content-Type");
}
//todo get rid of if
if (headers != null)
{
foreach (var header in headers) foreach (var header in headers)
{ {
//todo get rid of if.. //todo get rid of if..
@ -63,5 +60,17 @@ namespace Ocelot.RequestBuilder.Builder
return new OkResponse<Request>(new Request(httpRequestMessage, cookieContainer)); return new OkResponse<Request>(new Request(httpRequestMessage, cookieContainer));
} }
private byte[] ToByteArray(Stream stream)
{
using (stream)
{
using (MemoryStream memStream = new MemoryStream())
{
stream.CopyTo(memStream);
return memStream.ToArray();
}
}
}
} }
} }

View File

@ -12,7 +12,7 @@ namespace Ocelot.RequestBuilder.Builder
Stream content, Stream content,
IHeaderDictionary headers, IHeaderDictionary headers,
IRequestCookieCollection cookies, IRequestCookieCollection cookies,
string queryString, QueryString queryString,
string contentType); string contentType);
} }
} }

View File

@ -34,7 +34,7 @@ namespace Ocelot.RequestBuilder.Middleware
var request = await _requestBuilder var request = await _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.QueryString.Value, context.Request.ContentType); context.Request.Headers, context.Request.Cookies, context.Request.QueryString, context.Request.ContentType);
if (request.IsError) if (request.IsError)
{ {

View File

@ -106,6 +106,31 @@ namespace Ocelot.AcceptanceTests
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_return_response_201_with_complex_query_string()
{
var yamlConfiguration = new YamlConfiguration
{
ReRoutes = new List<YamlReRoute>
{
new YamlReRoute
{
DownstreamTemplate = "http://localhost:51879/newThing",
UpstreamTemplate = "/newThing",
UpstreamHttpMethod = "Get",
}
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(yamlConfiguration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/newThing?DeviceType=IphoneApp&Browser=moonpigIphone&BrowserString=-&CountryCode=123&DeviceName=iPhone 5 (GSM+CDMA)&OperatingSystem=iPhone OS 7.1.2&BrowserVersion=3708AdHoc&ipAddress=-"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.BDDfy();
}
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody) private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
{ {
_builder = new WebHostBuilder() _builder = new WebHostBuilder()

View File

@ -21,9 +21,6 @@ ReRoutes:
LocationId: Claims[LocationId] > value LocationId: Claims[LocationId] > value
UserType: Claims[sub] > value[0] > | UserType: Claims[sub] > value[0] > |
UserId: Claims[sub] > value[1] > | UserId: Claims[sub] > value[1] > |
- DownstreamTemplate: http://www.bbc.co.uk - DownstreamTemplate: http://jsonplaceholder.typicode.com/posts
UpstreamTemplate: / UpstreamTemplate: /posts
UpstreamHttpMethod: Get
- DownstreamTemplate: http://localhost:51879/api/products/{productId}
UpstreamTemplate: /products/{productId}
UpstreamHttpMethod: Get UpstreamHttpMethod: Get

View File

@ -69,7 +69,7 @@ namespace Ocelot.UnitTests.RequestBuilder
_request = new OkResponse<Request>(request); _request = new OkResponse<Request>(request);
_requestBuilder _requestBuilder
.Setup(x => x.Build(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<IHeaderDictionary>(), .Setup(x => x.Build(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Stream>(), It.IsAny<IHeaderDictionary>(),
It.IsAny<IRequestCookieCollection>(), It.IsAny<string>(), It.IsAny<string>())) It.IsAny<IRequestCookieCollection>(), It.IsAny<QueryString>(), It.IsAny<string>()))
.ReturnsAsync(_request); .ReturnsAsync(_request);
} }

View File

@ -21,7 +21,7 @@ namespace Ocelot.UnitTests.RequestBuilder
private HttpContent _content; private HttpContent _content;
private IHeaderDictionary _headers; private IHeaderDictionary _headers;
private IRequestCookieCollection _cookies; private IRequestCookieCollection _cookies;
private string _query; private QueryString _query;
private string _contentType; private string _contentType;
private readonly IRequestBuilder _requestBuilder; private readonly IRequestBuilder _requestBuilder;
private Response<Request> _result; private Response<Request> _result;
@ -137,7 +137,7 @@ namespace Ocelot.UnitTests.RequestBuilder
{ {
this.Given(x => x.GivenIHaveHttpMethod("POST")) this.Given(x => x.GivenIHaveHttpMethod("POST"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk")) .And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenTheQueryStringIs("?jeff=1&geoff=2")) .And(x => x.GivenTheQueryStringIs(new QueryString("?jeff=1&geoff=2")))
.When(x => x.WhenICreateARequest()) .When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectQueryStringIsUsed("?jeff=1&geoff=2")) .And(x => x.ThenTheCorrectQueryStringIsUsed("?jeff=1&geoff=2"))
.BDDfy(); .BDDfy();
@ -153,7 +153,7 @@ namespace Ocelot.UnitTests.RequestBuilder
_result.Data.HttpRequestMessage.RequestUri.Query.ShouldBe(expected); _result.Data.HttpRequestMessage.RequestUri.Query.ShouldBe(expected);
} }
private void GivenTheQueryStringIs(string query) private void GivenTheQueryStringIs(QueryString query)
{ {
_query = query; _query = query;
} }