写点什么

调用 Express API 时出现奇怪的 CORS 错误该怎么办?

  • 2020-12-18
  • 本文字数:3288 字

    阅读完需:约 11 分钟

调用 Express API时出现奇怪的CORS错误该怎么办?

想象一下这样一个场景:你用 Express 创建了一个 API,然后给前端加了一些 JavaScript 代码,这些 JS 代码会向这个 API 发送请求。事情本来很顺利,然后你在浏览器中加载了前端,突然在控制台中看到了一个奇怪的错误:


Access to fetch at 'https://your-api.com/user/1234' from origin 'https://your-website.com' 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.
复制代码


然后你可能会试着按照错误消息的提示,将请求的模式设置为 no-cors,但是对 API 的请求还是跑不通。就算你在网上搜索一番,也很难搞清楚为什么会发生这种事情,该怎么才能解决它。


好消息是,有一个 Express 库可用来修复这些 CORS 错误,但在我们着手解决这些错误之前,我们是不是该看看它们到底是什么意思?为了理解这些错误,我们先来看一下 CORS 究竟是什么。


什么是 CORS?为什么它会毁掉你美好的一天?


CORS 是跨域资源共享(Cross-Origin Resource Sharing)的简写,并且所有现代浏览器都支持它。这个概念有点拗口,所以我们把它拆开来细看,才能了解它到底做的是什么事情。


什么是“资源”?


资源是可在特定 URL 获取的内容,如 HTML 网页、图像或 JSON API 响应。实际上,它是构成万维网的“砖块”。


什么是“来源”?


一份资源的来源(origin)是协议+域+端口,例如网址https://your-api.com:8080/user/1234的源是https://your-api.com:8080。如果网址不包含端口,则源就只有协议+域。


跨域资源共享到底是做什么的?


当 Web 浏览器需要确保网站的前端 JavaScript(来源 A)仅在另一来源(来源 B)明确允许的情况下才可以访问 B 的资源时,就要用到跨域资源共享。如果来源 B 确实给出了许可,那么资源就会跨域共享!


CORS 可以帮助阻止恶意网站访问和使用敏感数据。当你在浏览器中看到那些烦人的 CORS 错误时,实际上是你的 Web 浏览器正在尽最大努力保护你免受被识别为潜在恶意请求的威胁。


CORS 如何工作?


Web 浏览器决定是否允许跨域共享资源时,会在前端 JavaScript 发出的请求上设置 Origin 标头。然后,浏览器检查在资源响应上设置的 CORS 标头。它在响应上检查的标头取决于浏览器发出的请求类型,但响应至少必须将 Access-Control-Allow-Origin 标头设置为一个受许可的值,才能让 Web 浏览器对发起请求的前端 JavaScript 给出响应。


CORS 请求示例


跨域请求的一个示例是,从网页上的前端 JavaScript(托管在一个域「来源 A」上)发起一个 GET 请求,到你托管在另一个域(来源 B)的 API 端点上。


浏览器通过https://your-website.com/user-profile网页上的 JavaScript 发出的请求将包含以下信息:


> GET /user/1234 HTTP/1.1> Host: your-api.com> Origin: https://your-website.com
复制代码


Origin 请求标头是由 Web 浏览器自动设置的——出于安全原因,通过 fetch 请求时无法设置其值。为了让上面的示例 CORS 请求正确运行,你的 API 发出的响应应该是这个样子:


< HTTP/1.1 200 OK< Access-Control-Allow-Origin: https://your-website.com< Vary: Origin< Content-Type: application/json; charset=utf-8< {"name":"Existing Person"}
复制代码


请注意,Access-Control-Allow-Origin 响应标头的值与 Origin 响应的值是呼应的:https://your-website.com。Web 浏览器会看到这个 CORS 响应标头,并确认它具有与网页上的前端 JavaScript 共享响应内容的权限。现在我们对 CORS 的概念和作用有了更好的了解,是时候设置一些 CORS 标头并修复你在网页上遇到的错误了。


如何设置 CORS 标头并摆脱那些烦人的错误


如你在上面的示例中所看到的,对于 Web 浏览器来说,在对 API 的请求中发送 Origin 标头是很重要的,但在响应中发送所有重要的 Access-Control-*标头的是你的 API。这些 CORS 标头会告诉 Web 浏览器是否允许将来自 API 的响应提供给前端 JavaScript。


为了帮助你解决你烦人的 CORS 错误,你需要用到 cors middleware package 这个库。在终端中转到包含 Express 应用程序的目录,然后安装它:


npm install cors
复制代码


注意:在这篇博客文章中,我会链接到 GitHub(而非 npm)上的 cors 软件包,因为在撰写本文时,npm 上的这个包的文档已经过时了。


安装完成后,你需要在应用程序中 require 它(require express 之后直接处理它即可):


const cors = require("cors");
复制代码


如果在不传递任何配置选项的情况下在 Express 应用程序中调用 cors 中间件,则默认情况下,它将在 API 响应中添加 CORS 响应标头 Access-Control-Allow-Origin: *。这意味着任何来源(即任何域上的网页)都可以向你的 API 发出请求。除非你要构建供公众使用的 API,否则你肯定不希望这么做。因此我们需要配置 cors 中间件,配置成只有你的网站才能向你的 API 发出 CORS 请求:


