Error while importing formData from swagger json to AWS API Gateway - amazon-web-services

I am using flask-restx to build an app with a swagger UI and I trying to upload this swagger file as a documentation part in AWS API Gateway. Through this swagger UI, I am enabling the user to upload a CSV file for further data processing.
I have the following swagger json:
{
"swagger": "2.0",
"basePath": "/",
"paths": {
"/upload_profile/csv": {
"post": {
"responses": {
"200": {
"description": "Profile uploaded"
},
"400": {
"description": "Validation Error"
},
"401": {
"description": "Not authorized"
}
},
"operationId": "Get uploaded profiles from user",
"parameters": [
{
"name": "csv_file",
"in": "formData",
"type": "file",
"required": true,
"description": "CSV file"
}
],
"consumes": [
"multipart/form-data"
],
"tags": [
"upload_profile"
]
}
}
},
"info": {
"title": "Upload Profile",
"version": "0.0.1"
},
"produces": [
"application/json"
],
"consumes": [
"application/json"
],
"tags": [
{
"name": "upload_profile",
"description": "Uploading User Profiles"
}
],
"responses": {
"ParseError": {
"description": "When a mask can't be parsed"
},
"MaskError": {
"description": "When any error occurs on mask"
}
}
}
When I go to API Gateway --> Documentation --> Import Documentation and paste the json, I get the following error:
How can the following issue be solved? If formData isn't supported by API Gateway, is there an alternate for hosting the swagger UI?

The problem is that AWS API Gateway expects swagger/OpenAPI version 3, and your file is version 2. If you only want a way to host swagger UI for documentation/collaboration purposes, take a look at SwaggerHub https://swagger.io/tools/swaggerhub/.
But, if you really have to use AWS API Gateway, then you need to get spec in OpenAPI-3 format. Since the API is rather small, I'd suggest preparing OpenAPI-3 spec yourself (rather than generating it) and testing it locally via swagger UI.

Related

AWS API Gateway (REST) - Request Validation passes even when there is unknown property

I have an API gateway with the following schema:
{
"swagger": "2.0",
"info": {
"description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.",
"version": "1.0.0",
"title": "Swagger Petstore",
"termsOfService": "http://swagger.io/terms/",
"contact": {
"email": "apiteam#swagger.io"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
}
},
"paths": {
"/pet": {
"post": {
"summary": "Add a new pet to the store",
"description": "",
"operationId": "addPet",
"consumes": [
"application/json",
"application/xml"
],
"produces": [
"application/xml",
"application/json"
],
"parameters": [
{
"in": "body",
"name": "body",
"description": "Pet object that needs to be added to the store",
"required": true,
"schema": {
"$ref": "#/definitions/Pet"
}
}
],
"responses": {
"405": {
"description": "Invalid input"
}
}}
}},
"definitions": {
"Pet": {
"required": ["id", "name"],
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "Id of the pet",
"example": 123
},
"name": {
"type": "string",
"description": "Name of the pet",
"example": "Jammy"
},
"nickname": {
"type": "string",
"description": "Nickname of the pet",
"example": "Jam"
}
}
}
}
}
When I send a request body with fields which are not present in the schema, I don't get 400 response from API gateway. I have applied the configuration to Validate body, headers, query string.
Is this an open issue in API gateway? Or am I missing something?
So with swagger v2 and openapiv3 specs the default behavior is to accept all additional properties that your spec does not define. If you include the required pet id and name and additional unused propertues like foo and bar, you post should succeed.
If you want more strict validation that fails when additional properties are sent then set additionalProperties to false in your pet schema or do that and change the spec version to 3.x.x

AWS Lambda Controller route not matching, with {proxy+} - 404 Not Found

I have a .NET core 3.1 project with a GET endpoint. Locally the route works fine - "/api" GET request returns JSON string.
After publishing to my AWS Lambda function, and invoking the lambda via Postman, I get a 404 Not Found response to the "/api" GET request. Full URL: "https://(lambda domain)/default/MyLambda2/api"
In my project's Startup.cs ConfigureServices and Configure methods, I added "LambdaLogger.Log" statements. My log lines show up in CloudWatch (so I am definitely reaching the app). It's just after that, the route fails.
In ConfigureServices method, I have
services.AddControllers();
In Configure method, I have
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
And in the Controller file
namespace LambdaTest.Controllers
{
[Route("api")]
public class ValuesController : ControllerBase
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
}
I have an API Gateway trigger defined for the lambda, with
API endpoint: "https://(lambda domain)/default/MyLambda2/{proxy+}"
API type: REST
Authorization: NONE
Method: ANY
In Resources tab, I have...
/MyLambda2
ANY
/{proxy+}
ANY
OPTIONS
... and I have all Resources deployed to "default" stage (via Actions > Deploy API).
Here is the default auto-generated serverless.template file...
{
"AWSTemplateFormatVersion": "2010-09-09",
"Transform": "AWS::Serverless-2016-10-31",
"Description": "An AWS Serverless Application that uses the ASP.NET Core framework running in Amazon Lambda.",
"Parameters": {},
"Conditions": {},
"Resources": {
"AspNetCoreFunction": {
"Type": "AWS::Serverless::Function",
"Properties": {
"Handler": "LambdaTest::LambdaTest.LambdaEntryPoint::FunctionHandlerAsync",
"Runtime": "dotnetcore3.1",
"CodeUri": "",
"MemorySize": 256,
"Timeout": 30,
"Role": null,
"Policies": [
"AWSLambda_FullAccess"
],
"Events": {
"ProxyResource": {
"Type": "Api",
"Properties": {
"Path": "/{proxy+}",
"Method": "ANY"
}
},
"RootResource": {
"Type": "Api",
"Properties": {
"Path": "/",
"Method": "ANY"
}
}
}
}
}
},
"Outputs": {
"ApiURL": {
"Description": "API endpoint URL for Prod environment",
"Value": {
"Fn::Sub": "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
}
}
}
}
What could be causing the route to not get picked up in lambda?
Thanks
Found the issue. I needed my route on the controller to be
[Route("MyLambda2/api")]

