# 响应处理示例

> For the complete documentation index, see [llms.txt](https://www.jetbrains.com.cn/help/idea/llms.txt).

在本主题中，我们将查看几个 HTTP 响应处理示例。 如需亲自尝试示例，请探索  auth-requests  和  test-responses  [requests collections](http-client-in-product-code-editor.html#open-requests-collection)。

## 检查响应页眉、正文和内容类型

在此示例中，我们将创建多个测试来验证以下内容：

* 请求已成功执行，即响应状态为 200 。

* 响应体内接收到报头。

* 响应的内容类型是 application/json 。

创建测试时，我们调用  `test`  方法 [客户端](http-client-reference.html) 对象。 在测试中，我们可以通过调用  `client` 对象的  `断言` 方法来断言特定条件，并引用 [回应](http-response-reference.html)对象的各种属性以进行验证。

```JAVASCRIPT
// Check response status, headers, and content-type
GET https://httpbin.org/get

> {%
    client.test("Request executed successfully", function() {
        client.assert(response.status === 200, "Response status is not 200");
    });

    client.test("Headers option exists", function() {
        client.assert(response.body.hasOwnProperty("headers"), "Cannot find 'headers' option in response");
    });

    client.test("Response content-type is json", function() {
        var type = response.contentType.mimeType;
        client.assert(type === "application/json", "Expected 'application/json' but received '" + type + "'");
    });
%}

```

## 使用全局变量

在此示例中，我们会将接收到的响应中的一个值捕获到 [全局变量](http-client-reference.html#global-variables-storage-reference)中，然后可在后续请求中使用。

第一个请求涉及响应处理程序脚本，将从接收的响应正文中保存身份验证令牌到  `auth_token`  变量中，并置于 [client.global](http-client-reference.html#global-variables-storage-reference) 下。 为了实现这一点，我们使用  `client.global.set(VariableName, VariableValue)` 。 作为  `VariableValue`  参数，我们使用从服务器返回的 [响应主体](http-response-reference.html#response-properties) 中  `令牌`  字段的值。 此值随后被分配给  `"auth_token"`  变量。

```HTTP_REQUEST_FULL
POST https://examples.http-client.intellij.net/body-echo
Content-Type: application/json

{
"token": "my-secret-token"
}

> {% client.global.set("auth_token", response.body.token); %}

```

请求执行之后，  `auth_token`  变量可以从后续请求（在  `{{auth_token}}`  变量中）和响应处理程序脚本（通过  `client.global.get("auth_token")`  结构）中访问。

```HTTP_REQUEST
//Accessing a variable
GET https://examples.http-client.intellij.net/headers
Authorization: Bearer {{auth_token}}

```

要从响应头中获取一个值，请使用  `valueOf`  方法的 [标头](http-response-reference.html#headers-reference) 对象。 如果收到多个名称相同的页眉，请改用  `valuesOf`  方法。 这将返回所有响应头值的数组。

```GENERIC
POST https://httpbin.org/cookies

//Saving a cookie from the first Set-Cookie header
> {%
    client.global.set("my_cookie", response.headers.valuesOf("Set-Cookie")[0]);
%}

```

## 将 Cookie 保存为全局变量

在此示例中，我们将发送一个返回 Cookie 的请求，使用响应处理程序脚本从响应中提取该 Cookie，将其值保存为 [全局变量](http-client-reference.html#global-variables-storage-reference)，然后在后续请求中重复使用。

假设端点在响应中返回一个  `SOCS`  Cookie。 我们使用 [response.cookiesByName("SOCS")](http-response-reference.html#cookies-by-name) 方法从响应中查找并提取此 Cookie。

将 Cookie 值保存为全局变量 (  `client.global.set()` ) 后，可以在后续请求中重复使用该值。 在下一个请求中，我们在  `Cookie`  页眉中引用  `{{SOCS_COOKIE}}`  以发送提取的值。

```JAVASCRIPT
            GET https://www.google.com

> {%
    const cookie = response.cookiesByName("SOCS")[0];

    if (cookie) {
        client.global.set("SOCS_COOKIE", cookie.value);
        console.log("Saved SOCS_COOKIE =", cookie.value);
    } else {
        console.log("SOCS cookie not found");
    }
%}

###

// Request 2 — Send the saved cookie to a test endpoint that echoes cookies
GET https://httpbin.org/cookies
    Cookie: SOCS={{SOCS_COOKIE}}
        
```

## 处理事件流的每一行

如果订阅事件流，服务器将在有新数据可用时自动向您的客户端发送事件。 这些数据可以是服务器发送事件或换行分隔的 JSON (NDJSON)。 在 IntelliJ IDEA 中，您可以使用 HTTP 客户端 [response.body.onEachLine](http-response-reference.html#textstreamresponse_reference) 方法对此事件流的每一行调用一个函数。

假设您有一台定期发送黄金价格信息的服务器。 在这个示例中，编写一个响应处理程序脚本，执行以下操作：

1.  将从服务器接收到的每个数据块（JSON 对象）记录并记录价格值。 当您运行请求时，您可以在   响应处理程序   选项卡中的   服务   工具窗口查看记录的信息。

2.  当事件数量超过 10 时停止处理接收到的数据。 请注意，这不会取消您对事件流的订阅——只要 HTTP 连接保持开放，您将继续接收事件（检查   控制台   选项卡的   服务   工具窗口）。

3.  测试获取的数据块：如果价格低于 45，则测试失败。 您可以在   测试   选项卡的   服务   工具窗口中查看测试结果。

```JAVASCRIPT
GET localhost/stocks/subscribe?symbol=GOLD

> {%
var updatesCount = 0;
response.body.onEachLine(
    (symbolUpdate, unsubscribe) => {
        updatesCount++;
        client.log(symbolUpdate.pricePresentation);
        if (updatesCount > 10) {
            unsubscribe();
            return;
        }

        client.test("Price test " + updatesCount, () => {
            client.assert(symbolUpdate.lastPrice >= 45, "Price must be >= 45");
            client.log(symbolUpdate.pricePresentation);
        });
    }
)
%}
        
```

## 使用 DOM API 处理 XML 响应

如果响应的  `Content-Type`  是 XML（例如  `application/xml`  或  `text/xml` ），HTTP 客户端会将  `response.body`  公开为 [DOM

文档](https://developer.mozilla.org/en-US/docs/Web/API/XMLDocument)。 要解析并验证响应，可以直接使用 [支持的 DOM 方法](javascript-api-supported-by-http-client.html#dom-methods)。 如果要应用字符串操作或正则表达式，可以使用  `new XMLSerializer().serializeToString(response.body)`  将 DOM  `文档`  序列化为字符串。

> **Note:**
> 在错误消息中，DOM  `文档`  可能显示为  `XmlDomDocument` 。 这是为 XML 响应支持  `response.body`  的内部实现。

### XML 响应验证

假设服务器以 XML 格式返回早餐菜单。 在此示例中，响应处理程序脚本从 XML 文档中提取值，并使用测试对其进行验证。

```JAVASCRIPT
GET https://www.w3schools.com/xml/simple.xml

> {%
    client.test("First food item is Belgian Waffles", () => {

        const foods = response.body.getElementsByTagName("food");
        client.assert(foods.length > 0, "No food elements found");

        const firstFood = foods[0];

        const name = firstFood
            .getElementsByTagName("name")[0]
            .textContent
            .trim();

        const calories = firstFood
            .getElementsByTagName("calories")[0]
            .textContent
            .trim();

        client.log("Name:", name);
        client.log("Calories:", calories);

        client.assert(name === "Belgian Waffles", "Unexpected food name: " + name);
        client.assert(calories === "650", "Unexpected calories: " + calories);
    });
%}
            
```

该脚本以 DOM  `文档`  格式解析  `response.body` ，并执行以下操作：

* 使用 `getElementsByTagName()` 检索所有 `food` 元素。

* 确保至少存在一个 `food` 元素。

* 选择第一个 `food` 元素。 然后，使用 `textContent` 提取其嵌套的 `名称` 和 `calories` 元素的文本值。

* 使用 `client.assert()` 验证提取的值是否与预期值匹配。

