当通过ngrok进行隧道传输时,为什么会出现CORS错误?

7

我知道这种问题之前已经被解决过了,但我仍然不确定为什么对我的情况不起作用。

我正在本地开发一个网站,并想在各种平台和设备上测试它,所以我决定使用ngrok来实现。

我的前端运行在3000端口上,我的express服务器运行在5000端口上。

所以我打开了ngrok并输入了ngrok http 3000

在我的本地PC上,服务器运行正常,https://example.ngrok.io没有任何问题。

但是在我的笔记本电脑(或其他设备)上,前端显示正确,但当它实际上要从后端获取数据时,会显示错误: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).

在我的express服务器上,我确保使用了cors包和app.use(cors());,我还尝试手动添加标头:

app.all('/*', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  next();
});

来源:为什么在OPTIONS路由上添加CORS标头不允许浏览器访问我的API?

以下是我获取和获取数据的代码,以防我做错了:

index.js(前端)

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(后端)

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

由于本地主机的性质,这是否可行?

火狐和谷歌浏览器都存在同样的问题。

感谢您的帮助!


响应的HTTP状态码是什么?您可以使用浏览器开发工具中的网络面板进行检查。它是否是4xx或5xx错误,而不是200 OK成功响应? - sideshowbarker
嘿@sideshowbarker,感谢您的回复,很抱歉我没有提供这些信息。奇怪的是,请求根本没有状态码(在此处显示:https://imgur.com/a/D3BJRkb),然后在控制台中出现了实际错误(https://imgur.com/a/XjYeysY)。当我使用我的运行服务器的PC从Postman进行相同的请求时,请求是正常的并且可以通过,但是在我的笔记本电脑上显示为这样(https://imgur.com/a/hDE34GR)。请注意,我也曾经使用OpenSSL创建过SSL证书,使服务器成为https,但即使在我的本地PC上也会出现完全相同的错误。 - TheBigMacTheory
3个回答

4
为了解决通过ngrok进行隧道传输时出现的CORS错误,必须在从客户端调用服务器之前在标头中添加以下内容。
headers : { 
  'ngrok-skip-browser-warning':true
}

3

步骤1:

与其让2个端口都处于活跃状态(客户端使用3000端口,服务器使用5000端口),我关闭了客户端端口,并直接从我的服务器中使用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());

步骤2:

现在我们有一个端口(端口5000)用于客户端和服务器,我进入了我的客户端,在那里我进行了获取请求(请参见上面的index.js),并修改了实际请求为相对路径:

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 

步骤三:

最后,我打开了ngrok并输入了以下命令:

ngrok http 5000

现在应该可以工作了。


嗨,谢谢提供有用的信息。抱歉,但我仍然不明白为什么客户端Web(React)和服务器(ExpressJS)具有相同的端口(5000)? - Truong Hoang
不同的端口怎么办?我的意思是我在8080端口上使用后端(php),我不能在同一个端口上使用。我使用wampserver和最新的Nuxt。 - Fahmi

-1
如果您正在使用ngrok与nodejs/express.js。
请删除cors导入并使用以下代码:
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();
});

将“YOUR-DOMAIN.TLD”替换为“*”,以便访问所有URL或您特定的网站URL。

有关更多详细信息,请参阅https://enable-cors.org/server_expressjs.html

谢谢。


没起作用。奇怪的是,只有在浏览器中 Access-Control-Allow-Origin 不在。 - Said Torres
@SaidTorres说:“只有在浏览器中,Access-Control-Allow-Origin才不存在。”这是什么意思? - Daniel Sogbey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接