From 182f78f61ec5d832d4c783065888880d86bb187e Mon Sep 17 00:00:00 2001 From: Jason Ren <40999116+jasonren0403@users.noreply.github.com> Date: Tue, 22 Oct 2024 15:16:38 +0800 Subject: [PATCH] change xmlhttprequest examples to fetch one and other fixes --- files/zh-cn/web/http/cors/index.md | 49 ++++++++++++++++-------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/files/zh-cn/web/http/cors/index.md b/files/zh-cn/web/http/cors/index.md index e6f1293469f2fa..f3c45fb3481d4b 100644 --- a/files/zh-cn/web/http/cors/index.md +++ b/files/zh-cn/web/http/cors/index.md @@ -84,12 +84,13 @@ CORS 请求失败会产生错误,但是为了安全,在 JavaScript 代码层 比如说,假如站点 `https://foo.example` 的网页应用想要访问 `https://bar.other` 的资源。`foo.example` 的网页中可能包含类似于下面的 JavaScript 代码: ```js -const xhr = new XMLHttpRequest(); -const url = "https://bar.other/resources/public-data/"; +const fetchPromise = fetch("https://bar.other"); -xhr.open("GET", url); -xhr.onreadystatechange = someHandler; -xhr.send(); +fetchPromise + .then((response) => response.json()) + .then((data) => { + console.log(data); + }); ``` 此操作实行了客户端和服务器之间的简单交换,使用 CORS 标头字段来处理权限: @@ -148,12 +149,19 @@ Access-Control-Allow-Origin: https://foo.example 如下是一个需要执行预检请求的 HTTP 请求: ```js -const xhr = new XMLHttpRequest(); -xhr.open("POST", "https://bar.other/resources/post-here/"); -xhr.setRequestHeader("X-PINGOTHER", "pingpong"); -xhr.setRequestHeader("Content-Type", "application/xml"); -xhr.onreadystatechange = handler; -xhr.send("Arun"); +const fetchPromise = fetch("https://bar.other/doc", { + method: "POST", + mode: "cors", + headers: { + "Content-Type": "text/xml", + "X-PINGOTHER": "pingpong", + }, + body: "Arun", +}); + +fetchPromise.then((response) => { + console.log(response.status); +}); ``` 上面的代码使用 `POST` 请求发送一个 XML 请求体,该请求包含了一个非标准的 HTTP `X-PINGOTHER` 请求标头。这样的请求标头并不是 HTTP/1.1 的一部分,但通常对于 web 应用很有用处。另外,该请求的 `Content-Type` 为 `application/xml`,且使用了自定义的请求标头,所以该请求需要首先发起“预检请求”。 @@ -263,7 +271,7 @@ CORS 最初要求浏览器具有该行为,不过在后续的[修订](https://g 如果上面两种方式难以做到,我们仍有其他办法: -1. 发出一个[简单请求](#简单请求)(使用 {{domxref("Response.url")}} 或 {{domxref("XMLHttpRequest.responseURL")}})以判断真正的预检请求会返回什么地址。 +1. 发出一个[简单请求](#简单请求)(使用 Fetch API 中的 {{domxref("Response.url")}} 或 {{domxref("XMLHttpRequest.responseURL")}})以判断真正的预检请求会返回什么地址。 2. 发出另一个请求(*真正*的请求),使用在上一步通过 `Response.url` 或 `XMLHttpRequest.responseURL` 获得的 URL。 不过,如果请求是由于存在 `Authorization` 字段而引发了预检请求,则这一方法将无法使用。这种情况只能由服务端进行更改。 @@ -278,20 +286,15 @@ CORS 最初要求浏览器具有该行为,不过在后续的[修订](https://g 本例中,`https://foo.example` 的某脚本向 `https://bar.other` 发起一个 GET 请求,并设置 Cookies。在 `foo.example` 中可能包含这样的 JavaScript 代码: ```js -const invocation = new XMLHttpRequest(); const url = "https://bar.other/resources/credentialed-content/"; -function callOtherDomain() { - if (invocation) { - invocation.open("GET", url, true); - invocation.withCredentials = true; - invocation.onreadystatechange = handler; - invocation.send(); - } -} +const request = new Request(url, { credentials: "include" }); + +const fetchPromise = fetch(request); +fetchPromise.then((response) => console.log(response)); ``` -第 7 行将 {{domxref("XMLHttpRequest")}} 的 `withCredentials` 标志设置为 `true`,从而向服务器发送 Cookies。因为这是一个简单 `GET` 请求,所以浏览器不会对其发起“预检请求”。但是,如果服务器端的响应中未携带 {{HTTPHeader("Access-Control-Allow-Credentials")}}`: true`,浏览器将**不会**把响应内容返回给请求的发送者。 +本代码创建了一个 {{domxref("Request")}} 对象,并在构造器中将 `credentials` 选项设置为 `"include"`,然后将该请求作为 `fetch()` 的参数传递。因为这是一个简单 `GET` 请求,所以浏览器不会对其发起预检请求。但是,浏览器会**拒绝** 任何不带 {{HTTPHeader("Access-Control-Allow-Credentials")}}`: true` 标头的相应,且**不会**把响应提供给调用的网页内容。 ![包含 Access-Control-Allow-Credentials 响应标头的简单 GET 请求的示意图](https://mdn.github.io/shared-assets/images/diagrams/http/cors/include-credentials.svg) @@ -327,7 +330,7 @@ Content-Type: text/plain [text/plain payload] ``` -即使第 10 行指定了 Cookie 是属于 `https://bar.other` 的内容的,但是,如果 `https://bar.other` 的响应中缺失 {{HTTPHeader("Access-Control-Allow-Credentials")}}`: true`(第 16 行),则响应内容会被忽略,不会提供给 web 内容。 +虽然请求的 `Cookie` 标头包含了为 `https://bar.other` 上的内容指定的 cookie,但如果 bar.other 没有像本例中演示的那样响应一个值为 `true` 的 {{HTTPHeader("Access-Control-Allow-Credentials")}},该响应将被忽略,网络内容将无法使用。 #### 预检请求和凭据