I've been working on website using react.js in the front and node.js in the back and whenever I send a patch request, I am getting Blocked by CORS like the following:
"Access to XMLHttpRequest at 'http://localhost:4000/admin/appointment/63efc1cc0eecac628d653b65' from origin 'http://localhost:3000' has been blocked by CORS policy: Method PATCH is not allowed by Access-Control-Allow-Methods in preflight response.
Appointments.js:50 AxiosError {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK', config: {…}, request: XMLHttpRequest, …}
xhr.js:247
PATCH http://localhost:4000/admin/appointment/63efc1cc0eecac628d653b65 net::ERR_FAILED"
My code for front end using axios to handle request is:
axiosInstance
.patch(
`/admin/appointment/${id}`,
{ status: "Finished" },
{
headers: {
Authorization: token,
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
}
)
.then((res) => {
console.log(res.data);
})
.catch((err) => {
console.log(err);
});
and My code from node js is:
router.patch('/appointment/:id', auth, async (req, res) => {
try {
const id = req.params.id;
const AppointmentToUpdate = req.body;
const updatedAppointment = await appointmentModel.update({ _id: id }, number, { runValidators: true });
res.json(updatedAppointment);
}catch (err) {
res.status(500).send(err.message);
}
})
and I have already installed cors and required it in my backend:
const cors = require("cors");
const app = express();
mongoose.connect(`mongodb://localhost:27017/frontdesk`);
app.use(
cors({
origin: "*",
methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
})
);
I've should mention that I used other methods like login "POST" request and "GET" request and all are working fine
Replace cors with the following code. It should solve your issue.
const options = {
"origin": "*",
"methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
"preflightContinue": false,
"optionsSuccessStatus": 204
}
app.use(cors(options));
Related
Whenever my frontend (React) runs at localhost:3000 and my backend (express) runs locally on localhost:8282, I get a 503 error and am able to see expected results.
My fronten has been deployed at netlify and backend in heroku. I run into cors error and some other weird error that I am unable to solve. Here are the code snippets:
getting the following errors:
Access to fetch at 'https://projectname.herokuapp.com/payment' from
origin 'https://projectnamee.netlify.app' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested resource.
If an opaque response serves your needs, set the request's mode to 'no-cors' to
fetch the resource with CORS disabled.
POST https://projectname.herokuapp.com/payment net::ERR_FAILED 503
fetch call in frontend:
const backend_api = process.env.NODE_ENV == 'production' ? 'https://projectname.herokuapp.com/payment' : 'http://localhost:8282/payment';
const purchase = token => {
let product = purchaseProduct
const body = {
token,
product
}
const headers = {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Methods": "*"
}
return fetch(backend_api, {
method: "POST",
headers,
body: JSON.stringify(body)
}).then(response => {
console.log("Response ", response)
const {status} = response;
console.log("STATUS ", status)
})
.catch(error => console.log(error))
}
backend index.js:
require('dotenv').config();
const cors = require("cors")
const express = require("express")
const stripe = require("stripe")(process.env.STRIPE_SEC_KEY)
const { v4: uuidv4 } = require('uuid');
const app = express();
// middleware
app.use(express.json())
// I tried a lot of variations of this, none worked
app.use(cors({
origin: '*'
}))
// routes
app.get("/", (req, res) => {
res.send("Works here")
})
app.post("/payment", (req, res) => {
const {product, token} = req.body;
console.log("Product", product)
console.log("price", product.price)
console.log("email", token.email)
const idempotencyKey = uuidv4()
return stripe.customers.create({
email: token.email,
source: token.id
}).then(customer => {
stripe.charges.create({
amount: product.price * 100,
currency: 'usd',
customer: customer.id,
receipt_email: token.email,
description: `Purchase of ${product.name}`,
shipping: {
name: token.card.name,
address: {
country: token.card.address_country
}
}
}, {idempotencyKey})
}).then(result => res.status(200).json(result))
.catch(err => console.log(err))
})
// listen
const port = process.env.PORT || 8282
app.listen(port, () => console.log(`Listening on port ${port}`))
I've a simple API in Express/Node and I also have a simple angular application for posting blogs. The only problem is when I hit the /contribute route using POST method. I'm getting this error on both chrome and firefox:
error: error { target: XMLHttpRequest, isTrusted: true, lengthComputable: false, … }
headers: Object { normalizedNames: Map(0), lazyUpdate: null, headers: Map(0) }
message: "Http failure response for localhost:3000/api/contribute: 0 Unknown Error"
name: "HttpErrorResponse"
ok: false
status: 0
statusText: "Unknown Error"
url: "localhost:3000/api/contribute"
: {…}
constructor: class HttpErrorResponse { constructor(init) }
: {…}
constructor: class HttpResponseBase { constructor(init, defaultStatus, defaultStatusText) }
: {…
Here's my server side code.
api.js
...
router.post('/contribute', (req, res) => {
console.log('Pushing new article');
let userPost = req.body;
let post = new Post(userPost);
post.save((error, registeredPost) => {
if (error) {
console.log(error);
} else {
res.status(200).send(registeredPost);
}
})
})
...
module.exports = router;
server.js
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const api = require('./routes/api');
const cors = require('cors');
app.use(bodyParser.json());
// app.use(cors({ origin: 'http://localhost:4200' })); <--- TRIED THIS ALSO
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
// 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', 'X-Requested-With,content-type');
// 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();
});
app.use('/api', api);
app.get('/', function(req, res) {
res.send('Server is up and running!');
})
app.listen(3000, function() {
console.log('Server listening port:3000');
});
Yes, server is up and running.
Here is angular code.
auth.service.ts
private _contributeUrl = "https://localhost:3000/api/contribute";
...
pushNewPost(newPost) {
console.log("here is the new post", newPost); // GETTING CORRECT OUTPUT
return this._http.post<any>(this._contributeUrl, newPost);
}
contribute.component.ts
this._auth.pushNewPost(this.makeNewPost)
.subscribe (
res => {
(<HTMLInputElement>document.getElementById("inputTitle")).value="";
this.editorForm.reset();
this.addSingle();
},
err => console.log(err)
);
Now the fun part is that the same code is working perfectly when I make a post request to this route using Postman without any error.
Please correct my mistake. After adding:
pushNewPost(newPost) {
console.log("here is the new post", newPost);
let headers = new HttpHeaders({
'Content-Type': 'application/json',
});
let options = { headers: headers };
return this._http.post<any>(this._contributeUrl, newPost);
}
I'm getting this:
Seems like you are not sending in the headers from angular. Make the following changes:
pushNewPost(newPost) {
// adding the headers
const headers = new HttpHeaders({
'Content-Type': 'application/json',
});
const options = { headers: headers };
return this._http.post<any>(this._contributeUrl, newPost, options);
}
I've created the following proxy with express:
import express from "express";
import cors from "cors";
import proxy from "express-http-proxy";
const app = express();
app.use(
cors({
origin: "http://localhost:8081",
credentials: true,
})
);
app.use("/", proxy("http://my-website:8810"));
app.listen(3000, () => {
console.log("server listening on port 3000");
});
From the frontend I'm using axios:
axios.defaults.withCredentials = true;
const res = await axios.get("http://localhost:3000", {
auth: {
username: "xxxxx",
password: "xxxxx",
},
headers: {
"Content-Type": "application/json",
},
});
But I still have the following cors issue:
Access to XMLHttpRequest at 'http://my-website:8810' (redirected from
'http://localhost:3000/') from origin 'http://localhost:8081' has been
blocked by CORS policy: Response to preflight request doesn't pass
access control check: No 'Access-Control-Allow-Origin' header is
present on the requested resource.
And after many hours facing this issue... here I am.
Could anyone explain to me what I'm doing wrong here?
Finally it works by using "request", something like:
app.use(
cors({
origin: "http://localhost:8081",
credentials: true,
})
);
router.get("/", (req, res) => {
request(
"http://my-website:8810",
{
auth: {
username: "node_proxy",
password: "password",
},
headers: { Accept: "application/json" },
},
(error, response, body) => {
res.send(body);
}
);
});
I am trying to call a JSON resource from a URL (on a Node.Js) environment from a React JS project. My attempts so far fail or return nothing.
The Resource API
/* GET users listing. */
app.get('/', function (req, res, next) {
// res.send('respond with a resource');
res.json([{
id: 1,
name: "Hiccup",
password: 'hiccup'
}, {
id: 2,
name: "King Arthur",
password: 'king-arthur'
}]);
});
React JS
componentDidMount() {
let url = 'http://localhost:4000/';
const myHeaders = new Headers();
fetch(url, {
method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default',
credentials: 'omit',
headers: {
'Content-Type': 'application/json'
},
})
.then(res => {
if (!res.ok) {
throw new Error('Network response was not ok');
}
return res.json();
})
.then(data => {
this.setState({ revData: data })
})
.catch(err => this.setState({ revData: err }));
}
This gives an error:
Access to fetch at 'http://localhost:4000/' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
:4000/:1
Failed to load resource: net::ERR_FAILED
Changing mode: 'cors', to mode: 'no-cors' doesn't help.
What am I missing? How should I be going on about it?
Thank you all in advance.
try :
npm install cors --save
and just add these lines in your main file where your request is going.
const cors = require('cors');
const express = require('express');
let app = express();
app.use(cors());
app.options('*', cors());
I am building a login system using express for node.js and react.js. In my back-end when a user logs in, it creates a cookie. When I go to Network > Login I can see this:
Set-Cookie:
user_id=s%3A1.E%2FWVGXrIgyXaM4crLOoxO%2Fur0tdjeN6ldABcYOgpOPk; Path=/; HttpOnly; Secure
But when I go to Application > Cookies > http://localhost:3000, there is nothing there. I believe that is because I am not allowing credentials to go through correctly when I do a post request from the client side. How do I go about this? Please, let me know if I can improve my question in any way.
//Login back-end
router.post('/login', (req, res, next) => {
if(validUser(req.body)) {
User
.getOneByEmail(req.body.email)
.then(user => {
if(user) {
bcrypt
.compare(req.body.password_digest, user.password_digest)
.then((result) => {
if(result) {
const isSecure = process.env.NODE_ENV != 'development';
res.cookie('user_id', user.id, {
httpOnly: true,
secure: isSecure,
signed: true
})
res.json({
message: 'Logged in'
});
} else {
next(new Error('Invalid Login'))
}
});
} else {
next(new Error('Invalid Login'))
}
});
} else {
next(new Error('Invalid Login'))
}
});
//Allow CORS index.js
app.use(
cors({
origin: "http://localhost:3000",
credentials: true
})
);
//Login client side (React.js)
loginUser(e, loginEmail, password) {
e.preventDefault();
let email = loginEmail;
let password_digest = password;
let body = JSON.stringify({ email, password_digest });
fetch("http://localhost:5656/api/login", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
credentials: "include",
body
})
.then(response => response.json())
.then(user => {
console.log(user);
});
}
You should be secure of set "credentials" in the server and in app.
Try to set on you index.js or app.js server side this:
app.use(function(req, res, next) {
res.header('Content-Type', 'application/json;charset=UTF-8')
res.header('Access-Control-Allow-Credentials', true)
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
)
next()
})
and in you client site add options like this:
let axiosConfig = {
withCredentials: true,
}
export async function loginUser(data) {
try {
const res = await axios.post(
`${URL}:${PORT}/${API}/signin`,
data,
axiosConfig
)
return res
} catch (error) {
console.log(error)
}
}
Edit
To set "credentials" in server we need this line:
res.header('Access-Control-Allow-Credentials', true)
This would let you handle credentials includes in headers.
You also have to tell to axios to set credentials in headers with:
withCredentials: true
Do not forget to adjust cors middleware.
Your node.js express code
const express = require("express");
const cors = require('cors')
const app = express();
app.use(cors(
{
origin: 'http://localhost:3000',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
));
app.use(function(req, res, next) {
res.header('Content-Type', 'application/json;charset=UTF-8')
res.header('Access-Control-Allow-Credentials', true)
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
)
next()
})
app.get("/auth", function(req, res){
res.cookie('token', 'someauthtoken')
res.json({id: 2});
});
app.listen(3030);
Your front-end code
import React, { useEffect } from 'react';
import axios from 'axios';
async function loginUser() {
try {
const res = await axios.get(
'http://localhost:3030/auth',
{
withCredentials: true,
}
)
return res
} catch (error) {
console.log(error)
}
}
function App() {
useEffect(() => {
loginUser();
}, [])
return (
<div>
</div>
);
}
export default App;
It is because you set httpOnly: true.
This will block the visibility to client side, like reading from javaScript document.cookie().
You can solve this by turn it off.
If you can't see your cookie in the browser, I think it is because you're setting hhtpOnly to true in the cookie's options.
cookie.httpOnly
Specifies the boolean value for the HttpOnly Set-Cookie attribute. When truthy, the HttpOnly attribute is set, otherwise it is not. By default, the HttpOnly attribute is set.
Note: be careful when setting this to true, as compliant clients will not allow client-side JavaScript to see the cookie in document.cookie
res.cookie('user_id', user.id, {
httpOnly: false, // try this
secure: isSecure,
signed: true
})
You need to configure cors in your backend server first.
First, install cors using npm i cors then in your express server add this line of code:
app.use(cors({
origin: "YOUR FRONTEND SITE URL HERE",
credentials: true,
}));
Then, in your frontend app where you are sending GET/POST requests to your backend, make sure to add in your request
If you've used fetch:
const res = await fetch('BACKEND SERVER URL', {
credentials: "include",
// other objects
});
If axios is used:
const res = await axios.post('BACKEND SERVER URL',
{ withCredentials: true },
// other objects,
);
This will solve the problem of storing cookies in frontend sent from backend.