title | description |
---|---|
API |
openapi-fetch API |
createClient accepts the following options, which set the default settings for all subsequent fetch calls.
createClient<paths>(options);
Name | Type | Description |
---|---|---|
baseUrl |
string |
Prefix all fetch URLs with this option (e.g. "https://myapi.dev/v1/" ) |
fetch |
fetch |
Fetch instance used for requests (default: globalThis.fetch ) |
querySerializer |
QuerySerializer | (optional) Provide a querySerializer |
bodySerializer |
BodySerializer | (optional) Provide a bodySerializer |
(Fetch options) | Any valid fetch option (headers , mode , cache , signal …) (docs |
The following options apply to all request methods (.GET()
, .POST()
, etc.)
client.GET("/my-url", options);
Name | Type | Description |
---|---|---|
params |
ParamsObject | path and query params for the endpoint |
body |
{ [name]:value } |
requestBody data for the endpoint |
querySerializer |
QuerySerializer | (optional) Provide a querySerializer |
bodySerializer |
BodySerializer | (optional) Provide a bodySerializer |
parseAs |
"json" | "text" | "arrayBuffer" | "blob" | "stream" |
(optional) Parse the response using a built-in instance method (default: "json" ). "stream" skips parsing altogether and returns the raw stream. |
fetch |
fetch |
Fetch instance used for requests (default: fetch from createClient ) |
middleware |
Middleware[] |
See docs |
(Fetch options) | Any valid fetch option (headers , mode , cache , signal , …) (docs) |
OpenAPI supports different ways of serializing objects and arrays for parameters (strings, numbers, and booleans—primitives—always behave the same way). By default, this library serializes arrays using style: "form", explode: true
, and objects using style: "deepObject", explode: true
, but you can customize that behavior with the querySerializer
option (either on createClient()
to control every request, or on individual requests for just one).
openapi-fetch ships the common serialization methods out-of-the-box:
Option | Type | Description |
---|---|---|
array |
SerializerOptions | Set style and explode for arrays (docs). Default: { style: "form", explode: true } . |
object |
SerializerOptions | Set style and explode for objects (docs). Default: { style: "deepObject", explode: true } . |
allowReserved |
boolean |
Set to true to skip URL encoding (false . |
const client = createClient({
querySerializer: {
array: {
style: "pipeDelimited", // "form" (default) | "spaceDelimited" | "pipeDelimited"
explode: true,
},
object: {
style: "form", // "form" | "deepObject" (default)
explode: true,
},
},
});
Style | Array id = [3, 4, 5] |
---|---|
form | /users?id=3,4,5 |
form (exploded, default) | /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 |
Style | Object id = {"role": "admin", "firstName": "Alex"} |
---|---|
form | /users?id=role,admin,firstName,Alex |
form (exploded) | /users?role=admin&firstName=Alex |
deepObject (default) | /users?id[role]=admin&id[firstName]=Alex |
Note
deepObject is always exploded, so it doesn’t matter if you set explode: true
or explode: false
—it’ll generate the same output.
Sometimes your backend doesn’t use one of the standard serialization methods, in which case you can pass a function to querySerializer
to serialize the entire string yourself. You’ll also need to use this if you’re handling deeply-nested objects and arrays in your params:
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
When serializing yourself, the string will be kept exactly as-authored, so you’ll have to call encodeURI or encodeURIComponent to escape special characters.
Similar to querySerializer, bodySerializer allows you to customize how the requestBody is serialized if you don’t want the default JSON.stringify() behavior. You probably only need this when using multipart/form-data
:
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 supports path serialization as outlined in the 3.1 spec. This happens automatically, based on the specific format in your OpenAPI schema:
Template | Style | Primitive id = 5 |
Array id = [3, 4, 5] |
Object id = {"role": "admin", "firstName": "Alex"} |
---|---|---|---|---|
/users/{id} |
simple (default) | /users/5 |
/users/3,4,5 |
/users/role,admin,firstName,Alex |
/users/{id*} |
simple (exploded) | /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 (exploded) | /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 (exploded) | /users/;id=5 |
/users/;id=3;id=4;id=5 |
/users/;role=admin;firstName=Alex |
Middleware is an object with onRequest()
and onResponse()
callbacks that can observe and modify requests and responses.
import createClient from "openapi-fetch";
import type { paths } from "./api/v1";
const myMiddleware: Middleware = {
async onRequest(req, options) {
// set "foo" header
req.headers.set("foo", "bar");
return req;
},
async onResponse(res, options) {
const { body, ...resOptions } = res;
// change status of response
return new Response(body, { ...resOptions, status: 200 });
},
};
const client = createClient<paths>({ baseUrl: "https://myapi.dev/v1/" });
// register middleware
client.use(myMiddleware);
onRequest(req, options) {
// …
}
onRequest()
takes 2 params:
Name | Type | Description |
---|---|---|
req |
MiddlewareRequest |
A standard Request with schemaPath (OpenAPI pathname) and params (params object) |
options |
MergedOptions |
Combination of createClient options + fetch overrides |
And it expects either:
- If modifying the request: A Request
- If not modifying:
undefined
(void)
onResponse(res, options) {
// …
}
onResponse()
also takes 2 params:
Name | Type | Description |
---|---|---|
req |
MiddlewareRequest |
A standard Response. |
options |
MergedOptions |
Combination of createClient options + fetch overrides |
And it expects either:
- If modifying the response: A Response
- If not modifying:
undefined
(void)
If you want to skip the middleware under certain conditions, just return
as early as possible:
onRequest(req) {
if (req.schemaPath !== "/projects/{project_id}") {
return undefined;
}
// …
}
This will leave the request/response unmodified, and pass things off to the next middleware handler (if any). There’s no internal callback or observer library needed.
To remove middleware, call client.eject(middleware)
:
const myMiddleware = {
// …
};
// register middleware
client.use(myMiddleware);
// remove middleware
client.eject(myMiddleware);
For additional guides & examples, see Middleware & Auth