I'm new to NestJS and on every route my web app is trying to query, it fails on the OPTIONS request, getting:
{"statusCode":404,"error":"Not Found","message":"Cannot OPTIONS
/authenticate"}
however trying a direct GET or POST request works fine.
after some researches I've realised that I simply needed to enable CORS (Access-Control-Allow-Origin), which I can do by editing my main.ts and passing cors: true to the NestFactory.create options (second parameter).
import { NestFactory } from '#nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule, { cors: true });
await app.listen(3000);
}
bootstrap();
Some extra info on CORS, if you enable it via:
import { NestFactory } from '#nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule, { cors: true });
await app.listen(3000);
}
bootstrap();
This will allow Cross Origin Requests from any domain. Which is generally not security best practice.
If you want to allow CORS to intercept your preflight requests, but also only allow origin requests from within the server, you can use this config:
.....
const app = await NestFactory.create(ApplicationModule, {cors: {
origin: true,
preflightContinue: false,
}});
.....
Anyone still looking for the answer
app.enableCors();
Related
Hi I have a FE react app and a BE nest.js app running on the same centos 7 virtual machine, my problem is that I can't make the rest calls from FE to BE due to the error reported under the thing that seems to me strange is that on my local machine, ubuntu there is no cors error, what is this due to? how can i fix it? i have to edit axios
Error:
Multi-origin request blocked (cross-origin): the origin match criterion does not allow the remote resource to be read from http: // localhost: 3001 / user. Reason: CORS request failed. Status code: (null)
Nest.js code:
import { ValidationPipe } from "#nestjs/common";
import { NestFactory } from "#nestjs/core";
import { SwaggerModule, DocumentBuilder } from "#nestjs/swagger";
import { AppModule } from "./app.module";
import * as cookieParser from "cookie-parser";
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
cors: true,
});
const config = new DocumentBuilder()
.setTitle("Backend ")
.setDescription("Api Backend")
.setVersion("1.0")
.addTag("Backend")
.addBearerAuth(
{ type: "http", scheme: "bearer", bearerFormat: "JWT" },
"access-token"
)
.build();
//Setup swagger module
var options = {
deepScanRoutes: true,
};
const document = SwaggerModule.createDocument(app, config, options);
SwaggerModule.setup("api", app, document);
app.useGlobalPipes(new ValidationPipe());
app.use(cookieParser());
//Enable cors
app.enableCors({
origin: ["http://localhost:3001","http://localhost:3006", "http://80.211.128.77:3001","http://memoryp.org:3006"],
methods: ["GET", "POST", "PUT", "DELETE"],
credentials: true,
});
await app.listen(3001);
}
bootstrap();
I am using react and express js but when trying to get the socket io to connect to the client from the server I get a cors error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/socket.io/?EIO=4&transport=polling&t=O6YJzcv. (Reason: CORS header ‘Access-Control-Allow-Origin’ does not match ‘http://localhost:3000/’)
The code from the backend looks like this:
const express = require('express');
const { createServer } = require('http');
const { Server } = require('socket.io');
const cors = require('cors')
const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer, {
cors: {
origin: 'http://localhost:3000/',
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true
}
});
app.use(cors())
io.on('connection', socket => {
console.log('connection to derver')
})
httpServer.listen(8080)
And the code from the client like this:
import { useState, useEffect } from 'react';
import axios from 'axios';
import { io } from "socket.io-client";
const socket = io("http://localhost:8080", {
withCredentials: true,
extraHeaders: {
"my-custom-header": "abcd"
}
});
function App() {
return (
<div className="App">
<form >
<label>dummy text</label>
</form>
</div>
);
}
export default App;
I dont know what is causing the error and I have been trying to debug it but only got so far. Tried finding other peoples code seing if that would work but copying havent solved it. I would preciate all the help i could get.
If you change the client socket.io initialization to only use a webSocket, then you won't have CORs issues because webSocket connections are not subject to CORs. But, by default, socket.io starts a connection with several regular http requests which are subject to CORs. So, you can tell socket.io to just start immediately with a webSocket connection by adding the transports option like this:
const socket = io("http://localhost:8080", {
withCredentials: true,
extraHeaders: {
"my-custom-header": "abcd"
},
transports: ["websocket"]
});
P.S. One cause of CORs issues in your code is your use of a custom header which is not explicitly enabled for CORs access and triggers CORs pre-flight authorization. But, if you configure it to just use the webSocket transport from the beginning, then you don't have to worry about any of that CORs stuff.
I was using the following code within my Flutter app and it was working with no problems, but today after I upgraded my Flutter, it doesn't work and gives me XMLHttpRequest error.
Future<void> _authenticate(
String email, String password, String urlSegment) async {
final host = UniversalPlatform.isAndroid ? '10.0.2.2' : '127.0.0.1';
final url = Uri.parse('http://$host:8000/api/$urlSegment');
try {
final http.Response response = await http.post(
url,
headers: {"Content-Type": "application/json"},
body: json.encode(
{
'email': email,
'password': password,
},
),
);
Does anything have been changed in new Flutter version? Should I change the following line of code that specifies my host address?
final host = UniversalPlatform.isAndroid ? '10.0.2.2' : '127.0.0.1';
EDIT: I tried to add cors to my NodeJS backend server and this is my app.ts file as following:
import express, { Request, Response, NextFunction } from "express";
import cors from "cors";
import dotenv from "dotenv";
dotenv.config();
import config from "config";
import responseTime from "response-time";
import connect from "./utils/connect";
import logger from "./utils/logger";
import routes from "./routes";
import deserializeUser from "./middleware/deserializeUser";
import { restResponseTimeHistogram, startMetricsServer } from "./utils/metrics";
import swaggerDocs from "./utils/swagger";
const allowedOrigins = ['http://localhost:8000' , 'https://10.0.2.2:8000', 'http://127.0.0.1:8000'];
const options: cors.CorsOptions = {
origin: allowedOrigins
};
const port = config.get<number>("port");
const app = express();
app.use(express.json());
app.use(cors(options));
app.use(deserializeUser);
app.use(
responseTime((req: Request, res: Response, time: number) => {
if (req?.route?.path) {
restResponseTimeHistogram.observe(
{
method: req.method,
route: req.route.path,
status_code: res.statusCode,
},
time * 1000
);
}
})
);
app.listen(port, async () => {
logger.info(`App is running at http://localhost:${port}`);
await connect();
routes(app);
startMetricsServer();
swaggerDocs(app, port);
});
But still doesn't work and I get the same error!
You've set the allowed origins to :8000, but that's the backend server's address. Instead, you need to set it to the Flutter debug server's address (and eventually to the web server where you host the production app, if that's not exactly the same as the backend server). (You can remove all the addresses ending in 8000.)
The problem is that the debug server picks a random port for each run. You can tell it to use a fixed port and then that becomes the port you need to include in your allowed origins.
Add --web-hostname=localhost --web-port=9999 as command line parameters to where you run your main.dart, then add localhost:9999 as an allowed origin.
(As a get-out-of-jail, also try * as an allowed origin.)
Finally, you should probably explicitly set the CORS allowed methods to the list of methods your server's API expects; probably OPTIONS, GET and POST.
I Use NestJs as a backend server and angular as a frontend
it's okay with me when I use chrome on pc and I can do all my requests
but when I use my android chrome with DevTools I receive this error
message: "Http failure response for http://localhost:3000/users/login: 0 Unknown Error"
here is a snapshot of the error message
enter image description here
it also send the same error with pc chrome if i didnt open CORS on NestJs
here Is My COSR Config
import { ValidationPipe } from '#nestjs/common';
import { NestFactory } from '#nestjs/core';
import { NextFunction, Request, Response } from 'express';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use((req: Request, res: Response, next: NextFunction) => {
console.log(req);
next();
});
app.useGlobalPipes(new ValidationPipe());
app.enableCors({
origin: true,
methods: ['GET', 'PUT', 'POST', 'DELETE'],
exposedHeaders: ['x-auth'],
});
await app.listen(3000);
}
bootstrap();
by the way when I log the request on my nest app
I didn't receive any request
I think NestJsrefused it immediately
I found Where is the problem
I was using the localhost as a Backend IP and the application was connecting on my local pc Backend and that was the problem
I solved this by editing the Backend IP to the production IP
and finally, everything works good ,, Thanks All
I have an application connecting to a Nestjs server to establish a WS connection (server is on a different URL, so it is a CORS request).
The WebsocketGateway is defined as such.
#WebSocketGateway(port, {
handlePreflightRequest: (req, res) => {
const headers = {
'Access-Control-Allow-Headers': 'Authorization',
'Access-Control-Allow-Origin': 'the page origin',
'Access-Control-Allow-Credentials': true,
};
res.writeHead(200, headers);
res.end();
}
})
Works like a charm on Chrome v87 and down and on Firefox. Since upgrading my browser to Chrome 88, the front-end socket-io connection goes on a connect-reconnect loop, as:
The preflight request passes and gets a 200 response, with the headers set above;
The actual connection fails with CORS error as the only message in the browser console
Just incase someone else needs this, in your decorator there is a cors property
#WebSocketGateway({ cors: true })
This is how i fixed
import { IoAdapter } from '#nestjs/platform-socket.io';
import { ServerOptions } from 'socket.io';
export class SocketAdapter extends IoAdapter {
createIOServer(
port: number,
options?: ServerOptions & {
namespace?: string;
server?: any;
},
) {
const server = super.createIOServer(port, { ...options, cors: true });
return server;
}
}
main.ts
const app = await NestFactory.create(AppModule, { cors: true });
app.useWebSocketAdapter(new SocketAdapter(app));