Làm cách nào để gửi một thông báo trạng thái http tùy chỉnh trong node / express?


89

Ứng dụng node.js của tôi được tạo mô hình giống như ứng dụng express /amples / mvc .

Trong hành động của bộ điều khiển, tôi muốn đưa ra trạng thái HTTP 400 bằng thông báo http tùy chỉnh. Theo mặc định, thông báo trạng thái http là "Yêu cầu không hợp lệ":

HTTP/1.1 400 Bad Request

Nhưng tôi muốn gửi

HTTP/1.1 400 Current password does not match

Tôi đã thử nhiều cách nhưng không có cách nào trong số đó đặt thông báo trạng thái http thành thông báo tùy chỉnh của tôi.

Chức năng bộ điều khiển giải pháp hiện tại của tôi trông giống như sau:

exports.check = function( req, res) {
  if( req.param( 'val')!=='testme') {
    res.writeHead( 400, 'Current password does not match', {'content-type' : 'text/plain'});
    res.end( 'Current value does not match');

    return;
  } 
  // ...
}

Mọi thứ hoạt động tốt nhưng ... có vẻ như không phải là cách thích hợp để làm điều đó.

Có cách nào tốt hơn để đặt thông báo trạng thái http bằng express không?


4
Chà, đây có vẻ là cách giải quyết duy nhất. Nhưng tôi sẽ không đưa ra lời khuyên như vậy, thông số HTTP 1.1 có mô tả lỗi được chuẩn hóa vì một số lý do chính đáng. Tôi nghĩ rằng việc gửi các mã trạng thái nổi tiếng kèm theo mô tả tùy chỉnh là một việc làm không tốt, nhưng điều đó tùy thuộc vào bạn.
schaermu

Hmmm - có lẽ đó là sự thật. Mặt khác, tôi cho rằng các trình duyệt chỉ kiểm tra mã trạng thái chứ không phải thông báo trạng thái http có thể đọc được của con người. Tôi nghĩ bạn nên sử dụng thông báo trạng thái http để vận chuyển một thông báo lỗi cụ thể (tức là không phải mặc định) nếu có. Thêm vào đó nó dễ dàng để lấy rằng việc sử dụng kịch bản phía khách hàng java (sử dụng jQuery bạn có thể làm "jqXHR.statusText" để có được những lỗi cho mục đích hiển thị)
lgersman

4
Đó không phải là về khả năng tương thích hoặc các vấn đề tiềm ẩn của trình duyệt, đó chỉ là thực tiễn xấu;) nếu bạn muốn thông báo lỗi hiển thị, hãy gửi nó dưới dạng nội dung, đó là mục đích đã định.
schaermu

6
Mô tả lỗi cụ thể không phải là một phần của thông số kỹ thuật. RCF-2616 nêu rõ cụ thể: "Các giá trị riêng lẻ của mã trạng thái số được xác định cho HTTP / 1.1 và một tập hợp ví dụ về Cụm từ lý do tương ứng, được trình bày bên dưới. Các cụm từ lý do được liệt kê ở đây chỉ là các khuyến nghị - chúng CÓ THỂ được thay thế bằng tương đương cục bộ mà không ảnh hưởng đến giao thức. "
Ted Bigham

