Why do I get a CORS Error when tunneling through ngrok?
Asked Answered
S

3

7

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!

Sweatband answered 4/3, 2020 at 19:57 Comment(2)
What’s the HTTP status code of the response? You can use the Network pane in browser devtools to check. Is it a 4xx or 5xx error rather than a 200 OK success response?Latini
Hey @sideshowbarker, thanks for your response and I'm sorry for leaving this info behind. It strangely appears that the request has no status code at all (shown here: imgur.com/a/D3BJRkb ) and then the actual error in the console ( imgur.com/a/XjYeysY ). When I do the same request with Postman from my PC that is running the server, the request is fine and goes through, but in my laptop it shows this (imgur.com/a/hDE34GR). Note that I have also created SSL certs sometime ago using OpenSSL to make the server https, but I get exactly the same error even from my local PC.Sweatband
S
3

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.

Sweatband answered 7/3, 2020 at 12:21 Comment(2)
Hi, thanks for uesful info. Sorry but I still don't understand why both client web( react) and server (expressjs) have the same port (5000) ?Attorn
What about different port? I mean I use backend (php) on port 8080, I cannot make it on the same port. I use wampserver and latest Nuxt.Sogdian
I
5

To solve CORS error when tunneling through ngrok. Have to append the following in headers from client before calling server.

headers : { 
  'ngrok-skip-browser-warning':true
}
Instant answered 15/5, 2023 at 10:12 Comment(1)
Didn't work in my caseLecky
S
3

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.

Sweatband answered 7/3, 2020 at 12:21 Comment(2)
Hi, thanks for uesful info. Sorry but I still don't understand why both client web( react) and server (expressjs) have the same port (5000) ?Attorn
What about different port? I mean I use backend (php) on port 8080, I cannot make it on the same port. I use wampserver and latest Nuxt.Sogdian
M
-1

If you are using ngrok with nodejs/express.js .

Remove the 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.

Metacenter answered 5/5, 2021 at 11:5 Comment(2)
Didn't work. Curiously, only in browser Access-Control-Allow-Origin is not present.Inheritor
@SaidTorres '...only in browser Access-Control-Allow-Origin is not present' what do you mean by thisMetacenter

© 2022 - 2025 — McMap. All rights reserved.