Why is the API Gateway corrupting my binary file?

I have an AWS API Gateway acting as a proxy to a backend service:
{
"apiKeySource": "HEADER",
"name": "-",
"createdDate": 1513820260,
"binaryMediaTypes": [
"application/zip",
"application/octet-stream"
],
"endpointConfiguration": {
"types": [
"EDGE"
]
},
"id": "-"
}
The integration definition is here:
{
"integrationResponses": {
"200": {
"responseTemplates": {
"application/json": null
},
"statusCode": "200"
}
},
"passthroughBehavior": "WHEN_NO_MATCH",
"timeoutInMillis": 29000,
"uri": "http://${stageVariables.backend}:7000/{proxy}",
"connectionType": "INTERNET",
"httpMethod": "ANY",
"cacheNamespace": "iv06s3",
"type": "HTTP_PROXY",
"requestParameters": {
"integration.request.path.proxy": "method.request.path.proxy",
"integration.request.header.X-Source-IP": "context.identity.sourceIp"
},
"cacheKeyParameters": [
"method.request.path.proxy"
]
}
I have an endpoint that generates a Zip file on the fly and returns it to the requester.
When I access the endpoint directly, the file is fine. When I access it via the API Gateway, it gets corrupted.
The corruption takes the form of bytes in the original file being converted to 0xEFBFBD. This is the UTF-8 'replacement character'.
My request has Accept set to application/zip and the response has Content-Type: application/zip.
My expectation is that the API Gateway should recognize this as a binary media type and leave the file alone, but it seems pretty clear that it's processing it as text content.
What am I doing wrong?
Setting the "Binary Media Type" to "multipart/form-data" resolved a similar issue for me.
See here: AWS Api Gateway as a HTTP Proxy is currupting binary uploaded image files

"Export as Swagger" and "Export as Swagger + Postman" from API gateway is missing 'parameters' object

I have an API gateway endpoint (/item/{itemId}) with a path parameter 'itemId' in it. Here's the swagger definition I used to create the endpoint in API gateway.
{
"swagger": "2.0",
"info": {
"version": "v1",
"title": "sample-postman-import"
},
"host": "example.com",
"basePath": "/api",
"schemes": ["https"],
"paths": {
"/item/{itemId}": {
"get": {
"produces": [
"application/json"
],
"parameters": [
{
"name": "itemId",
"in": "path",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "200 response"
}
}
}
}
}
After deploying the API, when I export it as a swagger definition, the exported definition is missing the 'parameters' object, making it an incomplete swagger file. I've seen the same issue when I
Tried exporting from the UI as shown in https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-export-api.html
Used the getExport API call from javascript aws-sdk https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/APIGateway.html#getExport-property
Here's what the export looks like:
{
"swagger": "2.0",
"info": {
"version": "v1",
"title": "sample-postman-import_old"
},
"host": "example.com",
"basePath": "/api",
"schemes": ["https"],
"paths": {
"/item/{itemId}": {
"get": {
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "200 response"
}
}
}
}
}
}
I had the very same issue when I have created my API Gateway with Terraform. On the AWS UI the parameter was shown but when I requested method information through the AWS CLI with aws apigateway get-method command the parameter was not provided. So make sure you have the "requestParameters" set as you want and if not, set it through the CLI or Terraform.

Autodesk BIM360: Folder Creation returns 400 Bad request

I called the POST-Folder Method via Postman with a JSON body according to this example. But I only receive the message "400 Bad Request" without any explanations. This is what my request looks like:
The service adress:
https://developer.api.autodesk.com/data/v1/projects/b.5823d0b2-0000-0000-00/commands
The HTTP-header
Authorization: Bearer 2_legged_token
Content-Type: application/vnd.api+json
The JSON-Body
{
"jsonapi": {
"version": "1.0"
},
"data": {
"type": "commands",
"attributes": {
"extension": {
"type": "commands:autodesk.core:CreateFolder",
"version": "1.0.0",
"data": {
"requiredAction": "create"
}
}
},
"relationships": {
"resources": {
"data": [
{
"type": "folders",
"id": "1"
}
]
}
}
},
"included": [
{
"type": "folders",
"id": "1",
"attributes": {
"name": "test",
"extension": {
"type": "folders:autodesk.bim360:Folder",
"version": "1.0.0"
}
},
"relationships": {
"parent": {
"data": {
"type": "folders",
"id": "urn:adsk.wipprod:fs.folder:co.Ai*****"
}
}
}
}
]
}
The response
{
"jsonapi": {
"version": "1.0"
},
"errors": [
{
"id": "f1266e76-a37e-400b-bff6-de84b11cdb00",
"status": "400",
"detail": "BadRequest"
}
]
}
What I have found out so far:
The project id is right. When I take a wrong project id I receive a different error.
The Json is also valid.
When I take a (surely) wrong parent-folder-urn I'll receive the same error message. So maybe this is a wrong urn format or something?
As of now, you can create a BIM 360 Docs Folder with commands endpoints, as you pointed out. For that you can use:
3-legged token
2-legged token with x-user-id header, this should contain the Autodesk User ID obtained, for instance, from GET users#me endpoint
"pure" 2-legged token will return bad request (as of August/2017)
Sorry about the documentation, the endpoint to create BIM 360 Docs folder via Commands was released a couple weeks back and we're just finishing to write the documentation.