I'm not entirely sure what is wrong with my aws api-gateway
setup. I have two regions I use, one for my staging (eu-west-1) environment and another for my live (us-east-1) environment.
When I build and run my api in staging, all works fine. However when I try to run my api on live, I get the following error:
{"message": "Internal server error"}
To try and debug this I ran the API using the 'test' functionality in the aws console and performed a GET request. To my surprise I noticed that the region in the request header was wrong (eu-west-1 instead of us-east-1). Also the test returned the following message with a 502 response:
{"Message":"Functions from 'us-east-1' are not reachable in this region ('eu-west-1')","Type":"User"}
Does this mean that my api is being run in the eu-west-1
region?
If I check my region in the console I am clearly in us-east-1
when running the test. Also the region in my api-gateway uri is us-east-1
.
https://.execute-api.us-east-1.amazonaws.com/prod
I can see that my request header has: Host=lambda.eu-west-1.amazonaws.com and in the output I have the following property:
Endpoint request URI: https://lambda.eu-west-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-east-1::function:/invocations
I have no idea why my regions are mixed up! I thought it might have something to do with my build process, but after double checking everything I am not able to see what could be causing it. I am hoping a fresh set of eyes could pick something up!
To build my api I use a combination of a swagger.yaml file and a cloudformation.json file.
SWAGGER: I have placeholders in this file which I replace running a node script before sending the file to aws.
---
swagger: 2.0
info:
title: ServerlessExpress
basePath: /YOUR_API_GATEWAY_STAGE
schemes:
- https
paths:
/:
x-amazon-apigateway-any-method:
produces:
- application/json
responses:
200:
description: 200 response
schema:
$ref: "#/definitions/Empty"
x-amazon-apigateway-integration:
responses:
default:
statusCode: 200
uri: arn:aws:apigateway:YOUR_AWS_REGION:lambda:path/2015-03-31/functions/arn:aws:lambda:YOUR_AWS_REGION:YOUR_ACCOUNT_ID:function:api-gateway-service/invocations
passthroughBehavior: when_no_match
httpMethod: POST
type: aws_proxy
options:
consumes:
- application/json
produces:
- application/json
responses:
200:
description: 200 response
schema:
$ref: "#/definitions/Empty"
headers:
Access-Control-Allow-Origin:
type: string
Access-Control-Allow-Methods:
type: string
Access-Control-Allow-Headers:
type: string
x-amazon-apigateway-integration:
responses:
default:
statusCode: 200
responseParameters:
method.response.header.Access-Control-Allow-Methods: "'GET,OPTIONS,POST'"
method.response.header.Access-Control-Allow-Headers: "'Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'"
method.response.header.Access-Control-Allow-Origin: "'*'"
passthroughBehavior: when_no_match
requestTemplates:
application/json: "{\"statusCode\": 200}"
type: mock
/{proxy+}:
x-amazon-apigateway-any-method:
produces:
- application/json
parameters:
- name: proxy
in: path
required: true
type: string
responses: {}
x-amazon-apigateway-integration:
uri: arn:aws:apigateway:YOUR_AWS_REGION:lambda:path/2015-03-31/functions/arn:aws:lambda:YOUR_AWS_REGION:YOUR_ACCOUNT_ID:function:api-gateway-service/invocations
httpMethod: POST
type: aws_proxy
options:
consumes:
- application/json
produces:
- application/json
responses:
200:
description: 200 response
schema:
$ref: "#/definitions/Empty"
headers:
Access-Control-Allow-Origin:
type: string
Access-Control-Allow-Methods:
type: string
Access-Control-Allow-Headers:
type: string
x-amazon-apigateway-integration:
responses:
default:
statusCode: 200
responseParameters:
method.response.header.Access-Control-Allow-Methods: "'GET,OPTIONS,POST'"
method.response.header.Access-Control-Allow-Headers: "'Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'"
method.response.header.Access-Control-Allow-Origin: "'*'"
passthroughBehavior: when_no_match
requestTemplates:
application/json: "{\"statusCode\": 200}"
type: mock
definitions:
Empty:
type: object
title: Empty Schema
CLOUDFORMATION:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "AWS Serverless Express.",
"Parameters": {
"AwsServerlessExpressS3Bucket": {
"Type": "String",
"Description": "The S3 bucket in which the lambda function code is stored. Bucket names are region-unique, so you must change this."
},
"LambdaFunctionS3Key": {
"Type": "String",
"AllowedPattern": ".*\\.zip",
"Description": "The S3 object for the lambda function code package.",
"Default": "lambda-function.zip"
},
"ApiGatewaySwaggerS3Key": {
"Type": "String",
"AllowedPattern": ".*\\.yaml",
"Description": "The S3 object for the swagger definition of the API Gateway API.",
"Default": "simple-proxy-api.yaml"
}
},
"Resources": {
"ApiGatewayApi": {
"Type": "AWS::ApiGateway::RestApi",
"Properties": {
"Description": "AWS Serverless Express API",
"BodyS3Location": {
"Bucket": {
"Ref": "ServerlessExpressBucket"
},
"Key": {
"Ref": "ApiGatewaySwaggerS3Key"
}
}
}
},
"ApiGatewayApiDeployment": {
"Type": "AWS::ApiGateway::Deployment",
"Properties": {
"RestApiId": {
"Ref": "ApiGatewayApi"
},
"StageName": "YOUR_API_GATEWAY_STAGE"
}
},
"LambdaApiGatewayExecutionPermission": {
"Type": "AWS::Lambda::Permission",
"Properties": {
"Action": "lambda:InvokeFunction",
"FunctionName": {
"Fn::GetAtt": ["LambdaFunction", "Arn"]
},
"Principal": "apigateway.amazonaws.com",
"SourceArn": {
"Fn::Join": ["", ["arn:aws:execute-api:", {
"Ref": "AWS::Region"
}, ":", {
"Ref": "AWS::AccountId"
}, ":", {
"Ref": "ApiGatewayApi"
}, "/*/*"]]
}
}
},
"LambdaFunction": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"S3Bucket": {
"Ref": "ServerlessExpressBucket"
},
"S3Key": {
"Ref": "LambdaFunctionS3Key"
}
},
"FunctionName": "api-gateway-service",
"Handler": "lambda.serverlessExpress",
"Description": "Service running on api-gateway",
"MemorySize": 128,
"Role": {
"Fn::Join": ["", ["arn:aws:iam::", {
"Ref": "AWS::AccountId"
}, ":role/service-lambda"]]
},
"Runtime": "nodejs4.3",
"Timeout": 30
}
}
},
"Outputs": {
"LambdaFunctionConsoleUrl": {
"Description": "Console URL for the Lambda Function.",
"Value": {
"Fn::Join": ["", ["https://", {
"Ref": "AWS::Region"
}, ".console.aws.amazon.com/lambda/home?region=", {
"Ref": "AWS::Region"
}, "#/functions/", {
"Ref": "LambdaFunction"
}]]
}
},
"ApiGatewayApiConsoleUrl": {
"Description": "Console URL for the API Gateway API's Stage.",
"Value": {
"Fn::Join": ["", ["https://", {
"Ref": "AWS::Region"
}, ".console.aws.amazon.com/apigateway/home?region=", {
"Ref": "AWS::Region"
}, "#/apis/", {
"Ref": "ApiGatewayApi"
}, "/stages/YOUR_API_GATEWAY_STAGE"]]
}
},
"ApiUrl": {
"Description": "Invoke URL for your API. Clicking this link will perform a GET request on the root resource of your API.",
"Value": {
"Fn::Join": ["", ["https://", {
"Ref": "ApiGatewayApi"
}, ".execute-api.", {
"Ref": "AWS::Region"
}, ".amazonaws.com/YOUR_API_GATEWAY_STAGE/"]]
}
}
}
}