58

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.

Francesco Borzi
  • 56,083
  • 47
  • 179
  • 252

17 Answers17

80

Try to use an approach described in here https://docs.nestjs.com/techniques/security#cors

const app = await NestFactory.create(ApplicationModule);
app.enableCors();
await app.listen(3000);
SharkofMirkwood
  • 11,483
  • 2
  • 17
  • 25
Georgii Rychko
  • 801
  • 5
  • 2
  • Also, I have a question: why do you build your server app using webpack? Usually, just simple `tsc` call is used. – Georgii Rychko Jun 21 '18 at 12:13
  • 2
    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? – Francesco Borzi Jun 21 '18 at 12:23
  • 1
    ShinDarth, have a look at this official example. There you can find how the app gets built https://github.com/nestjs/nest/tree/master/sample/10-fastify. – Georgii Rychko Jun 21 '18 at 13:18
  • Try to build your app using this example as a basis. – Georgii Rychko Jun 21 '18 at 13:18
  • 1
    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. – Georgii Rychko Jun 21 '18 at 13:21
  • `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: /.+/ });` – Karolis Mar 06 '19 at 08:07
62

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,
        });
David Dehghan
  • 22,159
  • 10
  • 107
  • 95
26

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,
});
wongz
  • 3,255
  • 2
  • 28
  • 55
16

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);
cyperpunk
  • 664
  • 7
  • 13
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.

antzshrek
  • 9,276
  • 5
  • 26
  • 43
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.

Francesco Borzi
  • 56,083
  • 47
  • 179
  • 252
5

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'))
    }
  },
  ...
});
Abolfazl Roshanzamir
  • 12,730
  • 5
  • 63
  • 79
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();
Dharman
  • 30,962
  • 25
  • 85
  • 135
Rafael Xavier
  • 956
  • 13
  • 13
2

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,
 });
Akib
  • 304
  • 2
  • 9
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);
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
1

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);
    },
});
zemil
  • 3,235
  • 2
  • 24
  • 33
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.

Anthony
  • 119
  • 2
  • 4
0
async function bootstrap() {
const app = await NestFactory.create(AppModule, new FastifyAdapter());
app.enableCors()
await app.listen(3000); 
}
bootstrap();
Shuvro
  • 222
  • 3
  • 7
0

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

Just A Question
  • 423
  • 6
  • 21
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.

-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

Leonar
  • 1
-2

run on production mode

npm run start:prod
Anojan
  • 297
  • 2
  • 4