오류 : 클라이언트로 전송 된 헤더를 설정할 수 없습니다


724

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

내 코드에 어떤 문제가 있는지 알 수 있습니까?


visionmedia에서 간단한 대답 : github.com/visionmedia/express/issues/634
shi11i

2
구글은이 질문에 나를 보냈지 만 ExpressJS의 최신 버전은이 res.headersSent 세트 / 전송 헤더에 안전 여부를 확인하는 데 사용할 수있는 부울
줄리안 소로

답변:


1112

resExpress 의 객체는 Node.js의http.ServerResponse 하위 클래스입니다 ( http.js 소스 읽기 ). 전화 res.setHeader(name, value)할 때까지 원하는만큼 전화를 걸 수 res.writeHead(statusCode)있습니다. 이후 writeHead에는 헤더가 구워지고, 만 호출 할 수 res.write(data)있으며 마지막으로res.end(data) .

오류 : "오류 : 헤더를 보낸 후 설정할 수 없습니다." 은 이미 본문 또는 완료 상태에 있지만 일부 함수가 헤더 또는 statusCode를 설정하려고 시도했음을 의미합니다. 이 오류가 표시되면 일부 본문이 이미 작성된 후 헤더를 보내려는 항목을 찾으십시오. 예를 들어 실수로 두 번 호출 된 콜백이나 본문이 전송 된 후 발생하는 오류를 찾으십시오.

귀하의 경우에 전화를 걸어 res.redirect()응답이 완료되었습니다. 그런 다음 코드에서 오류가 발생했습니다 ( res.reqis null). function(req, res, next)콜백이 아닌 실제 내에서 오류가 발생했기 때문에 Connect는이 오류를 잡아 500 오류 페이지를 보내려고했습니다. 그러나 헤더가 이미 전송되었으므로 Node.js는setHeader 는 본 오류를 던졌습니다.

Node.js / Express 응답 메소드의 포괄적 인 목록 및 호출시기 :

응답에 있어야 헤드 및 유지 헤드 :

  1. res.writeContinue()
  2. res.statusCode = 404
  3. res.setHeader(name, value)
  4. res.getHeader(name)
  5. res.removeHeader(name)
  6. res.header(key[, val]) (익스프레스 만)
  7. res.charset = 'utf-8' (Express 만 해당, Express 특정 방법에만 영향을 미침)
  8. res.contentType(type) (익스프레스 만)

응답은 Head에 있어야하며 Body 가됩니다 .

  1. res.writeHead(statusCode, [reasonPhrase], [headers])

응답 중 하나 일 수 있습니다 헤드 / 바디 와 남아 바디 :

  1. res.write(chunk, encoding='utf8')

응답 중 하나 일 수 있습니다 헤드 / 바디 및됩니다 완료 :

  1. res.end([data], [encoding])

응답은 헤드 / 바디 일 수 있으며 현재 상태를 유지합니다.

  1. res.addTrailers(headers)

응답에 있어야 헤드 및됩니다 완료 :

  1. return next([err]) (연결 / 표현 만)
  2. 미들웨어 내의 모든 예외 function(req, res, next)(Connect / Express 만 해당)
  3. res.send(body|status[, headers|status[, status]]) (익스프레스 만)
  4. res.attachment(filename) (익스프레스 만)
  5. res.sendfile(path[, options[, callback]]) (익스프레스 만)
  6. res.json(obj[, headers|status[, status]]) (익스프레스 만)
  7. res.redirect(url[, status]) (익스프레스 만)
  8. res.cookie(name, val[, options]) (익스프레스 만)
  9. res.clearCookie(name[, options]) (익스프레스 만)
  10. res.render(view[, options[, fn]]) (익스프레스 만)
  11. res.partial(view[, options]) (익스프레스 만)

13
그래, next () 또는 다른 cb를 두 번 호출했는지 확인하십시오.
Tony Gutierrez

3
익스프레스 링크가 죽은 것 같다
코란 오즈 터크에게

25
또한이 고전적인 실수를 조심하십시오 : res.redirect ()는 명령문 실행을 멈추지 않습니다 ... 따라서 반환하십시오. 그렇지 않으면 다른 코드가 실행되어 유명한 헤더 오류를 무의식적으로 유발할 수 있습니다. 설명 감사합니다!
KLoozen

