Commit b6eb111
#6501 feat(local): forward Lambda response streaming through start-api
sam local start-api was buffering Lambda invokes in a StringIO and then
running the result through API Gateway proxy JSON parsing, which made
it impossible to test functions that use awslambda.streamifyResponse
(or any other Lambda response-streaming pattern, e.g. Server-Sent
Events). The HTTP request to RIE was issued without stream=True and
the response body was materialised in full before the caller saw a
single byte.
This change adds a parallel "streaming-aware" invoke pipeline that the
API Gateway service uses by default while keeping the buffered code
path exactly as it was for non-streaming responses:
* docker/container.py: new wait_for_streaming_response /
_make_streaming_http_request methods that issue the RIE invoke with
stream=True and hand the caller the raw requests.Response. A
matching release_streaming_slot keeps the per-container concurrency
semaphore correctly balanced across the lifetime of the stream.
* lambdafn/runtime.py: new LambdaRuntime.invoke_streaming that builds
/ runs the container the same way invoke() does but returns a tuple
of (response, cleanup). The cleanup callable releases the slot and
invokes _on_invoke_done so warm containers stay warm while cold
containers are stopped after the stream is fully consumed.
* commands/local/lib/local_lambda.py: thin wrapper plumbing
invoke_streaming through LocalLambdaRunner.
* apigw/streaming_response.py (new): turns the streaming RIE response
into a flask.Response. When the upstream Content-Type is
application/vnd.awslambda.http-integration-response, the JSON
prelude is parsed and applied to the outgoing status/headers/cookies
before the body bytes (after the 8-NUL delimiter) are forwarded
chunk by chunk. Chunks are pulled with raw.read1() for minimal
latency, and call_on_close hooks the cleanup callable to the Flask
response lifecycle.
* apigw/local_apigw_service.py: _request_handler now invokes through
the streaming-aware helper. When the runtime advertises streaming
(via Lambda-Runtime-Function-Response-Mode), the streamed response
is forwarded straight to the browser with CORS headers merged in.
Otherwise the previously-buffered body is parsed and rendered
through the existing v1/v2 payload-format helpers.
* local/rapid/aws-lambda-rie-*: refreshed RIE binaries built from the
streaming-aware fork that lives in
aws-lambda-runtime-interface-emulator (case-insensitive response
mode comparison + streamingCopy pass-through).
Validated end-to-end with a Node.js Lambda using
awslambda.streamifyResponse: an EventSource client in a browser
receives one SSE frame per second over a 10-second stream rather than
seeing all 10 frames arrive together at the end.
Co-authored-by: Cursor <cursoragent@cursor.com>1 parent 9ffa5ed commit b6eb111
7 files changed
Lines changed: 664 additions & 4 deletions
File tree
- samcli
- commands/local/lib
- local
- apigw
- docker
- lambdafn
- rapid
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
271 | 271 | | |
272 | 272 | | |
273 | 273 | | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
274 | 314 | | |
275 | 315 | | |
276 | 316 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
35 | 39 | | |
36 | 40 | | |
37 | 41 | | |
| |||
60 | 64 | | |
61 | 65 | | |
62 | 66 | | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
63 | 73 | | |
64 | 74 | | |
65 | 75 | | |
| |||
630 | 640 | | |
631 | 641 | | |
632 | 642 | | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
633 | 761 | | |
634 | 762 | | |
635 | 763 | | |
| |||
735 | 863 | | |
736 | 864 | | |
737 | 865 | | |
738 | | - | |
739 | | - | |
740 | | - | |
741 | 866 | | |
742 | | - | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
| 885 | + | |
| 886 | + | |
| 887 | + | |
| 888 | + | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
| 892 | + | |
| 893 | + | |
| 894 | + | |
| 895 | + | |
| 896 | + | |
| 897 | + | |
| 898 | + | |
| 899 | + | |
| 900 | + | |
| 901 | + | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
743 | 912 | | |
744 | 913 | | |
745 | 914 | | |
| |||
0 commit comments