Méthode appropriée pour définir l'état de la réponse et le contenu JSON dans une API REST créée avec nodejs et express

187

Je joue avec Nodejs et j'exprime en construisant une petite API de repos. Ma question est la suivante: quelle est la bonne pratique / la meilleure façon de définir le statut du code, ainsi que les données de réponse?

Laissez-moi vous expliquer avec un peu de code (je ne mettrai pas le nœud et le code express nécessaire pour démarrer le serveur, juste les méthodes de routage concernées):

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];
  }
};

Le code ci-dessous fonctionne parfaitement, et lors de l'envoi d'une demande avec Postman, j'obtiens le résultat suivant: entrez la description de l'image ici

Comme vous pouvez le voir, l'état indique 200, ce qui est OK. Mais est-ce la meilleure façon de procéder? Y a-t-il un cas où je devrais devoir définir le statut moi-même, ainsi que le JSON renvoyé? Ou est-ce toujours géré par express?

Par exemple, je viens de faire un test rapide et j'ai légèrement modifié la méthode get ci-dessus:

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);
});

Comme vous pouvez le voir, si l'utilisateur n'est pas trouvé dans le tableau, je vais simplement définir un statut de 404.

Les ressources / conseils pour en savoir plus sur ce sujet sont plus que bienvenus.

dukable
la source
3
C'est ma réponse la mieux notée et elle n'est pas acceptée :( @dukable, je sais que cela fait un moment, mais cela a-t-il résolu votre problème?
Michał Dudak
@ MichałDudak: Oui, votre réponse devrait être celle acceptée. Mais cet utilisateur douteux n'est plus actif depuis le 15 octobre 2015 (comme le 31 juillet 2017). +1 pour votre réponse de toute façon;)
Amol M Kulkarni

Réponses:

230

La référence de l'API Express couvre ce cas.

Voir l' état et envoyer .

En bref, il vous suffit d'appeler la statusméthode avant d'appeler jsonou send:

res.status(500).send({ error: "boo:(" });
Michał Dudak
la source
32
Si vous souhaitez uniquement envoyer un code d'état (pas de données), la méthode seraitres.sendStatus(400);
internet-nico
3
Cela ne semble plus fonctionner. La réponse est envoyée avec le code d'état correct, mais pas de corps ....
LondonRob
2
Ignorez mon dernier commentaire. Si vous définissez le statut sur 204 (Aucun contenu), il n'envoie pas le corps.
LondonRob
2
@ internet-nico res.sendStatus(400);envoie également une chaîne de données, équivaut àres.status(400).send('Not Found')
Davide
74

Vous pouvez le faire de cette façon:

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

Cela définira le code d'état HTTP sur 400, cela fonctionne même dans express 4.

mzalazar
la source
17
express deprecated res.json(status, obj): Use res.status(status).json(obj) instead Donc, ce res.status(400).json(json_response)serait exact de nos jours.
Will Luce
Oui, merci ... il est marqué comme obsolète, mais fonctionne toujours: P Votre commentaire est valide, bon point.
mzalazar
En faveur de l'anwer -res.status(500).send({ error: "boo:(" });
prieragupd
41

état de 200 sera la valeur par défaut lors de l' utilisation res.send, res.jsonetc.

Vous pouvez définir le statut comme res.status(500).json({ error: 'something is wrong' });

Souvent, je fais quelque chose comme ...

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

Ensuite, demandez à mon middleware d'erreur d'envoyer la réponse et de faire tout ce que je dois faire en cas d'erreur.

De plus: res.sendStatus(status)a été ajouté à partir de la version 4.9.0 http://expressjs.com/4x/api.html#res.sendStatus

Jordonias
la source
23

Une liste de codes d'état HTTP

La bonne pratique concernant la réponse d'état est, de manière prévisible, d'envoyer le code d'état HTTP approprié en fonction de l'erreur (4xx pour les erreurs client, 5xx pour les erreurs serveur), en ce qui concerne la réponse JSON réelle, il n'y a pas de "bible" mais une bonne idée pourrait être pour envoyer (à nouveau) l'état et les données comme 2 propriétés différentes de l'objet racine dans une réponse réussie (de cette façon, vous donnez au client la possibilité de capturer l'état à partir des en-têtes HTTP et de la charge utile elle-même) et une 3ème propriété expliquant le erreur d'une manière compréhensible par l'homme en cas d'erreur.

L' API de Stripe se comporte de la même manière dans le monde réel.

c'est à dire

D'accord

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

Erreur

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

J'utilise ceci dans mon application Express.js:

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

La manière standard d'obtenir HttpResponse complète qui inclut les propriétés suivantes

  1. body // contient vos données
  2. en-têtes
  3. D'accord
  4. statut
  5. statusText
  6. type
  7. URL

Sur le backend , faites ceci

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')
})

Sur Frontend par exemple dans Angular, faites simplement:

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)
})
WasiF
la source
3
res.status(500).jsonp(dataRes);
Gustavo Grisales
la source
2
try {
  var data = {foo: "bar"};
  res.json(JSON.stringify(data));
}
catch (e) {
  res.status(500).json(JSON.stringify(e));
}
Sma Ma
la source
0

Tu pourrais faire ça

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

La meilleure façon d'envoyer une réponse d'erreur serait return res.status(400).send({ message: 'An error has occurred' }).

Ensuite, dans votre frontend, vous pouvez l'attraper en utilisant quelque chose comme ceci:

        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 })
        })

La simple journalisation errne fonctionnera pas, car votre objet de message envoyé réside dans err.response.data.

J'espère que cela pourra aider!

Radu
la source