이것을 피하기 위해 콜백이 끝나면 return을 사용하는 것이 좋습니다.
thethakuri

4
나는 일부러 내 미들웨어에 아주 작은 실수를 return하기 전에 next(), 덕분에이 오류에 저를 지적했다!
illcrx

113

나는이 오류를 잠시 동안 만났다. 내 머리를 감아 서 여기에 참고로 쓰고 싶었다고 생각합니다.

메소드를 사용하여 연결 하거나 표현 하기 위해 (미리 연결되어있는) 미들웨어를 추가 할 때 연결에app.use 항목을 추가 Server.prototype.stack하고 있습니다 (적어도 현재와 npm install connect같이,이 게시물과 같이 하나의 github와는 상당히 다릅니다). 서버가 요청을 받으면 스택을 반복하여 (request, response, next)메소드를 호출합니다 .

문제는 미들웨어 중 하나에서 항목이 응답 본문 또는 헤더에 쓰지만 ( 어떤 이유로 든 또는 어떤 이유로 보이는지) 호출하지 않고 전화 response.end()를 거는 것입니다.next() 핵심 Server.prototype.handle메소드가 완료되면 하는 것입니다. 그:

  1. 스택에 더 이상 아이템이 없거나
  2. 그것은 response.headerSent사실이다.

따라서 오류가 발생합니다. 그러나 발생하는 오류는 연결 http.js소스 코드 의 기본 응답입니다 .

res.statusCode = 404;
res.setHeader('Content-Type', 'text/plain');
res.end('Cannot ' + req.method + ' ' + req.url);

거기에서 response.end ()를 호출하지 않고 메소드 res.setHeader('Content-Type', 'text/plain');에서 설정했을 가능성이있는 을 호출합니다 .render

response.setHeader("Content-Type", "text/html");
response.write("<p>Hello World</p>");

모든 것을 구성해야하는 방법은 다음과 같습니다.

좋은 미들웨어

// middleware that does not modify the response body
var doesNotModifyBody = function(request, response, next) {
  request.params = {
    a: "b"
  };
  // calls next because it hasn't modified the header
  next();
};

// middleware that modify the response body
var doesModifyBody = function(request, response, next) {
  response.setHeader("Content-Type", "text/html");
  response.write("<p>Hello World</p>");
  response.end();
  // doesn't call next()
};

app.use(doesNotModifyBody);
app.use(doesModifyBody);

문제가있는 미들웨어

var problemMiddleware = function(request, response, next) {
  response.setHeader("Content-Type", "text/html");
  response.write("<p>Hello World</p>");
  next();
};

문제가있는 미들웨어는 호출 response.end()및 호출 없이 응답 헤더를 설정하여 next()connect의 서버를 혼란스럽게합니다.


7
+1 이것은 훌륭한 설명이지만 res.redirect ()를 사용하는 경우는 어떻습니까? 미들웨어가 특정 조건에 따라 리디렉션하려고 할 때이 문제가 자주 발생합니다. "Good Middleware"예제에 따라 미들웨어가 경로 재 지정되지 않아야합니까?
qodeninja

문제가 발생한 미들웨어로 인해이 정확한 문제가 있음을 알고 있지만 응답을 반환하지만 체인의 일부로 별도의 컨트롤러에서 추가 처리를 수행하려는 경우가 필요합니다.이 오류를 어떻게 억제합니까? ?
iQ.

57

이 Q & A의 일부 답변이 잘못되었습니다. 허용되는 답변도 "실제적인"것은 아니므로 더 간단한 용어로 설명하는 답변을 게시하고 싶습니다. 내 대답은 반복해서 게시 된 오류의 99 %를 다룰 것입니다. 오류의 실제 원인으로 허용되는 답변을 살펴보십시오.


HTTP는 요청 당 하나의 응답이 필요한주기를 사용합니다. 클라이언트가 요청 (예 : POST 또는 GET)을 보내면 서버는 하나의 응답 만 다시 보내야합니다.

이 오류 메시지 :

오류 : 헤더를 보낸 후 설정할 수 없습니다.

일반적으로 한 요청에 여러 응답을 보낼 때 발생합니다. 다음 함수는 요청 당 한 번만 호출되어야합니다.

  • res.json()
  • res.send()
  • res.redirect()
  • res.render()

(그리고 거의 사용되지 않는 몇 가지, 허용되는 답변을 확인하십시오)

