Hot to define a fallback mapping temmplate in AWS Api Gateway? - aws-lambda

I have a POST method exposed though an API in AWS API Gateway. It would process a certain JSON. But there is a weird requirement: I am supposed to accept anything and return always a 200 status code (as long as the service is available and working of course).
So if I receive a call with Content-Type: image/jpeg, application/xml or what/ever, I must be able to map the request to my Lambda function.
I have achieved to map any request to a custom type using the VTL (Velocity Template Language), the issue is that I must specify every single Content/Type I want to support in the Integration Request.
I would like to define a fallback mapping template for every Content-Type that is not among those that I have already defined. It is not allowed to specify "*/*" as Content-Type.
I can not use When no template matches the request Content-Type header option as passthrough because b y default the lambda function tries to deserialize the body from a JSON format.
Any ideas?

I think you should enable the When no template matches the request Content-Type header option. As documented your Lambda will get an API Gateway event. This event has a headers field that, on a POST should contain a content-type field. If your code understands the content-type then handle it. If not, return a response that has the correct status code and whatever is appropriate. This is not on the API gateway side but rather on the Lambda side.
See this blog for some additional ideas.

Related

How get AWS API Gateway & Lambda REST API to correctly handle a POST as application/x-www-form-urlencoded

I'm setting up a Lambda as a webhook handler that receive data POSTed from a remote API.
As per usual, the external webhook is POSTing the data in the form:
payload='SOME_JSON' for example payload='{"foo":"bar"}'
How can AWS API Gateway be configured to correctly handle application/x-www-form-urlencoded data POSTed from an external webhook, e.g., to correctly map the raw content string into a "form style" parameter name/value pair and pass the value (which is JSON) to the Lambda?
The problem is that AWS API Gateway, by default, tries to relay the entire raw string payload=JSONSTRING to the Lambda, but of course the payload= is not JSON, it's the form parameter name, so that generates a 400 error (body not in JSON format).
To test, I posted the same data to both the AWS API Gateway, and, so that I can see exactly what is POSTed from the webhook, also to webhook.site for debugging.
As shown below the in webhook.site screengrab, the raw data POSTed is in the usual webhook format, "parameter=value" eg payload=JSONSTRING, specifically: payload='{\"arg1\":\"val1\"}'
And as shown in the webhook.site screengrab, their site completely understood how to map that to a "parameter name" (payload) and the parameter value.
webhook.site screengrab:
The closest I've come is to get the API Gateway & Lambda to stop throwing 400 errors, by using API Gateway's "Body Mapping Template" to at least force the raw content "param=value" into JSON format using this body mapping:
{"body": "$input.body"}
as described in this helpful blog post: https://blog.summercat.com/using-aws-lambda-and-api-gateway-as-html-form-endpoint.html
(edit: that blog post was old, Body Mapping Template is not required, API Gateway now supports enabling "Use Lambda Proxy integration" on the Integration Request for the POST method which passed to the Lambda the full input object (headers, payload, etc) as JSON to get rid of the 400 errors. But the "body" key/value in the JSON is still not parse-able JSON, it is prefixed with the payload=")
But the problem is the the Lambda event hash still isn't in a usable format it still includes the "payload=...(escaped string)" e.g.
`{"body"=>"payload=%7B%22arg1%22%3A%22val1%22%7D"
So I hope there is some way to configure API Gateway to do what the rest of the world can do, and map the POSTed raw content "payload=JSONSTRING" to a JSON object that is passed to the Lambda, such as {"payload" : "JSONSTRING"} or perhaps just JSONSTRING?

Serverless Framework with lambda-proxy integation and API Model Validation

I have an issue validating a request with a model when the user changes the content-type of the request in a serverless framework lambda-proxy integration
As per AWS docs, we can not change too much when using lambda-proxy integration
For example, the passthrough behavior that explains what happens when a validation model does not match the request type, can not be used on lambda-proxy integration.
My problem: I want to reject all requests that are not JSON so they must be forced to use the model validation. But at the same time, I do not want to change the integration type from lambda-proxy to lambda.
What can I do to solve this issue?
BR
One thing you can do is inspect the headers in the event object to confirm that it is the type you expect and if not return an error:
https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html
We can enforce the Content-Type header straight into the API Gateway like below.
References can be found here: https://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html

Apache Nifi : How to pass post params and capture response from post API - traditional non rest, non json API

I'm trying to pull data from a post API that expects authentication and request parameters as part of the request body. I guess, what they do is access the data from the post variables.
What I have seen so far in documentation is how to send POST via JSON or headers. In my case, no headers just the post body parameters.
call to this api via curl --data option works just fine.
curl --data "username=xyz&password=xyz&function=xyz" http://example.com/api.php
How can I replicate above call in nifi?
I have tried multiple methods without success. Latest has been Generate flow file, update attributes (where i fill in the parameters), invoke http then putfile.
But I'm getting errors - the api is not abe to authenticate my request.
Thanks
If you need to send the following data in body, then put it into content of your flowfile.
username=xyz&password=xyz&function=xyz
The easiest way to put it into the Custom Text property of the GenerateFlowFile processor.
Usually for this kind of body you have to provide content type header:
content-type: application/x-www-form-urlencoded
If you don't need any additional headers then you don't have to define any additional attributes of the flow file.

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

RESTserver POST request format

I am developing an API using CodeIgniter and the RestServer for CI (see below). I am also using the Firefox RestClient plugin to test the API.
What I am wondering is how to do the test post (what format).
Tried {"desc":"value"} but it did not work. The API is not "seeing" the incoming post fields.
http://net.tutsplus.com/tutorials/php/working-with-restful-services-in-codeigniter-2/
the post body doesn't need to have a specific format, but the most convenient is to encode the body in the same way web browsers encode form data, specifically Content-Type: application/x-www-form-urlencoded. In particular, the Host and Content-Length headers are not optional, and the Content-Type header is usually needed to tell the server how to interpret the body. A well formed POST request will look like:
POST /path/to/resource HTTP/1.0
Host: example.com:80
Content-Length: 21
Content-Type: application/x-www-form-urlencoded
key=value&key2=value2
It's still up to the server to recognize the content-type header and parse the body that way.
Note that the data is after all the headers, not as part of the request path (in the first line).
Optionally, you can use Proxy Library which i wrote for CI. With that, you can simulate any of possible call to your API(its works for popular REST API too), with more simple syntax instead using cURL...
// An example call to your API end point using POST, will be simply
$this->load->library('proxy');
$this->proxy->http('POST', 'http://somesite.com/api/users', array('username' => 'foo', 'password' => 'bar'));
You can define whatsoever HTTP header too (like API Key or whatever else).

Resources