2013-08-28 61 views
10

我正在重建Node.js中的PHP應用程序,並在Express框架之上。如何使用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'); 

app。JS通過和調用包括:

app.use(util.overrideContentType()); 

app.use(express.bodyParser()); 

app.js文件。這使得bodyParser()來解析人體正常...

較少干擾,然後你可以訪問req.body正常。

+2

這是一個很好的答案,特別是如果您想使用同一個應用來處理來自SNS的通知和訂閱確認。 – supaseca

+0

http://docs.aws.amazon.com/sns/latest/dg/SendMessageToHttp.html#SendMessageToHttp.prepare AWS使用'text/plain'作爲Content-Type是否有原因?處理這件事真是令人頭疼。很高興在那裏有一個解決方案 – lasec0203

+0

看看[這個主題](https://forums.aws.amazon.com/thread.jspa?threadID=69413)並得出你自己的結論。注意日期。與其試圖尋找替代方法來解決問題,不如解決它。 – 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 
    } 
    }); 

編輯:問題是標準身材分析器不處理純/文這就是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運營後適當。

您也可以修改body parser來處理text/plain,但修改中間件不是一個好主意。只需使用上面的代碼。

+0

我認爲這可能是更早的階段。我的申請已經訂閱。 SNS會發布到它,因爲我可以在控制檯中看到它,但我無法訪問該帖子的正文。 – timstermatic

+1

啊,明白了,對不起。我現在明白你在做什麼。我相信即使文本是JSON格式,SNS也會以text/plain的形式發送內容。你如何設置你的身體解析器?標準表達式解析器只能處理application/json,application/x-www-form-encoded和multipart/form-data。我在上面添加了一些代碼,放在你的body parser之前。它會給你一個你的請求中的rawbody,你可以測試,以確保你從SNS獲取數據。記錄下來,然後你可能必須編寫你自己的身體分析器。 – AlexGad

+0

我無法得到這個工作。然而,它確實指出了我對req.on和chunking的正確方向,所以感謝您的意見。我已經把我的解決方案作爲接受的答案。 – timstermatic

5

這是基於AlexGad的answer.Particularly此評論:

標準快遞解析器將只處理應用程序/ JSON,應用程序/ x-WWW的形式編碼和多/表單數據。我在上面添加了一些代碼,放在你的body parser之前。

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

相關問題