이러한 res 함수가 호출 될 때 경로 콜백은 반환되지 않습니다. 함수의 끝이나 return 문에 도달 할 때까지 계속 실행됩니다. 응답을 보낼 때 돌아 오려면 다음과 같이하십시오 : return res.send().


이 코드를 예로 들어 보겠습니다.

app.post('/api/route1', function(req, res) {
  console.log('this ran');
  res.status(200).json({ message: 'ok' });
  console.log('this ran too');
  res.status(200).json({ message: 'ok' });
}

POST 요청이 / api / route1로 전송 되면 콜백의 모든 라인이 실행됩니다. 가 전송 된 후 캔은 헤더를 설정하지 때문에 오류 메시지가 발생합니다 res.json()두 번 호출되는 두 개의 응답이 전송됩니다 의미.

요청 당 하나의 응답 만 보낼 수 있습니다!


위의 코드 샘플의 오류는 명백했습니다. 보다 일반적인 문제는 여러 가지가있는 경우입니다.

app.get('/api/company/:companyId', function(req, res) {
  const { companyId } = req.params;
  Company.findById(companyId).exec((err, company) => {
      if (err) {
        res.status(500).json(err);
      } else if (!company) {
        res.status(404).json();      // This runs.
      }
      res.status(200).json(company); // This runs as well.
    });
}

콜백이 첨부 된이 경로는 데이터베이스에서 회사를 찾습니다. 존재하지 않는 회사에 대한 쿼리를 수행하면 else if지점에 들어가서 404 응답을 보냅니다. 그 후에, 우리는 다음 문장으로 계속해서 응답을 보냅니다. 이제 두 개의 응답을 보냈으며 오류 메시지가 나타납니다. 응답을 하나만 보내도록하여이 코드를 수정할 수 있습니다.

.exec((err, company) => {
  if (err) {
    res.status(500).json(err);
  } else if (!company) {
    res.status(404).json();         // Only this runs.
  } else {
    res.status(200).json(company);
  }
});

또는 응답이 전송 될 때 돌아갑니다.

.exec((err, company) => {
  if (err) {
    return res.status(500).json(err);
  } else if (!company) {
    return res.status(404).json();  // Only this runs.
  }
  return res.status(200).json(company);
});

큰 죄인은 비동기 함수입니다. 질문 에서 다음 과 같은 기능을 수행 하십시오 .

article.save(function(err, doc1) {
  if (err) {
    res.send(err);
  } else {
    User.findOneAndUpdate({ _id: req.user._id }, { $push: { article: doc._id } })
    .exec(function(err, doc2) {
      if (err) res.send(err);
      else     res.json(doc2);  // Will be called second.
    })

    res.json(doc1);             // Will be called first.
  }
});

findOneAndUpdate()코드 샘플 에는 비동기 함수 ( )가 있습니다. 오류가 없으면 ( err) findOneAndUpdate()이 호출됩니다. 이 함수는 비동기식이므로 res.json(doc1)즉시 호출됩니다. 에 오류가 없다고 가정합니다 findOneAndUpdate(). res.json(doc2)에서는 else다음 호출됩니다. 두 개의 응답이 전송되었으며 헤더를 설정할 수 없습니다 오류 메시지가 나타납니다.

이 경우 수정은을 제거하는 것 res.json(doc1)입니다. 두 문서를 모두 클라이언트로 다시 보내려면 다른 문서를로 res.json()작성할 수 있습니다 res.json({ article: doc1, user: doc2 }).


2
당신은 비동기 함수 내에서, 그리고해야returnres.json
Genovo

내 문제는 res.sendfor 루프를 사용 하고 있었습니다 .
Maihan Nijat

1
이것은 결국 문제를 이해하고 고치는 데 도움이되었습니다. 감사합니다. :)
Pankaj Parkar

시간을 절약 해 주셔서 감사합니다.
모하마드 파이살

이것은 확실히 최고의 답변입니다!
Juanma Menendez 2018 년

53

나는 똑같은 문제가 있었고 명령문 res.redirect없이 호출했기 때문에 그것이 즉시 호출되었다는 것을 깨달았습니다 .returnnext

auth.annonymousOnly = function(req, res, next) {
    if (req.user) res.redirect('/');
    next();
};

어느 것이 좋을까 :

auth.annonymousOnly = function(req, res, next) {
    if (req.user) return res.redirect('/');
    next();
};

43

많은 사람들이이 오류에 부딪쳤다. 비동기 처리와 혼동됩니다. 아마도 일부 코드는 첫 번째 틱에서 헤더를 설정하고 향후 틱에서 비동기 콜백을 실행 중일 것입니다. 그 사이에 응답 헤더가 전송되지만 30X 리디렉션과 같은 추가 헤더는 추가 헤더를 추가하려고 시도하지만 응답 헤더가 이미 전송되었으므로 너무 늦습니다.

정확히 무엇이 오류의 원인인지 확실하지 않지만 조사 할 수있는 영역으로 콜백을 확인하십시오.

코드를 단순화하는 간단한 팁 제거 app.configure()하고 전화하십시오app.use 최상위 범위에서 직접 하십시오.

Facebook 및 12 개 이상의 타사 인증 제공 업체를 수행 하는 everyauth 모듈 도 참조하십시오 .


30X 리디렉션은 HTTP 응답 코드입니다. w3.org/Protocols/rfc2616/rfc2616-sec10.html 코드 300-399는 리디렉션의 다른 변형이며 302 및 301은 일반적으로 클라이언트를 대체 URL로 보내는 데 사용됩니다. 노드에서 response.redirect (...)를 수행하면 응답으로 30X 리디렉션 헤더가 전송됩니다.
Peter Lyons

3
오 나는 연속으로 30 개의 리디렉션을 상상하고 있었다
Janac Meena

17

나는이 문제에 대해 머리를 끓 였고 콜백 처리에 대한 부주의 한 실수로 인해 발생했습니다. 반환되지 않은 콜백은 응답을 두 번 설정합니다.!

내 프로그램에는 요청을 확인하고 DB를 쿼리하는 코드가 있습니다. 오류가 있는지 확인한 후 유효성 검사 오류가있는 index.js를 다시 호출했습니다. 그리고 유효성 검사가 통과하면 성공 / 실패로 db에 도달합니다.

    var error = validateRequestDetails("create",queryReq);
    if (error)
        callback(error, null);
   else
    some code 
    callback(null, success);

발생한 일 : 유효성 검사에 실패하면 콜백 호출 및 응답 설정이 실패합니다. 그러나 반환되지 않았습니다. 따라서 여전히 방법이 db로 이동하여 success / failure에 도달합니다. 동일한 콜백을 다시 호출하여 응답이 두 번 설정되었습니다.

따라서 해결책은 간단합니다. 오류가 발생하면 메소드가 계속 실행되지 않도록 콜백을 '반환'해야하므로 응답 객체를 한 번 설정해야합니다

  var error = validateRequestDetails("create",queryReq);
    if (error)
        callback(error, null);
        return;
    else
       some code 
       callback(null, success);

1
감사! 이것은 내 문제이기도합니다. 그냥 Ctrl + F를하고 결국 두 번 호출 되는 원인이 callback(...)없는 return;후를 찾았습니다 res.send(...).

15

응답을 보낸 후 명령문을 전달하면 이러한 유형의 오류가 발생합니다.

예를 들면 다음과 같습니다.

res.send("something response");
console.log("jhgfjhgsdhgfsdf");
console.log("sdgsdfhdgfdhgsdf");
res.send("sopmething response");

응답이 전송되면 다음 res.send이 실행되지 않기 때문에보고있는 오류가 발생합니다 .

원하는 것을하려면 응답을 보내기 전에해야합니다.


이것은 내 정확한 문제였습니다 :)
Joel Balmer

