[小ネタ] LambdaをバックエンドにしたALBのマルチバリューヘッダー設定 #reinvent

2018.12.04

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、中村です。

ALBのバックエンドにLambdaを選択してみた! #reinvent

上記記事ではあまり触れませんでしたが、LambdaをバックエンドにしたALBでは高度な設定としてマルチバリューヘッダーというものがあります。 アプリケーションロードバランサー(ALB)のターゲットにAWS Lambdaが選択可能になりましたの高度な設定に掲載されています。

このマルチバリューヘッダーは、複数の値とともに送信されるHTTPヘッダーとクエリ文字列パラメーターが、Lambdaへ送信されます。 設定は簡単です。Lambdaを登録しているターゲットグループの説明タブ内属性で設定します。

これで終わりに思えるのですが、ターゲットのタブを見てみるとLambdaのヘルスチェックに失敗します。

エラー内容を見てみると、The response from the Lambda function is not in the expected format.と表示されています。どうやらマルチバリューヘッダーを有効にしたことで正しいLambdaのレスポンスが変更になったようです。
ちなみにLambdaの内容はこのような形になっています。Invokeされると Hello from Lambda!が返ってくる簡単なものです。

exports.handler = async (event) => {
    console.log(JSON.stringify((event)));
    
    const response = {
        'statusCode': 200,
        'statusDescription': '200 OK',
        'isBase64Encoded': false,
        'headers': {
            'Content-Type': 'text/html; charset=utf-8'
        },
        'body': JSON.stringify('Hello from Lambda!'),
    };
    
    console.log(JSON.stringify(response));
    return response;
};

ブログには記載がありませんでしたが、ドキュメントがありました。 Lambda Functions as Targets

With multi-value headers, the load balancer uses both cookies sent by the client and sends you an event that includes the following:

{
  "multiValueHeaders": {
      "Set-cookie": ["cookie-name=cookie-value;Domain=myweb.com;Secure;HttpOnly","cookie-name=cookie-value;Expires=May 8, 2019"],
      "Content-Type": ["application/json"]
  },
}
  • headersプロパティをmultiValueHeadersプロパティに変更
  • 配下のヘッダー情報をArray

の2つを行う必要がありそうです。実際に変更してみましょう。

exports.handler = async (event) => {
    console.log(JSON.stringify((event)));
    
    const response = {
        statusCode: 200,
        statusDescription: '200 OK',
        isBase64Encoded: false,
        multiValueHeaders: {
            'Content-Type': ['text/html; charset=utf-8']
        },
        body: JSON.stringify('Hello from Lambda!'),
    };
    
    console.log(JSON.stringify(response));
    return response;
};

無事ヘルスチェックが通りましたので、ALBにcurlしてみます。

$ curl http://xxxxxxxxxxxxxxxxxxxxx.us-east-1.elb.amazonaws.com
"Hello from Lambda!"

ALBからLambdaをInvokeできるようになりました!

まとめ

いかがでしたでしょうか。
ドキュメントを読めばすぐだったのですが、どうやら読み飛ばしていたようです。ブログを読んで同じ現象にハマった方が居ましたらLambdaのレスポンスを変更してみてください。