aws / aws/aws-lambda-dotnet

Memory Stream of response body is empty while running on Lambda using middleware.

Open
#1,457 2 comments 4 reactions 0 assignees View on GitHub
bug module/lambda-client-lib p2 queued
Dominant language
C#
Stars
1.7k
Forks
503
Avg merge
1d 5h
Merged PRs (30d)
18

Description

### Describe the bug

I have a ASP.NET middleware which copies the HTTP response body stream with a memory stream so that it can perform work involving sends logs to third party using response stream before the response is sent to the client. The code works properly when running locally using Kestrel or the integration tests server, but when running on AWS, all response body of the copied memory stream is empty, but the actual context response body of response contains the expected data.

### Expected Behavior

The copied response memory stream should have the same context body response on all hosting environments

### Current Behavior

The memory stream is empty when running on AWS Lambda only

### Reproduction Steps

Simplified middleware code using Minimal API of AWS looks like this:

Program.cs

```
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
ConfigureServices(builder);

WebApplication app = builder.Build();
ConfigurePipeline(app);

app.Run();

static void ConfigureServices(WebApplicationBuilder builder)
{
builder.Services.AddControllers();
builder.Services.AddAWSLambdaHosting(LambdaEventSource.RestApi);
}

static void ConfigurePipeline(WebApplication app)
{
app.UseMiddleware();
app.UseRouting();
app.MapControllers();
}
```

ResponseBodyStreamManipulatorMiddleware.cs
```
public class ResponseBodyStreamManipulatorMiddleware
{
private readonly RequestDelegate _next;

public ResponseBodyStreamManipulatorMiddleware(RequestDelegate next)
{
this._next = next;
}

public async Task InvokeAsync(HttpContext context)
{
context.Request.EnableBuffering();
Stream originalBodyStream = context.Response.Body;
using var responseBody = new MemoryStream();
context.Response.Body = responseBody;

await _next(context);

context.Response.Body.Seek(0, SeekOrigin.Begin);
using var reader = new StreamReader(responseBody);
var resBody = await reader.ReadToEndAsync();

Console.WriteLine("Response Data" + resBody); //resBody is empty while running in AWS Lambda
Console.WriteLine("responseBody " + resBody.Length); //resBody length is zero while running in AWS Lambda

context.Response.Body.Seek(0, SeekOrigin.Begin);
await responseBody.CopyToAsync(originalBodyStream);

}
}
```
IndexController.cs

```
[Route("")]
[ApiController]
public class IndexController : ControllerBase
{
[HttpGet]
[Route("")]
public ActionResult Get()
{
var result = new SampleResponse() { responseValue ="Test" };
return Ok(result);
}
}
```

### Possible Solution

No response

### Additional Information/Context

My ASP.NET application is using the Minimal API hosting pattern. The AWS Lambda hosting mode is set to LambdaEventSource.RestApi.

Running application in Lambda:

![image](https://user-images.githubusercontent.com/7733560/225593853-014ee72f-9d26-4074-8fff-f0fce02966c1.png)

Cloud Watch Logs memory stream of `responsebody `is empty :

![image](https://user-images.githubusercontent.com/7733560/225596947-13fea5f7-18b1-408d-8f81-bd2623beab2d.png)

we observe the `using var responseBody = new MemoryStream();` is loosing it value even though it's pointing to same object refrerence `context.Response.Body = responseBody;`

Note: The reason we require the responseBody stream is because we are using it for writing audit logs (internally we are calling third party by sending the resonseBody stream and right now copied responseBody stream going empty)

### AWS .NET SDK and/or Package version used

• Amazon.Lambda.AspNetCoreServer 8.0.0
• Amazon.Lambda.AspNetCoreServer.Hosting 1.5.1

### Targeted .NET Platform

.NET 6

### Operating System and version

AmazonLinux

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.