前試したときはダメだったのですが azure-function-express というモジュールが先日 v2.0.0 にアップデートしてたので試してみました。環境は以下のような感じです。
- Azure Functions Core Tools 2.0.1-beta.38
- node.js v8.11.4
ただ、前と同じでノーレスポンスになってしまいダメだったのでコードを読んでみたところ原因がわかったので、それを踏まえた内容を以下に書きます。
package.json の中はこんな感じです。
{ "name": "clova-with-azure-functions-v2", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "@line/clova-cek-sdk-nodejs": "^1.1.0", "azure-function-express": "^2.0.0", "express": "^4.16.3" } }
この形に持っていくまでの手順は以下のような流れです。
mkdir my-clova-sample cd my-clova-sample func init # 選択肢が出るので node を選択 func new # 選択肢が出るので HttpTrigger を選択して clova という名前で作成 npm init -y npm i @line/clova-cek-sdk-nodejs npm i azure-function-express npm i express
clova フォルダにある function.json で HTTP で受け入れるリクエストが定義されているのですが、デフォルトだと GET, POST なので今回は GET が不要なので削除しましょう。以下のような感じにします。
{ "disabled": false, "bindings": [ { "authLevel": "function", "type": "httpTrigger", "direction": "in", "name": "req", "methods": [ "post" // ここね ] }, { "type": "http", "direction": "out", "name": "res" } ] }
あとは、azure-function-express と clova-cek-sdk-nodejs のサイトを参考にしてさくっと書くだけです。ポイントは azure-function-express で渡ってくる req.body が string じゃなくて object に既に変換されている点です。生のデータはどうやってとれるのかというと req.rawBody です。clova-cek-sdk-nodejs のコードを見てると body には string とかみたいな生の値が入ってくるのを期待してるみたいなので、そこを調整してあげる必要があります。
なので、このような感じになります。
const createHandler = require("azure-function-express").createHandler; const express = require("express"); const clova = require('@line/clova-cek-sdk-nodejs'); const bodyParser = require('body-parser'); const clovaSkillHandler = clova.Client .configureSkill() .onLaunchRequest(responseHelper => { responseHelper.setSimpleSpeech({ lang: 'ja', type: 'PlainText', value: 'おはよう', }); }) .onIntentRequest(async responseHelper => { const intent = responseHelper.getIntentName(); const sessionId = responseHelper.getSessionId(); switch (intent) { case 'Clova.YesIntent': // Build speechObject directly for response responseHelper.setSimpleSpeech({ lang: 'ja', type: 'PlainText', value: 'はいはい', }); break; case 'Clova.NoIntent': // Or build speechObject with SpeechBuilder for response responseHelper.setSimpleSpeech( clova.SpeechBuilder.createSpeechText('いえいえ') ); break; case 'ThrowDiceIntent': responseHelper.setSimpleSpeech( clova.SpeechBuilder.createSpeechText('サイコロ!') ); break; } }) .onSessionEndedRequest(responseHelper => { const sessionId = responseHelper.getSessionId(); // Do something on session end }) .handle(); const clovaMiddleware = clova.Middleware({ applicationId: "<自分の Extension ID>" }); const app = express(); app.post('/api/clova', (req, res, next) => { req.body = req.rawBody; next(); }, // Azure Functions がしてくれるパースは今回はいらないので rawBody で置き換え clovaMiddleware, clovaSkillHandler); module.exports = createHandler(app);
これで Azure Functions にデプロイすると動きます!ローカルで動かす場合は func host start
して ngrok
で出来ます。