調べる効率が悪いのか、タイトルの構成で基本的なところ動くまでも結構時間かかってしまいました。イチから調べるよりこういったスタート地点のがあると良いと思いますので残しておきます。
主にSAMとSwaggerの関連性の部分が厳しかった。。。
コード
ディレクトリ構成は以下の通りです。
. ├── Makefile ├── README.md ├── bin │ ├── hello │ └── root ├── src │ ├── api │ │ ├── swagger.dev.yml │ │ └── swagger.prod.yml │ └── handler │ ├── hello │ │ └── main.go │ └── root │ └── main.go └── template.yml
GolangとAPIGatewayとのやりとり
こちらを使います。
aws-lambda-go/README_ApiGatewayEvent.md at v1.2.0 · aws/aws-lambda-go · GitHub
package main import ( "context" "fmt" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" ) func HandleRequest(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { msg := fmt.Sprintf("Processing request data for request %s.\n", req.RequestContext.RequestID) msg += fmt.Sprintf("Body size = %d.\n", len(req.Body)) msg += fmt.Sprintln("Headers:") for key, value := range req.Headers { msg += fmt.Sprintf(" %s: %s\n", key, value) } return events.APIGatewayProxyResponse{ IsBase64Encoded: false, Headers: map[string]string{"myheader": "myheader"}, Body: msg, StatusCode: 200, }, nil } func main() { lambda.Start(HandleRequest)
外部のSwaggerファイルを参照
APIGatewaiの定義部分で外部のSwaggerファイルを参照しています。この部分かなり悩んだのですが、こちらのブログにたどりついたおかげで、AWS::Include Transform
使うことで着地しました。
Api: Type: AWS::Serverless::Api Properties: StageName: !Sub ${Stage} DefinitionBody: Fn::Transform: Name: AWS::Include Parameters: Location: !Sub s3://${ArtifactBucket}/${SwaggerFile}
AWS::Include Transform
の Location
ではS3しか参照できないため、デプロイ直前にS3にSwaggerファイルをアップロードしています。
deploy: package aws s3 cp ./src/api/$(SWAGGER_FILE) s3://$(S3_STAGING_BUCKET)/ sam deploy --template-file ./.packaged.yml --stack-name $(STACK_NAME) --capabilities CAPABILITY_IAM \ --parameter-overrides \ Stage=$(STAGE) \ ArtifactBucket=$(S3_STAGING_BUCKET) \ SwaggerFile=$(SWAGGER_FILE) aws cloudformation describe-stacks --stack-name $(STACK_NAME) --query "Stacks[0].Outputs" --output table
Malformed Lambda proxy response
直前まで動いていたのに、突然繋がらなくなり、調べるとこのエラーが出るようになっていました。スタック作り直しても全く解決せずで困り果てていました。動きとしては何かのタイムアウトになているようで、Lambda管理画面から直接も実行できない状態でした。
解決策・・書きたいのですが、しばらく時間経ってから何も設定変更せずにDeployし直したら動くようになりました。
Wed Jun 13 11:29:12 UTC 2018 : Received response. Integration latency: 10700 ms Wed Jun 13 11:29:12 UTC 2018 : Endpoint response body before transformations: {"Message":"An error occurred and the request cannot be processed.","Type":"Service"} Wed Jun 13 11:29:12 UTC 2018 : Endpoint response headers: {Connection=keep-alive, x-amzn-RequestId=f897c580-6efc-11e8-92cb-79be3563d414, x-amzn-ErrorType=ServiceException, Content-Length=86, Date=Wed, 13 Jun 2018 11:29:12 GMT, Content-Type=application/json} Wed Jun 13 11:29:12 UTC 2018 : Execution failed due to configuration error: Malformed Lambda proxy response Wed Jun 13 11:29:12 UTC 2018 : Method completed with status: 502
参考資料
Swagger周りは結構ひっかかりました。
いつも助けてもらってますが、今回もクラメソさんのブログに助けてもらいました。
AWSのSwagger拡張のドキュメントも、どこ読めばよいかわかりにくかったのですが、ここをエントリポイントに探すと必要な情報にたどり着きやすかったです。
その他
ステージを細かく管理できない
現状ステージごとにスタックを作らなければなりません。そのうち修正が出てくるかも。
Stageというステージが勝手に作成されてしまう
最初は自分の設定ミスかと思いましたが、バグ?、仕様?のようです。 SAM Creates stage named "Stage" by default? · Issue #191 · awslabs/serverless-application-model · GitHub
こちらの方法で解決できる場合もありそうで、ステージの管理もある程度柔軟にできそうですが、複雑になりすぎて辛そう・・