API Gateway error "Unsupported Media Type" when trying to accept application/x-www-form-urlencoded data - aws-lambda

I am using the following tutorial:
https://www.twilio.com/docs/sms/tutorials/how-to-receive-and-reply-python-amazon-lambda
When I test the api in aws I receive a 415 error, Unsupported Media Type.
I assume this is related to the fact that Twilio sends its data in the form of application/x-www-form-urlencoded and AWS wants json.
The tutorial takes this into account. However, its code does not work for me.
I have searched the web, and tried numerous fixes to no avail.
The raw data from Twilio is (with sensitive information changed)
ToCountry=US&ToState=AK&SmsMessageSid=SM7777777777777777777777&NumMedia=0&ToCity=AAA&FromZip=99999&SmsSid=SM9999999999999999999&FromState=AK&SmsStatus=received&FromCity=BBB&Body=Is+this+json+&FromCountry=US&To=%2B15555555555&ToZip=88888&NumSegments=1&ReferralNumMedia=0&MessageSid=SM888888888888888888&AccountSid=AC6666666666666666&From=%2B14444444444&ApiVersion=2010-04-01
I enter this information in the body section of the test, run the test and the error is thrown.
There is also the same error when I try the actual webhook through Twilio.
I have also entered with surrounded in {}
I have also tried a jsonified version with the ampersands changed to commas, and the equal signs changed to colons with the items in quotes.
I also have tried:
{
"to_number": "+14444444444",
"from_number": "+15555555555",
"message": "hello does this API work"
}
I have also tried to add the following to the header of the test
"Content-Type": ["application/x-www-form-urlencoded"]
Many of the fixes I have tried involve changing the Integration Request mapping.
None have worked.
The one from the tutorial is:
#set($httpPost = $input.path('$').split("&"))
{
#foreach( $kvPair in $httpPost )
#set($kvTokenised = $kvPair.split("="))
#if( $kvTokenised.size() > 1 )
"$kvTokenised[0]" : "$kvTokenised[1]"#if( $foreach.hasNext ),#end
#else
"$kvTokenised[0]" : ""#if( $foreach.hasNext ),#end
#end
#end
}
And is of content type application/x-www-form-urlencoded
There is a stack on this topic:
Amazon Api gateway integration with Twilio
None of its solutions worked for me.
I thought the following was very promising, but it also failed for me.
https://gist.github.com/199911/68a43f83fd933b1e3ac6
I have also tried to change the lambda function. However I do not think it is the source. Its tests work.
Any help would be much appreciated.

Quote from AWS console:
You can configure binary support for your API by specifying which media types should be treated as binary types. API Gateway will look at the Content-Type and Accept HTTP headers to decide how to handle the body.
It sounds like you should configure your specific media type "application/x-www-form-urlencoded" under API gateway settings (Binary Media Types), which will tell the API gateway to accept that body type.
Navigate to Api Gateway Console:
Click on your API
On the left select settings (under API menu)
Scroll down and click Add Binary Media Type
Type application/x-www-form-urlencoded Click save
Hoping this will help.

Related

Power Platform error:502 message: ad Gateway

I am trying to run my app which is posting data through a flow which connects to an API. When I test my flow in Power Automate it runs successfully but when I Run() it in Power Apps it gives me a 502 error , Bad Gateway message. In my flow I provide a POST body in JSON since I used the "Ask in Power Apps" option and it appends the body value with a HTTP_Body variable. My flow body looks like this:
{
"username":"example.com",
"password":"mypassword"
}
I also have basic authentication which I use the same values and pass as plain text in flow and is requested as a parameters in my flow.Run(). I need to know how I can pass my HTTP_Body in Power Apps from two textboxes(username.Text and password.Text) avaialable from my Login page since i suspect that is where my error is coming from?
Any quick help would greatly appreciated!
I have tried :
.Run({username: txtusername.Text,password: txtPwd.Text},txtusername.Text,txtPwd.Text)) and tried UpdateContext to create a record but the error persists.

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?

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

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.

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.

Resources