AWS API Gateway and EC2 Service Proxy - amazon-web-services

I am trying to POST a json string to API Gateway and in turn have API Gateway send the JSON to an EC2 server.
My issue is I can't find good documentation from Amazon on how to accomplish this.
When I test the setup I get this
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Response><Errors><Error><Code>InvalidHttpRequest</Code><Message>The HTTP request is invalid. Reason: Unable to parse request</Message></Error></Errors><RequestID>1fa47f52-d75c-4ff8-8992-3eac11a79015</RequestID></Response>"
Which means very little to me. I assume it is an issue with API Gateway trying to send the request to EC2 and it can't so it generates this error. So perhaps I am setting up the EC2 AWS Service Proxy in API Gateway incorrectly. Which is likely because I have no idea what I am supposed to set 'Action' to right now I have it pointing to the EC2 instance, only cause i don't see any other place to put that info.
This really shouldn't be that hard I have successfully done this thing connecting to Lambda and have looked through all the documentation and all I can find is this: http://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-aws-proxy.html#getting-started-aws-proxy-add-resources
Which is less than helpful for this scenario. Any Ideas?

I think you confused AWS Service Proxy and HTTP Service proxy.
API Gateway can forward API calls to different type of backends:
- a lambda function
- an AWS Service (see http://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html for an example)
- an existing API, running on AWS or on premises (your use case)
When defining you API, be sure to define a POST verb and point the Endpoint URL to your EC2 instance URL
I just made a test using the JSON POST service available online at http://gurujsonrpc.appspot.com/ and it works as expected.
Here is the Swagger export of my test API.
{
"swagger": "2.0",
"info": {
"version": "2016-04-11T20:46:13Z",
"title": "test"
},
"host": "c22wfjg4d7.execute-api.eu-west-1.amazonaws.com",
"basePath": "/prod",
"schemes": [
"https"
],
"paths": {
"/": {
"post": {
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "200 response",
"schema": {
"$ref": "#/definitions/Empty"
}
}
},
"x-amazon-apigateway-integration": {
"responses": {
"default": {
"statusCode": "200"
}
},
"uri": "http://gurujsonrpc.appspot.com/guru",
"httpMethod": "POST",
"type": "http"
}
}
}
},
"definitions": {
"Empty": {
"type": "object"
}
}
}

Related

AWS Lambda API Application .Net Core Not responding

I created an AWS Lambda Application API using AWS Toolkit for .Net Core 3.1. It has 2 Get request that expecting text JSON in a request body and returning text JSON as an output. It does not require any database connection or any other AWS resources. Locally everything works fine, all tests are passing. I publish my app to AWS account using AWS Toolkit which runs Cloud Formation setting file, again no problems, all passing. This creates my AWS Lambda API app with my API endpoint. However, when I try to use I am getting "403 Forbidden" errors:
Other thing I notice is that the default API Gateway type is Edge, I am unsure if that's making a problem. I would like to set it up to Private in cloud formation stuck from .Net Core level. I assume it is something to be change here:
{
"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.",
"Resources": {
"AspNetCoreFunction": {
"Type": "AWS::Serverless::Function",
"Properties": {
"Handler": "AES.Protocol::AES.Protocol.LambdaEntryPoint::FunctionHandlerAsync",
"Runtime": "dotnetcore3.1",
"CodeUri": "",
"MemorySize": 256,
"Timeout": 30,
"Role": null,
"Policies": [
"AWSLambdaFullAccess"
],
"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/"
}
}
}
}
The previous question related to this API might be helpful.
I manage to find a solution. It seems like CloudFront is not supporting GET request with "body". So changing "GET" to "POST" request fix the problem.

Native way of view apigateway documentation in browser

I have an public AWS apigateway created providing a swagger file.
To document the API I have added to the swagger the following section:
"x-amazon-apigateway-documentation": {
"documentationParts": [
{
"location": {
"type": "API"
},
"properties": {
"description": "This is the API description"
}
},
{
"location": {
"type": "METHOD",
"method": "GET",
"path": "/foo/{bar}"
},
"properties": {
"description": "This is the method description"
}
}
]
}
Then I have published the documentation version 1.0 through AWS console.
Reached this point I want to give anyone the URL of my API documentation that ideally should be rendered in the browser in a nice way.
But, checking AWS docs regarding apigateway documentation I only find one way to access to it, that is using another AWS provided API:
http://apigateway.eu-central1.amazonaws.com/restapis/TheIdOfMyApiGateway/documentation/parts
Additionally, I should set some access keys in the request to retrieve it, making impossible for one agnostic user to simply view it in the browser setting no additional headers in the request.
Is there any way to achieve my aim?

List Documentation Parts AWS apigateway