6

res.end 또는 res.send 후 next () 함수를 호출하려고 할 때 때때로이 오류가 발생할 수 있습니다. res.send 또는 res.end 후에 next ()가 있으면 함수 를 삭제하십시오. 참고 : 여기서 next ()는 응답으로 클라이언트에 응답 한 후 ( 예 : res.send 또는 res.end)를 의미합니다. )으로 후에도 여전히 응답하기 위해 일부 코드를 실행하려고하므로 합법적이지 않습니다.

예 :

router.get('/',function (req,res,next){
     res.send("request received");
     next(); // this will give you the above exception 
});

next()위의 기능에서 제거 하면 작동합니다.


6

콜백 함수를 사용 return하는 경우 err블록 뒤에 사용 하십시오 . 이 오류가 발생할 수있는 시나리오 중 하나입니다.

userModel.createUser(data, function(err, data) {
    if(err) {
      res.status = 422
      res.json(err)
      return // without this return the error can happen.
    }
    return res.json(data)
  })

Node 버전 v10.16.0및 Express 에서 테스트4.16.4


4

이 오류는 2 개의 응답을 보낼 때 발생합니다. 예를 들면 다음과 같습니다.

if(condition A)
{ 

      res.render('Profile', {client:client_});

}

if (condition B){

      res.render('Profile', {client:client_});
    }
  }

