LP13
LP13

Reputation: 34079

Retuning stream in AWS API Gateway -> Lambda function?

I have created an API using AWS api gateway like https://api.mydomain.com/v1/download?id=1234". The download resource has GET method. And the GET method is invoking lambda function using Lambda Proxy Integration.

The Lambda function needs to act as Proxy. It needs to resolve correct backend endpoint based on header x-clientId and then forward the request to that backend endpoint and return response as it is. So it needs to be generic to handle GET request of different content-type.

My lambda function looks like ( .NET Core)

public async Task<APIGatewayProxyResponse> Route(APIGatewayProxyRequest input, ILambdaContext context)
{
    var clientId = headers["x-clientId"];            
    var mappings = new Mappings();
    var url = await mappings.GetBackendUrl(clientId, input.Resource);       

    var httpClient = new HttpClient();
    var response = await httpClient.GetAsync(url);
    response.EnsureSuccessStatusCode();

    var proxyResponse = new APIGatewayProxyResponse()
    {
        Headers = new Dictionary<string, string>(),
        StatusCode = (int)System.Net.HttpStatusCode.OK,
        IsBase64Encoded = false,
        Body = await response.Content.ReadAsString())
    };            
}

The handler above works as long as request and response's content-type is application/json or application/xml. However i am not sure how to handle response when backend returns stream.

For download API, the backend returns Content-Disposition: attachment; filename="somefilename and ContentType may be one of the following:
application/pdf
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
application/vnd.openxmlformats-officedocument.wordprocessingml.document
application/x-zip-compressed
application/octet-stream

For these streams, How do i set APIGatewayProxyResponse.Body?

For Excel file I have tried setting body like below

    var proxyResponse = new APIGatewayProxyResponse()
    {
        Headers = new Dictionary<string, string>(),
        StatusCode = (int)System.Net.HttpStatusCode.OK,
        IsBase64Encoded = true,
        Body = Convert.ToBase64String(await response.Content.ReadAsByteArrayAsync())
    };  

proxyResponse.Headers.Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
proxyResponse.Headers.Add("Content-Disposition", "attachment; filename=\"Report.xlsx\"");

When i access the Url from the browser and try to open the file. I get error

Excel cannot open the fileReport.xlsxbecuase the file format or file extension is not valid. Verify that the file has not been corrupted and that the extention matches the format of the file

I think the issue is how i am setting the response body

Update 1
So based on AWS doc Binary Data Now Supported by API Gateway. Now as per the documentation

you can specify if you would like API Gateway to either pass the Integration Request and Response bodies through, convert them to text (Base64 encoding), or convert them to binary (Base64 decoding). These options are available for HTTP, AWS Service, and HTTP Proxy integrations. In the case of Lambda Function and Lambda Function Proxy Integrations, which currently only support JSON, the request body is always converted to JSON.

I am using Lambda Function Proxy, which currently support JSON. However the example here shows how to do it with Lambda Proxy.
I think what i am missing here is Binary Media Types setting and Method Response settings. Below is my setting. Not sure if these settings are correct

Binary Media
enter image description here

Method Response enter image description here

Upvotes: 2

Views: 8819

Answers (1)

LP13
LP13

Reputation: 34079

here how solved it

1>add Binary Media Types. API->Settings->Binary Media Types -> add application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

2>In Method Response Add Content-Disposition and Content-Type headers for thestatus 200

enter image description here

3>In Integration Response map these headers to headers that are coming from the backend. And also set content handling convert to binary. (our backend api is returning file blob in body)

enter image description here

Upvotes: 1

Related Questions