質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.35%

  • AWS(Amazon Web Services)

    2730questions

    Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

  • Node.js

    2529questions

    Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

  • API

    1920questions

    APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

  • JSON

    1556questions

    JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

  • Slack

    246questions

    Slackは、Tiny Speckという企業からリリースされたコミュニケーションツールです。GoogleDriveやGitHubなど、さまざまな外部サービスと連携することができます。

AWS LambdaのNode.jsとJSONについて

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,787

HiroakiKamei

score 6

はじめまして、Node.js初心者です。
前回に続き、GoogleHomeからSlackに投稿したいです。

 前提・実現したいこと

GoogleHome→Dialogflow→APIGateway→AWSLambda→Slack

参考にしたサイト様
Dialogflow入門
AWS API Gateway+LambdaでSlackにメッセージをPOSTする(前編)
Google Home と Lambda で「"あ"のつくポケモンなーんだ」

DialogflowのFulfillmentでAPIGatewayをあてており、
Lambdaでこのコードを入れたところエラーがでます。
Dialogflow側では問題なくJSONが送られている状態です。

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

{
  "errorMessage": "RequestId: f396756f-0a52-11e8-967f-79dda54dff68 Process exited before completing request"
}

 該当のソースコード

console.log('Loading function');

const https = require('https');
const url = require('url');
const slack_url = process.env.SLACK_WEBHOOK_URL;
const slack_req_opts = url.parse(slack_url);
slack_req_opts.method = 'POST';
slack_req_opts.headers = {'Content-Type': 'application/json'};

exports.handler = function(event, context, callback) {
  if (!event.text) {
    callback('called without event.text');
    return;
  }
  var req = https.request(slack_req_opts, function (res) {
    if (res.statusCode === 200) {
      callback(null, 'posted to slack');
    } else {
      callback('status code: ' + res.statusCode);
    }
    });

    req.on('error', function(e) {
      console.log('problem with request: ' + e.message);
      context.fail(e.message);
    });

    // メッセージの編集
    const parameters = JSON.parse(event.body).result.parameters;
    var message = parameters.date + parameters.building + parameters.request;
    var slack_text = message;

    req.write(JSON.stringify({text: slack_text}));

    req.end();
};

 試したこと

上記の部分を下記に変更すれば問題なく動くのですが、ただ単にLambdaのテストで設定したテキストがSlackに送られる状況です。

 // メッセージの編集
    const parameters = JSON.parse(event.body).result.parameters;
    var message = parameters.date + parameters.building + parameters.request;
    var slack_text = message;
 // メッセージの編集
    var message = (event.text);
    var slack_text = message;

 補足情報

エラーコードをググって見たところ、処理が途中で終了してしまうと発生してしまうようで、
CloudWatchからエラーを探ったところ、

SyntaxError: Unexpected token u in JSON at position 0
at Object.parse (native)
at exports.handler (/var/task/index.js:29:29)


とでています。調べると
Uncaught Syntaxerror: Unexpected token u

コールバックと引数が一致していない?のでしょうか
ここからハマってしまいわからない状況です。

ご回答ご教授願います、よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

SyntaxError: Unexpected token u in JSON at position 0
コールバックと引数が一致していない?のでしょうか

いいえ。JSON.parseしようとしたevent.bodyがundefinedだった可能性が高いです。例えば以下のコードで同様のエラーが得られます。

const data = {};
JSON.parse(data.foo);

JSON.parseは渡されたJSONの文字列の先頭が{なら「Objectかな…」[なら「Arrayかな…」、1なら「Numberかな…」、と解析できますが、undefinedだと「先頭uなの!?」となって、結局

SyntaxError: Unexpected token u in JSON at position 0

とエラーを出して止まります。

エラーを先まで見ると、どこで止まったかが書いてあります。
イメージ説明
スクリプトの29行目の29文字目でエラーになったようです。スクリプトの29行目を確認しましょう。

    // メッセージの編集
    const parameters = JSON.parse(event.body).result.parameters;


JSON.parseのところだと分かります。このことから、event.bodyが変で、JSONの文字列が渡らなかったのかな、と予想できます。なので、原因を調べるために、以下のように1行追加して、もう一度テストしてみてください。困ったときは、おかしい行の前でconsole.logすれば、たいていの問題は原因がわかります。

    // メッセージの編集
    console.log(event); // 追加
    const parameters = JSON.parse(event.body).result.parameters;

今回の場合、API Gatewayからのアクセス、つまり、HTTPのリクエストがトリガーとなります。このときのeventオブジェクトには、HTTPのヘッダの情報やアクセス元の情報が入っていて、Lambdaのコンソールからテストしたときのような、単純な構造にはなっていません。

Lambdaのコンソールには、API Gatewayからのeventオブジェクトっぽいものでテストするサンプルがありますので、それを使いましょう。

テストイベントの設定から、
イメージ説明

API Gateway AWS Proxyを選び、
イメージ説明

2行目のbodyにJSONを書いてテストしてください。
イメージ説明

ここが問題なければ、AWSLambda → Slackは問題ありません。
次はAPIGatewayのコンソールからAPIGateway → AWSLambdaをテストしましょう。

イメージ説明

リクエスト本文にJSONを書いてテストしてください。

ここが問題なければ、APIGateway → AWSLambdaも問題ありません。
次はDialogflow → APIGatewayを確認することになりますが、長くなったので回答はここまでとします。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/02/08 11:34 編集

    おはようございます、ご返信ありがとうございます。

    (1)Lambda側では
    SyntaxError: Unexpected token o in JSON at position 1
    とでています。APIGatewayでは(2)で仰られたように

    {
    "text": "Posted Slack",
    "body": {
    "result": {
    "parameters": {
    "request": "出社",
    "date": "2018-02-06",
    "building": "本社",
    "place": "東京",
    "time": "08:30:00"
    }
    }
    }

    を入れて実行しています...

    キャンセル

  • 2018/02/08 15:20

    console.log(event)
    は書いてありますか?
    Lambdaでエラーが検知できたということは、console.logで原因がわかるはずですので、console.log(event)して、event.bodyとしてどんなものが渡ってきたのかを確認してください。

    console.log(event)
    は完成するまで残しておいて、何かあったらすぐに確認できようにしておくといいです。

    別件ですが、そのテストデータだと、
    JSON.parse(event.body).result.parameters
    が取れません。
    {"text": ..., "body": {"result": ...}}
    ではなくて、
    {"result": ...}
    が正しいのではないでしょうか。逆に、そのテストデータが正しいなら、Lambdaの方を修正する必要がありますね。

    キャンセル

  • 2018/02/13 12:31

    おはようございます、コメントありがとうございます。
    返信が遅れてしまいましてすいません。

    console.log(event)で渡ってきたものは

    { result:
    { parameters:
    { request: '出社',
    date: '2018-02-06',
    building: '本社',
    place: '東京',
    time: '08:30:00' } } }

    で、(ご指摘があったのでテストデータを{"result": ...}に変更しました)

    その後に続くエラーが

    SyntaxError: Unexpected token u in JSON at position 0
    at Object.parse (native)
    at exports.handler (/var/task/index.js:30:29)

    となっています。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • AWS(Amazon Web Services)

    2730questions

    Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

  • Node.js

    2529questions

    Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

  • API

    1920questions

    APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

  • JSON

    1556questions

    JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

  • Slack

    246questions

    Slackは、Tiny Speckという企業からリリースされたコミュニケーションツールです。GoogleDriveやGitHubなど、さまざまな外部サービスと連携することができます。