Here's my problem:
I have an API in NestJS, it is hosted on Firebase (Cloud functions).
My client is an Ionic - Angular web interface.
"@nestjs/cli": "^7.5.1",
"@types/node": "^14.14.6",
"typescript": "^4.0.5"
When I test the application locally with the command npm run start
everything works fine.
When I test in production with firebase serve --only functions
or firebase deploy --only functions
, I get the following error (on browser) when launching the server :
Some of them are good, the other not.
here is a bad one:
and a good one:
Once the first slave of requests is made, everything will run again for the next 5 minutes.
You'll tell me that it's not serious, I just have to make the requests when I put the API in production and the users will be able to use it normally.
Except that when the functions are not used for about 5 minutes, the API in production pauses, then it restarts as soon as it receives a request. This behavior seems normal to me, but because of errors and therefore inconsistencies in the results on the interface.
Here is my index.ts on my NestJS api:
const server = express();
export const createNestServer = async (expressInstance) => {
const app = await NestFactory.create(
AppModule,
new ExpressAdapter(expressInstance),
);
const whitelist = [
'http://localhost:8100/',
'http://localhost:8100',
'*',
undefined,
];
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, OPTIONS',
credentials: true,
preflightContinue: true,
optionsSuccessStatus: 200,
});
return app.init();
}
createNestServer(server)
.then((v) => console.log('Nest Ready'))
.catch((err) => console.error('Nest broken', err));
export const api = functions.https.onRequest(server);
My question is this: How can I make sure that the cors are activated from the beginning when the server is launched and do not return an error at launch?
SOLUTION :
Thanks to NeatNerd, here is the solution :
Tutorial to follow : https://softwarebrothers.co/blog/setting-up-nestjs-with-firebase-functions/
my new index.ts :
import { NestFactory } from '@nestjs/core';
import { ExpressAdapter } from '@nestjs/platform-express';
import { AppModule } from './app.module';
import * as express from 'express';
import * as functions from 'firebase-functions';
const server = express();
export const createNestServer = async (expressInstance) => {
const app = await NestFactory.create(
AppModule,
new ExpressAdapter(expressInstance),
);
const whitelist = [
'http://localhost:8100/',
'http://localhost:8100',
'*',
undefined,
];
app.enableCors({
origin: function (origin, callback) {
console.log(origin);
if (whitelist.filter((x) => x && x.startsWith(origin))) {
console.log('The CORS policy for this site allow access from ', origin);
callback(null, true);
} else {
console.log(
'
The CORS policy for this site does not allow access from ',
origin,
);
callback(
new Error(
'
The CORS policy for this site does not allow access from ' +
origin,
),
false,
);
}
},
allowedHeaders:
'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept, Observe',
methods: 'GET, OPTIONS',
credentials: true,
preflightContinue: true,
optionsSuccessStatus: 200,
});
return app.init();
};
createNestServer(server)
.then((v) => console.log('Nest Ready'))
.catch((err) => console.error('Nest broken', err));
export const api = functions
.region('us-central1')
.https.onRequest(async (request, response) => {
await createNestServer(server);
server(request, response);
});
I was missing the reference to createNestServer for each call. The tutorial that allowed me to set it up doesn't have this part. However, it is still quite complementary. https://fireship.io/snippets/setup-nestjs-on-cloud-functions/
The following option is also part of the solution : (keepConnectionAlive)``
export const config: TypeOrmModuleOptions = {
type: 'mysql',
port: 3306,
host: 'xxx.xxx.xxx.xxxx',
database: 'name_of_the_database',
username: 'username',
password: 'password',
synchronize: false,
entities: [Entity1, Entity2],
autoLoadEntities: true,
keepConnectionAlive: true,
};
This allows to keep the connexion open.
question from:
https://stackoverflow.com/questions/65644286/nestjs-prod-on-firebase-has-been-blocked-by-cors-policy-no-access-control-all