Skip to content

Commit

Permalink
Merge pull request #451 from aws/querystring-encoding-issue
Browse files Browse the repository at this point in the history
Fixed issue with not handling query string encoding
  • Loading branch information
normj authored Apr 29, 2019
2 parents 6414d0b + 290b238 commit 9feb6a6
Show file tree
Hide file tree
Showing 22 changed files with 63 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ protected override void MarshallRequest(InvokeFeatures features, APIGatewayProxy
requestFeatures.Path = Utilities.DecodeResourcePath(requestFeatures.Path);

requestFeatures.QueryString = Utilities.CreateQueryStringParamaters(
apiGatewayRequest.QueryStringParameters, apiGatewayRequest.MultiValueQueryStringParameters);
apiGatewayRequest.QueryStringParameters, apiGatewayRequest.MultiValueQueryStringParameters, true);

Utilities.SetHeadersCollection(requestFeatures.Headers, apiGatewayRequest.Headers, apiGatewayRequest.MultiValueHeaders);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ protected override void MarshallRequest(InvokeFeatures features, ApplicationLoad
requestFeatures.Path = Utilities.DecodeResourcePath(lambdaRequest.Path);

requestFeatures.QueryString = Utilities.CreateQueryStringParamaters(
lambdaRequest.QueryStringParameters, lambdaRequest.MultiValueQueryStringParameters);
lambdaRequest.QueryStringParameters, lambdaRequest.MultiValueQueryStringParameters, false);

Utilities.SetHeadersCollection(requestFeatures.Headers, lambdaRequest.Headers, lambdaRequest.MultiValueHeaders);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ internal static (string body, bool isBase64Encoded) ConvertAspNetCoreBodyToLambd
}
}

