Skip to content

HTTPS Direct URL with AWS Lambda AOT dose not responed content-type text/html, awayes application/octet-stream. #2076

Open
@CalvadosHof

Description

@CalvadosHof

Describe the bug

I wish return HTML direct to client from HTTPS Direct URL with AWS Lambda AOT Application, but it not work, return with content-type application/octet alwayes.
How to solve this problem?

Problem List

  1. APIGatewayProxyResponse with follwing parameter, but respose is content-type application/octet-stream.
  2. Overwrite APIGatewayProxyResponse by generated JsonDeserizer, but respose is content-type application/octet-stream.
  3. Specify TrimmerRootAssembly that Amazon.Lambda.APIGatewayEvents", but respose is content-type application/octet-stream.
  4. Overwrite LambdaSerializer by custom Serializer, but respose is content-type application/octet-stream.
  5. Specify JsonSerializable for Dictionary<string, string> and APIGatewayProxyResponse, but respose is content-type application/octet-stream.
  6. Specify DynamicallyAccessedMembers DynamicallyAccessedMemberTypes.All, but respose is content-type application/octet-stream.

Source Code
Sorry, comment as Japanese

using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Core;
using Amazon.Lambda.RuntimeSupport;
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net;
using System.Text.Json;
using System.Text.Json.Serialization;
[assembly: LambdaSerializer(typeof(MyLambdaJsonSerializer))]
[JsonSerializable(typeof(Dictionary<string, string>))]
[JsonSerializable(typeof(APIGatewayProxyResponse))]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]

internal partial class MyJsonContext : JsonSerializerContext { }

public class MyLambdaJsonSerializer : ILambdaSerializer
{
    private readonly JsonSerializerOptions _options;

    public MyLambdaJsonSerializer()
    {
        // ここで MyJsonContext.Default.Options を使用
        _options = MyJsonContext.Default.Options;
    }

    public T Deserialize<T>(Stream stream)
    {
        return JsonSerializer.Deserialize<T>(stream, _options);
    }

    public void Serialize<T>(T response, Stream stream)
    {
        JsonSerializer.Serialize(stream, response, _options);
    }
}

namespace CloudURLAOT01
{
    public class Function
    {
        /// <summary>
        /// 入力ストリームからデータを読み取り、FunctionHandlerを呼び出し、
        /// 結果を出力ストリームに書き込むアダプター関数
        /// </summary>
        public static void StreamHandler(Stream input, ILambdaContext context, MemoryStream output)
        {
            // 入力ストリームからテキストを読み込む
            string inputText;
            using (var reader = new StreamReader(input))
            {
                inputText = reader.ReadToEnd();
            }

            // 最小限のAPIGatewayProxyRequestを作成(必要に応じてプロパティを追加してください)
            var request = new APIGatewayProxyRequest { Body = inputText };

            // FunctionHandlerを同期的に呼び出す
            var function = new Function();
            APIGatewayProxyResponse response = function.FunctionHandler(request, context);

            // 出力ストリームに結果を書き込む(例:response.Bodyのみ)
            using (var writer = new StreamWriter(output, leaveOpen: true))
            {
                writer.Write(response.Body);
                writer.Flush();
            }
            output.Position = 0;
        }

        public static async Task Main(string[] args)
        {
            // ハンドラーを定義(ここではストリームベースの関数を利用)
            var handler = (Action<Stream, ILambdaContext, MemoryStream>)StreamHandler;

            // ビルダーから実行可能なブートストラップインスタンスを作成する
            using var bootstrap = LambdaBootstrapBuilder.Create(handler).Build();

            // ブートストラップインスタンスの RunAsync を呼び出してLambdaループを開始
            await bootstrap.RunAsync();
        }



        public APIGatewayProxyResponse FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
        {
            // クエリパラメータを手動で解析(Dictionary を使わず文字列処理)
            string queryString = request.QueryStringParameters != null && request.QueryStringParameters.Count > 0
                ? string.Join("&", request.QueryStringParameters.Select(kv => $"{kv.Key}={kv.Value}"))
                : "No query string";

            // HTMLレスポンスの作成
            string body = "<html><head><title>Lambda AOT</title></head><body>";
            body += "<h1>Hello from AWS Lambda (Native AOT)!</h1>";
            body += $"<p>QueryString: {queryString}</p>";
            body += $"<p>Timestamp: {DateTime.UtcNow:O}</p>";
            body += "</body></html>";

            return new APIGatewayProxyResponse
            {
                StatusCode = (int)HttpStatusCode.OK,
                Body = body,
                IsBase64Encoded = false,
                Headers = new Dictionary<string, string>
                {
                    { "Content-Type", "text/html; charset=utf-8" },
                    { "Content-Disposition", "inline" }, // ブラウザに inline 表示を指示
                    { "Access-Control-Allow-Methods", "GET, POST, OPTIONS" }
                }
            };
        }
    }
}

Regression Issue

  • Select this option if this issue appears to be a regression.

Expected Behavior

Recive HTML text with content-type text/html.

Current Behavior

All response is content-type application/octet-stream, but I wish text/html.

Reproduction Steps

Please try my sample program.
This program(you must remove additional logic for AOT) work well under non AOT, but under AOT, all of respose is content-type application/octet-stream.

Possible Solution

No response

Additional Information/Context

No response

AWS .NET SDK and/or Package version used

Amazon.Lambda.APIGatewayEvents 2.7.1
Amazon.Lambda.Core 2.5.1
Amazon.Lambda.RuntimeSupport 1.13.0
Amazon.Lambda.Serialization.SystemTextJson 2.4.4
Lambdajection.Core 0.9.2
Microsoft.DotNet.ILCompiler 8.0.16
Lambdajection.Framework 0.9.2

Targeted .NET Platform

.NET 8

Operating System and version

AWS Lambda HTTPS Direct

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugThis issue is a bug.module/lambda-client-libp2This is a standard priority issueresponse-requestedWaiting on additional info and feedback. Will move to close soon in 7 days.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions