Q&A

Webhookイベントオブジェクトの送信時にタイムアウトが発生しました

前提・実現したいこと

lineとkintneの連携をawsを使用して実施したいです。

発生している問題・エラーメッセージ

WebhookのURLの設定後、アップデートを押下すると、「検証」ではなく「確認」と表示されます。 また、「確認」を押下すると 「Webhookイベントオブジェクトの送信時にタイムアウトが発生しました」と表示されます。

該当のソースコード

//exports.handler = async (event) => { // TODO implement // const response = { // statusCode: 200, // body: JSON.stringify('Hello from Lambda!'), // }; // return response; //}; 'use strict';

const request = require('sync-request'); const Protocol = "https://";

// LINE 送信設定 const LineHost = "api.line.me"; const LinePath = "/v2/bot/message/reply"; const LineToken =

// kintone 送信設定 const Domain = "cybozu.com"; const Subdomain = "xxxx"; ※ドメイン名はマスクしました。 const Path = "/k/v1/record.json"; const AppId = "93"; const Token =

exports.handler = async (event) => {

// LINE から受信したデータをデバッグ表示
console.log('EVENT.BODY:', JSON.stringify(event.body, null, 2));

console.log('Function Start.');

// LINE から受信したデータ
let eventData = JSON.parse(event.body);
let type  = eventData.events[0].type;
let mode  = eventData.events[0].mode;
let token = eventData.events[0].replyToken;
let user  = eventData.events[0].source.userId;
let text  = "";
let response = {};

// LINE メッセージの返信を送信
if(type == "message"){
    text  = eventData.events[0].message.text;
    response = {
        replyToken: token,
        to:[user],
        messages:[
            {
                "type":"text",
                "text":"Re:" + text
            }
        ]
    };
    let url = Protocol + LineHost + LinePath;
    let res = funcPostLine(request, url, LineToken, response);
    console.log(res);
}

// LINE から受信したデータを kintone アプリに追加 
require('date-utils');
let dt = new Date();
let url = Protocol + Subdomain + '.' + Domain + Path;
let data = {
    "lineDateTime": { "value" : dt.toFormat("YYYY-MM-DDTHH24:MI:SSZ") },
    "lineUserId":   { "value" : user },
    "lineType":     { "value" : type },
    "lineMode":     { "value" : mode },
    "lineMessage":  { "value" : text },
};
let res = funcPostKintoneRecode(request, url, AppId, Token, data);
console.log(res);

console.log('Function end.');

// line の Webhook にレスポンスを返す
return {
    'statusCode': 200,
    'body': JSON.stringify(response)
};

};

// LINE にメッセージを送信 function funcPostLine(request, url, token, json) { let response = request('POST',url,{ headers: { "Content-type": "application/json", "Authorization": " Bearer " + "{" + token + "}" }, json: json, }); return response; }

// kintone アプリのデータ追加 function funcPostKintoneRecode(request, url, appId, token, json) { let response = request('POST',url,{ headers: { 'Content-type': 'application/json', 'X-Cybozu-API-Token': token }, json: { app : appId, record: json }, }); return JSON.parse(response.getBody('utf8')); }

試したこと

「確認」押下時にデバックを実施したが、コンソールに表示されているのは、 設定した上記ソースではなかったが、下記の表示がありました。

SET url https://n85oc39chi.execute-api.us-east-2.amazonaws.com/default/kenken Object instrument.js:109 SET active true undefined instrument.js:109 SET url https://n85oc39chi.execute-api.us-east-2.amazonaws.com/default/kenken Object instrument.js:109 SET url https://n85oc39chi.execute-api.us-east-2.amazonaws.com/default/kenken {skipWebhookUrlValidation: true}

補足情報(FW/ツールのバージョンなど)

  • 0
  • 7
  • 2141
  • twitter facebook

モジュールの読み込みエラーですね。 普段あまりNode.js触らないので分かりませんでしたが、sync-requestは非推奨になっているのでバージョンによってはLambdaでサポートしてないモジュールかもしれません。

https://designetwork.daichi703n.com/entry/2017/02/21/node-then-request

