NestJS enable cors in production
Asked Answered
R

17

69

I've enabled CORS in my NestJS app following the official tutorial, so my main.ts looks like the following:

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

and it works when I run the application using npm run start:dev.

However when I try to first compile the application using npm run webpack and then running it using node server.js, the cors will not work.

The http request from the client will fail with:

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.

Robles answered 20/6, 2018 at 13:18 Comment(1)
check if you have some extension in the browser blocking 3rd javascript, e.g. NoScript and Privacy BadgerStipule
R
6

Somehow the issue was compiling it using npm run webpack. If I compile it using prestart:prod then it will work.

Thanks @georgii-rychko for suggesting it via comments.

Robles answered 21/6, 2018 at 15:11 Comment(0)
P
88

Try the approach described here in the official docs: https://docs.nestjs.com/techniques/security/cors

const app = await NestFactory.create(ApplicationModule);
app.enableCors();
await app.listen(3000);
Parfait answered 21/6, 2018 at 12:11 Comment(6)
Also, I have a question: why do you build your server app using webpack? Usually, just simple tsc call is used.Parfait
Thank you but I've already tried this solution and unfortunately it does not work. I compile for production using npm run webpack which I guess it's the default way to do it with NestJS, isn't it?Robles
ShinDarth, have a look at this official example. There you can find how the app gets built github.com/nestjs/nest/tree/master/sample/10-fastify.Parfait
Try to build your app using this example as a basis.Parfait
Here is the compilation command from the scripts section of the package.json: "prestart:prod": "tsc". Just try to play with this example. In case you'll have questions - just put them here.Parfait
app.enableCors() uses default configs which seem to be invalid for some browsers (at least Chrome complains that wildcard is not allowed). Correct way would be to use app.enableCors({ origin: /.+/ });Gimcrack
T
69

If you are running NestJs with graphql you will run into a problem where Apollo server will override the CORS setting 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,
            },
        }),

then in your main.ts:

        app.enableCors({
            origin: true,
            methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
            credentials: true,
        });
Tubule answered 13/11, 2019 at 11:48 Comment(1)
Is this one still relevant ? As I saw the issue described here now we can use app.enableCors() directly github.com/nestjs/graphql/issues/2752Plasia
P
33

The documentation for the cors config object is here: https://github.com/expressjs/cors#configuration-options

I noticed nobody used an array for the origin, so in case anyone wanted some quick copy pasta

And in case you were wondering, I researched it too... http and https is considered different and so are subdomains or lack thereof (www.example.com and 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,
});
Preciado answered 5/4, 2022 at 1:48 Comment(0)
K
19

I was able to get it working by giving my own origin function. The complete enableCors function would be like for NestJS or any NodeJS server like:

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

and the appOptions if you are using NestJS Express:

const app = await NestFactory.create<NestExpressApplication>(AppModule);
Kiona answered 8/6, 2020 at 11:54 Comment(0)
M
8

Sad to know that you also tried:

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

And it's still not working.


Ensure that on your server side you have cors enabled, which should be something like this:

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

And also ensure that your browser is cors supported. If all these still doesn't work, I will advice you download Allow-Control-Allow-Origin extension for Chrome, it should fix your issue.

Maciemaciel answered 21/6, 2018 at 13:37 Comment(0)
B
7

maybe you get undefined in origin with the following whitelist .If you do not want to block REST tools or server-to-server requests, add a !origin check in the origin function like so:

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'))
    }
  },
  ...
});
Brenner answered 30/5, 2021 at 14:25 Comment(1)
A bit of more explanation regarding what does "if you do not want to block REST tools or server-to-server request" mean: I was configuring my NestJS app and then I realized that I am getting CORS error when I try to open swagger doc in my browser, so after reading this stackoverflow Q&A I understood what was wrong with my app; since I was sending a request to my NestJS app from the same origin, browser was not adding the origin header to the request. So we need to allow those requests to pass our CORS policy enforcer.Cannelloni
R
6

Somehow the issue was compiling it using npm run webpack. If I compile it using prestart:prod then it will work.

Thanks @georgii-rychko for suggesting it via comments.

Robles answered 21/6, 2018 at 15:11 Comment(0)
S
4

I was using Angular and Nest. So I just enable cors when I create app in main.ts.

const app = await NestFactory.create(AppModule, { cors: true });

Another option is:

 app.enableCors({
  origin: ['http://localhost:4200'],
  methods: ['GET', 'POST'],
  credentials: true,
 });
Suitor answered 1/6, 2023 at 4:46 Comment(0)
H
3

Bellow is my main.ts that finally worked pretty well.

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();
Halyard answered 28/9, 2021 at 21:2 Comment(0)
C
3

Who wants to use CORS policy dynamically (for example you store origins in the database):

app.enableCors({
    credentials: true,
    origin: async (requestOrigin: string, next: (err: Error | null, origin?: string[]) => void) => {
        const origins = await app.get(AppService).getOrigins();

        // origins: StaticOrigin = ['https://google.com', 'http://localhost'];
        next(null, origins);
    },
});
Calicle answered 27/3, 2023 at 16:24 Comment(0)
M
1

I tried all the other answers, but found the following works for me

const app = await NestFactory.create(AppModule, { cors: true });
await app.listen(3000);
Mosqueda answered 16/1, 2023 at 23:5 Comment(0)
C
0

None of the answers had worked until I realized nest start would run with no issues when I deleted my main.ts file.

Check that your main.ts is actually being called.

If it's not, deleting the /dist folder should do the trick.

Censer answered 17/12, 2021 at 23:19 Comment(0)
U
0
async function bootstrap() {
const app = await NestFactory.create(AppModule, new FastifyAdapter());
app.enableCors()
await app.listen(3000); 
}
bootstrap();
Underside answered 16/4, 2022 at 5:56 Comment(0)
C
0

I had to enable cors in azure. Just in case somebody has the same problem

Cryptozoite answered 29/7, 2022 at 11:37 Comment(0)
G
0

you need to ensure that the response will come with the correct header. Exemple, if you want to release all origins then the header should look like this:

Access-Control-Allow-Origin: *

enter image description here

And for this, use:

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

you need to check these details before coding.

Glenda answered 29/9, 2022 at 15:39 Comment(0)
K
-1
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();

Instead of "http://localhost:3000" paste your url client

Knurly answered 7/7, 2021 at 13:4 Comment(1)
What's the question?Primordial
P
-2

run on production mode

npm run start:prod
Plossl answered 6/8, 2022 at 18:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.