How do you configure AWS API Gateway HTTP GET to return the BASE64 string as binary data? - aws-lambda

I am trying to send binary data from my AWS Lambda function as a response to an AWS Gateway GET Method that DOES NOT use Lambda Proxy integration. I have tried all sorts of variations but still can't make it work, although I feel like I am close.
My API Gateway HTTP request is returning:
But what I want is is the actual binary data:
I did attempt using a mapping template, but was unsuccessful due to my lack of understanding the templating syntax/behavior(I tried $util.base64Decode($input.body) but that produced a server error).
But I wasn't sure if that was even necessary since I have the content handling set to Convert to binary.

I ran into this problem but I used a proxy url. Make sure to enable Binary Media Types. Also do not forget to deploy your changes, simply saving is not enough. Also make sure you have the correct content type in the header with client sending the payload.

Related

How to deal with 6 megabytes limit in AWS lambda services?

I have a three-tier app running in AWS. The midware was written in Python Flask and stored on a Linux machine.
However, they asked me to move to AWS Lambda services. There is a limit of 6 M for the returning data function. As I´m dealing with GEOJson, sometimes it´s necessary to return up to 15 M.
Despite the AWS lambda stuff is stateless, I could provide some way to return data partitioned, but it´s problematic I think it will be necessary to generate the whole map again and again until I could fulfill all data.
Is there a better way to deal with this? I´m programming in Python.
I'd handle this by sending the data to S3, and issuing a redirect or JSON response that points to the URL on S3 (with a temporary, expiring URL if the data should be secure). If the data's long-lived, you can just leave it there; if not, you could use S3's lifecycle rules to have the files automatically delete after 24 hours or so.
If you have control of the client too that receives those data, you can send a compressed result that is then uncompressed client side. So you'll be able to send that 15MB response too, which can become really small when compressed.
Or you can send a fragment of the whole response with a token or something indicating the client that the response is not complete. Than the client will make another request with that token to get the next fragment, and so on until there are no more fragments. At this point the client can join all fragments to get the full response.
Speaking of the 6MB limit, I hope that at some point we will have the ability to set what is the max payload size. since 6MB is fine for most cases, but not ALL cases
You can use presigned S3 URL to upload, using this there will be no bound by payload size.
Get HTTP GET request to API Gateway, then Lambda function get generate presigned URL and return it presigned S3 URL.
Then client directly update content to s3 using pre-signed s3 URL.
https://docs.aws.amazon.com/AmazonS3/latest/dev/ShareObjectPreSignedURL.html

Upload image to Lambda using gateway API

I'm trying to let user upload pictures to a lambda function for processing; using the gateway API interface.
I tried to specify a model for my POST method, but so far I keep getting the error
Invalid model specified: Validation Result: warnings : [], errors : [Invalid model schema specified]
... Not so helpful.
I understand that I cannot directly send raw data to lambda and must using some kind of formatting in-between.
What I understood is that I could make the gateway interface base64 encode the data for me.
I tried to do so by using the following model schema with the content type image/jpeg
{
"body" : $util.base64Encode($input.body)
}
How to send the image ?
There is no native support in API Gateway for binary data as you have seen. We are working on this but I don't have an ETA for you. Some customers have had success base64 encoding the data like you have in your question, only it should be in a mapping template in the Integration Request not the Method Request.
If you set the content type to image/jpeg, then the encoding will apply only when the Content-Type header on the incoming request is also image/jpeg, so make sure to set that.
You can also reject incoming requests to the method that don't send the right Content Type by setting the 'Request body passthrough' (passthroughBehavior in the API) to the recommended value ("when there are no templates defined" or 'WHEN_NO_TEMPLATES' in the API)
Docs for the passthrough behavior -> https://docs.aws.amazon.com/apigateway/api-reference/resource/integration/#passthroughBehavior
Since it seems like working with binary data and API Gateway is complicated, I think you should:
Upload the image using API Gateway as an S3 proxy
Set a trigger for your lambda function on PUT for the bucket where you've uploaded the image

POST call in Mulesoft

