Как по умолчанию возвращать ошибки в виде JSON вместо HTML с помощью экспресс?

По умолчанию Express возвращает ошибки в виде HTML-страниц. Поскольку я разрабатываю REST api, я хочу, чтобы все мои ошибки были в формате JSON. Как я могу настроить для этого экспресс?

Я ожидаю, что ответ будет выглядеть примерно так

{
  "statusCode": 404,
  "error": "Not Found"
}

но вместо этого я получаю

<!DOCTYPE html>
<html lang = "en">
<head>
    <meta charset = "utf-8">
    <title>Error</title>
</head>
<body>
    <pre>Cannot DELETE /object/</pre>
</body>
</html>

Это мое базовое приложение

export const app = express();
app.use(express.json());

app.get("/objects", listObjects);
app.get("/object/:id", getObject);
app.post("/object", createObject);
app.put("/object/:id", updateObject);
app.delete("/object/:id", deleteObject);

ОБНОВИТЬ: Чтобы уточнить, я хочу обрабатывать как json не ошибки моих обработчиков. Сделать это довольно просто.

То, что мне нужно, - это экспресс, чтобы перестать возвращать ошибки html для незарегистрированных обработчиков, таких как выполнение DELETE на / Assessment или GET на / anUnknownRoute

опубликуйте код обработки вашего маршрутизатора.

varatharajan 26.12.2018 12:35

Я обновил вопрос своим кодом приложения

Jakob 26.12.2018 13:05

опубликуйте свою функцию deleteObject. как вы возвращаете объект ответа.

varatharajan 26.12.2018 13:12

Моя функция deleteObject не имеет значения, потому что я не вызываю ее. Я вызываю DELETE для / object /, к которому не подключен обработчик, вместо / object /: id. Я хочу, чтобы эта ошибка выдавалась в формате json, а не html

Jakob 26.12.2018 13:16

app.delete (путь, обратный вызов [, обратный вызов ...]). он ясно показывает, что второй параметр - это функция обратного вызова. затем отправьте формат json из функции обратного вызова deleteObject.

varatharajan 26.12.2018 13:23

Поскольку я не добавляю идентификатор после косой черты, он не будет вызываться, но на самом деле это совершенно не имеет значения. Прочтите мое обновление в исходном посте, где я объяснюсь более четко

Jakob 26.12.2018 13:29
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
22
6
11 262
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете просто добавить 'Content-Type: application/json' в заголовки ответов и написать практически все, что захотите, в формате JSON, например.

function(err, req, res, next){
    res.setHeader('Content-Type', 'application/json');
    res.status(500);
    res.send(JSON.stringify(error));
});

Или вы можете использовать вместо него res.json. Пожалуйста, смотрите официальный документ для более подробной информации: https://expressjs.com/en/api.html#res.json

Если вы хотите возвращать ошибки в JSON по умолчанию, то вас может заинтересовать использование механизма экспресс-обработки ошибок по умолчанию: https://expressjs.com/en/guide/error-handling.html

Просто передайте error в обратный вызов next, чтобы перейти прямо к обработчику ошибок (пропуская все остальное в очереди между ними) и добавьте промежуточное ПО обработки ошибок в конец своей очереди промежуточного программного обеспечения. Это должно помочь.

P.S. Из FAQ по express.js:

In Express, 404 responses are not the result of an error, so the error-handler middleware will not capture them. This behavior is because a 404 response simply indicates the absence of additional work to do; in other words, Express has executed all middleware functions and routes, and found that none of them responded. All you need to do is add a middleware function at the very bottom of the stack (below all other functions) to handle a 404 response:

app.use(function (req, res, next) {
    res.status(404).send("Sorry can't find that!")
})

Очевидно, вы можете отправить ответ в формате JSON ...

Возможно, я не смог четко объяснить свою проблему. Я знаю, как вернуть ошибки json для любого заданного маршрута. Но когда, например, не обнаружен ни один маршрут, Express выдает собственные ошибки. Это простой html, но я хочу их в json.

Jakob 26.12.2018 13:22

