快递|将标头发送到客户端后无法设置标头

时间:2020-06-25 04:22:05

标签: node.js typescript express

我正在尝试使用passport-jwt和passport-local-mongoose创建一个简单的API,我设置了所有的JWT功能并建立了一些路由,例如一个注册路径和一个登录路径!这些路由中的一个ogf会收到一个get请求,以列出数据库中存在的所有文档,但是,当我尝试发出此请求时,服务器给了我这个错误:

DError [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:533:11)
    at ServerResponse.header (/home/mdsp/Documents/Challenges/passportJWTMongoose/node_modules/express/lib/response.js:771:10)
    at ServerResponse.json (/home/mdsp/Documents/Challenges/passportJWTMongoose/node_modules/express/lib/response.js:264:10)
    at /home/mdsp/Documents/Challenges/passportJWTMongoose/src/controllers/Document.ts:9:18
    at step (/home/mdsp/Documents/Challenges/passportJWTMongoose/src/controllers/Document.ts:33:23)
    at Object.next (/home/mdsp/Documents/Challenges/passportJWTMongoose/src/controllers/Document.ts:14:53)
    at fulfilled (/home/mdsp/Documents/Challenges/passportJWTMongoose/src/controllers/Document.ts:5:58)
    at processTicksAndRejections (internal/process/task_queues.js:97:5) {
  code: 'ERR_HTTP_HEADERS_SENT'
}

我对此进行了搜索,发现该错误通常是由于双重回调或类似原因引起的,但是我无法指定错误的出处以及为什么在我的代码中发生此错误。这是Document控制器:

import { Request, Response } from "express";

import DocumentModel from "../database/models/Document";

class Document {
  async index(req: Request, res: Response) {
    try {
      const documents = await DocumentModel.find();
      return res.status(200).json(documents);
    } catch (err) {
      console.log(err);
      return res.status(400).json({ error: err.message });
    }
  }
}

export default new Document();

这是我的路线文件:

import { Router } from "express";

import auth from "./middleware/auth";
import documentController from "./controllers/Document";

const router = Router();

router.get("/", (req, res) => {
  return res.json({ home: "My homepage" });
});

router.get("/documents", auth.requireJWT, documentController.index);

router.post("/auth/register", auth.register, auth.signJWTForUser);

router.post("/auth", auth.signIn, auth.signJWTForUser);

export default router;

这是auth.ts,我在其中配置了所有passport和JWT函数以进行拒绝,登录和请求JWT令牌:

import { config } from "dotenv";
config();
import passport from "passport";
import JWT from "jsonwebtoken";
import { Strategy, ExtractJwt } from "passport-jwt";
import { Request, Response, NextFunction } from "express";

import UserModel from "../database/models/User";

interface IRequestUser extends Express.User {
  _id?: string;
  email?: string;
  firstName?: string;
  lastName?: string;
}

const jwtSecret = process.env.JWT_SECRET!;
const jwtAlgorithm = "HS256";
const jwtExpiresIn = "7 days";

passport.use(UserModel.createStrategy());

async function register(req: Request, res: Response, next: NextFunction) {
  try {
    const { email, firstName, lastName, password } = req.body;

    const user = new UserModel({
      email: email,
      firstName: firstName,
      lastName: lastName,
    });

    const registeredUser = await UserModel.register(user, password);

    req.user = registeredUser;

    return next();
  } catch (err) {
    console.log(err.message);
    return next(err);
  }
}

passport.use(
  new Strategy(
    {
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: jwtSecret,
      algorithms: [jwtAlgorithm],
    },
    async (payload, done) => {
      try {
        const foundUser = await UserModel.findById(payload.sub);

        foundUser && done(null, foundUser);

        done(null, false);
      } catch (err) {
        console.log(err.message);
        done(err, false);
      }
    }
  )
);

function signJWTForUser(req: Request, res: Response) {
  if (req.user) {
    const user: IRequestUser = req.user;

    const token = JWT.sign({ email: user.email }, jwtSecret, {
      algorithm: jwtAlgorithm,
      expiresIn: jwtExpiresIn,
      subject: user._id!.toString(),
    });

    return res.json({ token });
  }
}

export default {
  initialize: passport.initialize(),
  register,
  signIn: passport.authenticate("local", { session: false }),
  requireJWT: passport.authenticate("jwt", { session: false }),
  signJWTForUser,
};

我应该在控制器上进行哪些改进以及导致此错误的原因?

1 个答案:

答案 0 :(得分:2)

您的护照策略设置自定义回调在找到用户时会发送两个休止符。

const foundUser = await UserModel.findById(payload.sub);

foundUser && done(null, foundUser);
done(null, false);    //<<<- HERE

我不是Passport.js专家-但是您应该按照文档将其调用一次。

const foundUser = await UserModel.findById(payload.sub);
done(null, foundUser);