メンチカツには醤油でしょ!!

AWS/Java/Node.js/Spreadsheets/Docker/Jenkins/コミュニティ・勉強会レポを主とした技術系ブログ

AWS LambdaでCannot find module (Windowsからgulp-zipでupload)

そもそものよくある問題は次の参考サイトへ

qiita.com

lealog.hateblo.jp

Windowsでのgulp-zipが問題?

Windowsでgulp-zipをした際に、Cannot find moduleが出ます。
シンプルにモジュール1つで試してみましたが、ダメでした。

github.com

コンソールからテスト

{
  "errorMessage": "Cannot find module 'moment'",
  "errorType": "Error",
  "stackTrace": [
    "Function.Module._load (module.js:417:25)",
    "Module.require (module.js:497:17)",
    "require (internal/module.js:20:19)",
    "Object. (/var/task/index.js:2:16)",
    "Module._compile (module.js:570:32)",
    "Object.Module._extensions..js (module.js:579:10)",
    "Module.load (module.js:487:32)",
    "tryModuleLoad (module.js:446:12)",
    "Function.Module._load (module.js:438:3)"
  ]
}

テスト実行時のCloudWatchのログは

Unable to import module 'index': Error
at Function.Module._load (module.js:417:25)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)
at Object. (/var/task/index.js:2:16)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)

indexなのかrequireのmoduleなのか。

だいたいがhandler名の問題だが…

// hello.js
exports.world = (event, context, callback) => {
  //
}

だとhello.worldで呼ぶべき、ともありますが、今回そんな感じではなさそう。
上記にも引用した AWSのLambdaで、zipにしたコードを動かす時にハマったこと - console.lealog(); に従って、WindowsのGit Bashで chmod +x index.js してみたが、うまくいかない。

Macだとうまくいくんだけど…う〜ん。。

ん、もしや…!?

WindowsだとダメでMacだとうまくいく

Windowsでnpm run make

zipアップ⇒だめ。
S3アップ⇒だめ。

Macでnpm run make

zipアップ⇒とおる。

 

gulp-zip ぁゃしぃ。。。

 

stackoverflow.com

.pipe(zip('simple-lambda.zip', { compress: false })) を試す。
⇒変わらずエラー

7-Zip(圧縮・解凍ソフト 7-Zip)で圧縮
⇒成功

ますます gulp-zip ぁゃしぃ。。。

これで解決

stackoverflow.com

gulp
    .src(['src/**'], { nodir: true, dot: true })
    .pipe(zip('simple-lambda.zip'))
    .pipe(gulp.dest('build/'));

nodirとdotの指定が必要でした。

HTTP Request Headerが正しく(?)送信されなかった問題

先頭の方は当初の記事で、訂正は後半に書きました。

そもそもリクエストヘッダーは大文字小文字を気にしないと、RFC 2616に書いてありますので、ロジック側で両方取れるように工夫すべきでした。

正しく送信されないのは小文字になってしまうから (訂正前)

X-My-Apps-Tokenx-my-apps-tokenになり、
API Gatewayのカスタムオーソライザー設定でのチェックは通過するが、
Lambdaのカスタムオーソライザーで下記のようなコードでトークンを取得しようとした際にうまく取得できません。

const myAppsToken = event.headers['X-My-Apps-Token'];

なお、API Gatewayのカスタムオーソライザーの設定では、
Lambda イベントペイロードにリクエストを設定していました。

アプリ版のPostmanを使用すると…

環境にもよると思います。

Windows + Chrome Postman : NG
Mac + Chrome Postman : ?
Windows + Postman Apps : OK
Mac + Postman Apps : OK

Chrome AppsのPostmanは既に非推奨なので、アップデートしましょう。 

Postmanだけでなくクライアントの仕様に依存

WindowsのGit Bashcurlしても同じ問題が発生しました。
あとで確認したら、Macのターミナルでも小文字で送信されてきました。。

デバッグ大事

Lambdaの先頭でconsole.log(event);してCloudWatchを見ましょう。

■ ここからが訂正版です ■

そもそも今回の原因が、API GatewayのカスタムオーソライザーからLambdaを呼び出す流れだったのですが、Lambdaの中で、

const myAppsToken = event.headers['X-My-Apps-Token'];

と書いていて取れないのが原因でした。大文字小文字を気にしないので

const myAppsToken = event.headers['x-my-apps-token'];

でも取れるべきです。
ここの記述をどうするのかベストなのかは、色々ありそうですが、
設計で小文字に寄せておけば丸められても問題なさそうです。

そもそも、カスタムオーソライザーの設定で、Lambdaイベントペイロードを、
トークンではなくリクエスで設定していたため、このような実装をしなければなりませんでしたが、トークン以外に拾うものがないため設定を戻しました。

