How do I change status and headers when streaming with lambda and function url?

1

Hello,

I'm new to working with AWS Lambda and streaming HTTP responses. I've been following this tutorial and specifically the "Create a response streaming function (AWS CloudFormation)" section. In that section, they use awslambda.HttpResponseStream.from to add metadata to the stream. However, when I implemented a similar Lambda handler, the result was not what I expected. Instead of adding the metadata to the response, it concatenated it with the response body.

Here's the code I used:

export const handler = awslambda.streamifyResponse(
  async (ev: APIGatewayProxyEventV2, stream: ResponseStream) => {
    const metadata = {
      status: 404,
      headers: {
        'Content-Type': 'text/html',
        'Cache-Control': 'no-cache',
      },
    }

    stream = awslambda.HttpResponseStream.from(stream, metadata)
    stream.setContentType('text/html')

    stream.write('Not found!')
    await new Promise((resolve) => setTimeout(resolve, 1000))
    stream.write('text1')
    await new Promise((resolve) => setTimeout(resolve, 1000))
    stream.write('text2')
    await new Promise((resolve) => setTimeout(resolve, 1000))
    stream.end()
  },
)

My goal is to change the response status and headers dynamically within the Lambda function. Is there a way to achieve this? I would appreciate any guidance or suggestions.

Thank you in advance!

  • I also noticed that responseStream.finished(), used in the example I said before, doesn't exist.

  • Where did you import the TypeScript type ResponseStream from?

  • I was importing it from this package https://github.com/astuyve/lambda-stream but I found a better solution for the awslambda types

    import type { Writable } from 'stream'
    
    import type { APIGatewayProxyEventV2, Context, Handler } from 'aws-lambda'
    
    declare global {
      namespace awslambda {
        export namespace HttpResponseStream {
          function from(writable: Writable, metadata: any): Writable
        }
    
        export type ResponseStream = Writable & {
          setContentType(type: string): void
        }
    
        export type StreamifyHandler = (
          event: APIGatewayProxyEventV2,
          responseStream: ResponseStream,
          context: Context,
        ) => Promise<any>
    
        export function streamifyResponse(
          handler: StreamifyHandler,
        ): Handler<APIGatewayProxyEventV2>
      }
    }
profile picture
질문됨 10달 전919회 조회
2개 답변
0
수락된 답변

For anyone who having the same issue, check your metadata, it seems that awslambda.HttpResponseStream will not apply the metadata if one of the properties is invalid. In my example, I spelled status instead of statusCode

profile picture
답변함 10달 전
-1

Here is an excerpt from the response streaming blog post :

Response streaming currently supports the Node.js 14.x and subsequent managed runtimes. You can also implement response streaming using custom runtimes. You can progressively stream response payloads through Lambda function URLs, including as an Amazon CloudFront origin, along with using the AWS SDK or using Lambda’s invoke API. You can not use Amazon API Gateway and Application Load Balancer to progressively stream response payloads, but you can use the functionality to return larger payloads with API Gateway.

So I would guess you are trying to view the headers using an API Gateway proxy to your lambda. Following the same tutorial you linked, I was able to get the response streaming working using Lambda Function URLs and curl. I also validated that the metadata set in the function was returned in the headers of the curl request, so it is possible to change the response status and headers dynamically within the Lambda function as you asked.

profile pictureAWS
답변함 10달 전
  • I'm not using API Gateway. I'm using my Function URL as one of my cloudfront's origin, but even requesting through the URL itself the metadata is returned concatenated to the body. Here's the curl header's response to my example:

    HTTP/1.1 200 OK
    Date: Fri, 07 Jul 2023 20:13:55 GMT
    Content-Type: text/html
    Transfer-Encoding: chunked
    Connection: keep-alive
    x-amzn-RequestId: 71ff8318-56fd-4eaf-81cc-6a8a03dc8ae2
    X-Amzn-Trace-Id: root=1-64a87203-148a57e50f6bf083130096db;sampled=0;lineage=e344ae8b:0
    

    And here's the body:

    {"status":404,"headers":{"Content-Type":"text/plain","Cache-Control":"no-cache"}}    Not found!text1text2
    

로그인하지 않았습니다. 로그인해야 답변을 게시할 수 있습니다.

좋은 답변은 질문에 명확하게 답하고 건설적인 피드백을 제공하며 질문자의 전문적인 성장을 장려합니다.

질문 답변하기에 대한 가이드라인

관련 콘텐츠