Step Functions を API にする
私は以前、Step Functionsの機能を紹介する記事を書きました。
これは「Lambdaを使わなくても色んなことができるよ!」という趣旨の記事だったのですが、このままでは味気ないので、Step FunctionsをAPIにしていきたいと思います。
今回登場するサービスは以下の3つです。
- Step Functions
- API Gateway HTTP API
- API Gateway REST API
ステートマシンを作成する
まずは土台となるステートマシンを作成していきます。
設定は以下の通りです。
- ステートマシン名: SampleWorkflow
- ステートマシンのタイプ: Express
「標準」のワークフローは状態遷移数に応じて課金されるのですが、「Express」はリクエスト数と実行時間に応じて課金されます。
つまり、ExpressワークフローはLambdaのような気持ちで使えるということです!
ワークフローの中身は、今回はシンプルに「Pass」ステートのみで構成します。
Passステートの出力は、
{
"message": "Hello, World!"
}
とします。
この状態でステートマシンを作成します。
(ロググループが既に存在するというエラーが出ることがあります。その場合は、画面上部「設定」からロググループ名を変更してあげます。)
IAMロールの作成
API GatewayがStep Functionsを呼び出すための権限を設定する必要があります。
まずはIAMポリシーを作成します。API GatewayがStep FunctionsのStartSyncExecution
というアクションを実行するためのポリシーを作成します。
ARNは、先ほど作成したステートマシンのARNを指定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "InvokeStepFunctions",
"Effect": "Allow",
"Action": "states:StartSyncExecution",
"Resource": "<ステートマシンのARN>"
}
]
}
ポリシー名はここではInvokeStepFunctionsPolicy
として作成します。
次にIAMロールを作成していきます。
次に、IAMロールの作成画面で、「カスタム信頼ポリシー」を選択します。
内容は以下のようになります。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "InvokeStepFunctions",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
次ページの「許可ポリシー」では、先程作成したInvokeStepFunctionsPolicy
を選択します。
ロール名はInvokeStepFunctionsRole
とし、ロールを作成します。
① API Gateway HTTP APIと統合する
それではStep FunctionsをAPI Gateway HTTP APIと統合していきます。この後に作成するREST APIよりもかなりシンプルな設定になります。
まずはAPI Gatewayのコンソールに移動し、「HTTP API」を選択します。
API名はSampleAPI
とし、「確認して作成」を押して作成します。
次にルートの設定をします。Routes
画面でGETの/
を定義しましょう。
次に、Step Functionsとの統合を設定します。Integrations
画面で「統合を作成してアタッチ」をクリックします。
以下のように設定し、作成します。
- 統合タイプ: AWS Step Functions
- 統合アクション: StartSyncExecution
- ステートマシンARN: 先ほど作成したステートマシンのARN
- IAMロール: 先ほど作成した
InvokeStepFunctionsRole
のARN
作成されたら、「デフォルトのエンドポイント」を叩いてみましょう。
curlで叩くと以下のように返ってきます。少々レスポンスが大きいですが、output
の部分にHello, World!
が含まれていることがわかりますね!
参考までに、JavaScriptで整形するとこのように書けます。
const res = await fetch(
"<API Gateway HTTP APIのエンドポイントURL>",
);
const data = await res.json();
const output = JSON.parse(data.output);
console.log(output);
Denoで実行してみました。良い感じですね!
このAPIは自身で利用する分には十分ですが、billingDetails
やexecutionArn
などの情報が含まれており、外部に公開するものとしては心もとないです。
API Gateway REST APIを使うと、このレスポンスをカスタマイズすることができるので、実際にやっていきましょう。
② API Gateway REST APIと統合する
API Gatewayのコンソールに移動し、「REST API」を選択します。
名前はSampleAPI2
とし、APIを作成します。
リソース画面で、「メソッドを作成」をクリックします。
「メソッドを作成」画面では以下のように埋めます。少々細かいですが、HTTP APIと同様の設定になります。
- メソッドタイプ: GET
- 統合タイプ: AWSのサービス
- AWSリージョン: ap-northeast-1 (お使いのリージョンに合わせてください)
- AWSサービス: Step Functions
- HTTPメソッド: POST
- アクション名: StartSyncExecution
- 実行ロール: 先ほど作成した
InvokeStepFunctionsRole
のARN
呼び出すステートマシンを指定するため、「マッピングテンプレート」を設定する必要があります。
上で作成したGETメソッドを選択し、「統合リクエスト」タブの「編集」をクリックします。
最下部までスクロールし、「マッピングテンプレート」を追加します。
コンテンツタイプはapplication/json
とし、
マッピングテンプレート: 以下の内容を入力します。ステートマシンのARNは先ほど作成したものを指定してください。
{
"input": "{}",
"stateMachineArn": "<ステートマシンのARN>"
}
ここまででちょうどHTTP APIと同様の設定ができました。
さらにレスポンスを整形するために、次は「統合レスポンス」の「マッピングテンプレート」を設定します。
編集ボタンを押すと空のマッピングテンプレートが表示されるので、中身を以下のように入力します。
#set($resp = $util.parseJson($input.body))
$resp.output
これで、レスポンスのoutput
部分のみを抽出することができます。設定されると以下のような画面になります。
最後に、APIをデプロイしましょう。画面右上の「API をデプロイ」ボタンをクリックします。
- ステージ: 新しいステージ
- ステージ名:
dev
としてデプロイします。(何か設定を変更するたび、デプロイが必要です。)
「ステージ」画面にURLが表示されるので、これを使ってAPIを叩いてみましょう。
curlで叩くと以下のようにmessage
のみが返っていますね!
まとめ
今回はStep FunctionsのステートマシンをAPI Gatewayと統合することで、APIとして利用できるようにしました。
また、
- HTTP APIではシンプルに統合が可能
- レスポンスの整形を行う場合はREST APIを利用するとよい
ということがわかりました。
API Gatewayでは他にも
- リクエストにパラメータを含める
- 認証を追加する
- カスタムドメインを設定する
といった機能があるため、これらを組み合わせることで本番運用可能なAPIも構築できそうですね。