I'm using POSTMAN dev tool to test this API :
http://localhost:3000/users
and I have this express.js script :
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const mongoConfig = require("./config/mongodb.config");
var bodyParser = require("body-parser");
// Routers
const userRouter = require("./core/user/user.route");
const app = express();
const port = process.env.PORT || 3000;
const URI = mongoConfig.mongoURI;
const connectionOptions = mongoConfig.connectionOption;
// Connect Mongo Atlas database
mongoose
.connect(URI, connectionOptions)
.then(() => {
console.log("Connection is established successfully ...");
})
.catch((err) => {
console.error(err);
});
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.json());
app.use(cors);
app.use("/users", userRouter);
app.listen(port, () => {
console.log("The server is running on port", `${port}`);
});
The problem is when I remove CORS :
// app.use(cors);
POSTMAN can get data but when I add CORS it blocks and returns this stack trace :
Could not get any response
There was an error connecting to http://localhost:3000/users.
Why this might have happened:
The server couldn't send a response:
Ensure that the backend is working properly
Self-signed SSL certificates are being blocked:
Fix this by turning off 'SSL certificate verification' in Settings > General
Proxy configured incorrectly
Ensure that proxy is configured correctly in Settings > Proxy
Request timeout:
Change request timeout in Settings > General
As far as I know, POSTMAN is dev tool and CORS is related only with a browser but I did not understand the reason behind it.
After debugging my server.js I found the bug was inside my server and it's not related to POSTMAN.
The problem is using cors before user using my routers will block the server ( unlimited looping ).
So when I changed this code :
app.use(cors);
app.use(express.json());
app.use("/users", userRouter);
To
app.use("/users", userRouter);
app.use(cors);
app.use(express.json());
The issue is solved but I did not understand why and what happens exactly inside the server.
Related
I have written a simple request response code in NODEJS but there is no response in return of the request is there .
The code for my app.js(Server file) is
const express = require('express');
const cors = require('cors')
const paymentroute = require('./routes/paymentRoutes');
const app = express();
app.use(cors);
app.use("/api",paymentroute);
app.listen(3100,()=>{
console.log(`listening to port 3100`);
})
The code for my req and res is
const express = require('express');
const router = express.Router();
// const { checkout } = require('../controllers/paymentController');
router.post("/checkout",(req,res) => {
console.log("this function is called ")
return res.json({success:"true"})
});
module.exports = router;
Even the console.log inside the res function is not working.
Just change app.use(cors); to app.use(cors());
const express = require('express');
const cors = require('cors');
const paymentroute = require('./routes/paymentRoutes');
const app = express();
app.use(cors());
app.use('/api', paymentroute);
app.listen(3100, () => {
console.log(`listening to port 3100`);
});
I think it is a connection-related issue often related to a networking issue caused by a Virtual Private Network (VPN) that in some cases is required by some API services or, in other cases, prevents you to reach an API service.
The issue seems to be a combo of having the no-cache header enabled and a request URL length over 64 characters. If the issue persists after doing this solution then try to upgrade to the latest version of Postman.
SOLUTION:
I had my port hardcoded... smh
app.listen(5432, () => {
console.log(`Server is listening on port 5432`)
})
Heroku REQUIRES a process.env.PORT, this solved the issue here:
require("dotenv").config()
const PORT = process.env.PORT || 5432
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`)
})
PROBLEM:
I have a simple ReactJS CRUD form with no validation hosted locally, and a NodeJS Express server hosted on Heroku. Just trying to get cors enabled but nothing I do is setting the headers for the preflight request. Receiving this error:
Access to XMLHttpRequest at
'https://cors-be.herokuapp.com/api/user/create' 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.
This is the index.js:
const express = require('express')
const cors = require('cors')
const app = express()
app.use(cors())
app.use(express.json())
app.options("*", cors()) // Edit 1
app.get("/", (req, res) => {
res.json({message: "API is listening"})
})
const userRouter = require("./api/user/router")
app.use("/api/user", userRouter)
app.listen(5432, () => {
console.log(`Server is listening on port 5432`)
})
CORS version installed in package.json:
"cors": "^2.8.5"
This should be enabling all cors across all origins but it isn't. I've tested it on Chrome, Firefox, and Edge with the same result so I'm sure it's not a browser-specific issue. Everything functions correctly on localhost. It's a preflight request error so it wouldn't be an issue with my endpoint code anyway. Been working on this longer than I care to admit and I'm at the point where I will be happy just to get past the preflight request and add origin configuration later.
Edit 1:
Pre-flight seems to be looking for OPTIONS so I've added:
app.options("*", cors())
new index.js:
const express = require('express')
const cors = require('cors')
const app = express()
app.use(cors())
app.use(express.json())
app.options("*", cors())
but still isn't working...
I am working on an API based service that was made and tested locally first and then deployed on AWS LightSail Ubuntu 20.04 . For whatever reason the server is not responding, as hitting any routes is neither logging nor sending a response back. FYI I tried other clients like the chrome console, postman etc. This is a simplified version of the code that was tested as well.
const express = require("express");
const bodyParser = require("body-parser");
const cors = require('cors');
const app = express();
app.use(cors({ origin: true }));
app.get("/", (req,res)=>{
res.send({
"msg":"worked"
});
console.log("hit hit hit");
});
app.listen(3000,()=>{
console.log("server started at port 3000");
})
const port = process.env.PORT || ("http://localhost:3002")
const postUrl=`${port}/post`;
addData=()=>{
console.log(postUrl)
console.log(process.env,"AS")
Axios.post(postUrl,this.state.form)
.then((response)=>{
this.setState({errorMessage:"",successMessage:response.data})})
.catch((err)=>{
this.setState({successMessage:"",errorMessage:err.response.data.message})
})
}
When I am calling the backend in the production process.env.PORT is blank.
(process.env.NODE_EV= production which is absolutely correct exactly like in the backend)
My backend is completely fine as it getting the process.env.PORT correctly.
But my frontend is not getting the process.env.PORT that's why it keeps calling the other address("http://localhost:3002").
App will completely work fine if I keep open my local machine backend because the "http://localhost:3002"
is available to serve. But in production, Heroku keeps changing the process.env.PORT which is showing its value in the backend, not in the frontend
How can I make my frontend to call my backend server properly in production??
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const port = process.env.PORT || 3002;
const cors = require("cors");
const path=require("path");
const routing = require("./routing/route");
require('dotenv').config();
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use("/",routing);
app.use(function (err, req, res, next) {
console.log("hii")
res.status(500).send({ message: err.message });
});
if(process.env.NODE_ENV ==="production"){
app.use(express.static("client/build"));
app.get("*",(req,res)=>{
res.sendFile(path.resolve((__dirname,"client","build","index.html")));
});
}
app.listen(port, () => {
console.log(` Server is started at http://localhost:${port}`);
});
server file
If your React application is served from your Node.JS application as you said, you could just use window.location. window.location is an object that stores statistics about the current page that the user is on, and you could use that to construct a URL and send the server a request, like so:
// This URL uses a template literal, which is a new feature of ES6.
// All but Internet Explorer supports it.
// This is using window.location.protocol, which is either `http:` or `https:`,
// depending on the protocol that the page was loaded with. window.location.host
// is the host that the page was loaded from, with the port number.
const postUrl =
`${window.location.protocol}//${window.location.host}/post`;
// And then requesting with the URL.
addData = () => {
console.log(postUrl);
console.log(process.env, "AS");
Axios.post(postUrl, this.state.form)
.then((response) => {
this.setState({errorMessage: "",successMessage: response.data});
})
.catch((err) => {
this.setState({successMessage: "",errorMessage: err.response.data.message});
});
}
I know this kind of problem has been solved before, but I can't figure out exactly why it is not working for my case.
I am working on a website locally and I want to test it out on various platforms and devices so I decided to use ngrok for this.
My front-end is running on port 3000 and my express server on port 5000.
So I opened ngrok and entered ngrok http 3000
On my local PC, where the server is running, the https://example.ngrok.io is working as intended without any problems.
But on my laptop (or another device), the front-end displays correctly but when it is actually going to get data from the back-end, it is showing the error: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5000/weather/51.87575912475586,0.9436600208282471. (Reason: CORS request did not succeed).
On my express server, I made sure to use the cors package and app.use(cors()); and I also tried adding the headers manually :
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
Source: Why doesn't adding CORS headers to an OPTIONS route allow browsers to access my API?
Here is also my code where I am fetching and getting data in case I am doing something wrong there:
index.js (front-end)
const response = await fetch(`http://localhost:5000/weather/${lat},${lng}`); //sending request to server-side
const json = await response.json();
console.log(json); //getting the weather data from server-side
server.js (back-end)
const express = require("express");
const mongoose = require("mongoose");
const fetch = require("node-fetch");
const cors = require('cors');
const nodemailer = require('nodemailer');
require('dotenv').config();
const users = require('./routes/api/users');
const app = express();
//Json Middleware
app.use(express.json());
app.use(cors());
//Getting URI from keys file
const db = require('./config/keys').mongoURI;
//Connect to the Database
mongoose.set('useUnifiedTopology', true);
mongoose.set('useCreateIndex', true);
mongoose.connect(db, {useNewUrlParser: true})
.then(()=> console.log("Database Connected"))
.catch(err=> console.log(err));
//Route for user routes
app.use('/api/users',users);
const dbport = process.env.PORT || 5000;
app.listen(dbport, () => console.log(`Server started on port ${dbport}`));
app.get('/weather/:latlon', async (req,res) =>{ //awating request from client-side
const latlon = req.params.latlon.split(',');
console.log(req.params);
const lat = latlon[0];
const lon = latlon[1];
console.log(lat,lon);
const api_key = process.env.API_KEY;
const weather_url = `https://api.darksky.net/forecast/${api_key}/${lat},${lon}?units=auto`; //getting data from weather API
const fetch_res = await fetch(weather_url);
const json = await fetch_res.json();
res.json(json); //sending weather data back to client-side
});
Is this possible to work or not due to the nature of localhost?
Both firefox and chrome had the same problem.
Thanks for the help!
After some days of head scratching, I finally found a solution and I'm posting it below for others that may have the same problem.
Step 1:
Instead of having 2 ports active (3000 for client and 5000 for server), I closed my client port and served my client folder/assets directly from my server using express:
const dbport = process.env.PORT || 5000;
app.listen(dbport, () => console.log(`Server started on port ${dbport}`));
app.use(express.static('client')); //serving client side from express
//Json Middleware
app.use(express.json());
Step 2:
Now that we have one port (port 5000) for both the client and the server, I went into my client side where I did my fetch requests (see above at index.js) and modified the actual requests to be relative:
const response = await fetch(`/weather/${lat},${lng}`); //sending request to server-side
const json = await response.json();
console.log(json); //getting the weather data from server-side
Step 3:
Finally, I opened ngrok and typed:
ngrok http 5000
It should now work.
If you are using ngrok with nodejs/express.js .
Remove he cors import and use this code:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "YOUR-DOMAIN.TLD"); // update to match
the domain you will make the request from
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-
Type, Accept");
next();
});
replace "YOUR-DOMAIN.TLD" with "*" to give access to all urls OR your specific website url.
Refer to https://enable-cors.org/server_expressjs.html for more details
Thank You.