Skip to content

请求、请求头与正文

FetchRequestFetchRequestInit 上增加必填的 url: stringFetchRequestInit<BODY> 扩展原生 RequestInit,将头替换为 RequestHeaders、正文替换为 RequestBodyType,并增加 timeouturlParamsabortController。原生 credentials、cache、mode、redirect、integrity 等受支持的 Fetch 选项继续透传。

普通调用直接把请求对象传给客户端方法;只有自行组合两份配置时才调用 mergeRequest。模板值放在 urlParams.path,查询串放在 urlParams.querybody 表示请求载荷;resultExtractor 应放在方法的第三个选项参数中,不属于请求对象。

请求字段

字段/类型契约
RequestHeaders / RequestHeadersCapable普通字符串键记录,值为 string | undefined,不是原生 Headers 实例。
RequestBodyTypeBodyInit | Record<string, any> | string | null;省略正文时保持缺失。
BaseURLCapable必填 baseURL: stringUrlParamsCapable 提供可选 urlParams
HttpMethodGET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE 字符串枚举;仍受平台限制。
CONTENT_TYPE_HEADER'Content-Type'ContentTypeValues.APPLICATION_JSON'application/json'TEXT_EVENT_STREAM'text/event-stream'

合并规则

mergeRequest(first, second): FetchRequestInit 对 path/query 记录做一层合并,对请求头按大小写不敏感规则合并,第二个请求优先。methodbodytimeoutsignalabortController 的第二个值为 nullish 时回退到第一个,因此此辅助函数中的 body: null 不能清空已有正文。其他原生字段遵循对象展开规则。空输入快捷路径在没有头时可能返回原对象,并非深复制。

mergeRequestOptions(first?, second?) 按第二个、第一个的顺序选择非 nullish 的 resultExtractorattributes,提取器最终回退到 Exchange。attributes 整体替换,不做合并。mergeRecords(first?, second?) 浅合并且后者优先,仅一个记录存在时可能返回原记录。mergeRecordToMap(record?, map?) 将记录或 Map 写入给定 Map(未传则新建),并返回同一个 Map。

请求头辅助函数

函数返回值与修改行为
getHeader(headers, name)返回最后一个大小写不敏感匹配值或 undefined,不修改输入。
deleteHeader(headers, name)删除所有大小写变体,返回 void
setHeader(headers, name, value)先删除所有变体,再按给定拼写设置;undefined 表示删除。
mergeHeaders(...records)返回新记录;后值优先,后续 undefined 删除继承头。

正文转换

RequestBodyInterceptor 在普通 order 为零的请求拦截器之前运行。字符串与 nullish 正文原样通过。Blob、File、FormData、URLSearchParams 保持原值,但移除所有 Content-Type 拼写,让 Fetch 决定类型与边界。ArrayBuffer、类型化数组/DataView、ReadableStream 原样通过,不调整请求头。其他对象(含数组)使用 JSON.stringify,仅在缺少 Content-Type 时补 JSON 类型。显式非 JSON Content-Type 不会阻止 JSON 序列化。循环对象或 BigInt 可能序列化失败并进入错误管线。

流式上传支持和额外的运行时特有请求字段仍由调用者负责。插入正文转换器前请阅读管线顺序

完整示例

ts
import { Fetcher, mergeRequest, getHeader } from '@ahoo-wang/fetcher';

const client = new Fetcher({ baseURL: 'https://api.example.com' });
const request = mergeRequest(
  { headers: { Authorization: 'Bearer demo' }, timeout: 3000 },
  { headers: { authorization: undefined }, timeout: 0, body: { name: 'Ada' } },
);
const exchange = client.resolveExchange({
  ...request,
  url: '/users',
  method: 'POST',
});
console.assert(
  getHeader(exchange.request.headers, 'authorization') === undefined,
);
console.assert(exchange.request.timeout === 0);

公开符号与源码

符号实现
BaseURLCapablefetchRequest.ts:23
HttpMethodfetchRequest.ts:37
UrlParamsCapablefetchRequest.ts:48
CONTENT_TYPE_HEADERfetchRequest.ts:55
ContentTypeValuesfetchRequest.ts:57
RequestHeadersfetchRequest.ts:68
RequestHeadersCapablefetchRequest.ts:81
RequestBodyTypefetchRequest.ts:88
FetchRequestInitfetchRequest.ts:112
FetchRequestfetchRequest.ts:176
mergeRequestmergeRequest.ts:65
mergeRequestOptionsmergeRequest.ts:118
getHeaderrequestHeaders.ts:17
deleteHeaderrequestHeaders.ts:29
setHeaderrequestHeaders.ts:39
mergeHeadersrequestHeaders.ts:56
mergeRecordsutils.ts:42
mergeRecordToMaputils.ts:71

包索引

基于 Apache License 2.0 发布。