Cụm từ lý do tùy chỉnh rất hay, nhưng (vì tin nhắn của bạn là "Mật khẩu hiện tại không khớp" ") có vẻ như bạn thực sự muốn mã 401 ở đây, trong trường hợp đó, bạn có thể không cần thay đổi thông báo.
Viết mã

Câu trả lời:


59

Bạn có thể kiểm tra tài liệures.send(400, 'Current password does not match') Look express 3.x này để biết chi tiết

CẬP NHẬT cho Expressjs 4.x

Sử dụng cách này (xem tài liệu 4.x express ):

res.status(400).send('Current password does not match');
// or
res.status(400);
res.send('Current password does not match');

41
Rất tiếc, điều này sẽ không đặt thông báo trạng thái http nhưng sẽ gửi 'Mật khẩu hiện tại không khớp' dưới dạng nội dung nội dung ...
lgersman

Điều này không đặt trạng thái HTTP, nhưng đưa ra cảnh báo vì chữ ký phương thức này không được dùng nữa.
nullability

1
Các res.status(400).send('Current password does not match');ví dụ làm việc cho tôi tham gia vào Express 4.
Tyler Collier

Hoạt động trongExpress ^4.16.2
Ajay

103

Không có câu trả lời hiện có nào đáp ứng được những gì OP yêu cầu ban đầu, đó là ghi đè Cụm từ lý do mặc định (văn bản xuất hiện ngay sau mã trạng thái) được gửi bởi Express.

Những gì bạn muốn là res.statusMessage. Đây không phải là một phần của Express, mà là một thuộc tính của đối tượng http.Response cơ bản trong Node.js 0.11+.

Bạn có thể sử dụng nó như thế này (được thử nghiệm trong Express 4.x):

function(req, res) {
    res.statusMessage = "Current password does not match";
    res.status(400).end();
}

Sau đó, sử dụng curlđể xác minh rằng nó hoạt động:

$ curl -i -s http://localhost:3100/
HTTP/1.1 400 Current password does not match
X-Powered-By: Express
Date: Fri, 08 Apr 2016 19:04:35 GMT
Connection: keep-alive
Content-Length: 0

6
Đây là cách chính xác để thiết lập statusMessagemột cái gì đó khác hơn là thông điệp tiêu chuẩn ánh xạ tới các StatusCode
peteb

4
Bạn có thể nhận được tài sản trong đối tượng tiềm ẩn vớires.nativeResponse.statusMessage
sebilasse

@RobertMoskal Đã kiểm tra bằng máy chủ Express tối thiểu (Express 4.16.1 và Node 12.9.0) và nó vẫn hoạt động đối với tôi. Kiểm tra mã ứng dụng của bạn: có thể có điều gì khác không ổn.
mamacdon

Không chắc tại sao đây không phải là câu trả lời được chấp nhận vì nó chắc chắn là giải pháp, ít nhất là tại thời điểm tôi viết bài này.
Aaron Summers

12

Ở phía máy chủ (Express middleware):

if(err) return res.status(500).end('User already exists.');

Xử lý ở phía khách hàng

Góc: -

$http().....
.error(function(data, status) {
  console.error('Repos error', status, data);//"Repos error" 500 "User already exists."
});

jQuery: -

$.ajax({
    type: "post",
    url: url,
    success: function (data, text) {
    },
    error: function (request, status, error) {
        alert(request.responseText);
    }
});

11

Một cách đơn giản để xử lý các lỗi tùy chỉnh như thế này trong express là:

function errorHandler(err, req, res, next) {
  var code = err.code;
  var message = err.message;
  res.writeHead(code, message, {'content-type' : 'text/plain'});
  res.end(message);
}

(bạn cũng có thể sử dụng express.errorHandler tích hợp sẵn cho việc này)

Sau đó, trong phần mềm trung gian của bạn, trước các tuyến đường của bạn:

app.use(errorHandler);

Sau đó, nơi bạn muốn tạo lỗi 'Mật khẩu hiện tại không khớp':

function checkPassword(req, res, next) {
  // check password, fails:
  var err = new Error('Current password does not match');
  err.code = 400;
  // forward control on to the next registered error handler:
  return next(err);
}

lỗi.status = 400; là phổ biến hơn tôi tin tưởng.
mkmelin

11

Bạn có thể sử dụng nó như thế này

return res.status(400).json({'error':'User already exists.'});

3

Trường hợp sử dụng của tôi đang gửi thông báo lỗi JSON tùy chỉnh, vì tôi đang sử dụng express để cấp nguồn cho API REST của mình. Tôi nghĩ đây là một kịch bản khá phổ biến, vì vậy tôi sẽ tập trung vào điều đó trong câu trả lời của tôi.

Phiên bản ngắn:

Xử lý lỗi nhanh

Xác định phần mềm trung gian xử lý lỗi như các phần mềm trung gian khác, ngoại trừ với bốn đối số thay vì ba, cụ thể là với chữ ký (err, req, res, next). ... Bạn xác định phần mềm trung gian xử lý lỗi sau cùng, sau các cuộc gọi app.use () và định tuyến khác

app.use(function(err, req, res, next) {
    if (err instanceof JSONError) {
      res.status(err.status).json({
        status: err.status,
        message: err.message
      });
    } else {
      next(err);
    }
  });

Tăng lỗi từ bất kỳ điểm nào trong mã bằng cách thực hiện:

var JSONError = require('./JSONError');
var err = new JSONError(404, 'Uh oh! Can't find something');
next(err);

Phiên bản dài

Cách ném lỗi thông thường là:

var err = new Error("Uh oh! Can't find something");
err.status = 404;
next(err)

Theo mặc định, Express xử lý điều này bằng cách đóng gói gọn gàng nó dưới dạng Phản hồi HTTP với mã 404 và nội dung bao gồm chuỗi thông báo được nối với dấu vết ngăn xếp.

Điều này không hiệu quả với tôi khi tôi đang sử dụng Express làm máy chủ REST chẳng hạn. Tôi muốn lỗi được gửi lại dưới dạng JSON, không phải dưới dạng HTML. Tôi cũng chắc chắn không muốn dấu vết ngăn xếp của tôi chuyển sang khách hàng của tôi.

Tôi có thể gửi JSON dưới dạng phản hồi bằng cách sử dụng req.json(), ví dụ: đại loại như req.json({ status: 404, message: 'Uh oh! Can't find something'}). Theo tùy chọn, tôi có thể đặt mã trạng thái bằng cách sử dụng req.status(). Kết hợp cả hai:

req.status(404).json({ status: 404, message: 'Uh oh! Can't find something'});

Công việc này như một cái duyên vậy. Điều đó nói rằng, tôi thấy khá khó sử dụng khi nhập mỗi khi gặp lỗi và mã không còn tự ghi lại như trước đây next(err)nữa. Nó trông quá giống với cách gửi một phản hồi bình thường (tức là hợp lệ) JSON. Hơn nữa, bất kỳ lỗi nào do phương pháp chuẩn vẫn dẫn đến kết quả đầu ra HTML.

Đây là nơi mà phần mềm trung gian xử lý lỗi của Express xuất hiện. Là một phần của lộ trình của tôi, tôi xác định:

app.use(function(err, req, res, next) {
    console.log('Someone tried to throw an error response');
  });

Tôi cũng phân lớp Lỗi thành một lớp JSONError tùy chỉnh:

JSONError = function (status, message) {
    Error.prototype.constructor.call(this, status + ': ' + message);
    this.status = status;
    this.message = message;
  };
JSONError.prototype = Object.create(Error);
JSONError.prototype.constructor = JSONError;

Bây giờ, khi tôi muốn đưa ra một Lỗi trong mã, tôi thực hiện:

var err = new JSONError(404, 'Uh oh! Can't find something');
next(err);

Quay lại phần mềm trung gian xử lý lỗi tùy chỉnh, tôi sửa đổi nó thành:

app.use(function(err, req, res, next) {
  if (err instanceof JSONError) {
    res.status(err.status).json({
      status: err.status,
      message: err.message
    });
  } else {
    next(err);
  }
}

Lỗi phân lớp thành JSONError rất quan trọng, vì tôi nghi ngờ rằng Express thực hiện instanceof Errorkiểm tra tham số đầu tiên được truyền cho a next()để xác định xem trình xử lý bình thường hay trình xử lý lỗi phải được gọi. Tôi có thể xóa instanceof JSONErrorkiểm tra và thực hiện các sửa đổi nhỏ để đảm bảo các lỗi không mong muốn (chẳng hạn như sự cố) cũng trả về phản hồi JSON.


2

Khi sử dụng Axios, bạn có thể truy xuất thông báo phản hồi tùy chỉnh bằng:

Axios.get(“your_url”)
.then(data => {
... do something
}.catch( err => {
console.log(err.response.data) // you want this
})

... sau khi đặt nó trong Express là:

res.status(400).send(“your custom message”)

0

Nếu mục tiêu của bạn chỉ là giảm nó thành một dòng đơn / đơn giản, bạn có thể dựa vào mặc định một chút ...

return res.end(res.writeHead(400, 'Current password does not match'));

-2

Trong trường hợp Restify, chúng ta nên sử dụng sendRaw()phương pháp

Cú pháp là: res.sendRaw(200, 'Operation was Successful', <some Header Data> or null)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.