어떤 이유로 인해 조건 A와 B가 사실이라고 상상해보십시오. 두 번째에 render그 오류가 발생합니다.


3

제 경우에는 문제를 일으킨 304 응답 (캐싱)이었습니다.

가장 쉬운 솔루션 :

app.disable('etag');

더 많은 제어를 원한다면 여기에 다른 해결책이 있습니다.

http://vlasenko.org/2011/10/12/expressconnect-static-set-last-modified-to-now-to-avoid-304-not-modified/


제 경우에도 304 응답입니다. 처리에 파이버를 사용하고 있습니다. 어떤 식 으로든 대답이 많은 도움이됩니다. 감사합니다
Dileep stanley

누구나 etag 헤더를 제거하는 데 어떤 영향이 있는지 설명 할 수 있습니까?
mattwilsn

2
ETag는 서버가 변경되지 않은 컨텐츠를 보내지 못하게합니다. 끄면이 기능이 비활성화됩니다. ETag 위키 백과 항목 ( en.wikipedia.org/wiki/HTTP_ETag )에는 더 긴 설명이 있습니다.
담임

3

필자의 경우 React 및 postal.js에서 componentWillUnmountReact 구성 요소 의 콜백 에서 채널을 구독 취소하지 않았을 때 발생했습니다 .


2

이 문제가 발생하고 다른 솔루션 중 어느 것도 도움이되지 않은 사람에게는 내 경우에는 이미지 업로드를 처리했지만 시간 초과를 처리하지 않은 경로에 나타 났으 므로 업로드가 너무 오래 걸리고 콜백이 발생했을 때 타임 아웃 응답이 전송 된 후 res.send ()를 호출하면 헤더가 이미 시간 초과를 처리하도록 설정되어 충돌이 발생했습니다.

이것은 매우 짧은 타임 아웃을 설정하고 상당히 큰 이미지로 경로를 쳐서 쉽게 재현되었으며 매번 충돌이 재현되었습니다.


1
이것을 피하기 위해 타임 아웃을 어떻게 처리 했습니까?

2

방금 이것을 배웠습니다. 이 함수를 통해 응답을 전달할 수 있습니다.

app.use(function(req,res,next){
  var _send = res.send;
  var sent = false;
  res.send = function(data){
    if(sent) return;
    _send.bind(res)(data);
    sent = true;
};
  next();
});

2

이 middlware를 추가하면 작동합니다

app.use(function(req,res,next){
 var _send = res.send;
var sent = false;
res.send = function(data){
    if(sent) return;
    _send.bind(res)(data);
    sent = true;
};
next();
});

2

응답이 클라이언트에 전달되고 다시 응답하려고 할 때 발생합니다. 코드를 확인하여 어딘가에 클라이언트에게 응답을 다시 반환하면이 오류가 발생하는지 확인해야합니다. 당신이 돌아오고 싶을 때 응답을 한 번 확인하고 돌려 보내십시오.


1

약속을 중첩 할 때이 문제가 발생했습니다. 약속 내부의 약속은 서버로 200을 반환하지만 외부 약속의 catch 문은 500을 반환합니다.이 문제를 해결하면 문제가 사라졌습니다.


정확히 어떻게 고쳤습니까? 약속과 같은 문제가 있습니다. 중첩을 피할 수 없습니다 ... return 문에서 실행을 어떻게 중지합니까?
saurabh

1

nuxt 에서 왔는데 , 문제는 구성 요소의 asyncData방법 에 있었고 , return데이터를 가져오고 거기에 헤더를 설정하는 것을 약속하는 것을 잊었습니다 .


1

코드가 단일 요청에 대해 여러 res.send () 문을 반환하는지 확인하십시오. 내가이 문제가있을 때처럼 ....

restify node 응용 프로그램 에서이 문제였습니다. 실수는

