API Gateway and Swagger UI - amazon-web-services

I currently have an API with multiple resources within our API Gateway, I'm working on a a Swagger UI page for the same.
A lot of the swagger ui definition I have written myself, although I know there is export functionality - it doesn't seem 100% ready yet.
When using the Try it out button from swagger, if I get back a 200, this is handled perfectly and the result shows as expected. I am trying to get the error codes to display and this is where I am stuck.
In API Gateway I have create a 401 in my Method response, including some allowed headers, this is being used in my Integration Response for HTTP status regex of Unauthorized.* - the content of this is just being passed through.
My swagger UI definition response looks like this (for the 401 in particular):
"401": {
"description": "Unauthorized",
"headers": {
"Access-Control-Allow-Origin": {
"type": "string"
}
}
},
This is just expecting a string response. My `produces' has everything needed, just in case;
"produces": ["application/json",
"text/json",
"application/xml",
"text/xml"],
The result through the inspector is correct -
However my swagger still produces this:
I have tried a multitude of things, including assigning an object to the response type, changing my regex expression to 4\d{2} to catch any 400 error, updated the definition produces - all with no luck.
Let me know if there is any other information needed to help.

I'm assuming you're using a custom authorizer or Cognito authorizer and this is what is producing the 401?
Unfortunately there is a known limitation where error methods, such as 401 or 403 from an authorizer, will not contain configured header mappings.

Related

How to set the api version being called in API Gateway when integrating with AWS Service CloudWatch?

I get the following error message when calling actions for CloudWatch in API Gateway.
"Error": {
"Code": "InvalidAction",
"Message": "Could not find operation DescribeAlarms for version 2009-05-15",
"Type": "Sender"
}
I've been using DescribeAlarms for testing. My setup is as follows.
Integration Type = AWS Service
AWS Service = CloudWatch
HTTP method = POST
Action = DescribeAlarms
The error references the API Version 2009-05-15, which only has ListMetrics and GetMetricStatistics according to it's documentation on page 54. ListMetrics does indeed work as expected with my setup.
The current version is 2010-08-01 but I don't see anyway to reference that in API Gateway. In an example of a POST request in the documentation it shows a header labeled x-amz-target with a value of GraniteServiceVersion20100801.API_Name.
My interpretation is I can put Name = x-amz-target and value 'GraniteServiceVersion20100801.DescribeAlarms' in my http header for the Integration Request in API Gateway.
This doesn't change the response and gives the same error message.
I also used the --debug in CLI when calling describe-alarms, and in the body it shows...
"body": {
"Action":"DescribeAlarms",
"Version":"2010-08-01"
}
So I also set http headers to include Content-Type with a value of 'application/x-amz-json-1.1' and then put in
{
"Action":"DescribeAlarms",
"Version":"2010-08-01"
}
but nothing changed with that either.
Any help or guidance would be greatly appreciated.
Under Method Integration -> URL Query String Parameters
I added Version as the Name and '2010-08-01' under Mapped From.
All actions are now working as expected.
I'm trying to PutMetrics directly from Api Gateway -> Cloudwatch using PutMetricData, Version in the query string params didn't work for me.
These 3 HTTP headers in the Integration Request solved it for me:
Content-Type 'application/json'
X-Amz-Target 'GraniteServiceVersion20100801.PutMetricData'
Content-Encoding 'amz-1.0'

AWS API Gateway integration request Http headers not being passed to lambda

This is similar to this post API-Gateway Integration Request HTTP Header not mapping query string to header but I can't see any answer for it and all of the answers are not related to what the question is intended.
I am trying to add the integration request parameters in API Gateway, but whenever I set 'Http Headers' as shown here and 'Mapping template' as passthrough, I could not see that header when I log inside the lambda.
Also in the integration response I cannot reference it inside the integration header response parameters. The "integration.response.header.cokers" will be returned blank when I invoke the API. This is how I configured the integration response
Ultimately the solution here is to implement a lambda proxy integration.
A proxy integration in API Gateway tells API Gateway to simply forward all headers to the integration for processing, which means you will see all of those values in your lambda function.
NOTE: Lambda has to return a specific response format back to API Gateway if it's a proxy integration. Ultimately, the response should be something like:
{
'statusCode': 200,
'headers': {
'echo-proxy': True
},
'body': 'some payload'
}
What you are trying to do right now is map everything manually, which is a deprecated approach and usually you don't want to do that unless you absolutely have to because it's kind of a pain.
If you have to map the headers manually start by mapping them in the the method request so it can carry on to the next step and so on. Basically like this:
Method Request -> Maps variable to Integration Request -> Maps variable to Body Mapping Template -> Maps variable to actual request header
What you have in your screenshot for the Integration Request -> HTTP Headers is:
Name: cokers
Mapped from: 'blah'
However, "mapped from" should look something like "method.request.header.coker" which is a standardized path (meaning to get the value from the Method Request Header field with name "coker").
Once you have added the coker header to the Method Request, and the Integration Request HTTP Headers are mapped correctly, you have to implement a mapping template. Set the content-type to application/json with passthrough set to "When there are no templates defined(recommended)" and a simple mapping template:
{
"headers": {
"coker" : "$input.params('coker')"
}
}
That is the way my API is setup and it returns the following to me because I had my lambda function return the event as a json object back to API GW:
{"body": "{\"headers\": {\"coker\": \"mapped\"}}", "statusCode": 200}
NOTE: the value of my header "coker" in the request on the client side is "mapped"
UPDATED ANSWER
To map the original "coker" header to "coker2" (or any other name you want to give it) you simply set the name of the header in your mapping template like so:
{
"headers": {
"coker2" : "$input.params('coker')"
}
}
Then edit your lambda function to return "coker2" header and you should get a response like this:
{"body": "{\"headers\": {\"coker2\": \"mapped\"}}", "statusCode": 200}

AWS API Gateway returning different status via Postman to Method Test

I have an AWS Lambda integrated into API Gateway. The lambda is current just returning an error:
exports.handler = (event, context, callback) => {
context.fail(JSON.stringify({
status: 500,
errors: 'This is definitely the same endpoint.'
}));
};
I have added an HTTP status 500 response in method response of API Gateway, and I have mapped an integration response using regex *"status":500.* to the 500 response.
When I test this using the Method Test functionality in AWS, I get the 500 response I expect:
But when send command to the endpoint with Postman, I get a 200 status:
How can this be? The Method Test seems to suggest my Integration Response and Method Response setups are correct, and I have my regex set up correctly, but what am I missing between the API Gateway and the rest of the world that would produce this different result?
Have you tried Deploying the API? Maybe a redeployment might fix the issues.
did you stumble across the Handle Custom Lambda Errors in API Gateway guide already?
The format suggested there is:
{
"isBase64Encoded" : "boolean",
"statusCode": "number",
"headers": { ... },
"body": "JSON string"
}
So you basically need to return this JSON structure. I check this with AWS serverless express library (line 100-105) - which we use - and it's returning this structure.
The major challenge is, that sending the HTTP response to the client is a task for the API Gateway and to do so, you must return a valid JSON response from the lambda in a format that the API gateway unterstands. The execution status of the lambda will be also 200 (because it worked A-Okay) but the API Gateway will transform your response into a 500. This is also why you nedd this double/triple JSON encoding (JSON-as-string in JSON-attributes).

Returning binary body and http headers from an AWS lambda through API gateway

I have a lambda that needs to return a binary object and some http headers (e.g. content-type) through an api gateway (using lambda integration) OR redirect to another URL. In the binary support examples (e.g. https://aws.amazon.com/blogs/compute/binary-support-for-api-integrations-with-amazon-api-gateway/) the lambda only returns the (base64 of the) binary object (the image). In my case, I also need to return a status code and http headers (or something equivalent). I struggle with how I can make this work with binary support in api gateway.
The lambda returns a json on this form:
{
"statusCode": 200,
"headers": {
"content-type": "image/jpeg"
},
"body": "/9j/4AAQS...gLDAoKCAwZK",
"isBase64Encoded": true
}
In the integration response I add body mappings for image/jpeg (etc) of the form:
$input.json('$.body')
And header mapping for 'content-type' like so:
integration.response.body.headers['content-type']
I've tried many variations of the above, but the result is consistently
Execution failed due to configuration error: Unable to transform response
How do I transform the json from the lambda into a form that can be converted to binary by the api gateway, with http headers and all? Can I get more debug logging out of the api gateway to show more specific what it is unhappy with?
Is there perhaps a way to get more debug logging out of the api gateway?
I recently got this working after facing a similar problem.
In my case, I was missing two things:
First, I needed to change the list of types AWS will send to the upstream in the "Accept" header"
"x-amazon-apigateway-binary-media-types" : [
"image/jpeg"
]
Secondly, I needed to set the Integration Response to "Convert to binary (if needed)":
"contentHandling": "CONVERT_TO_BINARY"
See this answer for the details, and sample config.
I also found that I wasn't being patient enough. Whenever I deployed the API, I was checking immediately, instead of waiting a few minutes for the changes to propagate.
I tired returning binary data with base64 encoding, but I couldn't manage to return it from Lambda function through API Gateway.
Therefore, I decided to redirect the URL. I changed the Method Response to 302 and added "Location" Response header. I also deleted response code 200 from Integration Response, selected 302 as response code and mapped integration.response.body.location value with Location header. My Lambda code returned location of redirect URL in this format:
{"location":"www.google.com/"}
Hope this helps.
I've been struggling to do the same for days, but couldn't find any documentation to back up that it's possible, instead I found this
https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-payload-encodings-workflow.html
When converting a text payload to a binary blob, API Gateway assumes that the > text data is a Base64-encoded string and outputs the binary data as a
Base64-decoded blob. If the conversion fails, it returns a 500 response
indicating an API configuration error. You do not provide a mapping template
for such a conversion, although you must enable the passthrough behaviors on
the API.
When converting a binary payload to a text string, API Gateway always applies > a Base64 encoding on the binary data. You can define a mapping template for
such a payload, but can only access the Base64-encoded string in the mapping
template through $input.body, as shown in the following excerpt of an example > mapping template.
which sounds to me that mapping like this is only possible the other way around; what I ended up doing is that just return Base64Encoded binary string and hard code the content-type and cache- control in header mapping; for the complete implementation see my blog post https://mesfinmoges.com/dynamic-image-resizing-using-amazon-s3-aws-lambda-mazon-api-gateway-amazon-cloudfront/

Autodesk Data Management API 403-Error

I am trying to receive data via Autodesk Data Management API. So far I've created an Forge-App and connected it with a BIM360 Integration.
Then I wanted to get a list of all hubs, but when I do so, I receive an JSON-Object which contains a warning:
warnings: [{
"AboutLink":null,
"Detail":""You don't have permission to access this API",
"ErrorCode": "BIM360DM_ERROR",
"HttpStatusCode": "403",
...
}]
I called the webservice via AJAX wich looks like that:
this.getToken(function(token) {
$.ajax({
url: "https://developer.api.autodesk.com/project/v1/hubs",
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "Bearer "+token);
}
}).done(...);
The token is a 3-legged one. I am not sure which API I do not have permission for because I am pretty sure, that I have permission for BIM360.(I created the Integration as an administrator).
In addition to was ZHong mentioned, I would suggest you try this sample. It will ask you to provision your Forge Client ID under your BIM 360 settings, just follow the steps that the app will present.
On both 2- or 3-legged, the app accessing the data (Forge Client ID) needs authorization from the account admin. Without that, the Hubs endpoint will not return your BIM 360 hub, and inside that, the sample applies for Projects endpoint.
Does everything else work fine? For example, can you get all the hubs successfully? I just verified on my side, and I can see the response including the same warning as you mentioned, but the hubs are listed correctly, and you can get the projects/items/versions without problem. I pasted my postman response as follow.
If you check the blog https://forge.autodesk.com/blog/tutorial-using-curl-3-legged-authentication-bim-360-docs-upload, it also has the same warning, but seems no impact to the following operation. I am not exactly sure what the warning means, l will check and update the details, but so far, it seems you can ignore it for now.