@Jakob, вы можете добавить промежуточное ПО, которое будет соответствовать любому из несовпадающих запросов (app.use('/', ...) {}). И тогда это сходится к той же идее, которую я написал выше.

Artem 26.12.2018 13:27

Последняя строка действительно решает мою конкретную проблему, но вводит новую. Вызов OPTIONS к существующей конечной точке больше не работает. Я предполагаю, что может быть и другое нежелательное поведение. Ручной ответ на OPTIONS в моем маршрутизаторе кажется настоящим шагом вниз. Неужели нет способа в express контролировать несовпадающие запросы, не нарушая при этом другое поведение?

Jakob 26.12.2018 13:47

@ Якоб Да, я плохо. Это не должно быть так сложно. Ознакомьтесь с FAQ по express.js. Они предоставляют кристально ясное объяснение того, как express.js обрабатывает ошибки 404. expressjs.com/en/starter/faq.html

Artem 27.12.2018 17:33

Спасибо за такую ​​настойчивость, но ваше последнее решение по-прежнему прерывает вызов OPTIONS на допустимые конечные точки. Действительно странно, что такие решения есть в официальных документах

Jakob 27.12.2018 21:15

@Jakob Не могли бы вы написать немного кода о том, как вы воспроизводите эту проблему. Это звучит как настоящая ошибка в самой популярной платформе Node.js: D Я также признаю, что неожиданное поведение вызвано каким-то кодом, который вы еще не упомянули.

Artem 30.12.2018 09:04

Это буквально все приложение: gist.github.com/Jakst/5bb4645f154eef8a6b6050d959ad3807 Выполнение вызова OPTIONS на / ping возвращает nope, но если вы удалите app.use(...), он вернет GET,HEAD.

Jakob 04.01.2019 16:11

Спасибо, я разместил ваш код в нижней части своего промежуточного программного обеспечения, и он работает: app.use (function (req, res, next) {res.status (404) .send ("Извините, не могу найти это!")})

Abdelhadi Abdo 18.05.2019 19:06

Я проверил исходный код express.js. Причина, по которой все это заканчивается в формате HTML, заключается в том, что по умолчанию они вызывают finalhandler (см. github.com/expressjs/express/blob/master/lib/application.js) ‌, который производит окончательный вывод только в формате HTML (OT: переменная NODE_ENV обрабатывается Finalhandler, а не Express). Пакет Finalhandler находится здесь: npmjs.com/package/finalhandler.

Rein 10.07.2020 11:19

В Express ответы 404 не являются результатом ошибки, поэтому промежуточное программное обеспечение обработчика ошибок не будет их захватывать - действительно полезно, много thx

danday74 15.04.2021 00:57
Ответ принят как подходящий

Вы добавляете пользовательское промежуточное ПО для обработки ошибок - которое является обычным промежуточным ПО, но с 4 аргументами вместо 3 - в стек промежуточного программного обеспечения. В этом обработчике ошибок вы используете res.status(code).send(jsonResponse) для отправки ошибки json.

Простой быстрый пример, который всегда будет отправлять ошибки JSON статуса 500:

const bodyParser = require('body-parser')
const express = require('express')

const jsonErrorHandler = async (err, req, res, next) => {
  res.status(500).send({ error: err });
}

const app = express()
// The other middleware
app.use(bodyParser.json())
// Your handler
app.use(jsonErrorHandler)

ха-ха, я забыл, что ему нужен четвертый аргумент, даже если он не использовался для правильного обнаружения ошибок, я часами боролся с этим глупым глупым перебором, этот ответ решил мою проблему! Благодарность

xunux 30.09.2020 18:52

То же самое, не забывайте аргумент next !! Спасибо @xunux, ты сэкономил мне пару часов своим комментарием

Rashomon 21.11.2020 13:56

все, что вам нужно сделать для получения ответа JSON об ошибках, - это добавить еще один аргумент в обработчик маршрута, который будет функцией промежуточного программного обеспечения, ответственной за ошибки.

Бывший: вы должны изменить это

app.get('/objects', listObjects); 

быть таким:

app.get('/objects', listObjects, (err, req, res, next) => {
    res.status(404).send({error: err.message})
});

Другие вопросы по теме