Skip to content

API

createClient

createClient 接受以下选项,这些选项设置所有后续 fetch 调用的默认设置。

ts
createClient<paths>(options);
名称类型描述
baseUrlstring使用此选项为所有 fetch URL 添加前缀(例如 "https://myapi.dev/v1/"
fetchfetch用于请求的 Fetch 实例(默认值:globalThis.fetch
querySerializerQuerySerializer(可选) 提供一个 querySerializer
bodySerializerBodySerializer(可选) 提供一个 bodySerializer
(Fetch 选项)任何有效的 fetch 选项(headersmodecachesignal 等)(文档

Fetch 选项

以下选项适用于所有请求方法(.GET().POST() 等)。

ts
client.GET("/my-url", options);
名称类型描述
paramsParamsObjectpathquery 参数。
body{ [name]:value }requestBody 数据。
querySerializerQuerySerializer(可选) 提供一个 querySerializer
bodySerializerBodySerializer(可选) 提供一个 bodySerializer
parseAs"json" | "text" | "arrayBuffer" | "blob" | "stream"(可选) 使用 内置实例方法 解析响应(默认值: "json")。"stream" 跳过解析,直接返回原始流。
fetchfetch用于请求的 Fetch 实例(默认:createClient 的 fetch)
middlewareMiddleware[]查看文档
(Fetch 选项)任何有效的 fetch 选项(headersmodecachesignal 等)(文档

querySerializer

OpenAPI 支持不同的对象和数组序列化方式。默认情况下,此库使用 style: "form", explode: true 序列化数组,使用 style: "deepObject", explode: true 序列化对象,但你可以使用 querySerializer 选项自定义此行为(在 createClient() 上控制每个请求,或在单个请求上为一个请求控制)。

对象语法

openapi-fetch 提供了常见的序列化方法:

选项类型描述
arraySerializerOptions设置数组的 styleexplode文档)。默认值:{ style: "form", explode: true }
objectSerializerOptions设置对象的 styleexplode文档)。默认值:{ style: "deepObject", explode: true }
allowReservedboolean设置为 true 以跳过 URL 编码(⚠️ 可能会破坏请求)(文档)。默认值:false
ts
const client = createClient({
  querySerializer: {
    array: {
      style: "pipeDelimited", // "form" (默认) | "spaceDelimited" | "pipeDelimited"
      explode: true,
    },
    object: {
      style: "form", // "form" | "deepObject" (默认)
      explode: true,
    },
  },
});

数组样式

样式数组 id = [3, 4, 5]
form/users?id=3,4,5
form (exploded, 默认)/users?id=3&id=4&id=5
spaceDelimited/users?id=3%204%205
spaceDelimited (exploded)/users?id=3&id=4&id=5
pipeDelimited/users?id=3|4|5
pipeDelimited (exploded)/users?id=3&id=4&id=5

对象样式

样式对象 id = {"role": "admin", "firstName": "Alex"}
form/users?id=role,admin,firstName,Alex
form (exploded)/users?role=admin&firstName=Alex
deepObject (默认)/users?id[role]=admin&id[firstName]=Alex

TIP

对于 deepObject 这种复杂的对象结构, 无论你设置 explode: true 还是 explode: false,它都会生成相同的输出。

替代函数语法

有时候你的后端不使用标准的序列化方法之一,此时你可以将一个函数传递给 querySerializer,自己序列化整个字符串。如果你处理你的参数中的深度嵌套对象和数组,也需要使用此方法:

ts
const client = createClient({
  querySerializer(queryParams) {
    const search = [];
    for (const name in queryParams) {
      const value = queryParams[name];
      if (Array.isArray(value)) {
        for (const item of value) {
          s.push(`${name}[]=${encodeURIComponent(item)}`);
        }
      } else {
        s.push(`${name}=${encodeURLComponent(value)}`);
      }
    }
    return search.join(","); // ?tags[]=food,tags[]=california,tags[]=healthy
  },
});

WARNING

当自己序列化时,字符串将保持与作者编写的内容完全一样,因此你必须调用 encodeURIencodeURIComponent 来转义特殊字符。

bodySerializer

类似于 querySerializer,bodySerializer 允许你自定义 requestBody 在你不想要默认 JSON.stringify() 行为的情况下的序列化方式。当使用 multipart/form-data 时可能会用到:

ts
const { data, error } = await client.PUT("/submit", {
  body: {
    name: "",
    query: { version: 2 },
  },
  bodySerializer(body) {
    const fd = new FormData();
    for (const name in body) {
      fd.append(name, body[name]);
    }
    return fd;
  },
});

路径序列化

openapi-fetch 支持根据你的 OpenAPI 架构中的具体格式自动进行路径序列化

模板样式基础类型 id = 5数组 id = [3, 4, 5]对象 id = {"role": "admin", "firstName": "Alex"}
/users/{id}simple (默认)/users/5/users/3,4,5/users/role,admin,firstName,Alex
/users/{id*}simple (爆炸)/users/5/users/3,4,5/users/role=admin,firstName=Alex
/users/{.id}label/users/.5/users/.3,4,5/users/.role,admin,firstName,Alex
/users/{.id*}label (爆炸)/users/.5/users/.3.4.5/users/.role=admin.firstName=Alex
/users/{;id}matrix/users/;id=5/users/;id=3,4,5/users/;id=role,admin,firstName,Alex
/users/{;id*}matrix (爆炸)/users/;id=5/users/;id=3;id=4;id=5/users/;role=admin;firstName=Alex

中间件

中间件是具有 onRequest()onResponse() 回调的对象,可以观察和修改请求和响应。

ts
import createClient from "openapi-fetch";
import type { paths } from "./my-openapi-3-schema"; // 由openapi-typescript生成

const myMiddleware: Middleware = {
  async onRequest(req, options) {
    // 设置 "foo" 标头
    req.headers.set("foo", "bar");
    return req;
  },
  async onResponse(res, options) {
    const { body, ...resOptions } = res;
    // 更改响应的状态
    return new Response(body, { ...resOptions, status: 200 });
  },
};

const client = createClient<paths>({ baseUrl: "https://myapi.dev/v1/" });

// 注册中间件
client.use(myMiddleware);

onRequest

ts
onRequest(req, options) {
  // …
}

onRequest() 接受 2 个参数:

名称类型描述
reqMiddlewareRequest带有 schemaPath(OpenAPI 路径名)和 paramsparams 对象)的标准 Request
optionsMergedOptionscreateClient 选项 + fetch 覆盖 的组合

它期望的结果要么是:

  • 如果修改请求: 一个 Request
  • 如果不修改: undefined(void)

onResponse

ts
onResponse(res, options) {
  // …
}

onResponse() 也接受 2 个参数:

名称类型描述
reqMiddlewareRequest一个标准的 Response
optionsMergedOptionscreateClient 选项 + fetch 覆盖 的组合

它期望的结果要么是:

  • 如果修改响应: 一个 Response
  • 如果不修改: undefined(void)

跳过

如果你想要在某些条件下跳过中间件,只需尽早 return

ts
onRequest(req) {
  if (req.schemaPath !== "/projects/{project_id}") {
    return undefined;
  }
  // …
}

这将保持请求/响应不变,并将其传递给下一个中间件处理程序(如果有的话)。不需要内部回调或观察器库。

移除中间件

要移除中间件,请调用 client.eject(middleware)

ts
const myMiddleware = {
  // …
};

// 注册中间件
client.use(myMiddleware);

// 删除中间件
client.eject(myMiddleware);

有关附加指南和示例,请参阅 中间件 & 身份认证

基于 MIT 许可发布