2013-04-04 24 views
29

Tôi muốn bắt lỗi từ bodyParser() middleware khi tôi gửi một đối tượng json và nó không hợp lệ vì tôi muốn gửi phản hồi tùy chỉnh thay vì lỗi 400 chung.Catch body bodyParser lỗi

Đây là những gì tôi có và nó hoạt động:

app.use (express.bodyParser()); 
app.use (function (error, req, res, next){ 
    //Catch bodyParser error 
    if (error.message === "invalid json"){ 
     sendError (res, myCustomErrorMessage); 
    }else{ 
     next(); 
    } 
}); 

Nhưng điều này dường như với tôi một cách tiếp cận rất xấu xí vì tôi so sánh các thông báo lỗi mà có thể thay đổi trong các phiên bản rõ ràng trong tương lai. Có cách nào khác để bắt lỗi bodyParser() không?

EDIT:

Đây là lỗi khi cơ thể yêu cầu có json không hợp lệ:

{ 
    stack: 'Error: invalid json\n at Object.exports.error (<path>/node_modules/express/node_modules/connect/lib/utils.js:55:13)\n at IncomingMessage.<anonymous> (<path>/node_modules/express/node_modules/connect/lib/middleware/json.js:74:71)\n at IncomingMessage.EventEmitter.emit (events.js:92:17)\n at _stream_readable.js:872:14\n at process._tickDomainCallback (node.js:459:13)', 
    arguments: undefined, 
    type: undefined, 
    message: 'invalid json', 
    status: 400 
} 

chồng Khá in:

Error: invalid json 
    at Object.exports.error (<path>/node_modules/express/node_modules/connect/lib/utils.js:55:13) 
    at IncomingMessage.<anonymous> (<path>/node_modules/express/node_modules/connect/lib/middleware/json.js:74:71) 
    at IncomingMessage.EventEmitter.emit (events.js:92:17) 
    at _stream_readable.js:872:14 
    at process._tickDomainCallback (node.js:459:13) 

Trả lời

5

Ok, đã tìm thấy:

bodyParser() là một hàm tiện lợi cho json(), urlencoded() và multipart(). Tôi chỉ cần gọi đến json(), bắt lỗi và gọi tới urlencoded() và multipart().

bodyParser source

app.use (express.json()); 
app.use (function (error, req, res, next){ 
    //Catch json error 
    sendError (res, myCustomErrorMessage); 
}); 

app.use (express.urlencoded()); 
app.use (express.multipart()); 
+4

Đó không phải là giải pháp. Bạn không xem xét rằng trước khi mã này có thể là một phần mềm trung gian khác.Nếu bạn nắm bắt theo cách như vậy một số ngoại lệ nó có thể dẫn đến tình trạng không thể đoán trước. Ít nhất thì tốt hơn nên viết: 'app.use (hàm (lỗi, req, res, next) {/ * Nút Shutdown * /}; app.use (bodyParser.json()); app.use (hàm (lỗi, req, res, next) {/ * nếu err.status == 4 ** sau đó xử lý lỗi json => res.status (400) .send(), nút tắt khác * /}); ' – Dao

+4

NGUY HIỂM NGUY HIỂM, điều này bắt bất kỳ lỗi nào trong phần mềm trung gian ở trên, như @Dao đã nói. Không an toàn – light24bulbs

17

Tôi nghĩ rằng đặt cược tốt nhất của bạn là để kiểm tra SyntaxError:

app.use(function (error, req, res, next) { 
    if (error instanceof SyntaxError) { 
    sendError(res, myCustomErrorMessage); 
    } else { 
    next(); 
    } 
}); 
+0

này không hoạt động bởi vì nó không phải là một Lỗi Cú pháp. Xem cập nhật câu hỏi. –

+0

@GabrielLlamas Với phiên bản Express mới nhất (4.6.1) mô-đun 'bodyParser' không còn được tích hợp sẵn, nó đã được chuyển thành [module] riêng của nó (https://github.com/expressjs/body-parser) và điều đó thực sự ném một 'SyntaxError' cho JSON không đúng định dạng. – James

+2

Nếu phần thân yêu cầu quá lớn, tuy nhiên, bạn sẽ nhận được một Lỗi thay vì một Cú pháp Cú pháp. Ví dụ: '{[Lỗi: Yêu cầu tổ chức quá lớn] loại: 'entity.too.large', thông điệp: 'yêu cầu tổ chức quá lớn', statusCode: 413, status: 413, dự kiến: 322.350, độ dài: 322350, giới hạn: 102400} ' –

1

tôi thấy kiểm tra SyntaxError là không đủ, do đó tôi làm:

if (err instanceof SyntaxError && 
    err.status >= 400 && err.status < 500 && 
    err.message.indexOf('JSON')) { 
    // process filtered exception here 
} 
1
(bodyParser, req, res) => new Promise((resolve, reject) => { 
    try { 
     bodyParser(req, res, err => { 
      if (err instanceof Error) { 
       reject(err); 
      } else { 
       resolve(); 
      } 
     }); 
    } catch (e) { 
     reject(e); 
    } 
}) 

Bullet-proof. Nhận thức trong tương lai. WTFPL-Cấp phép. Và cũng hữu ích w/async/await.

+0

Làm cách nào để tôi có thể đặt chức năng này vào ứng dụng của tôi làm phần mềm trung gian? – PoolOfPeas

0

Từ câu trả lời của @alexander nhưng với một ví dụ về ussage

app.use((req, res, next) => { 
    bodyParser.json({ 
     verify: addRawBody, 
    })(req, res, (err) => { 
     if (err) { 
      console.log(err); 
      res.sendStatus(400); 
      return; 
     } 
     next(); 
    }); 
}); 

function addRawBody(req, res, buf, encoding) { 
    req.rawBody = buf.toString(); 
}