Moja aplikacja node.js jest modelowana jak aplikacja express / examples / mvc .
W akcji kontrolera chcę wypluć status HTTP 400 za pomocą niestandardowego komunikatu http. Domyślnie komunikat o stanie http to „Złe żądanie”:
HTTP/1.1 400 Bad Request
Ale chcę wysłać
HTTP/1.1 400 Current password does not match
Próbowałem różnych sposobów, ale żaden z nich nie ustawił komunikatu o stanie http na moją niestandardową wiadomość.
Moja obecna funkcja kontrolera rozwiązania wygląda następująco:
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;
}
// ...
}
Wszystko działa dobrze, ale ... wydaje się, że nie jest to właściwy sposób.
Czy jest lepszy sposób na ustawienie komunikatu o stanie HTTP przy użyciu ekspresu?
Odpowiedzi:
Możesz sprawdzić tę dokumentację
res.send(400, 'Current password does not match')
Look express 3.x, aby uzyskać szczegółowe informacjeUPDATE dla Expressjs 4.x
Skorzystaj z tego sposobu (zobacz dokumentację 4.x ):
res.status(400).send('Current password does not match'); // or res.status(400); res.send('Current password does not match');
źródło
res.status(400).send('Current password does not match');
Przykład działa dla mnie Express, 4.Express ^4.16.2
Żadna z istniejących odpowiedzi nie spełnia tego, o co pierwotnie prosił PO, czyli zastąpienia domyślnego wyrażenia powodu (tekst pojawiający się bezpośrednio po kodzie statusu) wysłanego przez Express.
To czego chcesz
res.statusMessage
. To nie jest część Express, jest to właściwość bazowego obiektu http.Response w Node.js 0.11+.Możesz go używać w ten sposób (testowane w Express 4.x):
function(req, res) { res.statusMessage = "Current password does not match"; res.status(400).end(); }
Następnie użyj,
curl
aby sprawdzić, czy działa:$ 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
źródło
statusMessage
czegoś innego niż standardowa wiadomość mapowana na StatusCoderes.nativeResponse.statusMessage
Po stronie serwera (oprogramowanie pośredniczące Express):
if(err) return res.status(500).end('User already exists.');
Uchwyt po stronie klienta
Kątowy:-
$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); } });
źródło
Jednym eleganckim sposobem obsługi niestandardowych błędów, takich jak ten w ekspresowym, jest:
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); }
(możesz również użyć do tego wbudowanego express.errorHandler )
Następnie w oprogramowaniu pośrednim, przed trasami:
Następnie, gdzie chcesz utworzyć błąd „Bieżące hasło nie pasuje”:
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); }
źródło
Możesz tego używać w ten sposób
return res.status(400).json({'error':'User already exists.'});
źródło
Mój przypadek użycia wysyła niestandardowy komunikat o błędzie JSON, ponieważ używam ekspresu do zasilania mojego interfejsu API REST. Myślę, że jest to dość powszechny scenariusz, więc skupię się na tym w mojej odpowiedzi.
Krótka wersja:
Ekspresowa obsługa błędów
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); } });
Podnieś błędy z dowolnego miejsca w kodzie, wykonując:
var JSONError = require('./JSONError'); var err = new JSONError(404, 'Uh oh! Can't find something'); next(err);
Długa wersja
Kanoniczny sposób zgłaszania błędów to:
var err = new Error("Uh oh! Can't find something"); err.status = 404; next(err)
Domyślnie Express obsługuje to, starannie pakując je jako odpowiedź HTTP z kodem 404 i treścią składającą się z ciągu komunikatu dołączonego do śladu stosu.
Na przykład to nie działa, gdy używam Express jako serwera REST. Chcę, aby błąd został odesłany w formacie JSON, a nie HTML. Zdecydowanie nie chcę też, aby mój ślad stosu został przeniesiony do mojego klienta.
Mogę wysłać JSON jako odpowiedź używając
req.json()
np. coś w stylureq.json({ status: 404, message: 'Uh oh! Can't find something'})
. Opcjonalnie mogę ustawić kod statusu za pomocąreq.status()
. Połączenie tych dwóch:req.status(404).json({ status: 404, message: 'Uh oh! Can't find something'});
To działa jak urok. To powiedziawszy, uważam, że pisanie za każdym razem, gdy mam błąd, jest dość nieporęczne, a kod nie dokumentuje się już samoczynnie, jak nasz
next(err)
. Wygląda to zbyt podobnie do wysyłania normalnej (tj. Prawidłowej) odpowiedzi w formacie JSON. Co więcej, wszelkie błędy zgłaszane przez podejście kanoniczne nadal skutkują wynikiem w postaci HTML.W tym miejscu pojawia się oprogramowanie pośredniczące do obsługi błędów Express. W ramach moich tras definiuję:
app.use(function(err, req, res, next) { console.log('Someone tried to throw an error response'); });
Podklasuję również Error do niestandardowej klasy JSONError:
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;
Teraz, gdy chcę zgłosić błąd w kodzie, robię:
var err = new JSONError(404, 'Uh oh! Can't find something'); next(err);
Wracając do niestandardowego oprogramowania pośredniczącego do obsługi błędów, modyfikuję je, aby:
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); } }
Podklasowanie błędu do JSONError jest ważne, ponieważ podejrzewam, że Express
instanceof Error
sprawdza pierwszy parametr przekazany do a,next()
aby określić, czy należy wywołać normalną procedurę obsługi lub procedurę obsługi błędów. Mogę usunąćinstanceof JSONError
czek i wprowadzić drobne modyfikacje, aby zapewnić, że nieoczekiwane błędy (takie jak awaria) również zwrócą odpowiedź JSON.źródło
Korzystając z Axios, możesz pobrać niestandardową wiadomość z odpowiedzią za pomocą:
Axios.get(“your_url”) .then(data => { ... do something }.catch( err => { console.log(err.response.data) // you want this })
... po ustawieniu go w Express jako:
res.status(400).send(“your custom message”)
źródło
Jeśli Twoim celem jest po prostu zredukowanie go do jednej / prostej linii, możesz trochę polegać na domyślnych ...
return res.end(res.writeHead(400, 'Current password does not match'));
źródło
W przypadku Restify powinniśmy użyć
sendRaw()
metodySkładnia to:
res.sendRaw(200, 'Operation was Successful', <some Header Data> or null)
źródło