Как вернуть объекты сообщения об ошибке клиенту в Express? - PullRequest
1 голос
/ 21 марта 2020

У меня есть этот блок кода:

router.post('/users/login', async (req, res) => {
  try {
    const { email, password } = req.body
    const user = await User.findByCredentials(email, password)
    console.log(user) //false
    if (!user) {
      throw new Error('Login failed! Check authentication credentials')
    }
    const token = await user.generateAuthToken()
    res.status(200).json({ user, token })
  } catch (err) {
    console.log(err) //Error: Login failed! Check authentication credentials at C:\Users...
    res.status(400).json(err)
  }
})

Все отлично работает, пока не возникнет ошибка. При возникновении ошибки (user - false) в Почтальоне у меня возвращается только пустой объект {}. Также с res.status(400).json({error: err}) это дает мне { "err": {} }.

Я хочу получить подобный объект { "error": "Login failed! Check authentication credentials" }

Ответы [ 3 ]

2 голосов
/ 21 марта 2020

Объекты ошибок не сериализуются хорошо в JSON, потому что некоторые из их свойств не перечисляются и поэтому JSON.stringify() не включает их, когда res.json(err) использует его.
Именно поэтому res.json(err) не делает покажите, что вы хотите.

Возможные причины, по которым неперечислимые свойства не включены, состоят в том, что они могут содержать трассировки стека и другую информацию, которая не предназначена для отправки обратно клиенту. Это просто побочный продукт того, как работает объект Error и как JSON.stringify() реализован, а res.json() просто наследует эти проблемы и взаимодействие между ними. Я никогда не понимал, почему основное свойство .message не перечисляемо, поскольку для меня это никогда не имело смысла, но это так.

Существует несколько возможных решений:

  1. Вы можете добавить собственный метод .json2(), который включает все свойства объекта Error (даже не перечисляемые).
  2. Вы можете использовать Express схему обработки ошибок где вы вызываете next(err), и вы предоставляете централизованный обработчик ошибок, который вызывается, и вы можете выполнить свою собственную сериализацию ответа об ошибке там.
  3. Вы можете создать подкласс Error, который заполнит перечисляемые свойства, которые будут отображаться в JSON и используйте его.

Вариант № 3 может выглядеть следующим образом:

class RouteError extends Error {
    constructor(msg, statusCode = 500) {
        super(msg);
        // define my own enumerable properties so they
        // will show up in JSON automatically
        this.error = msg;
        this.statusCode = statusCode;
    }
}

router.post('/users/login', async (req, res) => {
  try {
    const { email, password } = req.body
    const user = await User.findByCredentials(email, password)
    console.log(user) //false
    if (!user) {
      throw new RouteError('Login failed! Check authentication credentials', 401)
    }
    const token = await user.generateAuthToken()
    res.status(200).json({ user, token })
  } catch (err) {
    console.log(err) //Error: Login failed! Check authentication credentials at C:\Users...
    res.status(err.statusCode).json(err);
  }
});

В этом примере будет сгенерирован этот ответ:

{"error":"Login failed! Check authentication credentials","statusCode":401}
1 голос
/ 21 марта 2020

JSON.stringify не может захватить не перечисляемые свойства объекта , как упоминает jfriend00, но есть несколько довольно прямых решений, о которых стоит упомянуть.

Один из способов - создать правильный объект Вы сами используете свойство err.message, которое содержит строку, предоставленную конструктору Error:

app.get("/foo", (req, res) => {
  try {
    throw new Error("hello world");
  }
  catch (err) {
    res.status(400).json({error: err.message});
  }
});

Другой подход, если вы действительно не можете прикоснуться к своему вызову res.json, - это throw объект настроить, как вам это нравится. Мне это не нравится, потому что вы теряете информацию трассировки стека (см .: 1 , 2 , 3 ), но она существует:

app.get("/foo", (req, res) => {
  try {
    throw {error: "hello world"};
  }
  catch (err) {
    res.status(400).json(err);
  }
});

В обоих случаях клиент видит

{
    error: "hello world"
}
0 голосов
/ 21 марта 2020

Вы можете выдать ошибку, если пользователь пуст или пуст. Другой поток отвечает на аналогичный вопрос.

Node.js с Express - выбросить Ошибка против следующей (ошибка)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...