所有文章 > 技术杂货铺 > TypeScript CORS指南:它是什么如何启用它
TypeScript CORS指南:它是什么如何启用它

TypeScript CORS指南:它是什么如何启用它

如果您以前使用 TypeScript 构建过强大的 Node.js API,我敢肯定您至少遇到过一次臭名昭著的 CORS 错误。或者也许您团队的前端人员已经抱怨过无数次了! 

CORS 往往比看上去更棘手。许多开发人员很难理解它的含义。更糟糕的是,开发人员花了数小时修复它,才意识到他们一直在往错误的方向思考。在这篇文章中,我将帮助您了解 CORS 是什么以及它为什么会发生。然后我将引导您了解如何在 Node.js 和 TypeScript 应用程序中启用 CORS。

什么是 CORS?

首先让我们了解一下 CORS 的真正含义。CORS 代表跨域资源共享。它是一条规则,用于确定是否允许浏览器从服务器检索某些数据。因此,要掌握 CORS,我们需要关注两件事:首先,谁制定了这条规则?其次,如何制定? 

当我们回答这些问题时,我们很容易弄清楚为什么会出现 CORS 错误以及如何修复它们。但在讨论这两件事之前,让我们先了解一下 CORS 的目的以及它存在的原因。 

客户端与服务器之间的资源共享

现代 Web 应用程序通常遵循客户端-服务器架构。因此,客户端(即应用程序的前端)向服务器发出 HTTP 请求。服务器接收此请求、理解它并相应地执行操作。 

现在,这个操作可以是任何操作,从获取数据库数据到写入数据库再到更新数据库中的条目 — 几乎任何操作都可以。但总而言之,它会向客户端发送响应。 

TypeScript CORS 指南:它是什么以及如何启用它 - 图片 2

客户端-服务器关系。

这样应用程序的前端和后端就可以相互通信和共享资源。但是 Web 应用程序的客户端始终在浏览器上运行。这就产生了一些复杂情况,因为前端开发人员无法完全控制很多事情。 

浏览器强制实施同源策略

网络浏览器已经存在了几十年。它们的存在改变了网络应用程序的工作方式,尤其是其安全性方面。这就是为什么浏览器默认对所有客户端应用程序实施同源策略。此策略规定,如果在浏览器上运行的应用程序从与您的应用程序来源不同的服务器请求资源,则浏览器将默认阻止该请求。

但这个起源到底是什么?

来源通常由域名、端口号和方案组成。方案表示 URL 的协议 — 例如,它是 HTTP 还是 HTTPS。域名和端口号一起表示 URL 中您或其他用户可见的部分。 

因此,如果您的 Web 应用程序在 abcd.com 上运行,并且您尝试请求位于 xyz.com 的资源,则浏览器(您的 abcd.com 正在其中运行并向 xyz.com 发出请求)将启动其同源策略。 

你需要 CORS!

现在的问题是,你的应用程序需要来自不同来源的提供商的资源。这个问题有很多用例。 

首先,您可以为您的 Web 应用程序采用解耦的客户端-服务器架构。这意味着您可以拥有一个在 abcd.com 上运行的完全独立的前端和一个在 xyz.com 上运行的独立后端。您需要它们相互交互,但由于它们位于不同的域上,并且本质上来自不同的来源,因此您无法实现。 

另一个用例是与第三方 API 和服务交互。您可以使用第三方 API 在您的网站上进行付款,或者使用第三方服务来处理应用程序上的身份验证。

无论用例如何,第三方服务总是会与您的应用程序有不同的来源。 

为了让您的应用程序与不同来源的 Web 服务器和 API 进行交互,您需要 CORS。CORS 将告诉浏览器取消其同源策略并启用相应客户端和服务器之间的资源共享。这就是 CORS 对您有所帮助的原因和方式。如果您想了解有关 CORS 的更多信息,请查看这本深入探讨该主题的 精彩指南。

现在我们来回答第一个问题,谁来实际设置 CORS?

服务器已启用 CORS

由于资源是从服务器检索的,因此服务器可以完全控制哪些客户端可以访问它。出于同样的原因,启用 CORS 也是在服务器端完成的。 

这意味着您的应用程序中将有一个后端组件。该后端组件应该确保将为哪些 URL 或客户端启用 CORS。 

现在来回答第二个问题。至于如何启用 CORS,让我们写一些代码吧!

使用 TypeScript 创建 Node.js 项目

在本教程中,我们将重点介绍使用 Node.js 和 Express 构建的后端,该后端使用 TypeScript 编写。我有一个类似的 JavaScript 教程,您也可以查看。 

在您选择的目录中,通过运行以下命令创建一个新的 npm 项目: 

mkdir nodejs-ts-cors && npm init -y

然后,我们通过运行以下命令安装 TypeScript 作为开发依赖项: 

npm i --save-dev typescript

如果您打开项目,您现在应该有一个package.json文件、一个package-lock.json文件和一个node_modules文件夹。 

接下来,在项目根目录下创建一个名为tsconfig.json的文件。此文件将指定 TypeScript 构建项目的所有配置。在其中添加以下代码:

{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist"
},
"lib": ["es2015"]
}

最后,我们需要替换package.json文件中的主要条目:

...
"main": "dist/server.js"
...

