I've spent the day getting up to speed with SAM and in particular the HttpApi, but have hit a brick wall. Here's what I want to achieve (the dream):
I'm pretty sure that's how it's supposed to work anyway. But here's what is confusing me. I'm adding the integrations to my api.yaml e.g.:
get:
summary: get item
tags:
- Items
responses:
'200':
description: Item returned successfully
content:
application/json:
schema:
$ref: '#/components/schemas/ItemResource'
'404':
$ref: '#/components/responses/NotFound'
x-amazon-apigateway-integration:
payloadFormatVersion: "2.0"
type: "aws_proxy"
httpMethod: "POST"
uri:
Fn::GetAtt [GetItemFunction, Arn]
connectionType: "INTERNET"
Now I was expecting that with this HttpApi would connect the routes in my OpenApi file with the Lambda I'm pointing to in the integration "GetItemFunction". So I could just define my Lambda like so:
GetItemFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/
Handler: get-item.handler
Runtime: nodejs12.x
But that doesn't seem to set the routes as expected (I'm testing with "sam local start-api"). Instead to make it work I need to do this:
GetItemFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/
Handler: get-item.handler
Runtime: nodejs12.x
Events:
GetAllItems:
Type: HttpApi
Properties:
ApiId: !Ref MyHttpApi
Path: /items/{id}
Method: get
This works, but now I'm defining the routes in the template.yaml file and not the api.yaml file which for my use case defeats the purpose. It also seems to behave in exactly the same way regardless of whether I add the 'x-amazon-apigateway-integration' in the api.yaml or not.
I'm sure I'm missing something here, if someone could set me on the right path it would be greatly appreciated!
When you declare the connection in SAM using the eventsource, then SAM creates the permissions. If you do not use an eventsoursce then SAM does not build the permissions and API gateway does not have rights to invoke the Lambda function. If you want to manually build it then create a role in the SAM template. here is a working example (simplified to one template):
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: OpenAPI test
Resources:
MyHttpApi:
Type: AWS::Serverless::HttpApi
Properties:
DefinitionBody:
openapi: "3.0.1"
info:
title: "OpenAPI test"
paths:
/:
get:
responses:
default:
description: Item returned successfully
x-amazon-apigateway-integration:
payloadFormatVersion: "2.0"
credentials: !GetAtt MyHttpApiRole.Arn
type: "aws_proxy"
httpMethod: "POST"
uri: !GetAtt GetItemFunction.Arn
connectionType: "INTERNET"
x-amazon-apigateway-importexport-version: "1.0"
MyHttpApiRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service: "apigateway.amazonaws.com"
Action:
- "sts:AssumeRole"
Policies:
- PolicyName: ApiDirectWriteToSQS
PolicyDocument:
Version: '2012-10-17'
Statement:
Action:
- lambda:InvokeFunction
Effect: Allow
Resource:
- !GetAtt GetItemFunction.Arn
GetItemFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/
Handler: app.handler
Runtime: nodejs12.x