代替案としてはNode.jsの標準モジュールであるhttpsモジュールで実装し直したり、requestモジュールを使うのがいいかと思います。(どっちを使うのかは申し訳ないですが、ご自分で実装して確認してください)

https://mjeld.com/nodejs-lambda-httpclient-request/

  • 2

Koki様 お世話になります。 何度もすみません。

Lambdaの関数でtestを実行したところ、下記の実行結果でした。 どこ設定が間違っているのでしょうか?

2021-12-27T10:58:22.179+09:00

コピー 2021-12-27T01:58:22.179Z undefined ERROR Uncaught Exception { "errorType": "Runtime.ImportModuleError", "errorMessage": "Error: Cannot find module 'sync-request'\nRequire stack:\n- /var/task/index.js\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js", "stack": [ "Runtime.ImportModuleError: Error: Cannot find module 'sync-request'", "Require stack:", "- /var/task/index.js", "- /var/runtime/UserFunction.js", "- /var/runtime/index.js", " at _loadUserApp (/var/runtime/UserFunction.js:202:13)", " at Object.module.exports.load (/var/runtime/UserFunction.js:242:17)", " at Object.<anonymous> (/var/runtime/index.js:43:30)", " at Module._compile (internal/modules/cjs/loader.js:1085:14)", " at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)", " at Module.load (internal/modules/cjs/loader.js:950:32)", " at Function.Module._load (internal/modules/cjs/loader.js:790:12)", " at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)", " at internal/main/run_main_module.js:17:47" ] }

2021-12-27T01:58:22.179Z undefined ERROR Uncaught Exception {"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module 'sync-request'\nRequire stack:\n- /var/task/index.js\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js","stack":["Runtime.ImportModuleError: Error: Cannot find module 'sync-request'","Require stack:","- /var/task/index.js","- /var/runtime/UserFunction.js","- /var/runtime/index.js"," at _loadUserApp (/var/runtime/UserFunction.js:202:13)"," at Object.module.exports.load (/var/runtime/UserFunction.js:242:17)"," at Object.<anonymous> (/var/runtime/index.js:43:30)"," at Module._compile (internal/modules/cjs/loader.js:1085:14)"," at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)"," at Module.load (internal/modules/cjs/loader.js:950:32)"," at Function.Module._load (internal/modules/cjs/loader.js:790:12)"," at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)"," at internal/main/run_main_module.js:17:47"]}

  • 0

Lambdaのデプロイボタンを押しましたか?デプロイボタンを押さないと変更内容が変更されません。 あとは友だち追加でKintoneに追加されないのは今回とはまた別のエラーの可能性もあるのでエラーを確認してほしいです。

  • 0

Koki様 ご回答ありがとうございます。 質問の方法がいたらず、申し訳ありません。

ご連携いただきました。ソースコードで修正いたしましたが、検証のエラーは消えず、 LINEで友達追加しても、kintoneには連携されません。 ソースコード以外にも問題があるんでしょうか?

お手数をおかけして大変申し訳ありません。

  • 0

ありがとうございます。

ソースコードタグを囲むがよくわからない

markdown記法ではソースコードを見やすくするための表記方法があります。

以下の記事をよく読んでほしいです。 https://zenn.dev/kmiura55/articles/better-question-line-dc#markdown%E8%A8%98%E6%B3%95%E3%82%92%E3%81%A1%E3%82%83%E3%82%93%E3%81%A8%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%AA%E3%81%84

https://qiita.com/yukataoka/items/9356171cd350c465b745

参考にしたサイトがあるならそれも質問に追記してほしいです。

ソースコードや頂いた参考記事を読みましたが、おそらく記事の内容が古くてWebhookで送信されるJsonが古い形式に対応しものになっています。古い形式だと接続確認をしたときに eventData.eventsの中身が空になるのでおそらくこのコードが想定している挙動にならないと思います。

そのため、接続確認でKintoneにデータ登録するのは諦めたほうがいいかと思います。

