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();
Related
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 have a nodejs application which starts asynchronously because of graphql.
require('custom-env').env();
import { DateTruncAggregateGroupSpecsPlugin } from './subgraphs/db/date_trunc_aggregate_group_specs_plugin';
import PgAggregatesPlugin from "#graphile/pg-aggregates";
import FederationPlugin from "#graphile/federation";
import ConnectionFilterPlugin from "postgraphile-plugin-connection-filter";
const PostGraphileDerivedFieldPlugin = require("postgraphile-plugin-derived-field");
import express from "express";
import { ApolloServer, gql } from "apollo-server-express";
const { makeSchemaAndPlugin } = require("postgraphile-apollo-server");
import pg from 'pg';
import { makeExtendSchemaPlugin } from "graphile-utils";
import { readFileSync } from 'fs';
import { resolve } from 'path';
import resolvers from './resolvers';
export let app = express();
export let server: any;
const { PORT, NODE_ENV, SCHEMA, DATABASE_URL } = process.env;
async function main() {
const { schema, plugin } = await makeSchemaAndPlugin(
new pg.Pool({
connectionString: DATABASE_URL
}),
SCHEMA,
{
subscriptions: false,
appendPlugins: [
FederationPlugin,
ConnectionFilterPlugin,
PostGraphileDerivedFieldPlugin,
PgAggregatesPlugin,
DateTruncAggregateGroupSpecsPlugin,
makeExtendSchemaPlugin((build) => ({
typeDefs: gql(readFileSync(resolve(__dirname, '../graphs/custom.graphql'), { encoding: 'utf-8' })),
resolvers
}))
],
graphileBuildOptions: {
connectionFilterRelations: true
}
}
);
const graphql = new ApolloServer({
debug: false,
schema,
plugins: [plugin],
introspection: true
});
await graphql.start();
graphql.applyMiddleware({
app,
path: '/graphql'
});
server = this.app.listen(PORT, () => console.info(`🚀 Running on PORT ${PORT} 🚀`));
}
main();
The above is my express server that adds graphql to it.
As you can see, the starting of the server is asynchronous.
Now I am using supertest to test APIs end-to-end. Supertest requires app to be passed in.
I need server to start before all tests in my project and tests to be able to use app for supertest reuqest.
How do I do that. With regualar server it is easy as starting of server is not asynchronous, so my app is ready to use by tests. But not in this case. How do I carry out supertest requests.
I have a simple but annoying issue. I am running a nodejs server with Apollo Server for GraphQL and express for handling the web requests. I am setting a cookie after a successful login in redis via express-session
I do set the origin and the credentials options for cors()
However, on the front-end I still get the error message, that there is a wildcard in use.
If I changed the origin to "http://localhost:3000/" it would throw me the message, that it is not included in the origin list.
The cookie gets set:
The response also gives me:
When setting the credentials of createHTTPLink to same-origin no cookie is set. as per documentation (https://www.apollographql.com/docs/react/networking/authentication/)
You just need to pass the credentials option. e.g. credentials: 'same-origin' as shown below, if your backend server is the same domain or else credentials: 'include' if your backend is a different domain.
Error Message:
Access to fetch at 'http://localhost:4000/graphql' from origin 'http://localhost:3000' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
Node JS index.ts
import "reflect-metadata";
import dotenv from "dotenv";
import { ApolloServer } from "apollo-server-express";
import Express from "express";
import { buildSchema } from "type-graphql";
import session from "express-session";
import connectRedis from "connect-redis";
import {redis} from "./services/redis"
import cors from "cors"
import { createConnection } from "typeorm";
// load .env file
dotenv.config()
const main = async () => {
await createConnection({
name: "default",
type: "postgres",
host: "localhost",
port: 5432,
username: process.env.TYPEORM_USERNAME,
password: process.env.TYPEORM_PASSWORD,
database: process.env.TYPEORM_DATABASE,
synchronize: true,
logging: true,
entities: [__dirname + "/modules/*/*.*"],
});
// build the graphQL schema
// load all the resolvers!
const schema = await buildSchema({
resolvers: [__dirname + "/modules/**/!(*.test).ts"],
});
// create the apollo server with the schema and make sure we have access
// to req and res in context!
const apolloServer = new ApolloServer({
schema,
context: ({req, res} : any) => ({req, res})
});
// initialise Express itself
const app = Express();
// add the cors for the react frontend
app.use(cors({
credentials: true,
origin: "http://localhost:3000"
}))
// create the redis connection
const RedisStore = connectRedis(session)
// setup the redis session
const redisSessionStore = session({
store: new RedisStore({
client: redis as any,
}),
name: process.env.COOKIE_NAME,
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
maxAge: 1000 * 60 * 60 * 24 * 1 * 365, // 1 year
},
} as any)
// make sure redis is used before we mix with apollo
app.use(redisSessionStore);
apolloServer.applyMiddleware({ app });
// start the server
app.listen(process.env.PORT, () => {
console.log(`Started on http://localhost:${process.env.PORT}/graphql`);
});
};
main();
React JS Front-End
import { ApolloClient, createHttpLink, InMemoryCache } from "#apollo/client";
const link = createHttpLink({
uri: "http://localhost:4000/graphql",
credentials: 'include'
})
const client = new ApolloClient({
link,
cache: new InMemoryCache(),
});
export default client;
The solution to this problem is to actually set the corsOptions on the Apollo Server configuration.
apolloServer.applyMiddleware({ app, cors: corsOptions });
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));
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();