2013-08-28 10 views
10

Expressフレームワークの上にあるNode.jsにPHPアプリケーションを再構築しています。Express/Node.jsを使用してAmazon SNSポスト本体にアクセスするには

アプリケーションの一部は、Amazon SNS notificationが投稿されたコールバックURLです。 SNSからのPOSTボディが現在PHP(作品)で次のように読まれ

:エクスプレスで

$notification = json_decode(file_get_contents('php://input')); 

私は次のことを試してみました:

app.post('/notification/url', function(req, res) { 
    console.log(req.body); 
}); 

ただし、コンソールを見て投稿が行われたときに次のログのみが記録されます。

{} 

ion:Express/Node.jsを使用してAmazon SNSの投稿本体にアクセスするにはどうすればいいですか

+0

コンテキストとして:この(合理的で素朴な)アプローチが失敗する理由は、SNS HTTPセットです。 "Content-Type:text/plain; charset = UTF-8" 参照:http://docs.aws.amazon.com/sns/latest/dg/SendMessageToHttp.html (SNSではJSONが実際にはうまくいきません) – Jason

答えて

22

別のアプローチは、のContent-Typeヘッダを修正することであろう。ここで

は、これを行うためのミドルウェア・コードです:

exports.overrideContentType = function(){ 
    return function(req, res, next) { 
    if (req.headers['x-amz-sns-message-type']) { 
     req.headers['content-type'] = 'application/json;charset=UTF-8'; 
    } 
    next(); 
    }; 
} 

これは、ファイルがutil.jsでルートプロジェクトディレクトリにあると呼ばれている前提としています

あなたの中
util = require('./util'); 

アプリ。JSを含むによって呼び出さ:app.jsファイル内

app.use(express.bodyParser()); 

app.use(util.overrideContentType()); 

。これはbodyParser()が適切に体...

控えめを解析することができます、あなたはその後、通常req.bodyアクセスすることができます。

+2

特に、同じアプリを使用してSNSからの通知と購読確認を処理したい場合は、これは素晴らしい答えです。 – supaseca

+0

http://docs.aws.amazon.com/sns/latest/dg/SendMessageToHttp.html#SendMessageToHttp.prepare AWSがContent-Typeとして 'text/plain'を使用する理由はありますか?これを扱うのは本当の頭痛でした。幸い、そこに解決策がありました – lasec0203

+0

[このトピック](https://forums.aws.amazon.com/thread.jspa?threadID=69413)を見て、あなた自身で結論を出してください。日付に注意してください。問題を回避するための代替案を見つけるのではなく、AWSがそれを修正する方が良いでしょう。 – Talma

3

AWS Node.js SDKをご覧ください。すべてのAWSサービスエンドポイントにアクセスできます。

var sns = new AWS.SNS(); 

    // subscribe 
    sns.subscribe({topic: "topic", Protocol: "https"}, function (err, data) { 
     if (err) { 
     console.log(err); // an error occurred 
     } else { 
     console.log(data); // successful response - the body should be in the data 
    } 
    }); 


    // publish example 
    sns.publish({topic: "topic", message: "my message"}, function (err, data) { 
     if (err) { 
     console.log(err); // an error occurred 
     } else { 
     console.log(data); // successful response - the body should be in the data 
    } 
    }); 

EDIT:問題は、標準のボディパーサーは、SNS、コンテンツタイプとして送信するものであるプレーン/テキストを処理していないということです。生の体を抽出するコードです。あなたの体のパーサ前にそれを置きます:あなたはその後、使用することができます

app.use(function(req, res, next) { 
    var d= ''; 
    req.setEncoding('utf8'); 
    req.on('d', function(chunk) { 
     d+= chunk; 
    }); 
    req.on('end', function() { 
     req.rawBody = d; 
     next(); 
    }); 
}); 

JSON.stringify(req.rawBody)); 

あなたのルート内のJavaScriptオブジェクトを作成し、適切なSNSポストに動作します。

また、text/plainを処理するように本体パーザーを変更することもできますが、ミドルウェアを変更することはできません。上記のコードを使用してください。

+0

私はこれが以前の段階かもしれないと思います。私のアプリケーションはすでに購読されています。 SNSはコンソールに表示されているように投稿しますが、投稿の本文にはアクセスできません。 – timstermatic

+1

ああ、それは、申し訳ありませんでした。私は今あなたがしていることを理解しています。私はテキストがJSON形式であっても、SNSがコンテンツをテキスト/プレーンとして送信すると信じています。どのようにあなたのボディパーサーをセットアップしましたか?標準高速パーサーは、アプリケーション/ json、アプリケーション/ x-www-form-encodedおよびmultipart/form-dataのみを処理します。上記のコードをあなたのボディパーサの前に追加しました。それはあなたがSNSからデータを取得していることを確認するためにテストすることができますあなたの要求から生身ものを与えるでしょう。これを記録し、あなた自身のボディパーサーを書く必要があるかもしれません。 – AlexGad

+0

私はこれを動作させることができませんでした。しかし、req.onとチャンクで正しい方向に私を指摘してくれましたので、入力に感謝します。私は受け入れられた答えとして私の解決策を入れました。 – timstermatic

5

これは、このコメントAlexGadのanswer.Particularlyに基づいています。

標準特急パーサが唯一のアプリケーション/ JSON、アプリケーション/ X-WWW-形式でエンコードおよびマルチパート/フォームデータを処理しますが。上記のコードをあなたのボディパーサの前に追加しました。

app.post('/notification/url', function(req, res) { 
    var bodyarr = [] 
    req.on('data', function(chunk){ 
     bodyarr.push(chunk); 
    }) 
    req.on('end', function(){ 
     console.log(bodyarr.join('')) 
    }) 
}) 
+0

技術的に正しいとすると、投票率の高い投稿は、指定された問題の「よりクリーンな」ソリューションです。よくテストされたフレームワークが仕事をしてくれるようにしてください。 – andreas

関連する問題