Modo corretto per impostare lo stato della risposta e il contenuto JSON in un'API REST creata con nodejs ed express


187

Sto giocando con Nodejs ed esprimo costruendo una piccola API di riposo. La mia domanda è: qual è la buona pratica / il modo migliore per impostare lo stato del codice e i dati di risposta?

Permettetemi di spiegare con un po 'di codice (non inserirò il nodo ed esprimerò il codice necessario per avviare il server, ma solo i metodi router interessati):

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

Il codice seguente funziona perfettamente e, quando invio una richiesta con Postman, ottengo il seguente risultato: inserisci qui la descrizione dell'immagine

Come puoi vedere, lo stato mostra 200, il che è OK. Ma è questo il modo migliore per farlo? Esiste un caso in cui dovrei impostare personalmente lo stato e il JSON restituito? O è sempre gestito da express?

Ad esempio, ho appena fatto un test rapido e ho leggermente modificato il metodo get sopra:

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

Come puoi vedere, se l'utente non viene trovato nell'array, imposterò solo uno stato di 404.

Risorse / consigli per saperne di più su questo argomento sono più che benvenuti.


3
Questa è la mia risposta più votata e non è accettata :( @ dukable, so che è passato un po 'di tempo, ma ha risolto il tuo problema?
Michał Dudak,

@ MichałDudak: Sì, la tua risposta dovrebbe essere quella accettata. Ma questo utente dukable non è attivo dal 15 ottobre 2015 (come il 31 luglio 2017). +1 comunque per la tua risposta;)
Amol M Kulkarni

Risposte:


230

Il riferimento API Express copre questo caso.

Vedi lo stato e invia .

In breve, devi solo chiamare il statusmetodo prima di chiamare jsono send:

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

32
Se si desidera solo inviare un codice di stato (nessun dato), il metodo sarebberes.sendStatus(400);
internet-nico

3
Questo non sembra funzionare più. La risposta viene inviata con il codice di stato corretto, ma nessun corpo ...
Londra,

2
Ignora il mio ultimo commento. Se si imposta lo stato su 204 (Nessun contenuto), non verrà inviato il corpo.
Londra,

2
@ internet-nico res.sendStatus(400);invia anche una stringa di dati, equivale ares.status(400).send('Not Found')
Davide

74

Potresti farlo in questo modo:

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

Questo imposterà il codice di stato HTTP su 400, funziona anche in Express 4.


17
express deprecated res.json(status, obj): Use res.status(status).json(obj) instead Quindi, res.status(400).json(json_response)sarebbe accurato al giorno d'oggi.
Will Luce,

Sì, grazie ... è contrassegnato come obsoleto, ma funziona ancora: P Il tuo commento è valido, buon punto.
mzalazar,


41

stato 200 sarà il valore predefinito quando si usa res.send, res.jsone così via

È possibile impostare lo stato come res.status(500).json({ error: 'something is wrong' });

Spesso farò qualcosa come ...

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

Quindi chiedi al mio middleware di errore di inviare la risposta e fare qualsiasi altra cosa che devo fare in caso di errore.

Inoltre: res.sendStatus(status)è stato aggiunto dalla versione 4.9.0 http://expressjs.com/4x/api.html#res.sendStatus


23

Un elenco di codici di stato HTTP

La buona pratica per quanto riguarda la risposta allo stato è, prevedibilmente, di inviare il codice di stato HTTP corretto in base all'errore (4xx per errori client, 5xx per errori del server), per quanto riguarda la risposta JSON effettiva non c'è "bibbia" ma una buona idea potrebbe essere inviare (di nuovo) lo stato e i dati come 2 diverse proprietà dell'oggetto root in una risposta corretta (in questo modo si sta dando al client la possibilità di acquisire lo stato dalle intestazioni HTTP e dal payload stesso) e una terza proprietà che spiega il errore in modo comprensibile all'uomo in caso di errore.

L' API di Stripe si comporta in modo simile nel mondo reale.

vale a dire

ok

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

Errore

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

13

Sto usando questo nella mia applicazione Express.js:

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

5

Il modo standard per ottenere HttpResponse completo che include le seguenti proprietà

  1. body // contiene i tuoi dati
  2. intestazioni
  3. ok
  4. stato
  5. statusText
  6. genere
  7. url

Sul backend , fai questo

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

Su Frontend, ad esempio in Angular, basta fare:

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

Potresti farlo

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

0

Il modo migliore per inviare una risposta di errore sarebbe return res.status(400).send({ message: 'An error has occurred' }).

Quindi, nel tuo frontend puoi prenderlo usando qualcosa del genere:

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

Solo la registrazione errnon funzionerà, poiché risiede l'oggetto messaggio inviato err.response.data.

Spero che aiuti!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.