2017-06-15 77 views
1

我試圖管,用於由遠程服務器處理,大意如下的請求POST請求:節點快遞/要求:管道與身體解析

var destination = request(url); 
req.pipe(destination).pipe(res); 

這只是正常的GET請求。但是對於POST請求我很掙扎。我認爲需要注意的一點是,對於POST請求,我在我的POST路由處理程序之前使用了一個body解析器,以便從POST請求中提取正文...這只是一個基本的文本正文解析器,因爲正文包含純文本:

var postRouteHandler = someFunction; 
var bodyParser = require('body-parser'); 
var textParser = bodyParser.text({ 
    limit: '50kb' 
}); 
app.use('/postRoute', [textParser, postRouteHandler]); 

this issuethis issue在我看來,關於POST要求做任何處理,你管的時候,才導致出現問題。事實上,當我刪除解析器時,管道似乎工作正常。

問題是我需要首先檢查身體,進行一些初始處理,然後確定是否將請求傳送到遠程服務器。所以我需要來解析管道之前的身體。

有沒有辦法解決這個問題?

回答

6

問題在於,對於流(如req),一旦閱讀完它就無法重置它。

由於body-parser已經讀取了流,管道將無法工作,因爲它會嘗試再次讀取流(此時已耗盡)。

一種解決方法是採取由body-parser閱讀文本,並且爲了創建一個最小req「克隆」爲request能夠沿着傳遞請求:

var intoStream = require('into-stream'); 
var bodyParser = require('body-parser'); 
var textParser = bodyParser.text({ limit: '50kb' }); 

var postRouteHandler = function(req, res) { 
    let text = req.body; 
    if (! shouldPipe(text)) { 
    return res.sendStatus(400); // or whatever 
    } 

    // Here's where the magic happens: create a new stream from `text`, 
    // and copy the properties from `req` that `request` needs to pass 
    // along the request to the destination. 
    let stream  = intoStream(text); 
    stream.method = req.method; 
    stream.headers = req.headers; 

    // Pipe the newly created stream to request. 
    stream.pipe(request(url)).pipe(res); 
}; 
app.use('/postRoute', [textParser, postRouteHandler]); 
+0

向大師學習!天才!這不僅是一個很好的解決方案,也是對問題發生原因的一個清晰而簡潔的解釋。你確實是大師@robertklep! – drmrbrewer

+0

...只是一件事......它應該是'request.post(url)'而不是'request(url)'? – drmrbrewer

+0

我非常肯定'request'將使用'req.method/stream.method'來確定執行的請求類型,因此您不必明確說明它。 – robertklep

1

如果解析器導致問題,您應該創建自己的中間件。誠實地說,你可能想要以與解析器不同的方式解析身體。

鑑於您對項目其餘部分的工作知識有限,您可以創建中間件來掛鉤正文解析器中間件,併發送請求克隆。然而,這不是非常有效,但會起作用,並可能有助於指引您朝着正確的方向發展。

var postRouteHandler = someFunction; 
var bodyParser = require('body-parser'); 
var textParseMiddleware = function (req, res, next) { 

    var requestclone = _.clone(req); 
    var textParser = bodyParser.text({ 
    limit: '50kb' 
    }); 

    textParser(requestclone, res, function(){ 
    console.log('examine the body here', requestclone.body); 
    }); 


} 

app.use('/postRoute', [textParserMiddleWare, postRouteHandler]); 

我還沒有測試過上面的代碼。

0

需要發送一個巨大的大數據通過POST,我得到錯誤:套接字掛斷/代碼:'ECONNRESET'。 能夠通過增加對主體解析器的限制來解決它。

var bodyParser = require('body-parser'); app.use(bodyParser.urlencoded({extended: true})); app.use(bodyParser.json({limit:'50mb'}));