Когда писать заголовки для потокового ответа? - PullRequest
0 голосов
/ 11 июля 2019

Я запрашиваю SQL-сервер из экспресс-API с помощью модуля node-mssql и передаю строки (с некоторыми промежуточными шагами) в поток ответов.Я хочу избегать записи заголовков, пока не узнаю, что запрос не выдаст ошибку перед какими-либо строками, поэтому я могу отправить полезное сообщение об ошибке клиенту вместо завершения потока с помощью экспресс-обработчика по умолчанию.Тем не менее, express записывает заголовки по умолчанию в какой-то момент, и у меня возникают проблемы при его идентификации.

Я пытался записать заголовки в прослушивателе .once ('data',) в конвейере, но в этот момент некоторые по умолчаниюповедение написало заголовки для меня, и это приводит к ошибке.

let request = await new sql.Request(pool);

res.writeHead(200, {
        'Transfer-Encoding': 'chunked',
        'charset' : 'utf-8',
        'Content-Type': 'application/json',
        'Content-Encoding': 'gzip'        
    })

ndjsonStream.on('error', next)

request.pipe(ndjsonStream)
    .pipe(transformer)
    .pipe(gzip)
    .pipe(res);

Вышеописанное работает, но не позволяет мне передать полезное сообщение об ошибке.

let request = await new sql.Request(pool);

ndjsonStream.once('data', () => {
    res.writeHead(200, {
        'Transfer-Encoding': 'chunked',
        'charset' : 'utf-8',
        'Content-Type': 'application/json',
        'Content-Encoding': 'gzip'        
    })
})

ndjsonStream.on('error', next)

request.pipe(ndjsonStream)
    .pipe(transformer)
    .pipe(gzip)
    .pipe(res);

request.query(query);

Это приводит к ошибке, потому что express заранее написал для меня несколько заголовков, прежде чем этот слушатель сработаетт.е. тип контента: текст / html.

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

1 Ответ

1 голос
/ 11 июля 2019

Как работает HTTP-ответ, вы ДОЛЖНЫ написать HTTP-заголовки, прежде чем начать отправлять какие-либо данные. Вот как был разработан формат ответа http. Итак, если вы собираетесь передать ответ, вы должны написать заголовки, а затем передать и следить за ошибками. Вы не можете изменить этот порядок.

Я хочу избегать записи заголовков, пока не узнаю, что запрос не выдаст ошибку раньше, чем строки

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

Если вы используете конвейер, то, по определению, заголовки уже записаны, и данные, вероятно, начали отправляться до того, как произошла ошибка. Это недостаток трубопровода, как вы его используете. У него есть некоторые преимущества (например, потенциально более низкое использование памяти и очень простое кодирование), но на самом деле не существует отличного способа справляться с ошибками при этом. Не пытаясь по-настоящему, действительно придумать несколько частей MIME и позволить вам присоединить последнюю часть MIME для передачи дополнительной информации об ошибке и создать собственное решение для трубопроводов, которое не просто вешает сокет на ошибку, но позволяет вам чтобы завершить текущую часть MIME и добавить еще одну, если вы используете трубопровод, вы принимаете упрощенное сообщение об ошибке, которое она обеспечивает.

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