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) |
wrapAsPathBasedClient wraps the result of createClient()
to return a Proxy-based client that allows path-indexed calls:
const client = createClient<paths>(clientOptions);
const pathBasedClient = wrapAsPathBasedClient(client);
pathBasedClient["/my-url"].GET(fetchOptions);
The fetchOptions
are the same than for the base client.
A path based client can lead to better type inference but comes at a runtime cost due to the use of a Proxy.
createPathBasedClient is a convenience method combining createClient
and wrapAsPathBasedClient
if you only want to use the path based call style:
const client = createPathBasedClient<paths>(clientOptions);
client["/my-url"].GET(fetchOptions);
Note that it does not allow you to attach middlewares. If you need middlewares, you need to use the full form:
const client = createClient<paths>(clientOptions);
client.use(...);
const pathBasedClient = wrapAsPathBasedClient(client);
client.use(...); // the client reference is shared, so the middlewares will propagate.
pathBasedClient["/my-url"].GET(fetchOptions);
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 |
::: tip
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 "./my-openapi-3-schema"; // generated by openapi-typescript
const myMiddleware: Middleware = {
async onRequest({ request, options }) {
// set "foo" header
request.headers.set("foo", "bar");
return request;
},
async onResponse({ request, response, 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);
Each middleware callback receives the following options
object with the following:
Name | Type | Description |
---|---|---|
request |
Request |
The current Request to be sent to the endpoint. |
response |
Response |
The Response returned from the endpoint (note: this will be undefined for onRequest ). |
schemaPath |
string |
The original OpenAPI path called (e.g. /users/{user_id} ) |
params |
Object |
The original params object passed to GET() / POST() / etc. |
id |
string |
A random, unique ID for this request. |
options |
ClientOptions |
The readonly options passed to createClient() . |
Each middleware callback can return:
- onRequest: Either a
Request
to modify the request, orundefined
to leave it untouched (skip) - onResponse Either a
Response
to modify the response, orundefined
to leave it untouched (skip)
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