HTTPタイプのファンクションを作成する
このページでは、HTTPタイプのファンクションの記法およびファンクション作成時のルールについて説明します。
HTTPタイプのファンクションの記法
ファンクションの実行ランタイムやエントリポイント、利用できるモジュールは ファンクションの書き方 で説明しました。ここでは主に、ファンクションの入力データについて説明します。
入力 (data)
ファンクションのエントリポイントでは、引数 data
で入力値を受け取ります。HTTPタイプのファンクションの場合、data
として req
オブジェクトと res
オブジェクトを値に持つオブジェクトを受け取ります。
これらの値はそれぞれ、Express.js の リクエスト(req) オブジェクトと レスポンス(res) オブジェクトです。HTTPタイプのファンクションではこれらの値を使ってHTTPリクエストを処理します。
req
でHTTPリクエストから情報を取得する
req
オブジェクトにはHTTPリクエストの情報が含まれています。例えば次のプロパティにアクセスできます。
req.method
: HTTPリクエストのメソッドreq.query
: クエリパラメータreq.body
: リクエストボディreq.get()
: ヘッダーの値を取得する
なお、Craft Functionsでは body-parser
を使ってContent-Typeヘッダーに基づいてリクエスト本文を解析しています。そのため、 req.body
および req.rawBody
オブジェクトに直接アクセスできます。
許可されている標準ヘッダー
Craft Functionsでは、次の標準ヘッダーが許可されています。
host
accept
accept-encoding
accept-language
access-control-request-method
access-control-request-headers
cache-control
cookie
connection
forwarded
priority
sec-ch-ua
sec-ch-ua-mobile
sec-ch-ua-platform
sec-fetch-dest
sec-fetch-site
sec-fetch-user
upgrade-insecure-requests
via
x-forwarded-for
x-forwarded-proto
authorization
user-agent
origin
referer
content-length
content-type
x-hub-signature-256
これ以外のヘッダーが必要な場合は craft-functions-custom-headers
を利用できます。このヘッダーにより、ファンクション内で追加情報が扱えるようになります。
res
でHTTPレスポンスを行う
HTTPタイプのファンクションでは res.send()
, res.json()
をはじめとする res
オブジェクトのレスポンス用のメソッドを使ってHTTPレスポンスを行います。
以下は res.send()
メソッドでプレーンテキストを返却する例です。
JSON形式 ( Content-Type: application/json
) で値を返す場合は res.json()
メソッドを使います。
200以外のステータスコードを返却する場合は res.status()
メソッドを使用します。
ファンクションの実行方法
HTTPタイプのファンクションは、ファンクションのエンドポイントURLにHTTPリクエストを行うことで実行できます。エンドポイントURLはファンクション詳細画面の「設定」タブで確認できます。
- ファンクションのURLは
https://DOMAIN_PREFIX.cev2.karte.io/functions/ENDPOINT_SUFFIX
の形式です。DOMAIN_PREFIX
はKARTEプロジェクトごとに付与されます。ENDPOINT_SUFFIX
はファンクションごとに付与されます。
HTTPタイプのファンクションは次のメソッドに対応しています。
GET
POST
PUT
DELETE
OPTIONS
ここでは、curlコマンドで GET
および POST
メソッドでファンクションを実行する方法を紹介します。
GET
リクエストの送信
以下はcurlコマンドでファンクションのエンドポイントURLに name
, age
クエリパラメータと共に GET
リクエストを送信する例です。
DOMAIN_PREFIX
およびENDPOINT_SUFFIX
はそれぞれ、実際のエンドポイントURLのものに置き換えます。- クエリパラメータ (
?name=Taro&age=20
) は、ファンクション内でreq.query
として参照できます。
POST
リクエストの送信
以下はcurlコマンドでファンクションのエンドポイントURLに POST
リクエストを送信する例です。
DOMAIN_PREFIX
およびENDPOINT_SUFFIX
はそれぞれ、実際のエンドポイントURLのものに置き換えます。- リクエストボディ (
-d
オプションの値) は、ファンクション内でreq.body
として参照できます。
HTTPタイプのファンクションのルール
HTTPタイプのファンクション特有のルールを説明します。
必ず res
で明示的にレスポンスする
HTTPタイプのファンクションでは、res
オブジェクトのメソッドを使ってHTTPレスポンスを送信する必要があります。レスポンスを行わない場合、ファンクションはタイムアウトするまで実行し続けることがあります。また、タイムアウトによって予期せぬ挙動となる場合があります。
次の例では res
オブジェクトでレスポンスを行わずに return
で値を返却しようとしています。HTTPタイプのファンクションは、return
で返り値を渡してもHTTPレスポンスを行いません。
このような場合は、例えば次のように、res.send()
メソッドでHTTPレスポンスを送ります。
res
によるレスポンスは1回の実行につき1回のみ
res.send()
, res.json()
等のHTTPレスポンスを行うメソッドは、ファンクションの1実行につき1回のみ使えます。2回目以降はエラーになるので注意しましょう。
例えば次のコードではリクエストのContent-Typeによって異なるレスポンスを行うコードですが、Content-Type: application/json
のリクエストを受け取った際にレスポンス用のメソッドが2回行われます。
改善方法としては、if文内でHTTPレスポンスを行う際に return
して、後続処理をスキップする方法があります。
その他仕様
ファンクションの記法に関わらない、HTTPタイプのファンクション特有の仕様を説明します。
特定のエラーレスポンス
ファンクションの終了ステータスは res.status()
で柔軟に設定できます。ただし、次の状況ではファンクションは特定のステータスコードを返却します。
res
によるレスポンスを行わずにファンクションを終了した場合、ファンクションはステータスコード500を返却します。- タイムアウトした場合、ファンクションはステータスコード504を返却します。
サンプルコード
HTTPタイプのファンクションのサンプルコードを紹介します。
リクエストの内容に基づきレスポンスを変える
以下はHTTPタイプのファンクションのサンプルコードです。このコードでは次の処理を行っています。
- HTTPリクエストのメソッドを検証
POST
リクエストのみを許容する
- リクエストの
Content-Type
ヘッダーの値によってHTTPレスポンスの内容を変えるapplication/json
の場合はリクエストボディのname
プロパティの値を使ってJSON文字列でレスポンスを行うtext/plain
の場合はリクエストボディの値をそのまま使ってテキストメッセージをレスポンスを行う- それ以外の場合は固定のメッセージでレスポンスを行う
req
, res
オブジェクトのより詳しい利用方法については、Express.jsのリファレンスを参照してください。
CORSへの対応
ブラウザからURLエンドポイントにリクエストする際には CORS (オリジン管理ソース共有、Cross-Origin Resource Sharing) への対応が必要です。具体的には、クライアントからのプリフライトリクエストに応答する必要があります。
以下は特定のオリジン ( https://hoge.example.com
) に対してクロスオリジンリクエストを許可する場合のレスポンス例です。
複数のオリジンに許可をする場合は、次のようにファンクション側で許可対象のオリジンリストを保持して、リクエスト内容と比較した上で Access-Control-Allow-Origin
の値を指定します。
イベント駆動タイプのファンクションの エンドポイント トリガーと同等のレスポンスをする場合は次のようにOriginヘッダーの値をそのまま Access-Control-Allow-Origin
ヘッダーの値に利用します。