Skip to content

Commit

Permalink
Merge branch 'feature/escape-a-little-less' of https://github.com/chr…
Browse files Browse the repository at this point in the history
  • Loading branch information
normj committed Apr 30, 2019
2 parents f590382 + f4173a1 commit 0965c3b
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ protected override void MarshallRequest(InvokeFeatures features, APIGatewayProxy

requestFeatures.Path = Utilities.DecodeResourcePath(requestFeatures.Path);

requestFeatures.QueryString = Utilities.CreateQueryStringParamaters(
requestFeatures.QueryString = Utilities.CreateQueryStringParameters(
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 @@ -10,6 +10,26 @@ namespace Amazon.Lambda.AspNetCoreServer
/// <typeparam name ="TStartup">The type containing the startup methods for the application.</typeparam>
public abstract class APIGatewayProxyFunction<TStartup> : APIGatewayProxyFunction where TStartup : class
{
/// <summary>
/// Default Constructor. The ASP.NET Core Framework will be initialized as part of the construction.
/// </summary>
protected APIGatewayProxyFunction()
: base()
{

}


/// <summary>
///
/// </summary>
/// <param name="startupMode">Configure when the ASP.NET Core framework will be initialized</param>
protected APIGatewayProxyFunction(StartupMode startupMode)
: base(startupMode)
{

}

/// <inheritdoc/>
protected override IWebHostBuilder CreateWebHostBuilder() =>
base.CreateWebHostBuilder().UseStartup<TStartup>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ protected override void MarshallRequest(InvokeFeatures features, ApplicationLoad
requestFeatures.Method = lambdaRequest.HttpMethod;
requestFeatures.Path = Utilities.DecodeResourcePath(lambdaRequest.Path);

requestFeatures.QueryString = Utilities.CreateQueryStringParamaters(
requestFeatures.QueryString = Utilities.CreateQueryStringParameters(
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 @@ -10,6 +10,26 @@ namespace Amazon.Lambda.AspNetCoreServer
/// <typeparam name ="TStartup">The type containing the startup methods for the application.</typeparam>
public abstract class ApplicationLoadBalancerFunction<TStartup> : ApplicationLoadBalancerFunction where TStartup : class
{
/// <summary>
/// Default Constructor. The ASP.NET Core Framework will be initialized as part of the construction.
/// </summary>
protected ApplicationLoadBalancerFunction()
: base()
{

}


/// <summary>
///
/// </summary>
/// <param name="startupMode">Configure when the ASP.NET Core framework will be initialized</param>
protected ApplicationLoadBalancerFunction(StartupMode startupMode)
: base(startupMode)
{

}

/// <inheritdoc/>
protected override IWebHostBuilder CreateWebHostBuilder() =>
base.CreateWebHostBuilder().UseStartup<TStartup>();
Expand Down
18 changes: 7 additions & 11 deletions Libraries/src/Amazon.Lambda.AspNetCoreServer/Internal/Utilities.cs
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, bool urlEncodeValue)
internal static string CreateQueryStringParameters(IDictionary<string, string> singleValues, IDictionary<string, IList<string>> multiValues, bool urlEncodeValue)
{
if (multiValues?.Count > 0)
{
Expand All @@ -78,7 +78,6 @@ internal static string CreateQueryStringParamaters(IDictionary<string, string> s
{
sb.Append("&");
}

sb.Append($"{kvp.Key}={(urlEncodeValue ? WebUtility.UrlEncode(value) : value)}");
}
}
Expand Down Expand Up @@ -121,16 +120,13 @@ internal static void SetHeadersCollection(IHeaderDictionary headers, IDictionary
headers[kvp.Key] = new StringValues(kvp.Value);
}
}

}

internal static string DecodeResourcePath(string resourcePath)
{
// Convert any + signs to percent encoding before url decoding the path.
resourcePath = resourcePath.Replace("+", "%2B");
resourcePath = resourcePath = WebUtility.UrlDecode(resourcePath);

return resourcePath;
}
internal static string DecodeResourcePath(string resourcePath) => WebUtility.UrlDecode(resourcePath
// Convert any + signs to percent encoding before URL decoding the path.
.Replace("+", "%2B")
// Double-escape any %2F (encoded / characters) so that they survive URL decoding the path.
.Replace("%2F", "%252F")
.Replace("%2f", "%252f"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,27 @@ public async Task TestEncodePlusInResourcePath()
[Fact]
public async Task TestEncodeSpaceInResourcePath()
{
var requestStr = GetRequestContent("encode-space-in-resource-path.json");
var response = await this.InvokeAPIGatewayRequest("encode-space-in-resource-path.json");

Assert.Equal(200, response.StatusCode);
Assert.Equal("value=tmh/file name.xml", response.Body);

}

[Fact]
public async Task TestEncodeSlashInResourcePath()
{
var requestStr = GetRequestContent("encode-slash-in-resource-path.json");
var response = await this.InvokeAPIGatewayRequestWithContent(new TestLambdaContext(), requestStr);

Assert.Equal(200, response.StatusCode);
Assert.Equal("{\"only\":\"a%2Fb\"}", response.Body);

response = await this.InvokeAPIGatewayRequestWithContent(new TestLambdaContext(), requestStr.Replace("a%2Fb", "a/b"));

Assert.Equal(200, response.StatusCode);
Assert.Equal("{\"first\":\"a\",\"second\":\"b\"}", response.Body);
}

[Fact]
Expand Down Expand Up @@ -313,12 +330,22 @@ private async Task<APIGatewayProxyResponse> InvokeAPIGatewayRequest(string fileN
}

private async Task<APIGatewayProxyResponse> InvokeAPIGatewayRequest(TestLambdaContext context, string fileName)
{
return await InvokeAPIGatewayRequestWithContent(context, GetRequestContent(fileName));
}

private async Task<APIGatewayProxyResponse> InvokeAPIGatewayRequestWithContent(TestLambdaContext context, string requestContent)
{
var lambdaFunction = new ApiGatewayLambdaFunction();
var request = JsonConvert.DeserializeObject<APIGatewayProxyRequest>(requestContent);
return await lambdaFunction.FunctionHandlerAsync(request, context);
}

private string GetRequestContent(string fileName)
{
var filePath = Path.Combine(Path.GetDirectoryName(this.GetType().GetTypeInfo().Assembly.Location), fileName);
var requestStr = File.ReadAllText(filePath);
var request = JsonConvert.DeserializeObject<APIGatewayProxyRequest>(requestStr);
return await lambdaFunction.FunctionHandlerAsync(request, context);
return requestStr;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
{
"resource": "/{proxy+}",
"path": "/api/resourcepath/encoding/a%2Fb",
"httpMethod": "GET",
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "en-US,en;q=0.9",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "US",
"Host": "uy8hsm9y23.execute-api.us-west-2.amazonaws.com",
"upgrade-insecure-requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36",
"Via": "2.0 078ca3a7cfdee29c8e3514176205c50a.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "5uiz6HWWKWR_HQCLcvX2GXppwJP5FJGXcr_OUs31D6H_JV9uioyyMg==",
"X-Amzn-Trace-Id": "Root=1-5cc7de85-72b4887ed3a6d79ba6a5388a",
"X-Forwarded-For": "50.35.64.182, 52.46.17.56",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
"multiValueHeaders": {
"Accept": [
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"
],
"Accept-Encoding": [
"gzip, deflate, br"
],
"Accept-Language": [
"en-US,en;q=0.9"
],
"CloudFront-Forwarded-Proto": [
"https"
],
"CloudFront-Is-Desktop-Viewer": [
"true"
],
"CloudFront-Is-Mobile-Viewer": [
"false"
],
"CloudFront-Is-SmartTV-Viewer": [
"false"
],
"CloudFront-Is-Tablet-Viewer": [
"false"
],
"CloudFront-Viewer-Country": [
"US"
],
"Host": [
"uy8hsm9y23.execute-api.us-west-2.amazonaws.com"
],
"upgrade-insecure-requests": [
"1"
],
"User-Agent": [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36"
],
"Via": [
"2.0 078ca3a7cfdee29c8e3514176205c50a.cloudfront.net (CloudFront)"
],
"X-Amz-Cf-Id": [
"5uiz6HWWKWR_HQCLcvX2GXppwJP5FJGXcr_OUs31D6H_JV9uioyyMg=="
],
"X-Amzn-Trace-Id": [
"Root=1-5cc7de85-72b4887ed3a6d79ba6a5388a"
],
"X-Forwarded-For": [
"50.35.64.182, 52.46.17.56"
],
"X-Forwarded-Port": [
"443"
],
"X-Forwarded-Proto": [
"https"
]
},
"queryStringParameters": null,
"multiValueQueryStringParameters": null,
"pathParameters": {
"proxy": "api/resourcepath/encoding/a%2Fb"
},
"stageVariables": null,
"requestContext": {
"resourceId": "kaaa27",
"resourcePath": "/{proxy+}",
"httpMethod": "GET",
"extendedRequestId": "Y7-05GJCPHcF7pA=",
"requestTime": "30/Apr/2019:05:35:01 +0000",
"path": "/Prod/api/resourcepath/encoding/a%2Fb",
"accountId": "626492997873",
"protocol": "HTTP/1.1",
"stage": "Prod",
"domainPrefix": "uy8hsm9y23",
"requestTimeEpoch": 1556602501793,
"requestId": "b34371ef-6b09-11e9-86d0-b596427e6920",
"identity": {
"cognitoIdentityPoolId": null,
"accountId": null,
"cognitoIdentityId": null,
"caller": null,
"sourceIp": "50.35.64.182",
"principalOrgId": null,
"accessKey": null,
"cognitoAuthenticationType": null,
"cognitoAuthenticationProvider": null,
"userArn": null,
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36",
"user": null
},
"domainName": "uy8hsm9y23.execute-api.us-west-2.amazonaws.com",
"apiId": "uy8hsm9y23"
},
"body": null,
"isBase64Encoded": false
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,12 @@ public string GetString(string value)
var path = this.HttpContext.Request.Path;
return "value=" + value;
}

[HttpGet("/api/[controller]/encoding/{first}/{second}", Name = "Multi")]
public ActionResult Multi(string first, string second) => Ok(new { first, second });

[HttpGet("/api/[controller]/encoding/{only}", Name = "Single")]
public ActionResult Single(string only) => Ok(new { only });

}
}

0 comments on commit 0965c3b

Please sign in to comment.