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!
Related
I am trying to send a PDF or text file to an AWS Lambda function (Node JS). I'd like to be able to process this file in the lambda function. I know often the best practice is to use a trigger function from an s3 bucket. However, I'd like to be able to send this lambda function a file from formdata, extract information from the file and then return the extracted info back.
I have been able to first encode the file in 64 bit binary data and send it to AWS lambda via a JSON, but often when I try to decode the file (especially a PDF) in the Lambda Function it is corrupted or empty.
Image files seem to work well for this type of encoding, but been unsuccessful with PDFs. Any help greatly appreciated. Rather then encode in base 64 is there a way I can obtain the file from a formdata? My code is below:
export const handler = async(event) => {
console.log("event", event)
var converted = atob(event.body) // RATHER HOW WOULD I READ A FILE FROM FORMDATA
const response = {
"statusCode": 200,
"headers": {"Content-Type":"text/html", //"application/pdf", // "multipart/form-data", //
"Access-Control-Allow-Origin":"*",
"Access-Control-Allow-Headers":"Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token"
},
"body": event,
"isBase64Encoded": true
}
return response;
};
thanks so much
I assume that you are using an API gateway to trigger the lambda function. In that case, you have to enable multipart/form-data in API gateway as mentioned in the documentation. The gist of the documentation is as follows:
In the Settings pane, choose Add Binary Media Type in the
Binary Media Types section. Type a required media type, for example, image/png, in the input text field.
Add Content-Type and Accept to the request headers for your proxy method.
Add those same headers to the integration request headers.
Deploy the API
PS: If you are using Lambda Proxy integration ({proxy+}, just steps 1 and 4 are enough.
Interesting issue when using Firebase buckets and axios in a JS environments.
When I upload a file into a bucket and send the file link returned by firebase to server in a request body, the link is auto decoded in the server.
Upload a file to bucket from web
Firebase returns a link: https://firebasestorage.googleapis.com/v0/b/[BUCKET_NAME]/o/[POINTER]%2Fimages%2F[FILE_NAME])
note the url encoded %2F that firebase uses around the 'images'
Save this to DB via a Cloud Function call by using axios.post()
Using headers: {'Content-Type': 'application/x-www-form-urlencoded'} due to Cloud Function limitations here. The url is nested in a JSON object as a String.
When this request is picked up in the Cloud Function, the URL in the object has been automatically urldecoded, resulting in:
https://firebasestorage.googleapis.com/v0/b/[BUCKET_NAME]/o/[POINTER]/images/[FILE_NAME])
note the / around the 'images'
Problem: Firebase doesn't return the file when %2F is replaced with / in the URL, only returning error:
Invalid HTTP method/URL pair.
I understand that I have only one option here, and it is to prevent this String to be URL decoded during the client-server axios call. Since I am using the mentioned headers, I'm not sure how this can be achieved.
Side quest: Why does Firebase enforce the urlencode this strongly and doesn't return the file independently of the representation of the path to file (encoded or not)?
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
Im developing a Lambda API in my AWS API Gateway. Im trying to retrieve some parameters from a POST call, but the body comes as a text instead of a JSON, or any type of collection.
I was advised to make the calls using a application/json content type, and also advised to use 'lambda proxy integration', but none of those configurations changed the response object.
api.post('/login', function(request) {
return new Promise((resolve, reject) => {
console.log(request.body)
Log return:
----------------------------289602992579875509977825
Content-Disposition: form-data; name="myformdata"
666666666666
----------------------------289602992579875509977825
Content-Disposition: form-data; name="otherparameter"
6666666666
There is any way I can get a collection of the parameters sent by client?
There is any solution for this using only lambda functions?
Some people are saying that is possible to get post parameters like a "query-string" (ex:one=1&two=2..). Im using PostMan for testing, but this is not working.
Thanks.
Claudia JS Reference:
https://github.com/claudiajs/claudia-api-builder/blob/master/docs/request-object.md
I have setup an express/serverless application to retrieve a pdf file on a GET request. But I just retrieve a corrupted repsonse pdf response. I just wondering If my settings are correct to achieve a correct response.
I'm using aws-serverless-express and want to return my pdf buffer to the client browser (it should open in the browser)
My code:
status = 200;
let fileName = "demo.pdf";
res.setHeader('Content-disposition', 'inline; filename="' + fileName + '"');
res.setHeader('Content-type', 'application/pdf');
res.setHeader('isBase64Encoded', true);//isBase64Encoded: true
let pdf = pdfBuffer.toString('base64');
res.status(status).send(pdf);
so I'm sending a base64 encoded string to APIGW. I'm not actually sure if I can set the isBase64Encoded flag via header. I read this before but I'm not so certain about that
I have done this whole procedure before, but didn't make use of aws-serverless-express (where I Could set the isBase64Encoded flag easily)
I'm also using serverless-apigw-binary to automatically setup APIGW for the correct decoding of the base64 encoded data
lambda is automatically encoding to base64, so I had to remove it and directly send the buffer.
I came across similar problem while using serverless Express. AWS Gateway needs a http response like this:
{
"header":{....}
"body": "/9j/4AAQSkZ...",
"isBase64Encoded": true
}
It's useless to put isBase64Encoded in the Http Response Header, AWS API Gateway only checks if the isBase64Encoded is outside the Http header. If it's true, then decode the body before sending it to a HTTP client.
Express (its response object) doesn't seem to allow to add something outside HTTP Header in a Http Response.
If you don't want to give up using Express, the workaround is to do the decoding in the browser, which is pretty easy:
var decodedData = Buffer.from(body,'base64')