リクエストではなくトークで設定した場合のLambdaの実装は

const token = event.authorizationToken;

となります。

当初はRequest Bodyの内容まで取ってトークンとbodyの内容の整合まで検証することを期待していたのでこういう設定にしていましたが、結局Request Bodyは取れないことが判ったので、むしろLambdaイベントペイロードにリクエストを設定するケースって何だろう…とも思います。

参考

stackoverflow.com

#devsumi 2018参加レポ (Developers Summit 2018) 最終日 (2/16)

デブサミ2日目 最終日!

今年も2日行けて良かった。活力注入。

【全員参加型】Botで専属トレーナー・栄養士を雇う世界が来ています。先進の擬人化技術を今日、体験しよう。
中嶋 一樹 [LINE]

LINE BotGoogle Homeの双方のインタフェースを利用したデモ。
デモの内容は、食べたものの栄養管理とワークアウト(筋トレ)の実績管理。

Node.jsベースのbot-expressというフレームワークが、インタフェースのリクエスト/レスポンスの仕様の差を埋める。(中嶋さん作)

Skillを作成、paramとactionに集中できる。
paramとは、たとえば予約であれば人数と時間が必須になるような、それら情報のこと。

自然言語理解(NLU; Natural Language Understanding)から、翻訳、Flow(文脈; 会話のステート管理)、Webhookも出せる。

www.npmjs.com

エンタープライズアジャイル
川口 恭伸 [楽天]

エンタープライズの中でどうアジャイルするか。

決定が早くないと負ける。
上から下までエンジニアな組織だと決定が早い。(ex. MS)

文化とプロセス(デリバリー含)を顧客価値に最適化した、顧客価値駆動開発。

アンケートにエモいとフィードバックする人が居るそうな。
でもエモくていいと思うし、エモくないと聞く意味が半減すると思ってるのは自分だけでしょうか。

1日目2日目のセッションを通して、今年はVUIが普及する?

今年のトレンドはVUIですね。
多くのデモがVUIであり、そのどれもがスムーズに作動していました。
また、VUIとBotの連携も元々の親和性から、王道になっていくと感じました。

ちょっと前まではPepperに話しかけるのが恥ずかしかったり、筒に話しかけるのが恥ずかしかったりしましたが、ちょうどその転換点に居合わせたような感じがありました。

(ちなみに去年はKubernetesだなと感じていました)

展示(Twilio) をすぐ試してみる

先行してポストしましたが、今回はいくつかのセッションをパスして、展示されていたTwilioを実際に実装してみました。

デブサミ実施中に実装するメリットとして、ブースで実際にQAして、席に戻って実装して、またQAにし戻れる、という点があると感じます。
(流石にブースでPCを広げてしまうと、展示ではなくハンズオンになってしまい、展示員さんをロックしてしまうので、それは遠慮しました)

実装上の質問などなど、その場で聞けるのは良いですね。今回デブサミをこのように使ったのは初めてだったのですが、調べながらやるより全然効率が違いますね!

(自分で自分の文章を引用w)
実装上の質問・仕様の質問もできたので、進みが良かったです。

ryoichi0102.hatenablog.com

日展示されているサービス郡を連携させて、何か作るってのも面白いかも、とデブサミが終わってから、新たな使い方かなと思いました。

ex. Amazon EchoからRedmineにチケット登録したりTwilioで電話をかけたりSendGridでメールを送ったり。(組み合わせに無理やり感が…)

その後 Hackers Barへ

内容がデブサミから離れていきますが、mohikanで話題のHackers Barへ行ってきました。店員さんがハッカーで、ライブコーディングしてくれるという稀有なバー。

意気揚々と1番乗りだったのですが、ライブコーディングは20:00~とのことで。
(最近18:00~に営業時間を拡張したものの、それは単に営業時間拡張という)
次回は20:00頃に伺おう。

それでもハーヴェストムーンのビールがボトルで置いてあったり、ちゃんと(?)スティンガーがあったり、フルHDモニターが3枚ドーンで、Macが繋がっていたりするわけです。

普通のバーなら世間話、近所の話とかが話題ですが、ここは主に技術の話で、ライブコーディングをしていない時は、みんなでググりながら会話して盛り上がるという体験ができます。
(この日はデブサミとかTwilioとかSpreadsheetsの話をしたのですが、なんと「前にTwilio使ってサービスやってました」なんて話も!)

f:id:ryoichi0102:20180220123212j:plain

hackers.bar

そして、Uber使って懇親会へ~。
(懇親会でみんなにTwilioで電話をかけてデモw)

テックな1日でした。