/** * These options will be used to configure the cors middleware to add * these headers to the response: *  * Access-Control-Allow-Origin: https://your-website.com * Vary: Origin */const corsOptions = {  origin: "https://your-website.com"};/** * This configures all of the following routes to use the cors middleware * with the options defined above. */app.use(cors(corsOptions));app.get("/user/:id", (request, response) => {  response.json({ name: "Existing Person" });});app.get("/country/:id", (request, response) => {  response.json({ name: "Oceania" });});app.get("/address/:id", (request, response) => {  response.json({ street: "Gresham Lane", city: "Lakeville" });});
复制代码


一般来说,你需要像上面的示例一样为 Express 应用程序中的所有路由启用 CORS,但是如果你只想为特定路由启用 CORS,则可以按以下方式配置 cors 中间件:


/** * These options will be used to configure the cors middleware to add * these headers to the response: *  * Access-Control-Allow-Origin: https://your-website.com * Vary: Origin */const corsOptions = {  origin: "https://your-website.com"};// This route is using the cors middleware with the options defined above.app.get("/user/:id", cors(corsOptions), (request, response) => {  response.json({ name: "Existing Person" });});// This route is using the cors middleware with the options defined above.app.get("/country/:id", cors(corsOptions), (request, response) => {  response.json({ name: "Oceania" });});/** * We never want this API route to be requested from a browser, * so we don't configure the route to use the cors middleware. */app.get("/address/:id", (request, response) => {  response.json({ street: "Gresham Lane", city: "Lakeville" });});
复制代码


启用“复杂”CORS 请求


上面的示例是为简单的 GET 请求配置 CORS 的。对于其他许多类型的 CORS 请求,Web 浏览器将在发出实际 CORS 请求之前先发出 CORS“预检”(pre-flight)请求。这个预请求使用了 OPTIONS HTTP 方法,它可以帮助浏览器确定是否允许发出 CORS 请求。


cors 中间件提供了启用 CORS 预检的说明,并允许你配置在对预检请求的响应中发送的标头。


不用再担心 COR 了 S


希望本文能够帮助你全面了解 CORS,但有时我们确实很难弄清楚如何配置才能让 CORS 请求正常工作。下面列举一些有用的资源:



祝大家跨域资源共享愉快!


原文链接:How To Fix Those Confusing Cors Errors When Calling Your Express API

2020-12-18 11:552694

评论

发布
暂无评论
发现更多内容

实时分析,快速迭代 —— 商品信息监控助力商家持续优化产品

技术冰糖葫芦

API 接口 API 测试 API 协议

望繁信科技出席2022浦东国际人才港论坛,获颁最具潜力的海归创业团队大奖

望繁信科技

数字化转型 流程挖掘 流程资产 流程智能 望繁信科技

生成对抗网络GAN简介

天翼云开发者社区

网络 GAN

华为云开源引领,KubeEdge晋级CNCF毕业项目

华为云开发者联盟

云原生 边缘计算 cncf kubeedge

软件测试学习笔记丨Selenium复用cookie

测试人

软件测试

提升前端开发效率的五种实用技术

天翼云开发者社区

前端开发

HyperWorks的模型简化

智造软件

软件 教程 Hypermesh

详解MES系统的生产过程实时监控与异常处理

万界星空科技

生产管理系统 mes 制造业数字化 万界星空科技mes 生产过程管理

SQL Server 可观测最佳实践

观测云

SQL Server

DevSecOps在数字政府建设中的实践研究

不在线第一只蜗牛

大数据 DevSecOps

私有云容灾方案设计浅谈

天翼云开发者社区

云计算 私有云

云智慧透视宝:率先适配华为原生鸿蒙的APM,为用户体验保驾护航

云智慧AIOps社区

APM 应用性能管理 应用性能监控

SD-WAN 跨国专线的应用场景

Ogcloud

SD-WAN SD-WAN组网 跨国组网 SD-WAN国际专线 国际网络专线

一块显卡理解一部完整电影!智源联合多所高校推出小时级的超长视频理解大模型Video-XL

智源研究院

合合信息发布智能文档处理“百宝箱”,助力文档应用开发

合合技术团队

App 科技 合合信息 文档解析

一文彻底弄懂MySQL优化之深度分页

不在线第一只蜗牛

MySQL 数据库

AI PC“加菜”了,双十一最值得关注的10款酷睿Ultra 200V AI PC

E科讯

精彩回顾|2024 ACDU 中国行·上海站成功举办!

墨天轮

数据库 sql 国产数据库 KaiwuDB

软件测试学习笔记丨selenium处理下拉框

测试人

软件测试

精准操控,稳如磐石:飞控+综控系统仿真揭秘

DevOps和数字孪生

飞管飞控

枫清科技仲光庆:AI+行业新范式,双轮驱动助力数智化升级

Fabarta

#人工智能 #大模型

人工智能 | 智谱 AI 大模型

测吧(北京)科技有限公司

测试

淘宝商品评论API返回值中的物流与评价关联分析

技术冰糖葫芦

API 接口 API 测试 API】 API 协议

天谋科技成为先进操作系统创新联盟智能制造协同创新实验室成员单位,出席揭牌仪式

Apache IoTDB

AI安全智能体,重塑网络安全新范式

云起无垠

AI 原生时代,更要上云:百度智能云云原生创新实践

Baidu AICLOUD

云原生 智能化 大模型

Web3 游戏周报(10.20 - 10.26)

Footprint Analytics

链游

调用 Express API时出现奇怪的CORS错误该怎么办?_语言 & 开发_Simon Plenderleith_InfoQ精选文章