diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Extensions/ApiGatewayResponseExtensions.cs b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Extensions/ApiGatewayResponseExtensions.cs
index 255e82145..28344f383 100644
--- a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Extensions/ApiGatewayResponseExtensions.cs
+++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Extensions/ApiGatewayResponseExtensions.cs
@@ -6,89 +6,63 @@
using System;
using System.IO;
using System.Text;
+using System.Text.Json;
-///
-/// Provides extension methods for converting API Gateway responses to HttpResponse objects.
-///
public static class ApiGatewayResponseExtensions
{
- ///
- /// Converts an APIGatewayProxyResponse to an HttpResponse.
- ///
- /// The API Gateway proxy response to convert.
- /// An HttpResponse object representing the API Gateway response.
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);
+ SetContentTypeAndStatusCode(response, apiResponse.Headers, apiResponse.MultiValueHeaders, apiResponse.StatusCode, isV2: false);
return response;
}
- ///
- /// Converts an APIGatewayHttpApiV2ProxyResponse to an HttpResponse.
- ///
- /// The API Gateway HTTP API v2 proxy response to convert.
- /// An HttpResponse object representing the API Gateway response.
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);
+ SetContentTypeAndStatusCode(response, apiResponse.Headers, null, apiResponse.StatusCode, isV2: true);
return response;
}
- ///
- /// Sets the headers on the HttpResponse object.
- ///
- /// The HttpResponse object to modify.
- /// The single-value headers to set.
- /// The multi-value headers to set.
private static void SetResponseHeaders(HttpResponse response, IDictionary? headers, IDictionary>? multiValueHeaders = null)
{
- if (headers != null)
+ var processedHeaders = new HashSet(StringComparer.OrdinalIgnoreCase);
+
+ if (multiValueHeaders != null)
{
- foreach (var header in headers)
+ foreach (var header in multiValueHeaders)
{
- response.Headers[header.Key] = header.Value;
+ response.Headers[header.Key] = new StringValues([.. header.Value]);
+ processedHeaders.Add(header.Key);
}
}
- if (multiValueHeaders != null)
+ if (headers != null)
{
- foreach (var header in multiValueHeaders)
+ foreach (var header in headers)
{
- response.Headers[header.Key] = new StringValues(header.Value.ToArray());
+ if (!processedHeaders.Contains(header.Key))
+ {
+ response.Headers[header.Key] = header.Value;
+ }
+ else
+ {
+ response.Headers.Append(header.Key, header.Value);
+ }
}
}
}
- ///
- /// Sets the body of the HttpResponse object.
- ///
- /// The HttpResponse object to modify.
- /// The body content to set.
- /// Indicates whether the body is Base64 encoded.
private static void SetResponseBody(HttpResponse response, string? body, bool isBase64Encoded)
{
if (!string.IsNullOrEmpty(body))
@@ -103,6 +77,70 @@ private static void SetResponseBody(HttpResponse response, string? body, bool is
bodyBytes = Encoding.UTF8.GetBytes(body);
}
response.Body = new MemoryStream(bodyBytes);
+ response.ContentLength = bodyBytes.Length;
+ }
+ }
+
+ private static void SetContentTypeAndStatusCode(HttpResponse response, IDictionary? headers, IDictionary>? multiValueHeaders, int statusCode, bool isV2)
+ {
+ string? contentType = null;
+
+ if (headers != null && headers.TryGetValue("Content-Type", out var headerContentType))
+ {
+ contentType = headerContentType;
+ }
+ else if (multiValueHeaders != null && multiValueHeaders.TryGetValue("Content-Type", out var multiValueContentType))
+ {
+ contentType = multiValueContentType[0];
+ }
+
+ bool isValidJson = false;
+ if (isV2 && contentType == null && response.Body != null)
+ {
+ response.Body.Seek(0, SeekOrigin.Begin);
+ using var reader = new StreamReader(response.Body, leaveOpen: true);
+ var bodyContent = reader.ReadToEnd();
+ response.Body.Seek(0, SeekOrigin.Begin);
+
+ isValidJson = IsValidJson(bodyContent);
+ if (isValidJson)
+ {
+ contentType = "application/json";
+ }
+ }
+
+ if (contentType != null)
+ {
+ response.ContentType = contentType;
+ }
+
+ if (isV2 && isValidJson && statusCode == 0)
+ {
+ response.StatusCode = 200;
+ }
+ else
+ {
+ response.StatusCode = statusCode;
+ }
+ }
+
+ private static bool IsValidJson(string strInput)
+ {
+ if (string.IsNullOrWhiteSpace(strInput)) { return false; }
+ strInput = strInput.Trim();
+ if ((strInput.StartsWith("{") && strInput.EndsWith("}")) ||
+ (strInput.StartsWith("[") && strInput.EndsWith("]")))
+ {
+ try
+ {
+ var obj = JsonSerializer.Deserialize