Help us understand the problem. What is going on with this article?

Serverless Framework v1.0のlambda-proxyを使って任意のレスポンスを返す

More than 3 years have passed since last update.

Serverless Framework v1.0で追加されたlambda-proxyを使ってHTTPステータスコードの操作と、任意のレスポンスを返してみたいと思います。
rc.2までのエラー操作はLabmda上で生成したエラーオブジェクトのmessageにセットしたJson文字列をマッピングテンプレートのVLTでパースしてエラー時の文言を生成していました。
以前までのエラーハンドリングのベストプラクティスに関してはこちらの記事で詳しく紹介されています。
Error Handling Patterns in Amazon API Gateway and AWS Lambda

lambda-proxyを使えば、こういった面倒くさい設定をせずにLambda内で返却するレスポンスの設定が可能となります。

動作環境

  • Serverless Framework v1.0.2
  • nodejs v4.3.2

Serverlessの基本的なセットアップについては、Serverless Framework v1.0の使い方まとめで詳しく書かれていますので、そちらを参考にしてください。

レスポンスオブジェクトの基本的な構造

レスポンス時に渡すオブジェクトの基本は以下のような構造になっています。

{
  statusCode: 200,    // HTTPステータスコード
  headers: {
    'x-custom-header' : 'My Header Value'    // レスポンスヘッダ
  },
  body: JSON.stringify('hello serverless')    // レスポンスボディ
}

HTTPステータスコード、レスポンスヘッダ、レスポンスボディの3つで構成されます。
たいした説明は必要無さそうですが、レスポンスヘッダにContent-Type未指定時はデフォルトでapplication/jsonなどの暗黙的な挙動があるので、動作確認しつつ確認してください。

詳細は公式ドキュメントのlambda-proxyを読んでください

HTTPレスポンス200(正常系)を返す

最も一般的なレスポンスになるかと思います。
プロジェクト作成時のサンプルでデフォルトで生成される内容とほぼ同等です。

module.exports.ok = (event, context, callback) => {
  const response = {
    statusCode: 200,
    body: JSON.stringify({message: 'Go Serverless v1.0! Your function executed successfully!'})
  };
  return callback(null, response);
};

特に説明もいらないとは思いますが、
{"message":"Go Serverless v1.0! Your function executed successfully!"}
というレスポンスを返します。
デフォルトのContent-Typeapplication/jsonなので、Content-Type未指定時にはbodyにJson文字列を渡してあげましょう。

HTTPレスポンスコード400(バリデーションエラー)を返す

module.exports.badrequest = (event, context, callback) => {
  const errors = {
    email: 'email require',
    password: 'must have length greater than or equal to 6'
  }
  const response = {
    statusCode: 400,
    body: JSON.stringify(errors)
  };
  return callback(null, response);
};

Lambda上で入力チェックをした際に、バリデーションエラーとしてエラー内容の詳細を返す場合などに便利です。
ajax経由で呼び出した場合のレスポンスには、jqXHR.responseJSON内にこのオブジェクトが格納されるので、このオブジェクトをパースしてエラー処理を行います。

Lambda上で成功とエラーを綺麗に分けたい場合は callback(new Error('[400] Bad Request')); のように返し、serverless.ymlでステータスコードをカスタムする ことが推奨されていますが、今回は割愛します。

HTTPレスポンスコード302(リダイレクト)を行う

module.exports.redirect = (event, context, callback) => {
  const response = {
    statusCode: 302,
    headers: {
      'Location': 'https://google.co.jp/'
    }
  };
  return callback(null, response);
};

リダイレクトを行います。
以前までは、serverless-plugin-multiple-responses 等のプラグインを利用しないとできなかったリダイレクト処理も可能になりました。
※ responseオブジェクト内に、bodyを定義すると動作しないので注意してください。

htmlコンテンツを返す

module.exports.html = (event, context, callback) => {
  const response = {
    statusCode: 200,
    headers: {
      'Content-Type': 'text/html;charset=UTF-8'
    },
    body: '<!DOCTYPE html><html lang="ja"><title>serverless-response-sample</title><body><h1>html response</h1><p>hello serverless!</p></body></html>'
  };
  return callback(null, response);
};

デフォルトではContent-Type: application/jsonを返していましたが、Content-Type: text/htmlを指定することでhtmlコンテンツも返却可能です。
これを上手く使えば、ある程度の動的コンテンツの生成もできそうですね。

最後に

今まで、VLTで記述したマッピングテンプレートを駆使してレスポンスの変換も行ってきたわけですが、これらがすべてLambda上で設定可能となりました。
serverless.yml の記述量も減り、保守のしやすさなども向上したのではないでしょうか。
今後もどういった進化を遂げていくのか楽しみですね。

今回のコードはgithubでも公開していますので、Serverless Framework採用時の足がかりにでもなればと思います。
github

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away