Add support for Lambda Response Streaming#2288
Add support for Lambda Response Streaming#2288normj wants to merge 21 commits intofeature/response-streamingfrom
Conversation
…-lambda-dotnet into normj/response-streaming
2ed63cc to
d60bb93
Compare
8c56514 to
1471d93
Compare
1471d93 to
d0861c6
Compare
There was a problem hiding this comment.
Pull request overview
Integrates Lambda response streaming into Amazon.Lambda.RuntimeSupport and exposes corresponding (preview) streaming APIs in Amazon.Lambda.Core, along with unit + integration test coverage and a deployable streaming handler test app.
Changes:
- Add streaming send path to
RuntimeApiClient/LambdaBootstrap, including per-invocation streaming state management. - Introduce streaming primitives (
ResponseStream,StreamingHttpContent, prelude support) and Core-facing preview APIs (LambdaResponseStreamFactory,HttpResponseStreamPrelude). - Add extensive unit/integration tests and a
ResponseStreamingFunctionHandlerstest Lambda project.
Reviewed changes
Copilot reviewed 37 out of 38 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/ResponseStreamingFunctionHandlers/aws-lambda-tools-defaults.json | Adds Lambda tooling defaults for streaming handler test app. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/ResponseStreamingFunctionHandlers/ResponseStreamingFunctionHandlers.csproj | New net10 test Lambda app project for streaming scenarios. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/ResponseStreamingFunctionHandlers/Function.cs | Streaming handler scenarios used by integration tests. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.UnitTests/TestHelpers/TestStreamingRuntimeApiClient.cs | Test runtime client that simulates streaming without real HTTP. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.UnitTests/TestHelpers/NoOpInternalRuntimeApiClient.cs | No-op internal runtime API client for unit tests. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.UnitTests/StreamingHttpContentTests.cs | Unit tests for StreamingHttpContent behavior. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.UnitTests/StreamingE2EWithMoq.cs | End-to-end tests covering bootstrap → streaming pipeline behavior. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.UnitTests/RuntimeApiClientTests.cs | Tests for streaming vs buffered header behavior on requests. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.UnitTests/ResponseStreamTests.cs | Unit tests for new ResponseStream implementation. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.UnitTests/ResponseStreamFactoryTests.cs | Unit tests for streaming factory state + send-task behavior. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.UnitTests/LambdaResponseStreamingCoreTests.cs | Tests for new Amazon.Lambda.Core.ResponseStreaming APIs and prelude serialization. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.UnitTests/LambdaBootstrapTests.cs | Adds bootstrap integration tests for streaming vs buffered paths. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.UnitTests/HandlerTests.cs | Updates test collection for streaming factory isolation. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.IntegrationTests/ResponseStreamingTests.cs | New integration tests invoking Lambda with response stream. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.IntegrationTests/IntegrationTestFixture.cs | Packages additional streaming test app; adjusts temp path/tool install flow. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.IntegrationTests/IntegrationTestCollection.cs | Disables parallelization and wires streaming fixture into integration collection. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.IntegrationTests/Helpers/LambdaToolsHelper.cs | Adjusts temp directory behavior (DEBUG uses repo paths). |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.IntegrationTests/Helpers/CommandLineWrapper.cs | Captures command output while running packaging commands. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.IntegrationTests/CustomRuntimeTests.cs | Removes NET6 target enum entry. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.IntegrationTests/BaseCustomRuntimeTest.cs | Updates runtime/framework assumptions (Dotnet10) + improves missing bundle diagnostics. |
| Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.IntegrationTests/Amazon.Lambda.RuntimeSupport.IntegrationTests.csproj | Moves integration tests to net10.0 and bumps package refs. |
| Libraries/src/Amazon.Lambda.RuntimeSupport/Client/RuntimeApiClient.cs | Adds StartStreamingResponseAsync entry point and streaming headers. |
| Libraries/src/Amazon.Lambda.RuntimeSupport/Client/ResponseStream.cs | Removes old buffered-chunk streaming ResponseStream implementation. |
| Libraries/src/Amazon.Lambda.RuntimeSupport/Client/IResponseStream.cs | Removes old public IResponseStream surface. |
| Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/ResponseStreaming/StreamingHttpContent.cs | New HttpContent for streaming serialization + error signaling. |
| Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/ResponseStreaming/StreamingConstants.cs | Moves streaming constants into streaming namespace and trims unused max size constant. |
| Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/ResponseStreaming/ResponseStreamLambdaCoreInitializerIsolated.cs | Wires RuntimeSupport streaming into Core via isolated initializer. |
| Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/ResponseStreaming/ResponseStreamFactory.cs | New per-invocation streaming state + send-task coordination. |
| Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/ResponseStreaming/ResponseStreamContext.cs | Extends context to carry runtime client, cancellation token, and send task. |
| Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/ResponseStreaming/ResponseStream.cs | New “true streaming” ResponseStream writing directly to HTTP output stream. |
| Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/LambdaBootstrap.cs | Initializes streaming integration, routes mid-stream errors to trailers, awaits send task, cleans up state. |
| Libraries/src/Amazon.Lambda.Core/ResponseStreaming/LambdaResponseStreamFactory.cs | Adds preview public factory API for response streaming streams. |
| Libraries/src/Amazon.Lambda.Core/ResponseStreaming/LambdaResponseStream.cs | Adds preview Stream subclass wrapper for streaming writes. |
| Libraries/src/Amazon.Lambda.Core/ResponseStreaming/ILambdaResponseStream.cs | Internal bridge interface for RuntimeSupport to implement. |
| Libraries/src/Amazon.Lambda.Core/ResponseStreaming/HttpResponseStreamPrelude.cs | Adds HTTP response prelude model + JSON serialization. |
| Libraries/Libraries.sln | Adds new test app project and updates VS version metadata. |
| .gitignore | Ignores **/.kiro/. |
| .autover/changes/c27a62e6-91ca-4a59-9406-394866cdfa62.json | Declares minor version changes for RuntimeSupport + Core (preview streaming). |
Comments suppressed due to low confidence (1)
Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/ResponseStreaming/ResponseStreamFactory.cs:27
ResponseStreamFactorywas changed tointernal, but the unit tests inAmazon.Lambda.RuntimeSupport.Testscall it directly. There is noInternalsVisibleToconfigured for the RuntimeSupport assembly, so this will not compile. Either make the type (and other test-used streaming types) public again, or add anInternalsVisibleTofor the test assembly.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/ResponseStreamingFunctionHandlers/Function.cs
Show resolved
Hide resolved
| // Declare trailers upfront — we always declare them since we don't know | ||
| // at request start time whether an error will occur mid-stream. | ||
| request.Headers.Add("Trailer", | ||
| $"{StreamingConstants.ErrorTypeTrailer}, {StreamingConstants.ErrorBodyTrailer}"); | ||
|
|
There was a problem hiding this comment.
The request declares a Trailer header, but the current implementation doesn’t appear to send actual HTTP trailing headers (it writes trailer-looking lines into the content stream). Consider using HttpRequestMessage.TrailingHeaders (populated once the handler outcome is known) so the error type/body are emitted as real trailers rather than body bytes.
| // Declare trailers upfront — we always declare them since we don't know | |
| // at request start time whether an error will occur mid-stream. | |
| request.Headers.Add("Trailer", | |
| $"{StreamingConstants.ErrorTypeTrailer}, {StreamingConstants.ErrorBodyTrailer}"); |
Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/ResponseStreaming/ResponseStream.cs
Show resolved
Hide resolved
...RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.IntegrationTests/IntegrationTestFixture.cs
Show resolved
Hide resolved
| if (_responseStream.HasError) | ||
| { | ||
| InternalLogger.GetDefaultLogger().LogError(_responseStream.ReportedError, "An error occurred during Lambda execution. Writing error trailers to response."); | ||
| await WriteErrorTrailersAsync(stream, _responseStream.ReportedError); | ||
| } |
There was a problem hiding this comment.
When an error occurs, SerializeToStreamAsync writes trailer-looking data via WriteErrorTrailersAsync directly into the content stream. With HTTP chunked transfer, these bytes are typically part of the body, not HTTP trailing headers. If Lambda expects real HTTP trailers, this should be implemented via HttpRequestMessage.TrailingHeaders instead of writing to the payload stream.
| var errorTypeHeader = $"{StreamingConstants.ErrorTypeTrailer}: {exceptionInfo.ErrorType}\r\n"; | ||
| var errorTypeBytes = Encoding.UTF8.GetBytes(errorTypeHeader); | ||
| await stream.WriteAsync(errorTypeBytes, 0, errorTypeBytes.Length, _cancellationToken); | ||
|
|
||
| var errorBodyJson = LambdaJsonExceptionWriter.WriteJson(exceptionInfo); | ||
| var errorBodyHeader = $"{StreamingConstants.ErrorBodyTrailer}: {errorBodyJson}\r\n"; | ||
| var errorBodyBytes = Encoding.UTF8.GetBytes(errorBodyHeader); |
There was a problem hiding this comment.
WriteErrorTrailersAsync formats the error type/body as UTF-8 header lines and writes them to the content stream. That is unlikely to be interpreted as HTTP trailers by the receiver. Prefer setting true trailing headers on the HttpRequestMessage rather than emitting these lines into the response payload.
| var errorTypeHeader = $"{StreamingConstants.ErrorTypeTrailer}: {exceptionInfo.ErrorType}\r\n"; | |
| var errorTypeBytes = Encoding.UTF8.GetBytes(errorTypeHeader); | |
| await stream.WriteAsync(errorTypeBytes, 0, errorTypeBytes.Length, _cancellationToken); | |
| var errorBodyJson = LambdaJsonExceptionWriter.WriteJson(exceptionInfo); | |
| var errorBodyHeader = $"{StreamingConstants.ErrorBodyTrailer}: {errorBodyJson}\r\n"; | |
| var errorBodyBytes = Encoding.UTF8.GetBytes(errorBodyHeader); | |
| // Serialize the exception information as JSON in the response payload | |
| var errorBodyJson = LambdaJsonExceptionWriter.WriteJson(exceptionInfo); | |
| var errorBodyBytes = Encoding.UTF8.GetBytes(errorBodyJson); |
In draft mode while still cleaning up the experience
Issue #, if available:
#1635
Description of changes:
Integrate Lambda response streaming support into the Amazon.Lambda.RuntimeSupport.
A hello world example of using response streaming. In this case sense I wrapped the
Streamreturned fromCreateStreamin aStreamWriterthe writes will be buffered inStreamWritertill the buffer is full. I call the flush method every 10 iterations to force sending data back to the client.For a use with API Gateway or Lambda Function URL you need to create the stream with the
CreateHttpStreampassing the status code and response headers.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.