Richtige Methode zum Festlegen des Antwortstatus und des JSON-Inhalts in einer REST-API, die mit nodejs und express erstellt wurde


184

Ich spiele mit Nodejs herum und drücke es aus, indem ich eine kleine Rest-API erstelle. Meine Frage ist, was ist die bewährte Methode / der beste Weg, um den Codestatus sowie die Antwortdaten festzulegen?

Lassen Sie mich dies mit ein wenig Code erklären (ich werde nicht den Knoten und den zum Starten des Servers erforderlichen Code ausdrücken, sondern nur die betreffenden Routermethoden):

router.get('/users/:id', function(req, res, next) {
  var user = users.getUserById(req.params.id);
  res.json(user);
});


exports.getUserById = function(id) {
  for (var i = 0; i < users.length; i++) {
    if (users[i].id == id) return users[i];
  }
};

Der folgende Code funktioniert einwandfrei. Wenn ich eine Anfrage mit Postman sende, erhalte ich das folgende Ergebnis: Geben Sie hier die Bildbeschreibung ein

Wie Sie sehen können, zeigt der Status 200 an, was in Ordnung ist. Aber ist das der beste Weg, dies zu tun? Gibt es einen Fall, in dem ich den Status sowie den zurückgegebenen JSON selbst festlegen muss? Oder wird das immer per Express erledigt?

Zum Beispiel habe ich gerade einen Schnelltest durchgeführt und die obige Methode get leicht modifiziert:

router.get('/users/:id', function(req, res, next) {
  var user = users.getUserById(req.params.id);
  if (user == null || user == 'undefined') {
    res.status(404);
  }
  res.json(user);
});

Wie Sie sehen können, setze ich nur den Status 404, wenn der Benutzer nicht im Array gefunden wird.

Ressourcen / Ratschläge, um mehr über dieses Thema zu erfahren, sind mehr als willkommen.


3
Dies ist meine am höchsten bewertete Antwort und wird nicht akzeptiert :( @dukable, ich weiß, es ist eine Weile her, aber hat es Ihr Problem gelöst?
Michał Dudak

@ MichałDudak: Ja, deine Antwort sollte die akzeptierte sein. Dieser dukable Benutzer ist jedoch seit dem 15. Oktober 2015 (Stand 31. Juli 2017) nicht mehr aktiv. +1 für Ihre Antwort sowieso;)
Amol M Kulkarni

Antworten:


227

Die Express-API-Referenz deckt diesen Fall ab.

Siehe Status und senden .

Kurz gesagt, Sie müssen die statusMethode nur aufrufen , bevor Sie aufrufen, jsonoder send:

res.status(500).send({ error: "boo:(" });

32
Wenn Sie nur einen Statuscode (keine Daten) senden möchten, wäre die Methoderes.sendStatus(400);
internet-nico

3
Das scheint nicht mehr zu funktionieren. Die Antwort wird mit dem richtigen Statuscode gesendet, aber ohne
Text

2
Ignoriere meinen letzten Kommentar. Wenn Sie den Status auf 204 (Kein Inhalt) setzen, wird der Text nicht gesendet.
LondonRob

2
@ Internet-Nico res.sendStatus(400);senden Sie auch eine Zeichenfolge Daten, entsprichtres.status(400).send('Not Found')
Davide

74

Sie könnten es so machen:

res.status(400).json(json_response);

Dadurch wird der HTTP-Statuscode auf 400 gesetzt, dies funktioniert sogar in Express 4.


17
express deprecated res.json(status, obj): Use res.status(status).json(obj) instead Also, res.status(400).json(json_response)wäre heutzutage genau.
Will Luce

Ja, danke ... es ist als veraltet markiert, funktioniert aber immer noch: P Ihr Kommentar ist gültig, guter Punkt.
Mzalazar


41

Status 200 wird der Standard sein bei der Verwendung res.send, res.jsonetc.

Sie können den Status wie einstellen res.status(500).json({ error: 'something is wrong' });

Oft mache ich so etwas wie ...

router.get('/something', function(req, res, next) {
  // Some stuff here
  if(err) {
    res.status(500);
    return next(err);
  }
  // More stuff here
});

Lassen Sie dann meine Fehler-Middleware die Antwort senden und alles andere tun, was ich tun muss, wenn ein Fehler auftritt.

Zusätzlich: res.sendStatus(status)wurde ab Version hinzugefügt 4.9.0 http://expressjs.com/4x/api.html#res.sendStatus


23

Eine Liste der HTTP-Statuscodes

Die bewährte Methode für die Statusantwort besteht darin, vorhersehbar den richtigen HTTP-Statuscode in Abhängigkeit vom Fehler zu senden (4xx für Clientfehler, 5xx für Serverfehler). In Bezug auf die tatsächliche JSON-Antwort gibt es keine "Bibel", aber eine gute Idee könnte sein (erneut) den Status und die Daten als 2 verschiedene Eigenschaften des Stammobjekts in einer erfolgreichen Antwort zu senden (auf diese Weise geben Sie dem Client die Möglichkeit, den Status aus den HTTP-Headern und der Nutzlast selbst zu erfassen ) und eine dritte Eigenschaft, die das erklärt Fehler auf menschlich verständliche Weise im Fehlerfall.

Die API von Stripe verhält sich in der realen Welt ähnlich.

dh

OK

200, {status: 200, data: [...]}

Error

400, {status: 400, data: null, message: "You must send foo and bar to baz..."}

13

Ich verwende dies in meiner Express.js-Anwendung:

app.get('/', function (req, res) {
    res.status(200).json({
        message: 'Welcome to the project-name api'
    });
});

5

Die Standardmethode zum Abrufen einer vollständigen HttpResponse mit den folgenden Eigenschaften

  1. body // enthält deine Daten
  2. Überschriften
  3. OK
  4. Status
  5. statusText
  6. Art
  7. URL

Auf Backend , dies zu tun

router.post('/signup', (req, res, next) => {
    // res object have its own statusMessage property so utilize this
    res.statusText = 'Your have signed-up succesfully'
    return res.status(200).send('You are doing a great job')
})

Am Frontend zB in Angular, einfach:

let url = `http://example.com/signup`
this.http.post(url, { profile: data }, {
    observe: 'response' // remember to add this, you'll get pure HttpResponse
}).subscribe(response => {
    console.log(response)
})


2
try {
  var data = {foo: "bar"};
  res.json(JSON.stringify(data));
}
catch (e) {
  res.status(500).json(JSON.stringify(e));
}

0

Du könntest das tun

            return res.status(201).json({
                statusCode: req.statusCode,
                method: req.method,
                message: 'Question has been added'
            });

0

Der beste Weg, eine Fehlerantwort zu senden, wäre return res.status(400).send({ message: 'An error has occurred' }).

Dann können Sie es in Ihrem Frontend mit so etwas abfangen:

        url: your_url,
        method: 'POST',
        headers: headers,
        data: JSON.stringify(body),
    })
        .then((res) => {
            console.log('success', res);
        })
        .catch((err) => {
            err.response && err.response.data && this.setState({ apiResponse: err.response.data })
        })

Nur die Protokollierung errfunktioniert nicht, da sich Ihr gesendetes Nachrichtenobjekt in befindet err.response.data.

Hoffentlich hilft das!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.