Правильный способ установить статус ответа и содержимое JSON в REST API, сделанном с помощью nodejs и express

188

Я играю с Nodejs и выражаюсь, создавая небольшой API отдыха. У меня вопрос, какова хорошая практика / лучший способ установить статус кода, а также данные ответа?

Позвольте мне объяснить с небольшим количеством кода (я не буду помещать узел и экспресс-код, необходимый для запуска сервера, только соответствующие методы маршрутизатора):

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

Код ниже работает отлично, и при отправке запроса с почтальоном, я получаю следующий результат: введите описание изображения здесь

Как видите, статус показывает 200, что нормально. Но это лучший способ сделать это? Есть ли случай, когда мне нужно было бы установить статус самостоятельно, а также возвращаемый JSON? Или это всегда обрабатывается экспресс?

Например, я только что сделал быстрый тест и немного изменил метод get выше:

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

Как вы можете видеть, если пользователь не найден в массиве, я просто установлю статус 404.

Ресурсы / советы, чтобы узнать больше об этой теме, более чем приветствуются.

dukable
источник
3
Это мой самый высокий рейтинг ответа, и он не принят :( @dukable, я знаю, что это было давно, но решило ли это вашу проблему?
Михал Дудак
@ МихалДудак: Да, ваш ответ должен быть принятым. Но этот сомнительный пользователь не активен с 15 октября 2015 года (по состоянию на 31 июля 2017 года). +1 для вашего ответа в любом случае;)
Amol M Kulkarni

Ответы:

230

Экспресс API ссылка охватывает этот случай.

Смотри статус и отправляй .

Короче говоря, вам просто нужно вызвать statusметод перед вызовом jsonили send:

res.status(500).send({ error: "boo:(" });
Михал Дудак
источник
32
Если вы хотите , чтобы отправить код состояния (нет данных), метод будетres.sendStatus(400);
интернет-Nico
3
Кажется, это больше не работает. Ответ отправлен с правильным кодом статуса, но без тела ....
LondonRob
2
Не обращайте внимания на мой последний комментарий. Если вы установите статус 204 (без содержимого), он не будет отправлять тело.
LondonRob
2
@ internet-nico res.sendStatus(400);тоже отправляет строковые данные, что эквивалентноres.status(400).send('Not Found')
Davide
74

Вы могли бы сделать это так:

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

Это установит код состояния HTTP на 400, он работает даже в экспресс 4.

mzalazar
источник
17
express deprecated res.json(status, obj): Use res.status(status).json(obj) instead Итак, res.status(400).json(json_response)было бы точно в наше время.
Будет Люс
Да, спасибо ... он помечен как устаревший, но все еще работает: P Ваш комментарий верен, хорошая точка зрения.
mzalazar
В пользу ответа -res.status(500).send({ error: "boo:(" });
praagagupd
41

статус 200 будет по умолчанию при использовании res.send, res.jsonи т.д.

Вы можете установить статус как res.status(500).json({ error: 'something is wrong' });

Часто я делаю что-то вроде ...

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

Затем сделайте так, чтобы мое промежуточное ПО с ошибкой отправило ответ, и в случае ошибки сделайте все, что мне нужно.

Дополнительно: res.sendStatus(status)добавлено с версии 4.9.0 http://expressjs.com/4x/api.html#res.sendStatus

Jordonias
источник
23

Список кодов состояния HTTP

Хорошая практика в отношении ответа о состоянии заключается в том, чтобы, как и ожидалось, отправлять правильный код состояния HTTP в зависимости от ошибки (4xx для ошибок клиента, 5xx для ошибок сервера), что касается фактического ответа JSON, «библии» нет, но хорошей идеей может быть отправить (снова) статус и данные как 2 разных свойства корневого объекта в успешном ответе (таким образом, вы даете клиенту возможность получить статус из заголовков HTTP и самой полезной нагрузки) и третье свойство, объясняющее ошибка понятным человеку в случае ошибки.

API в Stripe ведет себя аналогично в реальном мире.

т.е.

хорошо

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

ошибка

400, {status: 400, data: null, message: "You must send foo and bar to baz..."}
cmlndz
источник
13

Я использую это в моем приложении Express.js:

app.get('/', function (req, res) {
    res.status(200).json({
        message: 'Welcome to the project-name api'
    });
});
МРК
источник
5

Стандартный способ получить полный HttpResponse, который включает в себя следующие свойства

  1. тело // содержит ваши данные
  2. заголовки
  3. хорошо
  4. положение дел
  5. его статус
  6. тип
  7. URL

На бэкенде сделайте это

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

На Frontend например , в Angular, просто сделать:

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
источник
3
res.status(500).jsonp(dataRes);
Густаво Грисалес
источник
2
try {
  var data = {foo: "bar"};
  res.json(JSON.stringify(data));
}
catch (e) {
  res.status(500).json(JSON.stringify(e));
}
Сма Ма
источник
0

Вы могли бы сделать это

            return res.status(201).json({
                statusCode: req.statusCode,
                method: req.method,
                message: 'Question has been added'
            });
Prathamesh Подробнее
источник
0

Лучший способ отправить ответ об ошибке return res.status(400).send({ message: 'An error has occurred' }).

Затем в вашем интерфейсе вы можете поймать его, используя что-то вроде этого:

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

Просто регистрация errне будет работать, так как объект отправленного сообщения находится в err.response.data.

Надеюсь, это поможет!

Radu
источник