AWS
APIGateway

Slack Outgoing Webhooksで改行を含む投稿をAWS Lambdaに送信する

前提

こちらの記事を参考にSlackとAWSの設定を行った。
https://qiita.com/G-awa/items/fc803c285cb560dab796

しかし、Slackの投稿に改行が含まれているとLambdaが起動しない。
API Gatewayの本文マッピングテンプレートでform-urlencoded形式からjson形式に変換する際、特定の文字をエスケープする必要があるようだ。

必要なエスケープは以下のとおり。

エスケープ表記 対象の文字
\ \
\" "
\n (キャリッジリターン)
\r (ラインフィード)
\t (タブ)

対応

冒頭で提示した記事にある本文マッピングテンプレートの最後のブロックを以下のように変更する。

{
#foreach( $kvPair in $tokenisedEquals )
  #set($kvTokenised = $kvPair.split("="))
 "$util.urlDecode($kvTokenised[0])" : #if($kvTokenised[1].length() > 0)"$util.urlDecode($kvTokenised[1].replace("%5C", "%5C%5C").replace("%22", "%5C%22").replace("%0D", "%5Cr").replace("%0A", "%5Cn").replace("%09", "%5Ct"))"#{else}""#end#if( $foreach.hasNext ),#end
#end
}

別案

あるいはAPI GatewayでURLエンコードを行わず、Lambdaで行う方法もある。
その場合の本文マッピングテンプレートは、同じ箇所を以下のようにする。

{
#foreach( $kvPair in $tokenisedEquals )
  #set($kvTokenised = $kvPair.split("="))
 "$util.urlDecode($kvTokenised[0])" : #if($kvTokenised[1].length() > 0)"$kvTokenised[1]"#{else}""#end#if( $foreach.hasNext ),#end
#end
}

あとはLambda側の各言語のURIデコード処理を呼び出せばよい。
例えば、Node.jsの場合は以下のとおり。

index.js
exports.handler = (event, context, callback) => {
    var text = decodeURIComponent(event.text.replace(/\+/g, '%20'));
    // 以下省略
}