How to call a NodeJs resource from React Js - node.js

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());

Related

Cannot solve CORS Blocking Issue between React and Node

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));

Unable to solve 503 error for POST Request (express)

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}`))

No 'Access-Control-Allow-Origin' header in some chrome version

I am trying to upload some images to cloudinary through my client, it works fine on localhost, and in chrome version 87, but in chrome v89 i get No 'Access-Control-Allow-Origin' header error, any ideas on why this is happening?
this is my server route:
const uploader = require('../config/cloudinary.config')
router.post('/upload', uploader.single("imageUrl"), (req, res) => {
res.setHeader('Access-Control-Allow-Origin', 'client domain');
if (!req.file) {
res.status(500).json({ code: 500, message: 'Error loading the file' })
return;
}
res.json({ secure_url: req.file.path })
})
and this is my cors config:
const cors = require('cors')
const whitelist = [process.env.DOMAIN]
const corsOptions = {
origin: (origin, cb) => {
const originIsWhitelisted = whitelist.includes(origin)
cb(null, originIsWhitelisted)
},
credentials: true
}
You probably need to handle CORS preflight requests, which your browser presents as OPTION requests before the POST requests.
Add this line to your code.
router.options('/upload', cors())

Cross-Origin Request Blocked even after adding headers in server code

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);
}

Express proxy + axios + cors: still cors issue

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);
}
);
});

Resources