Я довольно новичок в Node.js и у меня возникли некоторые проблемы.
Я использую Node.js 4.10 и Express 2.4.3.
Когда я пытаюсь получить доступ к http://127.0.0.1:8888/auth/facebook , меня перенаправляют на http://127.0.0.1:8888/auth/facebook_callback .
Затем я получил следующую ошибку:
Error: Can't render headers after they are sent to the client.
at ServerResponse.<anonymous> (http.js:573:11)
at ServerResponse._renderHeaders (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:64:25)
at ServerResponse.writeHead (http.js:813:20)
at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/auth.strategies/facebook.js:28:15
at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:113:13
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/strategyExecutor.js:45:39)
at [object Object].pass (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/authExecutionScope.js:32:3)
at [object Object].halt (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/authExecutionScope.js:29:8)
at [object Object].redirect (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/authExecutionScope.js:16:8)
at [object Object].<anonymous> (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/auth.strategies/facebook.js:77:15)
Error: Can't set headers after they are sent.
at ServerResponse.<anonymous> (http.js:527:11)
at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:195:11)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:150:23)
at param (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:189:13)
at pass (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:191:10)
at Object.router [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:197:6)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15)
at Object.auth [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:153:7)
Error: Can't set headers after they are sent.
at ServerResponse.<anonymous> (http.js:527:11)
at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:207:9)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:150:23)
at param (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:189:13)
at pass (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:191:10)
at Object.router [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:197:6)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15)
at Object.auth [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:153:7)
Error: Can't set headers after they are sent.
at ServerResponse.<anonymous> (http.js:527:11)
at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:150:23)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:207:9)
at Object.auth [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:153:7)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15)
at HTTPServer.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:211:3)
at Object.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:105:14)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15)
Error: Can't set headers after they are sent.
at ServerResponse.<anonymous> (http.js:527:11)
at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:150:23)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:207:9)
at HTTPServer.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:211:3)
at Object.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:105:14)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15)
at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session.js:323:9
at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session.js:338:9
node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: Can't set headers after they are sent.
at ServerResponse.<anonymous> (http.js:527:11)
at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13)
at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:207:9)
at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session.js:323:9
at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session.js:338:9
at Array.<anonymous> (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session/memory.js:57:7)
at EventEmitter._tickCallback (node.js:126:26)
Вот мой код:
var fbId= "XXX";
var fbSecret= "XXXXXX";
var fbCallbackAddress= "http://127.0.0.1:8888/auth/facebook_callback"
var cookieSecret = "node"; // enter a random hash for security
var express= require('express');
var auth = require('connect-auth')
var app = express.createServer();
app.configure(function(){
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({secret: cookieSecret}));
app.use(auth([
auth.Facebook({
appId : fbId,
appSecret: fbSecret,
callback: fbCallbackAddress,
scope: 'offline_access,email,user_about_me,user_activities,manage_pages,publish_stream',
failedUri: '/noauth'
})
]));
app.use(app.router);
});
app.get('/auth/facebook', function(req, res) {
req.authenticate("facebook", function(error, authenticated) {
if (authenticated) {
res.redirect("/great");
console.log("ok cool.");
console.log(res['req']['session']);
}
});
});
app.get('/noauth', function(req, res) {
console.log('Authentication Failed');
res.send('Authentication Failed');
});
app.get('/great', function( req, res) {
res.send('Supercoolstuff');
});
app.listen(8888);
Могу ли я узнать, что не так с моим кодом?
javascript
node.js
express
DjangoRocks
источник
источник
Ответы:
res
Объект Экспресс подкласс Node.js - хhttp.ServerResponse
( читать источник http.js ). Вам разрешено звонитьres.setHeader(name, value)
так часто, как вы хотите, пока вы не позвонитеres.writeHead(statusCode)
. ПослеwriteHead
этого запекаются заголовки и можно только позвонитьres.write(data)
, и наконецres.end(data)
.Ошибка «Ошибка: невозможно установить заголовки после их отправки». означает, что вы уже в состоянии Body или Finished, но некоторые функции пытались установить заголовок или statusCode. Когда вы видите эту ошибку, попробуйте найти все, что пытается отправить заголовок после того, как часть тела уже написана. Например, ищите обратные вызовы, которые были случайно вызваны дважды, или любую ошибку, которая происходит после отправки тела.
В вашем случае вы позвонили
res.redirect()
, что привело к завершению ответа. Тогда ваш код выдал ошибку (res.req
естьnull
). и так как ошибка произошла в вашей реальнойfunction(req, res, next)
(не в обратном вызове), Connect смог ее перехватить и попытался отправить страницу с ошибкой 500. Но поскольку заголовки уже отправлены, Node.jssetHeader
выдал ошибку, которую вы видели.Полный список методов ответа Node.js / Express и когда они должны быть вызваны:
Ответ должен быть в голове и остается в голове :
res.writeContinue()
res.statusCode = 404
res.setHeader(name, value)
res.getHeader(name)
res.removeHeader(name)
res.header(key[, val])
(Экспресс только)res.charset = 'utf-8'
(Только Express; влияет только на методы, специфичные для Express)res.contentType(type)
(Экспресс только)Ответ должен быть в голове и становится телом :
res.writeHead(statusCode, [reasonPhrase], [headers])
Ответ может быть либо в голове / теле, и остается в теле :
res.write(chunk, encoding='utf8')
Ответ может быть в любой голове / теле и становится законченным :
res.end([data], [encoding])
Ответ может быть в любой голове / теле и остается в своем текущем состоянии:
res.addTrailers(headers)
Ответ должен быть в голове и становится законченным :
return next([err])
(Только подключение / экспресс)function(req, res, next)
(только Connect / Express)res.send(body|status[, headers|status[, status]])
(Экспресс только)res.attachment(filename)
(Экспресс только)res.sendfile(path[, options[, callback]])
(Экспресс только)res.json(obj[, headers|status[, status]])
(Экспресс только)res.redirect(url[, status])
(Экспресс только)res.cookie(name, val[, options])
(Экспресс только)res.clearCookie(name[, options])
(Экспресс только)res.render(view[, options[, fn]])
(Экспресс только)res.partial(view[, options])
(Экспресс только)источник
return
раньшеnext()
, спасибо, это указало мне на ошибку!Я тоже столкнулся с этой ошибкой некоторое время. Я думаю (надеюсь), что я обернул голову вокруг этого, хотел написать это здесь для справки.
Когда вы добавляете промежуточное программное обеспечение для соединения или экспрессии (которое построено на соединении) с использованием
app.use
метода, вы добавляете элементыServer.prototype.stack
в соединение (по крайней мере, с текущимnpm install connect
, который выглядит совсем не так, как один github на этот пост). Когда сервер получает запрос, он перебирает стек, вызывая(request, response, next)
метод.Проблема в том, что если в одном из элементов промежуточного программного обеспечения выполняется запись в тело или заголовки ответа (похоже, это либо / или по какой-то причине), но не вызывается,
response.end()
и вы вызываете егоnext()
по завершении основногоServer.prototype.handle
метода, он заметит который:response.headerSent
правдаИтак, выдает ошибку. Но ошибка, которую он выдает - это просто базовый ответ (из
http.js
исходного кода подключения :Здесь это вызов
res.setHeader('Content-Type', 'text/plain');
, который вы, скорее всего, установите в своемrender
методе, без вызова response.end () , что-то вроде:То, как все должно быть структурировано, выглядит следующим образом:
Хорошее Middleware
Проблемное промежуточное ПО
Проблемное промежуточное ПО устанавливает заголовок ответа без вызовов
response.end()
и вызововnext()
, что приводит в замешательство сервер подключения.источник
Некоторые из ответов в этом Q & A неправильны. Принятый ответ также не очень «практичен», поэтому я хочу опубликовать ответ, который объясняет вещи в более простых терминах. Мой ответ покроет 99% ошибок, которые я вижу, опубликованные снова и снова. По фактическим причинам ошибки посмотрите на принятый ответ.
HTTP использует цикл, который требует один ответ на запрос. Когда клиент отправляет запрос (например, POST или GET), сервер должен отправить ему только один ответ.
Это сообщение об ошибке:
обычно происходит, когда вы отправляете несколько ответов на один запрос. Убедитесь, что следующие функции вызываются только один раз за запрос:
res.json()
res.send()
res.redirect()
res.render()
(и еще несколько редко используемых, проверьте принятый ответ)
Обратный вызов маршрута не вернется при вызове этих функций res. Он будет продолжать работать до тех пор, пока не достигнет конца функции или оператора возврата. Если вы хотите вернуться при отправке ответа вы можете сделать это так:
return res.send()
.Возьмите для примера этот код:
Когда запрос POST отправляется в / api / route1, он запускает каждую строку в обратном вызове . Не может установить заголовки после отправки сообщения об ошибке будет отброшена , так как
res.json()
вызывается дважды, то есть два ответа отправляются.На один запрос может быть отправлен только один ответ!
Ошибка в приведенном выше примере кода была очевидной. Более типичная проблема - когда у вас есть несколько веток:
Этот маршрут с прикрепленным обратным вызовом находит компанию в базе данных. При выполнении запроса для несуществующей компании мы попадем внутрь
else if
филиала и отправим ответ 404. После этого мы перейдем к следующему утверждению, которое также отправляет ответ. Теперь мы отправили два ответа и появится сообщение об ошибке. Мы можем исправить этот код, убедившись, что отправляем только один ответ:или вернувшись при отправке ответа:
Большой грешник - асинхронные функции. Возьмите функцию из этого вопроса, например:
Здесь у нас есть асинхронная функция (
findOneAndUpdate()
) в примере кода. Если ошибок нет (err
)findOneAndUpdate()
будет вызван. Поскольку эта функция асинхронна,res.json(doc1)
она будет вызвана немедленно. Предположим, что нет ошибок вfindOneAndUpdate()
.res.json(doc2)
Вelse
будет называться. Теперь отправлено два ответа, и появляется сообщение об ошибке « Не удается установить заголовки» .Исправление, в этом случае, было бы удалить
res.json(doc1)
. Чтобы отправить оба документа клиенту,res.json()
в другом можно записать какres.json({ article: doc1, user: doc2 })
.источник
return
res.json
res.send
для цикла.У меня возникла такая же проблема, и я понял, что это потому, что я звонил
res.redirect
безreturn
оператора, поэтомуnext
функция также вызывалась сразу после этого:Который должен был быть:
источник
Многие люди попали в эту ошибку. Это путает с асинхронной обработкой. Скорее всего, часть вашего кода устанавливает заголовки в первом тике, а затем вы запускаете асинхронный обратный вызов в будущем. Между ними отправляется заголовок ответа, но затем дополнительные заголовки (например, перенаправление 30X) пытаются добавить дополнительные заголовки, но уже слишком поздно, поскольку заголовок ответа уже был передан.
Я не уверен точно, что является причиной вашей ошибки, но посмотрите на любые обратные вызовы как на возможные области для расследования.
Один простой совет, чтобы упростить ваш код. Избавьтесь
app.configure()
и просто позвонитеapp.use
прямо в область вашего верхнего уровня.См. Также модуль Everyauth , который предоставляет Facebook и дюжина других сторонних поставщиков аутентификации.
источник
Я вскинул голову над этой проблемой, и это произошло из-за неосторожной ошибки при обработке обратных вызовов. невозвращенные обратные вызовы приводят к тому, что ответ устанавливается дважды.!
Моя программа имела код, который проверяет запрос и запрашивает БД. после проверки, если есть ошибка, я перезванивал index.js с ошибками проверки. И если проверка проходит успешно, она идет вперед и поражает БД с успехом / неудачей.
Происходило следующее: проверка Incase завершается неудачно, вызывается обратный вызов и устанавливается ответ. Но не вернулся. Таким образом, он все еще продолжается, метод переходит к БД и поражает успех / неудачу. Он снова вызывает тот же обратный вызов, в результате чего ответ будет установлен дважды.
Таким образом, решение простое, вам нужно «вернуть» обратный вызов, чтобы метод не продолжал выполняться после возникновения ошибки и, следовательно, один раз установить объект ответа.
источник
callback(...)
без негоreturn;
после него, что в итоге вызывалоres.send(...)
вызов дважды.Этот тип ошибки вы получите при прохождении выписки после отправки ответа.
Например:
Это приведет к ошибке, которую вы видите, потому что после отправки ответа следующее
res.send
не будет выполнено.Если вы хотите что-то сделать, вы должны сделать это до отправки ответа.
источник
Иногда вы можете получить эту ошибку, когда пытаетесь вызвать функцию next () после res.end или res.send , попробуйте удалить, если у вас есть next () после res.send или res.end в вашей функции. Примечание: здесь next () означает, что после ответа клиенту своим ответом ( то есть res.send или res.end ) вы все еще пытаетесь выполнить некоторый код для повторного ответа, поэтому это недопустимо.
Пример :
источник
Если вы используете функции обратного вызова, используйте
return
послеerr
блока. Это один из сценариев, в которых может произойти эта ошибка.Протестировано на версии Node
v10.16.0
и экспресс4.16.4
источник
Эта ошибка происходит, когда вы отправляете 2 ответа. Например :
Представьте себе, если по какой-то причине условия A и B верны, то во второй
render
вы получите эту ошибкуисточник
В моем случае это был ответ 304 (кэширование), который вызывал проблему.
Самое простое решение:
Альтернативное решение здесь, если вы хотите больше контроля:
http://vlasenko.org/2011/10/12/expressconnect-static-set-last-modified-to-now-to-avoid-304-not-modified/
источник
В моем случае это произошло с React и postal.js, когда я не отписался от канала в обратном вызове
componentWillUnmount
моего компонента React.источник
Для всех, кто подходит к этому, и ни одно из других решений не помогло, в моем случае это проявилось на маршруте, который обрабатывал загрузку изображений, но не обрабатывал тайм-ауты , и, таким образом, если загрузка заняла слишком много времени и истекло время ожидания, когда был выполнен обратный вызов после отправки ответа на тайм-аут вызов res.send () привел к сбою, поскольку заголовки уже были настроены для учета тайм-аута.
Это было легко воспроизвести, установив очень короткий тайм-аут и выбрав маршрут с прилично большим изображением, авария воспроизводилась каждый раз.
источник
Просто наклонился к этому. Вы можете передать ответы через эту функцию:
источник
Добавьте эту промежуточную программу, и она будет работать
источник
Это происходит, когда ответ доставлен клиенту, и вы снова пытаетесь дать ответ. Вы должны проверить в своем коде, что где-то вы снова возвращаете ответ клиенту, который вызывает эту ошибку. Проверьте и верните ответ один раз, когда хотите вернуться.
источник
У меня была эта проблема, когда я вкладывал обещания. Обещание внутри обещания вернуло бы 200 на сервер, но тогда выражение catch внешнего обещания вернуло бы 500. Как только я исправил это, проблема исчезла.
источник
Пришел сюда из nuxt , проблема была в
asyncData
методе компонента , я забылreturn
пообещать, который выбирает данные и устанавливает там заголовок.источник
Проверьте, не возвращает ли ваш код несколько операторов res.send () для одного запроса. Как, когда у меня была эта проблема ....
Я был этой проблемой в моем приложении узла restify. Ошибка заключалась в том, что
switch (status) { case -1: res.send(400); case 0: res.send(200); default: res.send(500); }
Я занимался различными делами, используя переключатель без записи перерыва. Для тех, кто мало знаком с делом переключения, знайте, что без перерыва возвращайте ключевые слова. Код под регистром и последующими строками будет выполнен независимо от того, что. Так что, хотя я хочу отправить один res.send, из-за этой ошибки он возвращал несколько операторов res.send, что вызвало
switch (status) { case -1: res.send(400); break; case 0: res.send(200); break; default: res.send(500); break; }
источник
Вполне вероятно, что это скорее узел, 99% случаев это двойной обратный вызов, который заставляет вас ответить дважды или следующий () дважды и т. Д., Черт возьми. Это решило мою проблему, используя next () внутри цикла. Удалите next () из цикла или прекратите вызывать его более одного раза.
источник
Я получил аналогичную ошибку при попытке отправить ответ в функции цикла. Простым решением было переместить
вне цикла, поскольку вы можете отправить заголовок ответа только один раз.
https://www.tutorialspoint.com/nodejs/nodejs_response_object.htm
источник
Я просто добавляю ключевое слово возврата как:
return res.redirect("/great");
и Уолла!источник
У меня была та же проблема, которая была вызвана мангустом.
чтобы исправить это, вы должны включить
Promises
, чтобы вы могли добавить:mongoose.Promise = global.Promise
к вашему коду, который позволяет использоватьnative js promises
.Другие альтернативы этому решению:
а также
но вам нужно сначала установить эти пакеты.
источник
Ошибка найти самостоятельно после RND:
1) мой код ошибки:
return res.sendStatus(200).json({ data: result });
2) мой код успеха
return res.status(200).json({ data: result });
Разница в том, что я использовал sendStatus () вместо status () .
источник
В Typescript моей проблемой было то, что я не закрывал соединение через веб-сокет после получения сообщения.
источник
Если вы не получили помощь сверху: для noobs Причиной этой ошибки является отправка запроса несколько раз, давайте разберемся в некоторых случаях: - 1. `
`в приведенном выше вызове next () дважды вызовет ошибку
router.delete('/:orderId', (req, res, next) => { Order.remove({_id:req.params.orderId},(err,data)=>{ if(err){ **res.status(500).json(err);** }else{ res.status(200).json(data); } *res.status(200).json(data);* }) })
здесь ответ отправляется дважды, проверьте, отправили ли вы уже ответ
источник
В моем случае это происходит из-за нескольких обратных вызовов. Я вызвал
next()
метод несколько раз во время кодаисточник
Моя проблема заключалась в том, что у меня был
setInterval
бег, который имелif/else
блок, гдеclearInterval
метод был внутриelse
:Выкладывать
clearInterval
до того, какif/else
сделали трюк.источник
В моем случае, в цикле, я поставил
res.render()
так, возможно, пытались вызвать несколько раз.источник
Все, что я должен был сделать в случае этой ошибки, это res.end ().
Другая проблема, с которой вы можете столкнуться, это наличие кода после res.json и res. написать. В этом случае вам нужно использовать return, чтобы остановить выполнение после этого.
источник