switch (status) { case -1: res.send(400); case 0: res.send(200); default: res.send(500); }

쓰기 중단없이 스위치를 사용하여 다양한 사례를 처리하고있었습니다. 스위치 케이스에 익숙하지 않은 사용자에게는 중단없이 키워드를 반환하십시오. 대소 문자와 다음 행의 코드는 무엇이든 실행됩니다. 따라서 단일 res.send를 보내고 싶지만이 실수로 인해 여러 res.send 문이 반환되었습니다.

헤더는 클라이언트로 전송 된 후 헤더를 설정할 수 없습니다. 이것을 추가하거나 return res.send (200)와 같은 각 res.send () 메소드 전에 return을 사용하여 해결되었습니다.

switch (status) { case -1: res.send(400); break; case 0: res.send(200); break; default: res.send(500); break; }


당신에게 영감을 주셔서 감사합니다. 조건이 다른 경우에도 해결했습니다.
Amr AbdelRahman

1

이것은 노드 문제 일 가능성이 큽니다. 99 %의 시간은 이중 콜백으로 두 번 응답하거나 다음으로 두 번 () 두 번 응답하는 것입니다. 루프 내에서 next ()를 사용하는 문제를 해결했습니다. 루프에서 next ()를 제거하거나 호출을 두 번 이상 중지하십시오.



1

나는 단순히 다음 return res.redirect("/great");과 같은 리턴 키워드를 추가합니다 .


1

몽구스로 인한 동일한 문제가있었습니다.

사용하도록 수정해야 합니다. 코드 Promises에 다음 mongoose.Promise = global.Promise을 추가 할 수 있습니다 native js promises.

이 soloution의 다른 대안은 다음과 같습니다.

var mongoose = require('mongoose');
// set Promise provider to bluebird
mongoose.Promise = require('bluebird');

// q
mongoose.Promise = require('q').Promise;

그러나 먼저이 패키지를 설치해야합니다.


1

RND 후 자체적으로 오류 찾기 :

1) 내 오류 코드 :

return res.sendStatus(200).json({ data: result });

2) 내 성공 코드

return res.status(200).json({ data: result });

차이가 나는 사용이다 sendStatus을 () 대신에 상태 () .


0

Typescript에서 내 문제는 메시지를받은 후 웹 소켓 연결을 닫지 않았다는 것입니다.

WebSocket.on("message", (data) => {
    receivedMessage = true;
    doSomething(data);
    localSocket.close(); //This close the connection, allowing 
});

0

위의 도움을받지 못한 경우 : 멍청한 놈들이 오류의 원인은 요청을 여러 번 보내는 것입니다.

module.exports = (req,res,next)=>{
        try{
           const decoded  = jwt.verify(req.body.token,"secret");
           req.userData = decoded;
           next();
        }catch(error){
            return res.status(401).json({message:'Auth failed'});
        }
        next();   
        }

`next ()를 두 번 호출하면 오류가 발생합니다.

  1. 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);* }) })

여기에 응답이 두 번 발송됩니다 이미 응답을 보냈는지 확인하십시오.


0

제 경우에는 여러 개의 콜백으로 인해 발생합니다. next()코드 중에 메소드를 여러 번 호출했습니다.


0

내 문제는 setInterval실행이 있었고 if/else블록 이 있었고 clearInterval메소드가 내부에있는 곳 이었습니다 else.

      const dataExistsInterval = setInterval(async () => {
        const dataExists = Object.keys(req.body).length !== 0;
        if (dataExists) {
          if (!req.files.length) {
            return res.json({ msg: false });
          } else {
              clearInterval(dataExistsInterval);
            try {
            . . .

퍼팅 clearInterval(가) 전에 if/else트릭을했다.



-1

이 오류가 발생했을 때해야 할 일은 res.end ()였습니다.

 auth.annonymousOnly = function(req, res, next) {
 // add other task here   
   res.end();    
  };

직면 할 수있는 다른 문제는 res.json 및 res 뒤에 코드가 있다는 것입니다. 쓰다. 이 경우 return을 사용하여 실행을 중지해야합니다.

 auth.annonymousOnly = function(req, res, next) {

  if(!req.body.name)
  {
    res.json({error:"some error"});
    return;
  }
  let comp = "value"; // this is the code after res.json which may cause some problems so you have to use return 
};
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.