Skip to content

Commit

Permalink
Add api gateway extensions
Browse files Browse the repository at this point in the history
Add docs

move to new folder
  • Loading branch information
gcbeattyAWS committed Dec 10, 2024
1 parent 1af7cf4 commit 3e41671
Show file tree
Hide file tree
Showing 3 changed files with 280 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
<ItemGroup>
<PackageReference Include="Spectre.Console" Version="0.49.1" />
<PackageReference Include="Spectre.Console.Cli" Version="0.49.1" />
<PackageReference Include="Amazon.Lambda.APIGatewayEvents" Version="2.7.1" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageReference Include="Blazored.Modal" Version="7.3.1" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="8.0.11" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
namespace Amazon.Lambda.TestTool.Extensions;

using Amazon.Lambda.APIGatewayEvents;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using System;
using System.IO;
using System.Text;

/// <summary>
/// Provides extension methods for converting API Gateway responses to HttpResponse objects.
/// </summary>
public static class ApiGatewayResponseExtensions
{
/// <summary>
/// Converts an APIGatewayProxyResponse to an HttpResponse.
/// </summary>
/// <param name="apiResponse">The API Gateway proxy response to convert.</param>
/// <returns>An HttpResponse object representing the API Gateway response.</returns>
public static HttpResponse ToHttpResponse(this APIGatewayProxyResponse apiResponse)
{
var httpContext = new DefaultHttpContext();
var response = httpContext.Response;

response.StatusCode = apiResponse.StatusCode;

SetResponseHeaders(response, apiResponse.Headers, apiResponse.MultiValueHeaders);

SetResponseBody(response, apiResponse.Body, apiResponse.IsBase64Encoded);

return response;
}

/// <summary>
/// Converts an APIGatewayHttpApiV2ProxyResponse to an HttpResponse.
/// </summary>
/// <param name="apiResponse">The API Gateway HTTP API v2 proxy response to convert.</param>
/// <returns>An HttpResponse object representing the API Gateway response.</returns>
public static HttpResponse ToHttpResponse(this APIGatewayHttpApiV2ProxyResponse apiResponse)
{
var httpContext = new DefaultHttpContext();
var response = httpContext.Response;

response.StatusCode = apiResponse.StatusCode;

SetResponseHeaders(response, apiResponse.Headers);

if (apiResponse.Cookies != null)
{
foreach (var cookie in apiResponse.Cookies)
{
response.Headers.Append("Set-Cookie", cookie);
}
}

SetResponseBody(response, apiResponse.Body, apiResponse.IsBase64Encoded);

return response;
}

/// <summary>
/// Sets the headers on the HttpResponse object.
/// </summary>
/// <param name="response">The HttpResponse object to modify.</param>
/// <param name="headers">The single-value headers to set.</param>
/// <param name="multiValueHeaders">The multi-value headers to set.</param>
private static void SetResponseHeaders(HttpResponse response, IDictionary<string, string>? headers, IDictionary<string, IList<string>>? multiValueHeaders = null)
{
if (headers != null)
{
foreach (var header in headers)
{
response.Headers[header.Key] = header.Value;
}
}

if (multiValueHeaders != null)
{
foreach (var header in multiValueHeaders)
{
response.Headers[header.Key] = new StringValues(header.Value.ToArray());
}
}
}

/// <summary>
/// Sets the body of the HttpResponse object.
/// </summary>
/// <param name="response">The HttpResponse object to modify.</param>
/// <param name="body">The body content to set.</param>
/// <param name="isBase64Encoded">Indicates whether the body is Base64 encoded.</param>
private static void SetResponseBody(HttpResponse response, string? body, bool isBase64Encoded)
{
if (!string.IsNullOrEmpty(body))
{
byte[] bodyBytes;
if (isBase64Encoded)
{
bodyBytes = Convert.FromBase64String(body);
}
else
{
bodyBytes = Encoding.UTF8.GetBytes(body);
}
response.Body = new MemoryStream(bodyBytes);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
namespace Amazon.Lambda.TestTool.UnitTests.Extensions;

using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.TestTool.Extensions;
using System.IO;
using System.Text;
using Xunit;

public class ApiGatewayResponseExtensionsTests
{
[Fact]
public void ToHttpResponse_APIGatewayProxyResponse_SetsCorrectStatusCode()
{
var apiResponse = new APIGatewayProxyResponse
{
StatusCode = 200
};

var httpResponse = apiResponse.ToHttpResponse();

Assert.Equal(200, httpResponse.StatusCode);
}

[Fact]
public void ToHttpResponse_APIGatewayProxyResponse_SetsHeaders()
{
var apiResponse = new APIGatewayProxyResponse
{
Headers = new Dictionary<string, string>
{
{ "Content-Type", "application/json" },
{ "X-Custom-Header", "CustomValue" }
}
};

var httpResponse = apiResponse.ToHttpResponse();

Assert.Equal("application/json", httpResponse.Headers["Content-Type"]);
Assert.Equal("CustomValue", httpResponse.Headers["X-Custom-Header"]);
}

[Fact]
public void ToHttpResponse_APIGatewayProxyResponse_SetsMultiValueHeaders()
{
var apiResponse = new APIGatewayProxyResponse
{
MultiValueHeaders = new Dictionary<string, IList<string>>
{
{ "X-Multi-Header", new List<string> { "Value1", "Value2" } }
}
};

var httpResponse = apiResponse.ToHttpResponse();

Assert.Equal(new[] { "Value1", "Value2" }, httpResponse.Headers["X-Multi-Header"]);
}

[Fact]
public void ToHttpResponse_APIGatewayProxyResponse_SetsBodyNonBase64()
{
var apiResponse = new APIGatewayProxyResponse
{
Body = "Hello, World!",
IsBase64Encoded = false
};

var httpResponse = apiResponse.ToHttpResponse();

httpResponse.Body.Seek(0, SeekOrigin.Begin);
var bodyContent = new StreamReader(httpResponse.Body).ReadToEnd();
Assert.Equal("Hello, World!", bodyContent);
}

[Fact]
public void ToHttpResponse_APIGatewayProxyResponse_SetsBodyBase64()
{
var originalBody = "Hello, World!";
var base64Body = Convert.ToBase64String(Encoding.UTF8.GetBytes(originalBody));
var apiResponse = new APIGatewayProxyResponse
{
Body = base64Body,
IsBase64Encoded = true
};

var httpResponse = apiResponse.ToHttpResponse();

httpResponse.Body.Seek(0, SeekOrigin.Begin);
var bodyContent = new StreamReader(httpResponse.Body).ReadToEnd();
Assert.Equal(originalBody, bodyContent);
}

[Fact]
public void ToHttpResponse_APIGatewayHttpApiV2ProxyResponse_SetsCorrectStatusCode()
{
var apiResponse = new APIGatewayHttpApiV2ProxyResponse
{
StatusCode = 201
};

var httpResponse = apiResponse.ToHttpResponse();

Assert.Equal(201, httpResponse.StatusCode);
}

[Fact]
public void ToHttpResponse_APIGatewayHttpApiV2ProxyResponse_SetsHeaders()
{
var apiResponse = new APIGatewayHttpApiV2ProxyResponse
{
Headers = new Dictionary<string, string>
{
{ "Content-Type", "application/xml" },
{ "X-Custom-Header", "CustomValue" }
}
};

var httpResponse = apiResponse.ToHttpResponse();

Assert.Equal("application/xml", httpResponse.Headers["Content-Type"]);
Assert.Equal("CustomValue", httpResponse.Headers["X-Custom-Header"]);
}

[Fact]
public void ToHttpResponse_APIGatewayHttpApiV2ProxyResponse_SetsCookies()
{
var apiResponse = new APIGatewayHttpApiV2ProxyResponse
{
Cookies = new[] { "session=abc123; Path=/", "theme=dark; Max-Age=3600" }
};

var httpResponse = apiResponse.ToHttpResponse();

Assert.Contains(httpResponse.Headers["Set-Cookie"], v => v == "session=abc123; Path=/");
Assert.Contains(httpResponse.Headers["Set-Cookie"], v => v == "theme=dark; Max-Age=3600");
}

[Fact]
public void ToHttpResponse_APIGatewayHttpApiV2ProxyResponse_SetsBodyNonBase64()
{
var apiResponse = new APIGatewayHttpApiV2ProxyResponse
{
Body = "Hello, API Gateway v2!",
IsBase64Encoded = false
};

var httpResponse = apiResponse.ToHttpResponse();

httpResponse.Body.Seek(0, SeekOrigin.Begin);
var bodyContent = new StreamReader(httpResponse.Body).ReadToEnd();
Assert.Equal("Hello, API Gateway v2!", bodyContent);
}

[Fact]
public void ToHttpResponse_APIGatewayHttpApiV2ProxyResponse_SetsBodyBase64()
{
var originalBody = "Hello, API Gateway v2!";
var base64Body = Convert.ToBase64String(Encoding.UTF8.GetBytes(originalBody));
var apiResponse = new APIGatewayHttpApiV2ProxyResponse
{
Body = base64Body,
IsBase64Encoded = true
};

var httpResponse = apiResponse.ToHttpResponse();

httpResponse.Body.Seek(0, SeekOrigin.Begin);
var bodyContent = new StreamReader(httpResponse.Body).ReadToEnd();
Assert.Equal(originalBody, bodyContent);
}
}

0 comments on commit 3e41671

Please sign in to comment.