internal static string CreateQueryStringParamaters(IDictionary<string, string> singleValues, IDictionary<string, IList<string>> multiValues)
internal static string CreateQueryStringParamaters(IDictionary<string, string> singleValues, IDictionary<string, IList<string>> multiValues, bool urlEncodeValue)
{
if (multiValues?.Count > 0)
{
Expand All @@ -78,7 +78,8 @@ internal static string CreateQueryStringParamaters(IDictionary<string, string> s
{
sb.Append("&");
}
sb.Append($"{kvp.Key}={value}");

sb.Append($"{kvp.Key}={(urlEncodeValue ? WebUtility.UrlEncode(value) : value)}");
}
}
return sb.ToString();
Expand All @@ -95,7 +96,7 @@ internal static string CreateQueryStringParamaters(IDictionary<string, string> s
{
sb.Append("&");
}
sb.Append($"{kvp.Key}={kvp.Value}");
sb.Append($"{kvp.Key}={(urlEncodeValue ? WebUtility.UrlEncode(kvp.Value) : kvp.Value)}");
}
return sb.ToString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,24 @@ public async Task TestGetNoQueryStringAlbMv()
public async Task TestGetEncodingQueryStringAlb()
{
var response = await this.InvokeApplicationLoadBalancerRequest("values-get-querystring-alb-encoding-request.json");
Assert.Equal("?url=http://www.gooogle.com", response.Body);
var results = JsonConvert.DeserializeObject<TestWebApp.Controllers.RawQueryStringController.Results>(response.Body);
Assert.Equal("http://www.gooogle.com", results.Url);
Assert.Equal(DateTimeOffset.Parse("2019-03-12T16:06:06.549817+00:00"), results.TestDateTimeOffset);

Assert.True(response.Headers.ContainsKey("Content-Type"));
Assert.Equal("application/json; charset=utf-8", response.Headers["Content-Type"]);
}

[Fact]
public async Task TestGetEncodingQueryStringAlbMv()
{
var response = await this.InvokeApplicationLoadBalancerRequest("values-get-querystring-alb-mv-encoding-request.json");
Assert.Equal("?url=http://www.gooogle.com", response.Body);
var results = JsonConvert.DeserializeObject<TestWebApp.Controllers.RawQueryStringController.Results>(response.Body);
Assert.Equal("http://www.gooogle.com", results.Url);
Assert.Equal(DateTimeOffset.Parse("2019-03-12T16:06:06.549817+00:00"), results.TestDateTimeOffset);

Assert.True(response.MultiValueHeaders.ContainsKey("Content-Type"));
Assert.Equal("application/json; charset=utf-8", response.MultiValueHeaders["Content-Type"][0]);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public async Task TestGetAllValues()
{
var context = new TestLambdaContext();

var response = await this.InvokeAPIGatewayRequest(context, "values-get-all-apigatway-request.json");
var response = await this.InvokeAPIGatewayRequest(context, "values-get-all-apigateway-request.json");

Assert.Equal(200, response.StatusCode);
Assert.Equal("[\"value1\",\"value2\"]", response.Body);
Expand All @@ -38,7 +38,7 @@ public async Task TestGetAllValues()
[Fact]
public async Task TestGetAllValuesWithCustomPath()
{
var response = await this.InvokeAPIGatewayRequest("values-get-different-proxypath-apigatway-request.json");
var response = await this.InvokeAPIGatewayRequest("values-get-different-proxypath-apigateway-request.json");

Assert.Equal(200, response.StatusCode);
Assert.Equal("[\"value1\",\"value2\"]", response.Body);
Expand All @@ -49,7 +49,7 @@ public async Task TestGetAllValuesWithCustomPath()
[Fact]
public async Task TestGetSingleValue()
{
var response = await this.InvokeAPIGatewayRequest("values-get-single-apigatway-request.json");
var response = await this.InvokeAPIGatewayRequest("values-get-single-apigateway-request.json");

Assert.Equal("value=5", response.Body);
Assert.True(response.MultiValueHeaders.ContainsKey("Content-Type"));
Expand All @@ -59,7 +59,7 @@ public async Task TestGetSingleValue()
[Fact]
public async Task TestGetQueryStringValue()
{
var response = await this.InvokeAPIGatewayRequest("values-get-querystring-apigatway-request.json");
var response = await this.InvokeAPIGatewayRequest("values-get-querystring-apigateway-request.json");

Assert.Equal("Lewis, Meriwether", response.Body);
Assert.True(response.MultiValueHeaders.ContainsKey("Content-Type"));
Expand All @@ -69,7 +69,7 @@ public async Task TestGetQueryStringValue()
[Fact]
public async Task TestGetNoQueryStringApiGateway()
{
var response = await this.InvokeAPIGatewayRequest("values-get-no-querystring-apigatway-request.json");
var response = await this.InvokeAPIGatewayRequest("values-get-no-querystring-apigateway-request.json");

Assert.Equal(string.Empty, response.Body);
Assert.True(response.MultiValueHeaders.ContainsKey("Content-Type"));
Expand All @@ -79,17 +79,19 @@ public async Task TestGetNoQueryStringApiGateway()
[Fact]
public async Task TestGetEncodingQueryStringGateway()
{
var response = await this.InvokeAPIGatewayRequest("values-get-querystring-apigatway-encoding-request.json");
var response = await this.InvokeAPIGatewayRequest("values-get-querystring-apigateway-encoding-request.json");
var results = JsonConvert.DeserializeObject<TestWebApp.Controllers.RawQueryStringController.Results>(response.Body);
Assert.Equal("http://www.gooogle.com", results.Url);
Assert.Equal(DateTimeOffset.Parse("2019-03-12T16:06:06.549817+00:00"), results.TestDateTimeOffset);

Assert.Equal("?url=http://www.gooogle.com", response.Body);
Assert.True(response.MultiValueHeaders.ContainsKey("Content-Type"));
Assert.Equal("text/plain; charset=utf-8", response.MultiValueHeaders["Content-Type"][0]);
Assert.Equal("application/json; charset=utf-8", response.MultiValueHeaders["Content-Type"][0]);
}

[Fact]
public async Task TestPutWithBody()
{
var response = await this.InvokeAPIGatewayRequest("values-put-withbody-apigatway-request.json");
var response = await this.InvokeAPIGatewayRequest("values-put-withbody-apigateway-request.json");

Assert.Equal(200, response.StatusCode);
Assert.Equal("Agent, Smith", response.Body);
Expand All @@ -100,15 +102,15 @@ public async Task TestPutWithBody()
[Fact]
public async Task TestDefaultResponseErrorCode()
{
var response = await this.InvokeAPIGatewayRequest("values-get-error-apigatway-request.json");
var response = await this.InvokeAPIGatewayRequest("values-get-error-apigateway-request.json");

Assert.Equal(500, response.StatusCode);
Assert.Equal(string.Empty, response.Body);
}

[Theory]
[InlineData("values-get-aggregateerror-apigatway-request.json", "AggregateException")]
[InlineData("values-get-typeloaderror-apigatway-request.json", "ReflectionTypeLoadException")]
[InlineData("values-get-aggregateerror-apigateway-request.json", "AggregateException")]
[InlineData("values-get-typeloaderror-apigateway-request.json", "ReflectionTypeLoadException")]
public async Task TestEnhancedExceptions(string requestFileName, string expectedExceptionType)
{
var response = await this.InvokeAPIGatewayRequest(requestFileName);
Expand All @@ -122,7 +124,7 @@ public async Task TestEnhancedExceptions(string requestFileName, string expected
[Fact]
public async Task TestGettingSwaggerDefinition()
{
var response = await this.InvokeAPIGatewayRequest("swagger-get-apigatway-request.json");
var response = await this.InvokeAPIGatewayRequest("swagger-get-apigateway-request.json");

Assert.Equal(200, response.StatusCode);
Assert.True(response.Body.Length > 0);
Expand All @@ -132,7 +134,7 @@ public async Task TestGettingSwaggerDefinition()
[Fact]
public void TestGetCustomAuthorizerValue()
{
var requestStr = File.ReadAllText("values-get-customauthorizer-apigatway-request.json");
var requestStr = File.ReadAllText("values-get-customauthorizer-apigateway-request.json");
var request = JsonConvert.DeserializeObject<APIGatewayProxyRequest>(requestStr);
Assert.NotNull(request.RequestContext.Authorizer);
Assert.NotNull(request.RequestContext.Authorizer.StringKey);
Expand Down Expand Up @@ -176,7 +178,7 @@ public void TestCustomAuthorizerSerialization()
[Fact]
public async Task TestGetBinaryContent()
{
var response = await this.InvokeAPIGatewayRequest("values-get-binary-apigatway-request.json");
var response = await this.InvokeAPIGatewayRequest("values-get-binary-apigateway-request.json");

Assert.Equal((int) HttpStatusCode.OK, response.StatusCode);

Expand Down Expand Up @@ -284,7 +286,7 @@ public async Task TestMissingResourceInRequest()
[Fact]
public async Task TestDeleteNoContentContentType()
{
var response = await this.InvokeAPIGatewayRequest("values-delete-no-content-type-apigatway-request.json");
var response = await this.InvokeAPIGatewayRequest("values-delete-no-content-type-apigateway-request.json");

Assert.Equal(200, response.StatusCode);
Assert.True(response.Body.Length == 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
}
},
"httpMethod": "GET",
"path": "/api/rawquerystring",
"path": "/api/rawquerystring/json",
"queryStringParameters": {
"url": "http://www.gooogle.com"
"url": "http://www.gooogle.com",
"testDateTimeOffset": "2019-03-12T16%3A06%3A06.5498170%2B00%3A00"
},
"headers": {
"accept": "text/html,application/xhtml+xml",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
}
},
"httpMethod": "GET",
"path": "/api/rawquerystring",
"path": "/api/rawquerystring/json",
"multiValueQueryStringParameters": {
"url": [ "http://www.gooogle.com"]
"url": [ "http://www.gooogle.com" ],
"testDateTimeOffset": [ "2019-03-12T16%3A06%3A06.5498170%2B00%3A00" ]
},
"multiValueHeaders": {
"accept": [ "text/html", "application/xhtml+xml" ],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
{
"resource": "/{proxy+}",
"path": "/api/rawquerystring",
"path": "/api/rawquerystring/json",
"httpMethod": "GET",
"headers": null,
"queryStringParameters": {
"url": "http://www.gooogle.com"
"url": "http://www.gooogle.com",
"testDateTimeOffset": "2019-03-12T16:06:06.549817+00:00"
},
"pathParameters": {
"proxy": "api/rawquerystring"
"proxy": "api/rawquerystring/json"
},
"stageVariables": null,
"requestContext": {
Expand Down
17 changes: 17 additions & 0 deletions Libraries/test/TestWebApp/Controllers/RawQueryStringController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,22 @@ public string Get()
{
return this.Request.QueryString.ToString();
}

[HttpGet]
[Route("json")]
public Results Get([FromQuery] string url, [FromQuery] DateTimeOffset testDateTimeOffset)
{
return new Results
{
Url = url,
TestDateTimeOffset = testDateTimeOffset
};
}

public class Results
{
public string Url { get; set; }
public DateTimeOffset TestDateTimeOffset { get;set;}
}
}
}

0 comments on commit 9feb6a6

Please sign in to comment.