createFetchExecutor(baseURL, options?) — @routar/core
Uses the native fetch API. Ideal for SSR where per-request dynamic headers are needed. Built into @routar/core — no additional package required.
import { createFetchExecutor } from '@routar/core'
const executor = createFetchExecutor('https://api.example.com')Options
createFetchExecutor(baseURL, {
defaultHeaders: async () => {
const token = await getServerToken()
return token ? { Authorization: `Bearer ${token}` } : {}
},
plugins: [logger()],
retry: 2,
timeout: 5_000,
})| Option | Type | Description |
|---|---|---|
defaultHeaders | () => Promise<Record<string, string>> | Record<string, string> | Applied to every request. Evaluated per-request, so safe for SSR token injection. |
plugins | ExecutorPlugin[] | Plugins applied before the fetch call |
retry | number | { count, shouldRetry? } | Number of retries on failure |
timeout | number | Per-attempt timeout in milliseconds — throws TimeoutError on expiry |
Empty responses
Responses with status 204, 205, or 304 resolve to null. A 200 response with an empty body also resolves to null instead of throwing a SyntaxError.
HttpError
Non-2xx responses throw HttpError. The parsed JSON error payload is available on .body (or null if the body was empty or not JSON):
import { HttpError } from '@routar/core'
try {
await todoApi.getDetail({ path: { id: 999 } })
} catch (err) {
if (err instanceof HttpError) {
console.log(err.status) // 404
console.log(err.statusText) // 'Not Found'
console.log(err.body) // { message: 'Not found' } | null
}
}Query parameter serialization
Arrays are serialized as repeated keys: ids=1&ids=2. This differs from Axios’s default (ids[]=1&ids[]=2). If you switch executors and use array query params, verify your server-side parsing is compatible.
SSR usage (Next.js)
import { createFetchExecutor } from '@routar/core'
export const serverExecutor = createFetchExecutor(process.env.API_BASE_URL!, {
defaultHeaders: async () => {
const { cookies } = await import('next/headers')
const token = (await cookies()).get('access_token')?.value
return token ? { Authorization: `Bearer ${token}` } : {}
},
timeout: 10_000,
})defaultHeaders is called on every request, so it picks up the current request’s cookies in Server Components and Route Handlers.