Skip to content

Commit a856be1

Browse files
authored
Improve API Gateway v1 streaming (#6573)
1 parent c68b2e1 commit a856be1

File tree

7 files changed

+69
-83
lines changed

7 files changed

+69
-83
lines changed
Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
export const handler = awslambda.streamifyResponse(
2-
async (_event: unknown, responseStream: any) => {
3-
responseStream = awslambda.HttpResponseStream.from(responseStream, {
2+
async (event, stream) => {
3+
stream = awslambda.HttpResponseStream.from(stream, {
44
statusCode: 200,
5-
headers: { "Content-Type": "text/plain" },
5+
headers: {
6+
"Content-Type": "text/plain; charset=UTF-8",
7+
"X-Content-Type-Options": "nosniff",
8+
},
69
});
710

8-
responseStream.write("Hello");
11+
stream.write("Hello ");
912
await new Promise((resolve) => setTimeout(resolve, 3000));
10-
responseStream.write(" World");
11-
responseStream.end();
13+
stream.write("World");
14+
15+
stream.end();
1216
},
1317
);

examples/aws-apigv1-stream/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"name": "aws-apigv1-stream",
33
"version": "1.0.0",
44
"dependencies": {
5+
"@types/aws-lambda": "^8.10.161",
56
"hono": "^4",
67
"sst": "^4"
78
}

examples/aws-apigv1-stream/sst.config.ts

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
* An example on how to enable streaming for API Gateway REST API routes.
77
*
88
* ```ts title="sst.config.ts"
9-
* api.route("GET /", "index.handler", {
9+
* api.route("GET /", {
10+
* handler: "index.handler",
1011
* streaming: true,
1112
* });
1213
* ```
@@ -16,30 +17,24 @@
1617
*
1718
* ```ts title="index.ts"
1819
* export const handler = awslambda.streamifyResponse(
19-
* async (_event: unknown, responseStream: any) => {
20-
* responseStream = awslambda.HttpResponseStream.from(responseStream, {
20+
* async (event, stream) => {
21+
* stream = awslambda.HttpResponseStream.from(stream, {
2122
* statusCode: 200,
22-
* headers: { "Content-Type": "text/plain" },
23+
* headers: {
24+
* "Content-Type": "text/plain; charset=UTF-8",
25+
* "X-Content-Type-Options": "nosniff",
26+
* },
2327
* });
2428
*
25-
* responseStream.write("Hello");
29+
* stream.write("Hello ");
2630
* await new Promise((resolve) => setTimeout(resolve, 3000));
27-
* responseStream.write(" World");
28-
* responseStream.end();
31+
* stream.write("World");
32+
*
33+
* stream.end();
2934
* },
3035
* );
3136
* ```
3237
*
33-
* :::note
34-
* Streaming is currently not supported in `sst dev`.
35-
* :::
36-
*
37-
* To test this in your terminal, use the `curl` command with the `--no-buffer` option.
38-
*
39-
* ```bash "--no-buffer"
40-
* curl --no-buffer https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/prod
41-
* ```
42-
*
4338
*/
4439
export default $config({
4540
app(input) {
@@ -51,10 +46,12 @@ export default $config({
5146
},
5247
async run() {
5348
const api = new sst.aws.ApiGatewayV1("MyApi");
54-
api.route("GET /", "index.handler", {
49+
api.route("GET /", {
50+
handler: "index.handler",
5551
streaming: true,
5652
});
57-
api.route("GET /hono", "hono.handler", {
53+
api.route("GET /hono", {
54+
handler: "hono.handler",
5855
streaming: true,
5956
});
6057
api.deploy();
Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
import { APIGatewayProxyEventV2 } from "aws-lambda";
1+
export const handler = awslambda.streamifyResponse(
2+
async (event, stream) => {
3+
stream = awslambda.HttpResponseStream.from(stream, {
4+
statusCode: 200,
5+
headers: {
6+
"Content-Type": "text/plain; charset=UTF-8",
7+
"X-Content-Type-Options": "nosniff",
8+
},
9+
});
210

3-
export const handler = awslambda.streamifyResponse(myHandler);
11+
stream.write("Hello ");
12+
await new Promise((resolve) => setTimeout(resolve, 3000));
13+
stream.write("World");
414

5-
async function myHandler(
6-
_event: APIGatewayProxyEventV2,
7-
responseStream: awslambda.HttpResponseStream
8-
): Promise<void> {
9-
return new Promise((resolve, _reject) => {
10-
responseStream.setContentType('text/plain')
11-
responseStream.write('Hello')
12-
setTimeout(() => {
13-
responseStream.write(' World')
14-
responseStream.end()
15-
resolve()
16-
}, 3000)
17-
})
18-
}
15+
stream.end();
16+
},
17+
);

examples/aws-lambda-stream/sst.config.ts

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,34 +17,25 @@
1717
* `@types/aws-lambda` will augment the global namespace.
1818
*
1919
* ```ts title="index.ts"
20-
* import { APIGatewayProxyEventV2 } from "aws-lambda";
21-
*
22-
* export const handler = awslambda.streamifyResponse(myHandler);
23-
*
24-
* async function myHandler(
25-
* _event: APIGatewayProxyEventV2,
26-
* responseStream: awslambda.HttpResponseStream
27-
* ): Promise<void> {
28-
* return new Promise((resolve, _reject) => {
29-
* responseStream.setContentType('text/plain')
30-
* responseStream.write('Hello')
31-
* setTimeout(() => {
32-
* responseStream.write(' World')
33-
* responseStream.end()
34-
* resolve()
35-
* }, 3000)
36-
* })
37-
* }
20+
* export const handler = awslambda.streamifyResponse(
21+
* async (event, stream) => {
22+
* stream = awslambda.HttpResponseStream.from(stream, {
23+
* statusCode: 200,
24+
* headers: {
25+
* "Content-Type": "text/plain; charset=UTF-8",
26+
* "X-Content-Type-Options": "nosniff",
27+
* },
28+
* });
29+
*
30+
* stream.write("Hello ");
31+
* await new Promise((resolve) => setTimeout(resolve, 3000));
32+
* stream.write("World");
33+
*
34+
* stream.end();
35+
* },
36+
* );
3837
* ```
3938
*
40-
* To test this in your terminal, use the `curl` command with the `--no-buffer` option.
41-
*
42-
* ```bash "--no-buffer"
43-
* curl --no-buffer https://u3dyblk457ghskwbmzrbylpxoi0ayrbb.lambda-url.us-east-1.on.aws
44-
* ```
45-
*
46-
* Streaming is also supported through API Gateway REST API.
47-
*
4839
*/
4940
export default $config({
5041
app(input) {

platform/src/components/aws/apigatewayv1-lambda-route.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ export class ApiGatewayV1LambdaRoute extends Component {
4848

4949
const self = this;
5050
const api = output(args.api);
51+
const fnStreaming = output(args.handler).apply((handler) =>
52+
handler && typeof handler === "object" && "streaming" in handler
53+
? handler.streaming
54+
: undefined,
55+
);
56+
const streaming = all([output(args.streaming), fnStreaming]).apply(
57+
([routeStreaming, fnStreaming]) => routeStreaming ?? fnStreaming ?? false,
58+
);
5159

5260
const method = createMethod(name, args, self);
5361
const fn = createFunction();
@@ -67,7 +75,7 @@ export class ApiGatewayV1LambdaRoute extends Component {
6775
args.handler,
6876
{
6977
description: interpolate`${api.name} route ${method} ${path}`,
70-
streaming: args.streaming,
78+
streaming,
7179
},
7280
args.handlerTransform,
7381
{ parent: self },
@@ -89,7 +97,6 @@ export class ApiGatewayV1LambdaRoute extends Component {
8997
}
9098

9199
function createIntegration() {
92-
const streaming = output(args.streaming ?? false);
93100
return new apigateway.Integration(
94101
...transform(
95102
args.transform?.integration,

platform/src/components/aws/apigatewayv1.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -620,20 +620,7 @@ export interface ApiGatewayV1RouteArgs {
620620
*/
621621
apiKey?: Input<boolean>;
622622
/**
623-
* Enable streaming for the route. The route handler must use `awslambda.streamifyResponse`
624-
* to stream responses.
625-
*
626-
* :::note
627-
* Streaming is only supported for API Gateway REST APIs, not HTTP APIs.
628-
* :::
629-
*
630-
* @default `false`
631-
* @example
632-
* ```js
633-
* {
634-
* streaming: true
635-
* }
636-
* ```
623+
* @deprecated Set `streaming: true` on the function definition passed to `api.route()` instead.
637624
*/
638625
streaming?: Input<boolean>;
639626
/**

0 commit comments

Comments
 (0)