从 localhost Vue 项目调用 api 时出现 NodeJS CORS 错误

Posted

技术标签:

【中文标题】从 localhost Vue 项目调用 api 时出现 NodeJS CORS 错误【英文标题】:NodeJS CORS error when calling api from localhost Vue project 【发布时间】:2021-09-13 11:29:53 【问题描述】:

我有一个带有 NodeJS/Express 后端和 VueJS 前端的项目。我面临的问题是我不断收到 CORS 错误:

跨源请求被阻止:同源策略不允许读取位于 https://localhost:8080/api/plot 的远程资源。 (原因:CORS 请求未成功)。

我已经在我的 NodeJS 后端的 index.js 文件中添加了 CORS 中间件:

const express = require('express');

const app = express();

app.use((req, res, next) => 
  res.header('Access-Control-Allow-Origin', '*');
  res.header(
    'Access-Control-Allow-Headers',
    'Authorization, X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Allow-Request-Method',
  );
  res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');
  res.header('Allow', 'GET, POST, OPTIONS, PUT, DELETE');
  next();
);

我也尝试过不同的方法:

const express = require('express');
const cors = require('cors');

const app = express();

app.use(cors());

在 Vue 项目中,我已将代理添加到我的 vue.config.js 文件中:

module.exports = 
  devServer: 
    port: 8080,
    proxy: 
      '^/api': 
        target: 'http://localhost:3000',
        changeOrigin: true,
        secure: false,
        pathRewrite:  '^/api': '/api' ,
        logLevel: 'debug',
      ,
    ,
  ,
;

然后我将 API 调用的 URL 更改为发布 8080:

import axios from 'axios';

export const addPlot = async (plot) => 
  const url = `https://localhost:8080/api/plot`;
  return await axios.post(url, plot).then((res) => 
    console.log(res);
  );
;

【问题讨论】:

您的开发服务器似乎在 http://localhost:8080/ 上运行,并且您正在向 HTTP 端点发送 HTTPS 请求。 @MichalLevý 请求被发送到 8080 的原因是因为代理。这会将发送到 3000 的所有流量重定向到端口 8080。这通常可以修复 CORS 错误。 我知道。但是端口 8080 是 HTTP(无 SSL),您正在使用 HTTPS 进行 Axios 调用 .... @MichalLevý 非常感谢!这解决了问题! 【参考方案1】:

首先,当您使用 Webpack 开发服务器代理时,您不需要使用任何 CORS 配置 Express(假设在生产中您将从同一个 Express 服务器构建您的 Vue 应用程序)

您收到 CORS 错误的原因是您的应用是从 http://localhost:8080(Webpack 开发服务器)提供的,但您正在向 https://localhost:8080/api/plot 发出 Axios 请求 - 重要部分是 HTTPS://并且因为浏览器使用same-origin policy,只有当协议+主机+端口都相同时,浏览器才会触发CORS飞行前请求

只要让你的 Axios 调用 HTTP 而不是 HTTPS,你应该没问题...

【讨论】:

【参考方案2】:

    确保您处理预检请求(204 答案为空的选项) https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request

    尝试添加Access-Control-Expose-Headers https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers

允许服务器指示应生成哪些响应标头 可用于在浏览器中运行的脚本,以响应 跨域请求

【讨论】:

感谢您的回答。但我不完全明白我应该怎么做?【参考方案3】:

因此,CORS 错误基本上是一个安全错误,其中浏览器不允许您的项目可能需要从服务器接受某些/大部分资源。你可以通过两种方式来处理它,这两种方式取决于服务器的环境。

    在开发过程中 (www.localhost:port),您需要在项目文件夹中安装一个名为 cors (npm install cors) 的库。之后,您需要将库导入到您的代码中。此后,您将需要使用 cors 对象作为中间件(ps。我不完全知道中间件是什么 - 感谢所有 *** 委员会的积极回答)。示例:

    const express = require('express'); const cors = require('cors'); const app = express();

    app.use(cors()) // app.get(....)

    不过,在生产过程中,您的免费选择是有限的。如果你仔细检查错误,备注说明 https 协议允许跨资源(更多,但 http 不允许),所以你的 VPS 需要一个安全套接字层证书,SSL 证书,我买了 8美元一年。获得它是相当令人生畏的,但答案永远不会超过几次搜索,最多。获取 SSL 证书需要一个端口转发的 IP 地址,所以我强烈建议每月额外支付 6 美元来租用 VPS。 Linode 提供一些免费信用,截至目前,(非赞助),所以你可能想匆匆忙忙。无论如何,获取此类证书的步骤包括安装 OPENSSL、生成证书签名请求 (CSR),然后将其传递给您的 CA,然后按照他们指示您遵循的步骤进行操作,然后搜索有关说明在您的服务器中使用这些证书。你猜对了 - 在 *** (:

如需补充说明,请评论,我会尽力解答。

【讨论】:

以上是关于从 localhost Vue 项目调用 api 时出现 NodeJS CORS 错误的主要内容,如果未能解决你的问题,请参考以下文章

从运行在不同端口的 Vue 应用程序调用 node express 服务器 API

如何使用 Axios 从 localhost VueJS 调用服务器?

vue入门:对vue项目中api接口的封装管理

vue.config.js的proxy为啥不起作用

如何从API调用中选择单个JavaScript对象/ JSON项目

如何测试从 Flutter 应用程序到 localhost 服务的 api 调用?