Through Terraform I have created an AWS apigateway based on a swagger file.
I that swagger file I have added the specific AWS endpoints to document the API, like:
"x-amazon-apigateway-documentation": {
"documentationParts": [
{
"location": {
"type": "API"
},
"properties": {
"description": "This is the API description"
}
},
{
"location": {
"type": "METHOD",
"method": "GET",
"path": "/foo/{bar}"
},
"properties": {
"description": "This is the method description"
}
}
]
}
Then I have published the documentation version 1.0 through AWS console and I am trying to fetch that documentation via HTTP as stated in :
List Documentation Parts
But, unfortunately, I can't. I am doing a GET to the endpoint
http://apigateway.eu-central1.amazonaws.com/restapis/<TheIdOfMyApiGateway>/documentation/parts
And it doesn't even give me a 4XX code but neither response nor HTTP code at all.
What I am doing wrong?
My bad was a typo in the region.
I was missing a dash, the correct endpoint is:
http://apigateway.eu-central-1.amazonaws.com/restapis/<TheIdOfMyApiGateway>/documentation/parts
With eu-central-1 instead of eu-central1
I check the naming of the regions in AWS Regions

ApiGateway CloudFormation without lambda

I am trying to create a template so that when i call api/divide/inputvalue, The api sends back response from DynamoDB which corresponds to inputvalue mapping.
Its pretty straight forward since i am fetching value directly from db without any business logic hence I don't need any lambda. But all the examples that I google or all tutorials they are using lambdas and i am now lost that how can i make it working without lambda
This is what I have so far. There is bug in this template right now since I haven't provided Uri in ApiGateway::Method. Which is what I am currently stuck at.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Deployment": {
"Type": "AWS::ApiGateway::Deployment",
"Properties": {
"RestApiId": { "Ref": "restApiName" },
"Description": "First Deployment",
"StageName": "StagingStage"
},
"DependsOn" : ["restApiMethod"]
},
"restApiMethod": {
"Type": "AWS::ApiGateway::Method",
"Properties": {
"AuthorizationType": "NONE",
"HttpMethod": "GET",
"ResourceId": {"Ref": "apiRestResource"},
"RestApiId": {"Ref": "restApiName"},
"Integration": {
"Type": "AWS",
"IntegrationHttpMethod": "GET",
"IntegrationResponses": [{"StatusCode": 200}],
"Uri": { "Fn::Sub":"arn.aws.apigateway:${AWS::Region}:dynamodb:action/${restApiName.Arn}"}
},
"MethodResponses": [{"StatusCode": 200}]
},
"DependsOn": ["apiRestResource"]
},
"apiRestResource": {
"Type": "AWS::ApiGateway::Resource",
"Properties": {
"RestApiId": {"Ref": "restApiName"},
"ParentId": {
"Fn::GetAtt": ["restApiName","RootResourceId"]
},
"PathPart": "divide"
},
"DependsOn": ["restApiName"]
},
"restApiName": {
"Type": "AWS::ApiGateway::RestApi",
"Properties": {
"Name": "CalculationApi"
}
}
}
}
According to the documentation, the Uri property is structured as follows for AWS service-proxy integration types:
If you specify AWS for the Type property, specify an AWS service that follows the form: arn:aws:apigateway:region:subdomain.service|service:path|action/service_api. For example, a Lambda function URI follows the form: arn:aws:apigateway:region:lambda:path/path. The path is usually in the form /2015-03-31/functions/LambdaFunctionARN/invocations. For more information, see the uri property of the Integration resource in the Amazon API Gateway REST API Reference.
The uri API Gateway property reference provides more details:
For AWS integrations, the URI should be of the form arn:aws:apigateway:{region}:{subdomain.service|service}:{path|action}/{service_api}. Region, subdomain and service are used to determine the right endpoint. For AWS services that use the Action= query string parameter, service_api should be a valid action for the desired service. For RESTful AWS service APIs, path is used to indicate that the remaining substring in the URI should be treated as the path to the resource, including the initial /.
For an AWS service proxy to the dynamodb service calling the Query Action, the Uri should be something like this (using the YAML short-form of Fn::Sub to insert a Ref for the current AWS region):
!Sub "arn:aws:apigateway:${AWS::Region}:dynamodb:action/Query"
As for your broader use-case of using API Gateway to access DynamoDB without using Lambda functions, refer to Andrew Baird's tutorial blog post, "Using Amazon API Gateway as a Proxy for DynamoDB", and translate the specified Management Console steps to corresponding CloudFormation template resources.

Export Amazon API Gateway to Postman doesn't show requests (GET/POST/etc...)

I recently started working with the Amazon API Gateway, and I tried the feature to export the requests. All of the videos I have seen showed that the exported request also included the methods. GET,POST,etc..
I tried different versions at postman, and looking at the export, I don't see the request. I just exporting the JSON and the Swagger files and got the same result.
Is there a switch I missed or something to get the methods to show up in the exported postman collection ?
{
"swagger": "2.0",
"info": {
"version": "2017-01-04T18:34:30Z",
"title": "LambdaMicroservice"
},
"host": "mh4p5iqeyl.execute-api.us-west-2.amazonaws.com",
"basePath": "/prod",
"schemes": [
"https"
],
"paths": {
"/wef_hello": {
"x-amazon-apigateway-any-method": {
"responses": {
"200": {
"description": "200 response"
}
}
}
}
}
}
To answer my own question, and maybe help someone else out.
I think I just needed to deploy the API so it is published, and now it generates the request properly.
Cheers