Add support for Lambda Response Streaming#2288
Add support for Lambda Response Streaming#2288normj wants to merge 46 commits intofeature/response-streamingfrom
Conversation
…-lambda-dotnet into normj/response-streaming
2ed63cc to
d60bb93
Compare
96dc138 to
0bd63a9
Compare
…aders with chunk encoding which wasn't supported in SocketHandler
… of Stream so that we can potentially expose more methods in the future.
d3dbe0c to
1a86609
Compare
| { | ||
| var parts = hostAndPort.Split(':'); | ||
| _host = parts[0]; | ||
| _port = parts.Length > 1 ? int.Parse(parts[1], CultureInfo.InvariantCulture) : 80; |
There was a problem hiding this comment.
why default to 80 over 443? just because its http and not https?
There was a problem hiding this comment.
Reality is there should always be a port defined in hostAndPort. Change the code to not have a default and throw an error if port is not set.
| // Check if we've received the complete response (ends with \r\n\r\n for headers, | ||
| // or we've read the content-length worth of body) | ||
| var text = responseText.ToString(); | ||
| if (text.Contains("\r\n\r\n")) |
There was a problem hiding this comment.
nit: make constant since its used multiple times
| } | ||
| } | ||
|
|
||
| if (totalRead > 16384) |
There was a problem hiding this comment.
whats 16384 here? can you add a comment
There was a problem hiding this comment.
Added comment but the value is an arbitrary safety net value.
|
|
||
| [CollectionDefinition("Integration Tests")] | ||
| public class IntegrationTestCollection : ICollectionFixture<IntegrationTestFixture> | ||
| [CollectionDefinition("Integration Tests", DisableParallelization = true)] |
There was a problem hiding this comment.
why did we have to disable parallelization?
There was a problem hiding this comment.
I was probably dealing with some test instability. I removed the flag and tests were successful form. See if the GitHub checks are successful with the flag removed.
|
|
||
| namespace Amazon.Lambda.Core.ResponseStreaming | ||
| { | ||
| /// <summary> |
There was a problem hiding this comment.
nit: could you give more context as to why the prelude is needed?
| public class HttpResponseStreamPrelude | ||
| { | ||
| /// <summary> | ||
| /// The Http status code to include in the response prelude. |
There was a problem hiding this comment.
nit: all docs for the fields of this class has "to include in the response prelude.". It feels redundant.
| public IDictionary<string, string> Headers { get; set; } = new Dictionary<string, string>(); | ||
|
|
||
| /// <summary> | ||
| /// The response headers to include in the response prelude. This collection supports setting multiple values for the same headers. | ||
| /// </summary> | ||
| public IDictionary<string, IList<string>> MultiValueHeaders { get; set; } = new Dictionary<string, IList<string>>(); |
There was a problem hiding this comment.
is there a reason why both are needed? why not just have 1 that supports multi value?
There was a problem hiding this comment.
For API Gateway REST APIs the JSON for the prelude must use MultiValueHeaders but Lambda URLs you have to use Headers. The properties here are 1 to 1 mirror of the union of the specs for API Gateway Rest APIs and Function URLs. If API Gateway HTTP APIs ever support they would probably require the Headers collection. At the point of generating the JSON via the ToByteArray we don't have the context to say what is the event source. It is up to the user to know which one to use.
I updated the docs for the properties to call out when to use the properties.
| /// <exception cref="InvalidOperationException">Thrown if the stream is already completed or an error has been reported.</exception> | ||
| Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken = default); | ||
|
|
||
|
|
There was a problem hiding this comment.
nit: remove extra whitespace
| /// </summary> | ||
| long BytesWritten { get; } | ||
|
|
||
|
|
There was a problem hiding this comment.
nit: remove extra whitespace
| /// <param name="responseStream">The response stream that provides data and error state.</param> | ||
| /// <param name="userAgent">The User-Agent header value.</param> | ||
| /// <param name="cancellationToken">Cancellation token.</param> | ||
| public async Task SendStreamingResponseAsync( |
There was a problem hiding this comment.
should we be measuring the performance of this HTTP client against the default one?
There was a problem hiding this comment.
The default HTTP client doesn't work for this scenario hence the reason we have to use our custom implementation.
|
|
||
| // The wait time is a sanity timeout to avoid waiting indefinitely if SetHttpOutputStreamAsync is not called or takes too long to call. | ||
| // Reality is that SetHttpOutputStreamAsync should be called very quickly after CreateStream, so this timeout is generous to avoid false positives but still protects against hanging indefinitely. | ||
| private readonly static TimeSpan _httpStreamWaitTimeout = TimeSpan.FromSeconds(30); |
There was a problem hiding this comment.
do we want to make this customizable by the user?
There was a problem hiding this comment.
No, this is just a sanity check but it should never be reached unless we have a bug. Plus this is more of an implementation detail that users won't understand and by exposing a config it makes this implementation detail part of our public API contract.
* release_2026-04-08 * Update test app CloudFormation templates * Updated changelog
* Add [S3Event] annotation attribute and source generator support - S3EventAttribute with Bucket (required), ResourceName, Events, FilterPrefix, FilterSuffix, Enabled - S3EventAttributeBuilder for Roslyn AttributeData parsing - TypeFullNames constants and Events hashset registration - SyntaxReceiver secondary attribute registration - EventTypeBuilder S3 event type mapping - AttributeModelBuilder S3 branch - CloudFormationWriter ProcessS3Attribute (SAM S3 event with Ref, Events list, Filter rules) - LambdaFunctionValidator ValidateS3Events (params, return type, dependency check) - DiagnosticDescriptors InvalidS3EventAttribute (AWSLambda0133) Add S3Event annotation tests - ValidS3Events.cs.txt test source with 3 test functions - S3EventsTests.cs CloudFormation writer tests (attribute application + property sync) - S3Events project references in TestServerlessApp.csproj and test project IT test PR comments change file fixes PR comments * add header
* treat warnings as errors * Change file
* chore: improve test flakiness * update changelog
…enerator (#2324) * Phase 1: Add FunctionUrlAttribute with source generator wiring and CloudFormation FunctionUrlConfig generation - New FunctionUrlAttribute class with AuthType property (NONE/AWS_IAM) - New FunctionUrlAuthType enum - Source generator detects FunctionUrlAttribute and maps to EventType.API - Generated wrapper uses HttpApi V2 request/response types (same payload format) - CloudFormationWriter emits FunctionUrlConfig on the function resource - Dependency validation checks for Amazon.Lambda.APIGatewayEvents - SyntaxReceiver detects missing [LambdaFunction] on [FunctionUrl] methods - 6 new unit tests for CloudFormation template generation (JSON + YAML) Phase 2: Add CORS support to FunctionUrlAttribute - AllowOrigins, AllowMethods, AllowHeaders, ExposeHeaders, AllowCredentials, MaxAge properties - FunctionUrlAttributeBuilder parses all CORS properties from AttributeData - CloudFormationWriter emits Cors block under FunctionUrlConfig only when CORS properties are set - 4 new unit tests for CORS generation and no-CORS scenarios Phase 3: FunctionUrlConfig orphan cleanup and attribute switching - Remove FunctionUrlConfig from template when [FunctionUrl] attribute is removed - Clean transition when switching from [FunctionUrl] to [HttpApi] or [RestApi] - 4 new unit tests for orphan cleanup and attribute switching scenarios Phase 4: End-to-end source generator test for FunctionUrl - FunctionUrlExample.cs test source with [FunctionUrl] + [FromQuery] + IHttpResult - Generated wrapper snapshot using HttpApi V2 payload format - Serverless template snapshot with FunctionUrlConfig - Full Roslyn source generator verification test IT tests Update Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/FunctionUrlAttributeBuilder.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> copilot comments change file fix cleanup add header PR comments * fix template * fix test
* release_2026-04-14 * Update test app CloudFormation templates * Updated changelog
Add CODEOWNERS file
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.