API Gateway doesn't pass headers to Lambda - node.js

I am trying to make a multipart http query through API Gateway to a Lambda. I have set the binary media type to 'multipart/form-data'. The issue is that I need to access the Content-Type header, so that I can parse the body correctly in my lambda logic.
But when I console log the lambda event, I can see that the Content-Type header is missing, even though I can see that it is well sent by my client.
Also, everything works perfectly in local with serverless-offline, without going through API Gateway.
So I'm guessing API Gateway does its own processing of my request and send a different version of it to my Lambda, with different headers.
How can I force API Gateway to pass this header to my Lambda ?
Thank you very much!

In the integration request try adding an HTTP Header Content-Type mapped from application/x-www-form-urlencoded.
Then add a mapping template for multipart/form-data
{
"Content-Type" : "$input.params('Content-Type')",
"body_base64" : "$util.base64Encode($input.body)"
}
If you are using an OpenAPI template to create the api with terraform or serverless then configure the x-amazon-apigateway-integration: node
requestTemplates:
multipart/form-data: "{\n \"Content-Type\"\
\ : \"$input.params('Content-Type')\",\n \"body_base64\" : \"$util.base64Encode($input.body)\"\
\n}"
passthroughBehavior: "never"
type: "aws"

Related

How to capture what Alexa console sends to the endpoint?

I am currently learning about the chatbots and developed two different skills. One has an endpoint on Azure and the other's endpoint is on AWS. Everything works fine. I would like to know if there is a way to see what the Alexa console sends to your endpoint (including the header)? The Alexa console only shows the body. I would like to capture header and body so I can test my endpoints with Postman.
POST / HTTP/1.1
Content-Type : application/json;charset=UTF-8
Host : your.application.endpoint
Content-Length :
Accept : application/json
Accept-Charset : utf-8
Signature:
SignatureCertChainUrl:
https://s3.amazonaws.com/echo.api/echo-api-cert.pem
It's the HTTP HEADER that Alexa is sending with its Body
For more info : Request and Response JSON Reference

How to avoid headers passed back to API Gateway from Lambda via Serverless framework being remapped?

I'm hitting an issue when I try to respond in a Serverless Lambda function with the WWW-Authenticate challenge header.
I am setting in my response
{
statusCode: 401,
headers: {
'WWW-Authenticate': 'Basic realm="My realm"',
},
body: "",
}
The function runs successfully but in the response I don't have a WWW-Authenticate header; instead, I have an x-amzn-Remapped-WWW-Authenticate header.
How can I have this header passed through verbatim?
I read the docs about passing custom response headers, but it seems that these need to be set in serverless.yml. Since these response headers need to be dynamic based on the request headers I don't think that will help me.
The function is the default lambda-proxy type.
By default The Serverless Framework uses the Lambda Proxy Integration method. This does lots of the heavy lifting for you, but also gets in the way.
If you want a more transparent experience you need to use Lambda Integration, and handle the response yourself. Though you'll need to get more hands on, including CORS response headers.
integration: lambda
You can read more about the two methods here: https://serverless.com/framework/docs/providers/aws/events/apigateway/#lambda-integration

Using AWS Lambda and API Gateway to serve static javascript?

I am writing a third party widget that executes javascript client side to add a button to the users site. Essentially, the user will include a tag on their site that includes a path to my widget. The URL for that path will include the app_id for the particular user calling the widget. For example
<script src="www.widget.com/widget/{USER_ID}">
I want to be able to use AWS Lambda and API Gateway to do some quick authentication that the user is allowed to download the widget and serve the javascript content. This is super simple with something like res.sendFile in Express.js, but API Gateway doesn't seem to support sending a file. Is there any way that I can use API Gateway to serve the javascript quickly, without having to stringify the entire file?
You can setup api gateway to proxy all requests to s3 which hosts the file (S3 proxy example). Otherwise you can setup a Http Proxy integration and then run a backend http server that serves the entire file.
To perform authentication on the request you can execute a lambda function as a custom authorizer
If you have a lambda integration type, the only was is to return the entire file in the response using callback lambda documentation for callback.
First, you can respond something like this in your Lambda function:
{
statusCode: 200,
headers: {
"content-type": "text/javascript"
},
body: buildMyJavascriptFileInTextFormat(event.user_id),
isBase64Encoded: false,
}
Then go to your API Gateway resource and set up the integration following these steps:
Method Request:
Add a query string called user_id.
Integration Request:
{
"user_id": "$input.params('user_id')"
}
Integration Response
Go to Status code: 200, create a Mapping template called: text/javascript and set up this:
$input.path('body')
Method Response
In the box of Response Body for 200 change the Content-Type to text/javascript.

Gzipped response in AWS Lambda -> API Gateway

I can't seem to get a gzipped response from Lambda through the API Gateway.
I'm gzipping my response in Lambda and setting the "Content-Encoding" header in API Gateway.
I'm not sure which part is the problem.
Here's the final return from Lambda to API Gateway:
zlib.gzip(myJsonString, function (err, buffer) {
if ( err ) { return handleError(err, context) }
return context.succeed(buffer.toString('binary'));
});
I've tried just passing the buffer, base64 encoding it, etc.
Making a GET request from Chrome:
If I remove the Content-Encoding header from the gateway I get binary/base64/buffer array as a string response in the browser.
If I set the header, the GET request fails entirely with no response but testing in the AWS console returns the payload with quotes around it.
I don't know what's going on here but If Amazon actually wants people to use this thing we need to be able to compress our responses. Seems like it should just be a checkbox in API Gateway and then I could simply return a JSON string from Lambda and have it zipped up automatically.
As for Nov 17, 2016 - Binary Data Now Supported by API Gateway
Let me know if you figured that out!

ContentType is null when making Get requests using ServiceStack JsonServiceClient

In my integration tests, ContentType is null when I make Get requests using ServiceStack's JsonServiceClient. However all the Post requests have a ContentType. Is it excluded on purpose? ie. Do I need a content type for http get requests?
Is there a way I can set the ContentType using this client?
There is no Content-Type for GET Requests since it doesn't have a Request body.
The Content-Type on the Request Header specifies what format the Request Body is in, likewise when on the Response Body specifies what format the Response Body is in.
You may instead be after the Accept HTTP Request Header which tells the server the preferred Content Types it would like the Response in.

Resources