SlackとAPI GatewayとLambdaで日本語を扱う

記事タイトルとURLをコピーする

技術1課から技術2課に移動になった寺田です。
やっている仕事の内容は特に変わりません。

サーバーレスということで、
SlackのSlash Commands(スラッシュコマンド)を、
API Gateway, Lambda, Dynamo DBのトリオを with Pythonで動かそうと頑張っています。

今回は、API GatewayからLambdaへ日本語を渡す際に、
かなりハマったので、解決方法を簡単に記載します。

はじめに

Lambdaには、Blueprintというものがあるのはご存知だと思います。
Lambdaってこういうとこに使いたいよね、というサンプルコードが集まったものです。

今回利用しているBlueprintは、
”slack-echo-command-python”という名称のものになります。
選択をするとコードがすでに書き込まれた状態で表示されるので、
あわせて、API Gatewayと、SlackのSlash Commandsをちょっと設定すれば、
Slash Commandsが簡単に利用できるようになります。

api-slack-slack-Blueprint
今回はこのBlueprintを使用して進めました。

日本語が表示されない

普通に英語でテストするとなんの問題もなく表示されます。

api-slack-en-ok


api-slack-en-ok-return


日本語でテストをすると、文字化けをおこしてしまいます。

api-slack-jp-ng


api-slack-jp-ng-return

API Gatewayのログをたどる

API Gatewayのログをたどって見ると、
どうも、API GatewayからLambdaに渡すところで、文字化けの原因があるように見えました。

URLエンコードをマルチバイト文字へデコードする


結論は、Slackから送られるデータは "x-www-form-urlencoded" 形式なので、
マルチバイト文字列を扱うには "$util.urlDecode()" でデコードする必要があります。

参考URL https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html

実際のAPI Gatewayの設定

統合リクエストを開いた中にある、 本文マッピングテンプレートに、

{ "body": $util.urlDecode($input.json("$")) }

と設定します。

api-slack-request-mapping


これで無事日本語が表示されました。

api-slack-jp-ok

slackへ日本語を返すとき

今回の件とは別ですが、SlackへLambdaからpythonで日本語を返す際は、json形式にする必要があります。
Blueprintのreturnの部分を

return { "text" : ("%s invoked %s in %s with the following text: %s" % (user, command, channel, command_text))}

とすることで、前のと併せて最終的にSlackから日本語入力を渡し、
Slackへ日本語で返すことができます。

まとめ

SlackのSlash commandsで日本語を扱ったblogは少なく、結構長いことハマり続けたので、公開することにしました。

ぜひ、サーバーレスでSlackをより使いやすくしましょう!