接続確認でエラーを出さないようにするには以下のコードに修正すればエラーが無くなると思います。 コメントの `接続確認の箇所が修正箇所です。

'use strict';

const request = require('sync-request');
const Protocol = "https://";

// LINE 送信設定
const LineHost = "api.line.me";
const LinePath = "/v2/bot/message/reply";
const LineToken = "LINEのチャンネルアクセストークン";

// kintone 送信設定
const Domain = "cybozu.com";
const Subdomain = "サブドメインを設定";
const Path = "/k/v1/record.json";
const AppId = "アプリIDを設定";
const Token = "アプリのトークンを設定";

exports.handler = async (event) => {

    // LINE から受信したデータをデバッグ表示
    console.log('EVENT.BODY:', JSON.stringify(event.body, null, 2));

    console.log('Function Start.');

    // LINE から受信したデータ
    let eventData = JSON.parse(event.body);
    // 接続確認
    if (eventData.events.length == 0) {
        return {
            statusCode: 200,
            body: 'OK'
        }
    }

    // Webhookデータで必要な値を取得
    let type = eventData.events[0].type;
    let mode = eventData.events[0].mode;
    let token = eventData.events[0].replyToken;
    let user = eventData.events[0].source.userId;
    let text = "";
    let response = {};

    // LINE メッセージの返信を送信
    if (type == "message") {
        text = eventData.events[0].message.text;
        response = {
            replyToken: token,
            to: [user],
            messages: [{
                "type": "text",
                "text": "Re:" + text
            }]
        };
        let url = Protocol + LineHost + LinePath;
        let res = funcPostLine(request, url, LineToken, response);
        console.log(res);
    }

    // LINE から受信したデータを kintone アプリに追加 
    require('date-utils');
    let dt = new Date();
    let url = Protocol + Subdomain + '.' + Domain + Path;
    let data = {
        "lineDateTime": {
            "value": dt.toFormat("YYYY-MM-DDTHH24:MI:SSZ")
        },
        "lineUserId": {
            "value": user
        },
        "lineType": {
            "value": type
        },
        "lineMode": {
            "value": mode
        },
        "lineMessage": {
            "value": text
        },
    };
    let res = funcPostKintoneRecode(request, url, AppId, Token, data);
    console.log(res);

    console.log('Function end.');

    // line の Webhook にレスポンスを返す
    return {
        'statusCode': 200,
        'body': JSON.stringify(response)
    };
};

// LINE にメッセージを送信
function funcPostLine(request, url, token, json) {
    let response = request('POST', url, {
        headers: {
            "Content-type": "application/json",
            "Authorization": " Bearer " + "{" + token + "}"
        },
        json: json,
    });
    return response;
}

// kintone アプリのデータ追加
function funcPostKintoneRecode(request, url, appId, token, json) {
    let response = request('POST', url, {
        headers: {
            'Content-type': 'application/json',
            'X-Cybozu-API-Token': token
        },
        json: {
            app: appId,
            record: json
        },
    });
    return JSON.parse(response.getBody('utf8'));
}
  • 1

Koki様 ご返信ありがとうございます。アクセストークンは削除し、変更しました。 ・ソースコードタグを囲むがよくわからないですが、下記サイトの手順で作業をすすめソースコードも下記サイトの内容をコピペしてurlとアクセストークンを変更しています。 https://qiita.com/yukataoka/items/9356171cd350c465b745 ・ソースコードはLambdaのindex.jsに入れています。 ・botのプログラムの実行環境  上記のサイトの手順で作成したため、botのプログラムの実行環境がどこになるのか理解できていません。  AWSはLambdaのサービスを使用しました。

よくわかっておらず、大変申し訳ありません。 どうぞ宜しくお願いします。

  • 0

いくつか修正してください。 ・kintoneとLINEのアクセストークンは外部に公開してはいけない値なので消してください。あと、消したら両者のアクセストークンが悪用されないように変更することをおすすめします ・ソースコードが見づらいので、ソースコード全体をソースコードタグで囲むようにしてください ・提示したソースコードはLambdaですか?質問に書いている内容だけだと何で実行しているプログラムなのかがわからないので、botのプログラムの実行環境を追加してください(使用しているAWSのサービスも合わせて書いてください)

  • 1
本当によろしいですか? question.vm