I want to use Amazon API Gateway as a proxy for another AWS service and integrate other services with API Gateway.
Resolution
AWS service APIs are REST APIs that you can make an HTTPS request to. To integrate another service with API Gateway, build an HTTPS request from API Gateway to the service API.
Configure an API Gateway REST API with an AWS service
The following example integrates the Amazon Simple Notification Service (Amazon SNS) Publish API with API Gateway:
- Create an Amazon SNS topic and note the topic's Amazon Resource Name (ARN).
- Create a subscription to the topic.
- Use the AWS Identity and Access Management (IAM) console to create an AWS service proxy execution role.
Note: For the Amazon SNS example configuration, use the sns:Publish API action.
- Create a REST API.
- To import the REST API, use the following example OpenAPI 2.0 definition template:
{
"swagger": "2.0",
"info": {
"version": "2019-10-09T14:10:24Z",
"title": "aws-service-integration"
},
"basePath": "/dev",
"schemes": [
"https"
],
"paths": {
"/test": {
"post": {
"produces": [
"application/json"
],
"parameters": [
{
"name": "Message",
"in": "query",
"required": true,
"type": "string"
},
{
"name": "TopicArn",
"in": "query",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "200 response",
"schema": {
"$ref": "#/definitions/Empty"
}
}
},
"x-amazon-apigateway-request-validator": "Validate body, query string parameters, and headers",
"x-amazon-apigateway-integration": {
"credentials": "arn:aws:iam::account-id:role/apigateway-sns-role",
"uri": "arn:aws:apigateway:your-region:sns:action/Publish",
"responses": {
"default": {
"statusCode": "200"
}
},
"requestParameters": {
"integration.request.header.Content-Type": "'application/x-www-form-urlencoded'",
"integration.request.querystring.Message": "method.request.querystring.Message",
"integration.request.querystring.TopicArn": "method.request.querystring.TopicArn"
},
"requestTemplates": {
"application/json": "Action=Publish&TopicArn=$util.urlEncode(*YOUR-TOPIC-ARN*)&Message=$util.urlEncode($input.params('Message'))"
},
"passthroughBehavior": "when_no_match",
"httpMethod": "POST",
"type": "aws"
}
}
}
},
"definitions": {
"Empty": {
"type": "object",
"title": "Empty Schema"
}
},
"x-amazon-apigateway-request-validators": {
"Validate body, query string parameters, and headers": {
"validateRequestBody": true,
"validateRequestParameters": true
}
}
}
Note: Replace arn:aws:iam::account-id:role/apigateway-sns-role with your IAM role's ARN, YOUR-TOPIC-ARN with your SNS topic's ARN, and your-region with your AWS Region.
The preceding template creates the method for your API Gateway API, the parameters for the method request, and the parameters for the integration request.
- (Optional) To test the API, run the following curl command:
curl -X POST 'YOUR-API-URL/stage/resource-path?Message=hello&TopicArn=YOUR-TOPIC-ARN'
Note: Replace YOUR-API-URL with your API URL and YOUR-TOPIC-ARN with your SNS topic's ARN.
For more information, see Tutorial: Create a REST API with an AWS integration.
Get an HTTPS request from the service API
Note: If you receive errors when you run AWS Command Line Interface (AWS CLI) commands, then see Troubleshoot AWS CLI errors. Also, make sure that you use the most recent AWS CLI version.
To get an HTTPS request from an API call, run the following publish command:
aws sns publish --topic-arn arn:aws:sns:us-east-1:123456789012:test --message "hi" --debug
Note: Replace arn:aws:sns:us-east-1:123456789012:test with your Amazon SNS topic's ARN.
Example output for the Amazon SNS configuration:
2018-11-22 11:56:39,647 - MainThread - botocore.client - DEBUG - Registering retry handlers for service: sns
2018-11-22 11:56:39,648 - MainThread - botocore.hooks - DEBUG - Event before-parameter-build.sns.Publish: calling handler <function generate_idempotent_uuid at 0x11093d320>
2018-11-22 11:56:39,649 - MainThread - botocore.endpoint - DEBUG - Making request for OperationModel(name=Publish) (verify_ssl=True) with params: {'body': {'Action': u'Publish', u'Message': u'hello', 'Version': u'2010-03-31', u'TopicArn': u'arn:aws:sns:us-east-1:123456789012:test'}, 'url': u'https://sns.us-east-1.amazonaws.com/', 'headers': {'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', 'User-Agent': 'aws-cli/1.15.74 Python/2.7.14 Darwin/16.7.0 botocore/1.9.23'}, 'context': {'auth_type': None, 'client_region': 'us-east-1', 'has_streaming_input': False, 'client_config': <botocore.config.Config object at 0x1118437d0>}, 'query_string': '', 'url_path': '/', 'method': u'POST'}
2018-11-22 11:56:39,650 - MainThread - botocore.hooks - DEBUG - Event request-created.sns.Publish: calling handler <bound method RequestSigner.handler of <botocore.signers.RequestSigner object at 0x111843750>>
2018-11-22 11:56:39,650 - MainThread - botocore.hooks - DEBUG - Event choose-signer.sns.Publish: calling handler <function set_operation_specific_signer at 0x11093d230>
2018-11-22 11:56:39,650 - MainThread - botocore.auth - DEBUG - Calculating signature using v4 auth.
2018-11-22 11:56:39,651 - MainThread - botocore.auth - DEBUG - CanonicalRequest:
POST
/
content-type:application/x-www-form-urlencoded; charset=utf-8
host:sns.us-east-1.amazonaws.com
x-amz-date:20181122T062639Z
content-type;host;x-amz-date
The output contains the HTTPS request, the passed headers, and the request is a POST HTTP method.
(Optional) Check your integration configuration
To verify that your integration setup is configured correctly, run the following get-integration command:
aws apigateway get-integration --rest-api-id 1234123412 --resource-id y9h6rt --http-method POST
Example output for the Amazon SNS configuration:
{
"type": "AWS",
"httpMethod": "POST",
"uri": "arn:aws:apigateway:eu-north-1:sns:action/Publish",
"credentials": "arn:aws:iam::123456789:role/apigateway-sns-role",
"requestParameters": {
"integration.request.header.Content-Type": "'application/x-www-form-urlencoded'",
"integration.request.querystring.Message": "method.request.querystring.Message",
"integration.request.querystring.TopicArn": "method.request.querystring.TopicArn"
},
"requestTemplates": {
"application/json": "Action=Publish&TopicArn=$util.urlEncode('arn:aws:sns:eu-north-1:123456789:test-standard')&Message=$util.urlEncode($input.params('Message'))"
},
"passthroughBehavior": "WHEN_NO_MATCH",
"timeoutInMillis": 29000,
"cacheNamespace": "v2e7yo",
"cacheKeyParameters": [],
"integrationResponses": {
"200": {
"statusCode": "200"
}
},
"responseTransferMode": "BUFFERED"
}
For larger message payloads, run the following Amazon SNS integration on your API:
"requestParameters": {
"integration.request.header.Content-Type": "'application/x-www-form-urlencoded'"
},
"requestTemplates": {
"application/json": "Action=Publish&TopicArn=$util.urlEncode('*YOUR-TOPIC-ARN*')&Message=$util.urlEncode($input.body)"
}
Note: Replace YOUR-TOPIC-ARN with your SNS topic's ARN.
Amazon SNS supports the maximum header size of 16KB. Before you send the request to your integration, use a request mapping template to convert an incoming HTTP request into a different format. Because the Amazon SNS topic ARN is hardcoded into the mapping template, clients don't pass through the SNS topic ARN in their request.
Related information
Methods for REST APIs in API Gateway
Integrations for REST APIs in API Gateway
Parameter mapping examples for REST APIs in API Gateway