@bwt-st/http
v0.2.1
Published
Framework-agnostic HTTP client for BWT-ST projects.
Readme
@bwt-st/http
基于原生 fetch 的无框架 TypeScript HTTP 客户端,不依赖 Axios。提供统一的请求配置、查询参数、JSON 请求体、Token 注入、超时、响应解包和错误标准化能力。
安装
pnpm add @bwt-st/http库不会读取 import.meta.env,不会创建全局单例,也不会自动重试或刷新 Token。基础 URL、认证状态和业务错误提示由宿主项目负责。
快速使用
建议在业务项目的基础设施层创建一次客户端并统一导出:
// src/services/http.ts
import { createHttpClient } from '@bwt-st/http'
export const http = createHttpClient({
baseURL: '/api',
timeout: 15_000,
hooks: {
getAccessToken: () => localStorage.getItem('access-token'),
onUnauthorized: () => {
// 在业务层处理退出登录或跳转
},
},
})
const user = await http.get<User>('/users/1')工厂和客户端
createHttpClient(options)
创建一个 HttpClient 实例。
| 配置 | 类型 | 默认值 | 说明 |
| -------------- | ----------------- | ------------------ | ------------------------------------------------------- |
| baseURL | string | 必填 | 相对路径使用的基础地址;请求路径是绝对 URL 时直接使用。 |
| timeout | number | 15000 | 超时时间,单位为毫秒。 |
| successCodes | ApiCode[] | [0, 200] | API 响应信封中的成功业务码。 |
| headers | HeadersInit | {} | 所有请求的默认请求头。 |
| hooks | HttpClientHooks | {} | Token、未授权和错误回调。 |
| fetch | typeof fetch | globalThis.fetch | 测试或特殊运行环境使用的 fetch 实现。 |
HttpClient
实例提供以下方法:
http.get<Response>(url, options?)
http.post<Response, Data>(url, data?, options?)
http.put<Response, Data>(url, data?, options?)
http.patch<Response, Data>(url, data?, options?)
http.delete<Response>(url, options?)
http.request<Response, Data>(config)
http.configureHooks(hooks)请求配置
HttpRequestConfig 在原生 RequestInit 基础上增加:
| 属性 | 类型 | 说明 |
| ---------------- | ---------------- | ---------------------------------------------- |
| url | string | 请求路径或绝对 URL。 |
| method | string | HTTP 方法,快捷方法会自动设置。 |
| headers | HeadersInit | 覆盖或追加当前请求头。 |
| params | HttpQuery | 查询参数,数组会生成多个同名参数。 |
| data | Data | 请求数据,普通对象会自动 JSON 序列化。 |
| body | BodyInit \\ | null | 直接指定请求体,优先于 data。 |
| responseType | 'json' \\ | 'text' \\ | 'blob' \\ | 'arraybuffer' | 响应解析方式。 |
| requestOptions | RequestOptions | Token 和响应解包控制。 |
| 原生选项 | RequestInit | 支持 signal、credentials、cache 等选项。 |
const result = await http.get<PageResult<User>>('/users', {
params: {
page: 1,
pageSize: 20,
status: ['active', 'pending'],
},
})null 和 undefined 查询参数会被忽略。普通对象、数组和基础值通过 data 发送时会转为 JSON,并自动设置 Content-Type: application/json;FormData、Blob、ArrayBuffer 和 URLSearchParams 会直接作为请求体发送。
const user = await http.post<User, CreateUserInput>('/users', {
name: 'Ada',
email: '[email protected]',
})
const form = new FormData()
form.append('avatar', file)
await http.post<{ url: string }>('/avatar', form)响应约定
默认 JSON 响应需要符合以下信封结构:
interface ApiResponse<T> {
code: number | string
message?: string
data: T
}code 为 0 或 200 时,客户端默认返回 data:
const user = await http.get<User>('/users/1')需要保留完整信封时关闭解包:
const response = await http.get<ApiResponse<User>>('/users/1', {
requestOptions: { unwrap: false },
})公开接口可以关闭 Token 注入:
await http.get<PublicConfig>('/public/config', {
requestOptions: { withToken: false },
})二进制或文本响应:
const file = await http.get<Blob>('/reports/latest', {
responseType: 'blob',
})
const text = await http.get<string>('/version.txt', {
responseType: 'text',
requestOptions: { unwrap: false },
})204、blob 和 arraybuffer 响应不会进行 API 信封解包。使用 responseType: 'text' 时,通常应同时设置 unwrap: false。
错误处理
所有请求错误都会被转换为 HttpError:
class HttpError extends Error {
readonly code?: ApiCode
readonly status?: number
readonly details?: unknown
}常见错误码:
| code | 含义 |
| ------------------- | ------------------------- |
| ETIMEDOUT | 超过客户端超时时间。 |
| ERR_CANCELED | 请求被 AbortSignal 取消。 |
| ERR_NETWORK | 网络连接失败。 |
| HTTP 状态码或业务码 | 服务端返回错误。 |
import { HttpError } from '@bwt-st/http'
try {
await http.get<User>('/users/1')
} catch (error) {
if (error instanceof HttpError && error.status === 404) {
showMessage('用户不存在')
} else {
showMessage('请求失败,请稍后重试')
}
}onUnauthorized 会在 HTTP 状态码或业务码为 401 时执行;onError 会在每次错误标准化后执行。请求超时只会中止当前客户端请求,不提供重试策略。
其他导出
| 导出 | 类型 | 用途 |
| ----------------------------------------------- | ---- | ------------------------------- |
| HttpError | 类 | 统一的请求错误类型。 |
| isApiResponse | 函数 | 判断数据是否符合 API 信封结构。 |
| unwrapResponse | 函数 | 按成功码解包响应。 |
| normalizeHttpError | 函数 | 将未知错误转换为 HttpError。 |
| ApiCode、ApiResponse<T> | 类型 | 业务码和 API 信封。 |
| HttpQueryValue、HttpQuery | 类型 | 查询参数类型。 |
| PageQuery、PageResult<T> | 类型 | 常见分页类型。 |
| HttpRequestConfig<T>、HttpRequestOptions<T> | 类型 | 完整请求配置和快捷方法配置。 |
| HttpResponseType、RequestOptions | 类型 | 响应解析和解包配置。 |
| HttpClientHooks、HttpClientOptions | 类型 | 客户端和回调配置。 |
运行环境
- Node.js
>=20.19.0 - 浏览器或 Node.js 原生支持
fetch - 详细 API 与场景示例可参阅仓库的
docs/http/index.md