I am trying to make a HTTPS POST call in mulesoft to an external API. I had read in the mulesoft documentation and also in other posts that in order to send the request body, a map has to be prepared.
Hence, i am using the "Set-Payload" to prepare a map.
Eg: #[{'key':'value'}]
When I am using the logger to display it, it prints a map (as expected).
But when the POST call is being made, i am receiving the following error:
Response code 503 mapped as failure. Message payload is of type: BufferInputStream
Payload : org.glassfish.grizzly.utils.BufferInputStream#3f8f77a
Could anyone let me know where am i going wrong?
Thanks in Advance.
The server you're trying to call is returning status 503. Have you tried calling the external API using other client SOAP/Postman/Curl?
Also check this out:
http://forums.mulesoft.com/questions/2009/consume-get-restful-service.html
You should set proper mimetype for muleMessage and set the http POST method, then it should work.
While posting the data male sure how your http is expecting the input. What ever the transformations you want to make before posting do it, finally when posting the data to http cross check your data type with the data in the server your are trying to send. Both needs to match. Then it work.
I generally try to Isolate HTTP interaction problems into two parts. One is related to request itself for e.g. URL,Method,Headers,Payload,MimeType and other should be related to transport and network interaction with Server itself. To better view the information for both of the above details use a htt[ proxy/debugger [for. e.g. Fiddler] around the traffic flowing while you make a request. This will throw more light on the stuff hindering you while making this call successfully.
You can try any of the below sugestions-:
Set payload as map, mention MIME Type as application/json and then use json to object transformer (with return class as java.util.HashMap).
Set payload as simple string. This could help.
Status code 503 implies that the server is currently unable to handle the request due to a temporary overloading or maintenance of the server. The implication is that this is a temporary condition which will be alleviated after some delay.
Please try resending the message or hit the API with Postman.
It looks like you need to change the port in the request-config to 443 since you're using HTTPS.
<http:request-config name="HTTP_Request_Configuration" protocol="HTTPS" host="jiratst.murex.com" port="443" doc:name="HTTP Request Configuration" basePath="/rest/api/2/project">
try using input {'key':'value'} in set payload instead of Array.

Trying to call parse.com cloud function using maigun route action

I'm trying to use a parse.com cloud function in a mailgun route action (forward).
My action is like this (with my app id and JS key included of course):
forward("https://myAppId:javascript-key:myJSkey#api.parse.com/1/functions/hello")
In the mailgun logs, I see it call, but I get the following error:
HTTP Error 401: Unauthorized Server response: 401 HTTP Error 401: Unauthorized
My function is just a simple response.send("OK");
Obviously I'm missing something.
Greg
The issue I think is that the Cloud Code calling convention requires you use special Parse headers, not just keys: it may be different if its being called from a browser with sets the referer headers. I'm not sure you'll be able to call it this way directly from Mailgun: you may need a proxy of some sort.
EDIT: I think you'll need to use the Express Webhook implementation instead, and then you can use standard basic authentication. Cloud Code is really for cases where you have control over the HTTP client you're using.

Authorization header not sent using AFNetworking

I'm developing an iOS app that makes frequent requests to a web server, and I'm using AFNetworking (which I very much like). However, I'm running into a problem with authorization that I just can't solve.
The server requires me to provide an authorization header in order to get the response that I want. Specifically, the authorization headers should be like so:
Authorization = "ApiKey some-user-name:someNumericalApiKey"
I'm using AFNetworking throughout the project, and everything works fine, except for this authorization issue. I'm using the following code:
[myClient setDefaultHeader:#"Authorization" value:#"ApiKey some-user-name:someNumericalApiKey"];
where myClient points to an AFHTTPClient object. Strange enough, when I log the request in XCode using AFHTTPRequestOperationLogger, the logger claims that I have the correct headers set. However, the authorization header does not seem to reach the server - I can't see it in the server log.
To isolate the problem, I've tried to make the exact same request using good old NSURLRequest, as well as curl, and the requests library in Python - all of these work fine, i.e. the authorization header is sent & received (i.e. I can see it in the server log), and the server response is what it should be.
If anyone has run into the same problem (and has found a solution) I would very much appreciate to hear from you.
Thanks.
Sometimes (especially with Django) this is caused by redirection stripping of header parameters. For instance, /Object redirects to /Object/ in the background and removes the necessary auth parameter during the switch.
If you're using AFNetworkActivityLogger with level AFLoggerLevelDebug then you should be able to check this out in the console. If you see a POST request with /Object and the response with /Object/ then this might indicate redirection stripping is taking place.
If you construct your operation manually then the defaultHeaders are not applied, that might be the cause of your problem.

Resources