NestJS 在生产中启用 cors

NestJS enable cors in production

我在 the official tutorial 之后在我的 NestJS 应用中启用了 CORS,因此我的 main.ts 如下所示:

import { FastifyAdapter, NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, new FastifyAdapter(), { cors: true });
  await app.listen(3000);
}
bootstrap();

当我 运行 使用 npm run start:dev 的应用程序时它有效。

但是,当我尝试先使用 npm run webpack 编译应用程序,然后使用 node server.js 运行 编译应用程序时,cors 将无法工作。

来自客户端的 http 请求将失败并显示:

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. The response had HTTP status code 404.

尝试使用此处描述的方法https://docs.nestjs.com/techniques/security#cors

const app = await NestFactory.create(ApplicationModule);
app.enableCors();
await app.listen(3000);

很遗憾知道您也尝试过:

const app = await NestFactory.create(ApplicationModule);
app.enableCors();
await app.listen(3000);

而且还是不行。


确保在您的服务器端启用了 cors,应该是这样的:

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Accept');
  next();
});

并确保您的浏览器是 cors supported. If all these still doesn't work, I will advice you download Allow-Control-Allow-Origin Chrome 的扩展,它应该可以解决您的问题。

问题是使用 npm run webpack 编译它。如果我使用 prestart:prod 编译它,那么它将起作用。

感谢@georgii-rychko 通过评论提出建议。

如果您运行使用 graphql 连接 NestJs,您将 运行 遇到 Apollo 服务器将覆盖 CORS 设置的问题 see link. This below fixed the problem. I wasted 8 hrs of my life on this. :-( I hope you see this and you don't do that. see link and link

        GraphQLModule.forRoot({
            debug: process.env.NODE_ENV !== 'production',
            playground: process.env.NODE_ENV !== 'production',
            typePaths: ['./**/*.graphql'],
            installSubscriptionHandlers: true,
            context: ({req}) => {
                return {req};
            },
            cors: {
                credentials: true,
                origin: true,
            },
        }),

然后在你的 main.ts:

        app.enableCors({
            origin: true,
            methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
            credentials: true,
        });

我可以通过提供我自己的 origin 函数来让它工作。完整的 enableCors 函数对于 NestJS 或任何 NodeJS 服务器来说就像:

var whitelist = ['https://website.com', 'https://www.website.com'];
app.enableCors({
origin: function (origin, callback) {
  if (whitelist.indexOf(origin) !== -1) {
    console.log("allowed cors for:", origin)
    callback(null, true)
  } else {
    console.log("blocked cors for:", origin)
    callback(new Error('Not allowed by CORS'))
  }
},
allowedHeaders: 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept, Observe',
methods: "GET,PUT,POST,DELETE,UPDATE,OPTIONS",
credentials: true,
});

如果您使用的是 NestJS Express,则还有 appOptions:

const app = await NestFactory.create<NestExpressApplication>(AppModule);

也许您使用以下白名单获得 undefined 来源。如果您不想阻止 REST 工具 服务器到服务器requests,在原始函数中添加一个 !origin 检查,如下所示:

const whitelist = ['example.com', 'api.example.com'];
app.enableCors({
  origin: function (origin, callback) {
    if (!origin || whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  },
  ...
});
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const PORT = 5000;
  const app = await NestFactory.create(AppModule);

  app.enableCors({credentials: true, origin: "http://localhost:3000"});

  await app.listen(PORT, () => console.log(`Server started`));
}

bootstrap();

而不是“http://localhost:3000”粘贴您的 url 客户端

下面是我的main.ts,最终效果很好。

import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
import { AppModule } from './app.module';

async function bootstrap() {
    const app = await NestFactory.create<NestExpressApplication>(
        AppModule,
    );

    app.useStaticAssets(join(__dirname, '..', 'public'));
    app.setBaseViewsDir(join(__dirname, '..', 'views'));
    app.setViewEngine('hbs');

    app.use((req, res, next) => {
        res.header('Access-Control-Allow-Origin', '*');
        res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
        res.header('Access-Control-Allow-Headers', 'Content-Type, Accept');
        next();
    });

    app.enableCors({
        allowedHeaders:"*",
        origin: "*"
    });

    await app.listen(3000);
}

bootstrap();

None 的答案一直有效,直到我意识到 nest start 在我删除我的 main.ts 文件时 运行 没有问题。

检查您的 main.ts 是否确实被呼叫。

如果不是,删除 /dist 文件夹应该可以解决问题。

cors 配置对象的文档在此处:https://github.com/expressjs/cors#configuration-options

我注意到没有人使用数组作为原点,以防万一有人想要一些快速复制意大利面

如果您想知道,我也进行了研究...http 和 https 被认为是不同的,子域或缺少子域也是如此(www.example.com 和 app.example.com)。

app.enableCors({
  origin: [
    'http://localhost:3000',
    'http://example.com',
    'http://www.example.com',
    'http://app.example.com',
    'https://example.com',
    'https://www.example.com',
    'https://app.example.com',
  ],
  methods: ["GET", "POST"],
  credentials: true,
});
async function bootstrap() {
const app = await NestFactory.create(AppModule, new FastifyAdapter());
app.enableCors()
await app.listen(3000); 
}
bootstrap();