This is my node,js API,that works with no problems using postman, but when I try to make a request from a different origin like a react project the request is blocked
const express = require('express');
const mongoose = require('mongoose');
const app = express();
const port = process.env.PORT || 9000;
const routes = require('./routes/routes');
const token = require('./config/config');
const cors = require('cors')
app.use(cors())
app.use(express.json());
app.use('/api', routes);
app.listen(port, () => console.log('server listening on port', port));
const url = "mongodb://localhost/titles_db";
mongoose.connect(url,{})
.then( () => console.log('DB connected'))
.catch( (e) => console.log('Erorr on db connection'));
and this is the function that is called on my request
searchTitles = (req, res) => {
const terms = req.query.terms;
const format = req.query.format;
titleSchema.find({title: {$regex:terms, $options: 'i'}})
.then( data => {
if(format == 'json')
res.json(data);
else{
res.setHeader("Content-Type", "text/plain");
res.send(data);
}
})
.catch( error => res.json( {message: error}))
}
and here is the function that makes the request on the frontend
const getFieldText = e => {
setTerm({term: e.target.value });
const url = `http://localhost:9000/api/titles/?terms=${e.target.value}&format=json`
fetch(url)
.then(response => console.log(response))
.then(data => console.log(data));
}
even including cors library on node
const cors = require('cors')
app.use(cors())
I get this response
Response { type: "cors", url: "http://localhost:9000/api/titles/?terms=aaaaaa&format=json", redirected: false, status: 403, ok: false, statusText: "Forbidden", headers: Headers, body: ReadableStream, bodyUsed: false }
I added an options array but I have the same result
var corsOptions = {
origin: 'http://localhost:3000',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
app.use(cors(corsOptions))
configure the cross headers like this (in your server node config):
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', "http://localhost:8080");
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, authorization, Access-Control-Allow-Origin');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', 'true');
// Pass to next layer of middleware
next();
});
Related
Tried everything I could find on here in regards to setting up cors for my node server. Tried aliasing my localhost and that doesn't seem to work either. Also tried using the CORS unblock extension.
error: localhost/:1 Access to fetch at
'http://localhost:8080/api/login' from origin 'http://localhost:3000'
has been blocked by CORS policy: Response to preflight request doesn't
pass access control check: It does not have HTTP ok status.
:8080/api/login:1 Failed to load resource: net::ERR_FAILED
im trying to use magic link authentication in my react app. I got this POST request being made to my node server
const res = await fetch(`http://localhost:8080/api/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + didToken,
},
});
my server code is
const express = require("express");
const cors = require("cors");
const { Magic } = require('#magic-sdk/admin');
require('dotenv').config();
const app = express()
const magic = new Magic(process.env.MAGIC_SECRET_KEY);
app.use("*", (req, res) => res.status(404).json({ error: "not found" }));
// Allow requests from client-side
app.use(cors({origin: process.env.CLIENT_URL}));
app.all('*', (req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept, Authorization'
);
res.sendStatus(200);
next();
});
app.post('api/login', async (req, res) => {
console.log("login fired")
try {
const didToken = req.headers.authorization.substr(7);
await magic.token.validate(didToken);
res.status(200).json({ authenticated: true });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
module.exports = app
app.use(cors({origin: process.env.CLIENT_URL}));
I'd be curious what this URL is. If you want an open CORS policy you don't need to set anything any there.
Put a "/" in front of this route
app.post('/api/login', async (req, res) => {
I was able to reproduce your problem locally and this server setup worked for me to fix it.
const express = require("express");
const cors = require("cors");
const port = 8080;
const app = express();
app.use(cors());
app.post("/api/login", async (req, res) => {
console.log("login fired");
try {
res.status(200).json({ authenticated: true });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});
module.exports = app;
I have installed cors via npm and used the app.use(cors());middleware, but it is not solving my issue. I am running my frontend React App on Port localhost:3000
Access to XMLHttpRequest at 'http://localhost:3087/authenticate-token' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Here below is the whole code from my app.js file:
const bodyParser = require("body-parser");
const cors = require("cors");
const dotenv = require("dotenv");
const express = require("express");
const mongoose = require("mongoose");
const session = require("express-session");
// const request = require('req')
const app = express();
dotenv.config();
// Parse Application/json
app.use(bodyParser.json());
// Base URL
// app.locals.baseURL = "h";
app.use(cors());
app.use(
session({
secret: process.env.ACCESS_TOKEN_SECRET,
saveUninitialized: true,
resave: false,
cookie: {
secure: true,
},
})
);
// DB Config
const db = require("./config/keys").mongoURI;
// Connect to MongoDB
mongoose
.connect(db, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log("MongoDB Connected"))
.catch((err) => console.log(err));
// Routes
app.use("/", require("./routes/auth"));
app.use("/pages", require("./routes/pages"));
app.use("/signUpModule", require("./routes/signUpModule"));
app.use("/users", require("./routes/users"));
const PORT = process.env.PORT || 3087;
app.listen(PORT, console.log(`Server running on ${PORT}`));
Below I have added the code from my end point:
const express = require("express");
// Authenticate Token
router.get(
"authenticate-token",
authFunctions.authenticateToken,
(req, res) => {
res.send({user: req.user, tokenValid: true});
);
Try to add this to your app.js file:
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header(
// "Access-Control-Allow-Origin",
"Origin, X-Requested-With, Content-Type, Accept, Authorization"
);
if (req.method == "OPTIONS") {
res.header("Access-Control-Allow-Methods", "GET PATCH DELETE POST PUT");
return res.status(200).json({});
}
next();
});
So, it so happens that the issue was coming from the client-side where I was using axio to make a request. At first I had the following:
export const userAuthenticated = async (token) => {
const response = await axios.get(`${API_BASE_URL}/authenticate-token`, {
headers: {
authorization: token,
}
});
if (response.statusText === "OK") return response.data;
};
Then later, I changed to the following, which worked:
export const userAuthenticated = async (token) => {
const response = await axios({
headers: {
authorization: token,
},
method: "get",
url: `${API_BASE_URL}/authenticate-token`,
});
if (response.statusText === "OK") return response.data;
};
I've set up a GraphQL server using express-graphql and Restify, which works perfectly on Postman. However, when actually calling it from our frontend we keep getting CORS issues. I've tried just about everything.
The weird thing is that if we remove all headers from the frontend axios request, CORS is no longer an issue - but then we get the "query must be a string" error from graphql.
Full code:
const restify = require('restify');
const { graphqlHTTP } = require('express-graphql');
const corsMiddleware = require('restify-cors-middleware2');
const schema = require('./Schemas');
const { auth } = require('./middleware');
const { bugsnag } = require('./utils/config');
const PORT = process.env.PORT || 3004;
const app = restify.createServer();
app.use(bugsnag.requestHandler);
app.use(function crossOrigin(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
const allowHeaders = ['Accept', 'Accept-Version', 'Content-Type', 'Api-Version', 'Origin', 'X-Requested-With']; // added Origin & X-Requested-With
res.header('Access-Control-Allow-Headers', allowHeaders.join(', '));
// res.header('Access-Control-Allow-Credentials', true); // tried both with and without this
return next();
});
app.use(auth.authenticateUser);
app.post(
'/graph',
graphqlHTTP((req, res, graphQLParams) => {
console.log(req);
return {
schema,
context: {
user: req.user,
},
};
})
);
app.get(
'/graph',
graphqlHTTP({
schema,
graphiql: true,
})
);
app.listen(PORT, () => console.log(`Listening on port ${PORT}!`));
Other things I've tried:
const cors = corsMiddleware({
preflightMaxAge: 5,
origins: ['*'],
allowHeaders: ['X-App-Version'],
exposeHeaders: [],
});
app.pre(cors.preflight);
app.use(cors.actual);
I also tried:
app.use(function crossOrigin(req, res, next) {
console.log('Adding cors headers');
const allowHeaders = ['Accept', 'Accept-Version', 'Content-Type', 'Api-Version', 'Origin', 'X-Requested-With'];
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Allow-Headers', allowHeaders.join(', '));
res.header("Access-Control-Allow-Origin", "http://localhost:3000");
next();
});
I also tried basically every combination of all of the above, and none worked. I even tried removing the auth header from the request and removing the auth middleware, and that didn't work either (although it did get us to the point where at least it was a 404 error due to "query not being a string" rather than the CORS issue.
This isn't very well documented in the restify-cors-middleware2 package, but turns out I need to set the allowCredentialsAllOrigins and credentials properties, as well as add a lot more allowHeaders:
const cors = corsMiddleware({
preflightMaxAge: 5,
origins: ['*'],
allowHeaders: [
'X-App-Version',
'Accept',
'Accept-Version',
'Content-Type',
'Api-Version',
'Origin',
'X-Requested-With',
'Authorization',
],
exposeHeaders: [],
credentials: true,
allowCredentialsAllOrigins: true,
});
app.pre(cors.preflight);
app.use(cors.actual);
I'm sending post request from "angular->port 4200" to "expressjs server->port 8000".
As an example i'm folowing this example: https://github.com/kuncevic/angular-httpclient-examples/blob/master/client/src/app/app.component.ts
I'm getting two error :
1)undefined from Nodejs(data and req.body.text)
2)Message received from background. Values reset
Angular side:
callServer() {
const culture = this.getLangCookie().split("-")[0];
const headers = new HttpHeaders()
headers.set('Authorization', 'my-auth-token')
headers.set('Content-Type', 'application/json');
this.http.post<string>(`http://127.0.0.1:8000/appculture`, culture, {
headers: headers
})
.subscribe(data => {
});
}
expressjs side:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
var path = require('path');
app.all("/*", function(req, res, next){
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
next();
});
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
app.post('/appculture', function (req, res) {
var currentCulture = `${req.body.text} from Nodejs`;
req.body.text = `${req.body.text} from Nodejs`;
res.send(req.body)
})
app.listen(8000, () => {
console.log('server started');
})
Either you are not sending anything of there is no value in body.text
Try to console.log(req.body) instead of req.body.text.
Try to console.log(culture) and this.getLangCookie() on the client side to see if you are actually sending something.
You can also make use of the network tab in the browser to inspect the request that you are sending.
Angular side:
callServer() {
const culture = this.getLangCookie().split("-")[0];
const headers = new HttpHeaders()
headers.set('Authorization', 'my-auth-token')
headers.set('Content-Type', 'application/json');
this.http.get(`http://127.0.0.1:8000/appculture?c=` + culture, {
headers: headers
})
.subscribe(data => {
});
}
Nodejs side:
app.get('/appculture', function (req, res) {
currentCulture = req.query.c;
res.send(req.body)
})
I'm trying to set up a basic user signup form with React, Node, and Express, and using fetch. However, I'm getting the following errors in the Chrome console when I try and send a post request:
1) "OPTIONS http://localhost:7001/v1/register 500 (Internal Server Error)"
2) "Access to fetch at 'http://localhost:7001/v1/register' from origin 'http://localhost:3001' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status."
My eventual goal is to save the user's email and password in a database, but for now all I want is for the request to go through to the backend and have the backend log the body to make sure everything works. I've tried several different ways of setting headers, and I have no idea what's wrong. Below is the code.
Frontend form submit function:
handleSubmit(e) {
e.preventDefault();
const signUpInfo = this.state; // { email: 'test#gmail.com', password: '123' }
console.log(signUpInfo);
fetch('http://localhost:7001/v1/register', {
method: 'POST',
body: JSON.stringify(signUpInfo),
headers: {
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(response => console.log('Success:', response))
.catch(error => console.error('Error:', error));
}
server.js
const express = require('express');
const compression = require('compression');
const cfg = require('config');
const path = require('path');
const logger = require('morgan');
const cookieParser = require('cookie-parser')
const bodyParser = require('body-parser');
const config = require('config');
const app = express();
app.use(compression());
app.use(bodyParser());
app.use(cookieParser());
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.static(path.join(__dirname, 'public')));
app.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,DELETE");
res.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Access-Control-Allow-Headers, Content-Type, Authorization, Origin, Accept");
res.setHeader('Access-Control-Allow-Credentials', true)
next();
});
// CONTROLLERS
const userController = require('./controllers/userController.js');
// ROUTES
app.post('/v1/register', userController.register);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
app.listen('7001', function() {
console.log('API server listening on port 7001!');
});
module.exports = app;
userController.js
exports.register = async (req, res, next) => {
try {
console.log(req.body);
res.status(200).json({ status: 200, data: req.body, message: "test" });
} catch (err) {
console.log(err);
res.status(500).json({ status: 500, data: null, message: err });
}
}
All I'm looking for is for the backend console to print out the body. It works with axios and $.ajax, but not with fetch. I've also tried using a proxy server to no avail (and would like to get it to work without a proxy).
Not sure if this is relevant, but I'm using Chrome as the browser and Sequelize.
Any help would be greatly appreciated. I feel like I'm missing something fundamental. Any helpful articles to deepen my learning would be a plus!
Instead of using
const app= express();
try to use
const app=express().use('*', cors());
and remove
app.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,DELETE");
res.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Access-Control-Allow-Headers, Content-Type, Authorization, Origin, Accept");
res.setHeader('Access-Control-Allow-Credentials', true)
next();
});
see if this works.
First Install "cors":
npm i cors
Second import "cors":
cors = reqquire("cors");
Third use "cors":
const app = express();
app.use("*", cors());