并添加一个新脚本,该脚本可以在从 TypeScript 编译后在运行时直接运行我们的 JavaScript 代码:

...  
"scripts": {
"start": "tsc && node dist/server.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
...

创建一个 Express 和 TypeScript 服务器

在创建用于发送资源的端点之前,我们需要设置服务器。要创建服务器,我们将安装 Express,如下所示: 

npm i --save express@4.17.1

要将 Express 与 TypeScript 的类和类型一起使用,我们还需要安装types/express, 如下所示: 

npm install -save-dev @types/express@4.17.1

现在在根目录中创建一个名为server.ts的文件,内容如下:

const app:any = express();
const port:Number = 3000;

app.get('/', (req, res) => {
res.send('NodeJS + Express + Typescript App Up! 👍');
});

app.listen(port, () => {
console.log(`Server running on port ${port}`);
});

如果你现在运行命令npm run start,我们的 TypeScript 编译器将编译我们的server.ts文件,在dist/server.js文件中生成其等效的 JavaScript 代码,并在本地主机上提供服务。如果你访问“http://localhost:3000”,你应该会得到以下响应:

TypeScript CORS 指南:它是什么以及如何启用它 - 图片 3

您将收到的回复视图。

太棒了!现在让我们创建一个发回一些资源的简单端点。

创建 REST API

让我们编写一个简单的 REST API 来返回一些 JSON 数据。我们将创建一个端点/dog来返回一些关于(您猜对了)狗的 JSON 数据!

app.get('/dog',(req,res)=>{
res.json({
'name':'Bruno',
'age':'5',
'image':'https://post.medicalnewstoday.com/wp-content/uploads/sites/3/2020/02/322868_1100-800x825.jpg'
})
})

太棒了!现在让我们测试一下。您需要重新运行npm run start 命令。如果您现在访问“http://localhost:3000/dog”,您应该会得到以下响应:

TypeScript CORS 指南:它是什么以及如何启用它 - 图片 4

您将收到的回复视图。

因此,现在 TypeScript 中似乎有一个 GET API 可以返回一些资源。但是,当我们从 React 或 Angular 等客户端应用程序请求此资源时会发生什么?

CORS 错误

为了演示这一点,我们将创建一个 React 应用并尝试向上述端点发出请求。首先,让我们通过运行以下命令创建一个新的 React 项目:

npx create-react-app dog-app

完成后,打开项目并使用以下代码更新App.js文件:

import {useState} from 'react';
import './App.css';

function App() {
const [dogData,setDogData]=useState();
const getDogData=async()=>{
const response=await fetch('http://localhost:3000/dog');
const data=await response.json();
setDogData(data);
}
return (
<div className="App">
<header className="App-header">
<button onClick={getDogData} disabled={dogData}>Get Dogg!</button>
{dogData &&
<div>
<h3>{dogData?.name}</h3>
<h3>{dogData?.age}</h3>
<img src={dogData?.image} />
</div>
}
</header>
</div>
);
}

export default App;

此代码在页面上呈现一个按钮。单击按钮时,它会调用一个函数,该函数向端点“http://localhost:3000/dog”发出请求。然后,它会获取收到的资源或 JSON 数据,将该数据推送到应用组件的状态,并将其显示在页面上。 

让我们测试一下。您必须运行 npm 才能开始运行它,并且它可能会要求您在其他端口上打开此应用程序,因为我们已经将端口 3000 用于 TypeScript 和 Express 后端服务器。一旦它进入您的浏览器,如果您按下Get Dogg!按钮,您应该会在控制台上收到如下错误:

TypeScript CORS 指南:它是什么以及如何启用它 - 图片 5

点击“Get Dogg!”按钮后出现 CORS 错误。

启用 CORS

我们需要消除该 CORS 错误。一种解决方案是,我们可以为该客户端手动启用端点上的 CORS。我们可以通过在响应的标头上添加键“Access-Control-Allow-Origin”来实现这一点。此键的值是您希望为其启用 CORS 的应用程序或客户端的 URL。 

在我们的例子中,它是“http://localhost:3001”或你的 React 应用程序正在运行的任何位置。

app.get('/dog',(req,res)=>{
res.set('Access-Control-Allow-Origin', 'http://localhost:3001');
...
})

现在您的 React 应用程序将能够从“http://localhost:3000”访问资源。如果您刷新后端,请再次单击“Get Dogg!”按钮。

TypeScript CORS 指南:它是什么以及如何启用它 - 图片 6

Get Dogg! 按钮正在运行。

我们现在可以从 TypeScript API 中取回数据!太棒了。我们已成功在 Node.js 和 TypeScript 应用程序中启用 CORS。

结论

还有另一种在 Node.js 和 TypeScript 服务器中启用 CORS 的巧妙方法。您可以使用 CORS 中间件依赖项,它允许您以更自定义的方式轻松配置 CORS。Node.js 的实现类似于 TypeScript,您可以在本教程中了解如何执行此操作。 

如果您想要针对这个古老的 CORS 问题进行前端特定的破解,这里有针对ReactAngular的解决方案。但请记住,处理 CORS 的正确方法是在服务器上设置适当的访问控制允许来源。但总而言之,我希望这足以帮助您掌握 CORS 并了解如何在 Node.js 和 TypeScript 应用程序中启用它。

#你可能也喜欢这些API文章!