bricks/aidocs/jsoncall.md
2025-10-05 06:39:58 +08:00

391 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Bricks HTTP 模块技术文档
本模块为 `bricks` 前端框架提供了一套完整的 HTTP 请求处理工具集支持多种响应类型文本、JSON、二进制流等并封装了自动参数注入、错误处理、会话管理与登录重定向等功能。
---
## 目录
- [概述](#概述)
- [核心功能](#核心功能)
- [公共函数](#公共函数)
- [基类:`HttpText`](#基类httptext)
- [派生类](#派生类)
- [`HttpArrayBuffer`](#httparraybuffer)
- [`HttpBin`](#httpbin)
- [`HttpResponse`](#httpresponse)
- [`HttpResponseStream`](#httpresponsestream)
- [`HttpRaw`](#httpraw)
- [`HttpJson`](#httpjson)
- [快捷方法](#快捷方法)
- [使用示例](#使用示例)
---
## 概述
`bricks.Http*` 系列类基于 `fetch` API 构建,旨在统一前端网络请求行为。主要特性包括:
- 自动附加设备信息和会话参数
- 支持 GET/POST 请求及 FormData 或 JSON 数据格式
- 统一的错误提示机制401、403、其他错误
- 可扩展的响应处理器文本、JSON、流式解析等
- 登录拦截与跳转支持(待完善)
该模块适用于 Web 应用中需要与后端服务交互的所有场景。
---
## 核心功能
| 功能 | 描述 |
|------|------|
| 参数合并 | 自动注入 `_webbricks_`, 屏幕宽高, 移动端标识等参数 |
| 会话管理 | 从响应头读取 `Set-Cookie` 并保存会话;发送时自动携带 |
| 错误处理 | 对 401、403 和非 OK 状态码进行统一 UI 提示 |
| 登录重定向 | 当返回 401 且存在 `login_url` 时触发登录流程(目前未完全实现) |
| 流式响应处理 | 支持逐行处理 chunked 响应数据(如 Server-Sent Events |
---
## 公共函数
### `url_params(data)`
将对象转换为 URL 查询字符串。
#### 参数
- `data`: `{[key: string]: any}` — 要编码的对象
#### 返回值
- `string` — 格式化后的查询字符串(例如 `"a=1&b=2"`
#### 示例
```js
url_params({a: 1, b: 'hello'}) // → "a=1&b=hello"
```
> ⚠️ 所有值都会通过 `encodeURIComponent` 编码。
---
## 基类:`HttpText`
所有 HTTP 客户端类的基类。
### 构造函数 `constructor(headers?)`
#### 参数
- `headers?`: `{[key: string]: string}` — 自定义请求头,默认为 `{ Accept: "text/html" }`
#### 行为说明
- 若未传入 `headers`,默认使用:
```js
{ "Accept": "text/html" }
```
- 使用 `bricks.extend()` 合并默认头与用户头。
- 自动收集以下上下文参数作为请求参数:
- `_webbricks_`: 固定值 `1`
- `width`: 屏幕宽度(来自 `bricks.app.screenWidth()`
- `height`: 屏幕高度(来自 `bricks.app.screenHeight()`
- `_is_mobile`: 是否为移动端(`'1'` 或 `'0'`
> ✅ 这些参数会在每次请求中自动附加。
### 方法
#### `url_parse(url)`
解析 URL 中的查询参数,并将其合并到内部 `this.params` 中。
##### 参数
- `url`: `string` — 原始 URL含 query
##### 返回值
- `string` — 清除 query 的基础 URL
##### 示例
```js
const client = new bricks.HttpText();
client.url_parse("/api/data?a=1&b=2");
// 结果client.params 包含 a=1, b=2
// 返回 "/api/data"
```
#### `add_own_params(params)`
合并用户参数与内部参数(包括 session
##### 参数
- `params`: `Object | FormData | null`
##### 返回值
- `Object | FormData` — 合并后的参数对象
##### 行为逻辑
- 如果是 `FormData`,直接追加键值对
- 否则创建新对象,合并 `this.params` 和 `params`
- 若存在 `bricks.app.get_session()`,额外添加 `session` 字段
#### `add_own_headers(headers)`
合并自定义请求头与实例默认头。
##### 参数
- `headers`: `{[key: string]: string} | null`
##### 返回值
- `Object` — 合并后的 headers
> 使用 `Object.assign(this.headers, headers)` 实现浅合并。
#### `async bricks_fetch(url, {method, headers, params})`
底层 `fetch` 封装,负责构建最终请求选项。
##### 参数
- `url`: `string` — 请求地址
- `method`: `'GET'|'POST'|'HEAD'|...` — HTTP 方法(默认 `'GET'`
- `headers`: `Object` — 请求头
- `params`: `Object|FormData` — 请求参数
##### 处理逻辑
| 条件 | 行为 |
|------|------|
| `params instanceof FormData` | 强制设为 POST`body = params` |
| `GET/HEAD` 请求 | 将 `params` 转为 query string 拼接到 URL |
| 其他方法(如 POST | `body = JSON.stringify(params)` |
##### 返回值
- `Response` — fetch 返回的原生响应对象
#### `async httpcall(url, opts)`
高层封装,包含状态码判断与错误处理。
##### 参数
- `url`: `string`
- `opts`: `{method, headers, params}`
##### 流程
1. 调用 `bricks_fetch` 发起请求
2. 检查响应状态:
- **401** 且配置了 `bricks.app.login_url` → 触发 `withLoginInfo`
- **403** → 显示“禁止访问”弹窗
- 非 `ok` → 显示通用错误弹窗
3. 成功则调用 `get_result_data()` 获取结果
4. 解析 `Set-Cookie` 并调用 `bricks.app.save_session(session)` 保存会话
##### 返回值
- `string | null` — 成功返回响应内容,失败返回 `null`
#### `async withLoginInfo(url, params)`
处理 401 时尝试重新登录(当前仅为占位实现)。
> ❗ 当前仅创建一个 `urlwidget` 加载登录页,未完成回调或重试逻辑。
#### `async get_result_data(resp)`
提取响应体数据的方法(可被子类覆盖)。
##### 默认实现(`HttpText`
```js
return await resp.text();
```
---
## 派生类
### `HttpArrayBuffer`
继承自 `HttpText`,用于下载二进制文件(如字体、模型等)。
#### 重写方法
```js
async get_result_data(resp) {
return await resp.arrayBuffer();
}
```
---
### `HttpBin`
继承自 `HttpText`,以 Blob 形式获取响应(适合图片、音频等)。
#### 重写方法
```js
async get_result_data(resp) {
return await resp.blob();
}
```
---
### `HttpResponse`
继承自 `HttpText`,直接返回原始 `Response` 对象。
#### 重写方法
```js
async get_result_data(resp) {
return resp;
}
```
> ✅ 适用于需手动处理 header 或 stream 的高级场景。
---
### `HttpResponseStream`
继承自 `HttpResponse`,专用于处理流式响应(如 SSE
#### 方法:`async handle_chunk(resp, handler)`
逐行解析 chunked 文本流,并调用 `handler(line)`。
##### 参数
- `resp`: `Response` — fetch 返回的响应对象
- `handler`: `(line: string) => void` — 每一行数据的处理器
##### 实现细节
- 使用 `ReadableStream.getReader()` + `TextDecoder`
- 按 `\n` 分割缓冲区,确保跨 chunk 边界正确切分
- 最终剩余内容也会传递给 `handler`
##### 示例用法
```js
const streamClient = new bricks.HttpResponseStream();
const resp = await streamClient.get('/stream-endpoint');
await streamClient.handle_chunk(resp, (line) => {
console.log('Received:', line);
});
```
---
### `HttpRaw`
与 `HttpBin` 相同,返回 `Blob`。
> ⚠️ 注释中可能表示未来用途不同,但当前实现与 `HttpBin` 完全一致。
---
### `HttpJson`
专用于 JSON 接口通信,设置默认 Accept 头并解析 JSON 响应。
#### 构造函数增强
```js
this.headers = { "Accept": "application/json" };
bricks.extend(this.headers, headers); // 用户头可覆盖
```
#### 重写方法
```js
async get_result_data(resp) {
return await resp.json();
}
```
> ✅ 推荐用于 RESTful API 调用。
---
## 快捷方法
模块末尾导出多个常用快捷函数,绑定到全局命名空间:
| 变量名 | 类型 | 说明 |
|--------|------|------|
| `bricks.hc` | `new HttpText()` | 文本客户端实例 |
| `bricks.tget` | `Function` | `hc.get` 的绑定方法GET 文本) |
| `bricks.tpost` | `Function` | `hc.post` 的绑定方法POST 文本) |
| `bricks.jc` | `new HttpJson()` | JSON 客户端实例 |
| `bricks.jcall` | `Function` | `jc.httpcall` 的绑定方法(调用 JSON 接口) |
| `bricks.jget` | `Function` | `jc.get` 的绑定方法GET JSON |
| `bricks.jpost` | `Function` | `jc.post` 的绑定方法POST JSON |
### 示例
```js
// 获取 HTML 内容
const html = await bricks.tget('/page', { params: { id: 123 } });
// 调用 JSON 接口
const data = await bricks.jpost('/api/user', {
headers: { 'X-Token': 'abc' },
params: { name: 'Alice' }
});
```
---
## 使用示例
### 1. 发送普通 GET 请求
```js
const client = new bricks.HttpText();
const result = await client.get('/api/hello', {
params: { q: 'test' }
});
console.log(result); // 输出服务器返回的文本
```
### 2. 发送 JSON POST 请求
```js
const jsonClient = new bricks.HttpJson();
const user = await jsonClient.post('/api/users', {
params: { name: 'Bob', age: 30 }
});
// 自动设置 Content-Type 和 Accept并解析 JSON
```
### 3. 下载文件为 ArrayBuffer
```js
const bufferClient = new bricks.HttpArrayBuffer();
const resp = await bufferClient.get('/model.bin');
const arrayBuf = await resp; // 已是 arrayBuffer
```
### 4. 处理实时日志流
```js
const streamClient = new bricks.HttpResponseStream();
const resp = await streamClient.get('/logs/stream');
await streamClient.handle_chunk(resp, (line) => {
console.log('[LOG]', line);
});
```
---
## 注意事项
- 依赖 `bricks.app` 提供 `screenWidth()`, `screenHeight()`, `get_session()`, `save_session()` 等方法
- 依赖 `bricks.extend(obj, src)` 实现对象合并(类似 jQuery.extend
- `objget(headers, 'Set-Cookie')` 用于安全获取响应头(需外部定义)
- 登录流程尚未完整实现,`withLoginInfo` 仅为原型
---
## 待优化建议
| 问题 | 建议改进 |
|------|---------|
| `bufffer` 拼写错误 | 修复 `if (buffer != ''){ yield bufffer; }` 中的拼写 |
| `withLoginInfo` 无实际登录能力 | 应支持模态框输入并回调重试请求 |
| `handle_chunk` 正则 `/\\r?\\n/gm` 不必要 | 可简化为 `.split('\n')` |
| `bricks_fetch` 中 `method = 'POST'` 修改外层变量风险 | 应使用局部变量 |
---
## 版本信息
- 创建时间:未知
- 框架版本Bricks Framework v1.x+
- 作者Bricks Team
> 文档最后更新2025年4月5日