The HttpClient library provides a factory for creating an http client that uses fetch
under the hood and provides extra features like hooks, timeouts and automatic mapping and parsing for the JSON content type.
Also, this http client captures any error and returns a response based on the response status with type inference:
HttpClientResponseSuccess<T>
: when the response has a success status code.HttpClientResponseError
: when the response has a error status code.HttpClientRequestError
: when the request failed for any reason.
All of these types are combined under the HttpClientResponse<T>
type.
Install the library using your preferred package manager:
npm i -D @astro-tools/http-client
For getting an instance of HttpClient
, just use the httpClient
factory with the desired options:
import { httpClient } from '@astro-tools/http-client';
const myHttpClient = httpClient({ baseUrl: 'https//my-api-server.com',});
then use the generated client to make requests to the baseUrl:
import { HttpClientResponseStatus } from '@astro-tools/http-client';
const response = await myHttpClient({ path: '/example', bodyAdapter: (body: MyExampleResponse) => mapMyExample(body),});
if (response.status === HttpClientResponseStatus.RESPONSE_SUCCESS) { console.info(response.body);}
Alternatively, the throwOnError
helper can be used to throw an Error if the request result is an error. The type inference will work as usual:
import { HttpClientResponseStatus, throwOnError } from '@astro-tools/http-client';
const response = throwOnError(await myHttpClient({ path: '/example', bodyAdapter: (body: MyExampleResponse) => mapMyExample(body),}));
console.info(response.body);
Example
Section titled “Example”This example is using the httpClient
to create an instance of HttpClient
and make requests trying to get the example data:
<script lang="ts">import Output from '@/libs/examples/Output.svelte';import { onMount } from 'svelte';
import { httpClient } from '@astro-tools/http-client';import { exampleBodyAdapter } from './example-body-adapter';
const publicAPIClient = httpClient({ baseUrl: () => `${location.origin}/api`, beforeRequest: (request, requestOptions) => { console.debug('beforeRequest', request, requestOptions); }, afterResponse: (response) => { console.debug('afterResponse', response); return response; },});
async function makeRequest(path: string): Promise<void> { const response = await publicAPIClient({ path, requestOptions: { headers: { 'X-Test': 'test', }, }, bodyAdapter: exampleBodyAdapter, });
console.debug('HttpClientResponse', response);}
onMount(async () => { await makeRequest('/example.json'); await makeRequest('/example-fail.json');});</script>
<Output text={'Take a look to the Developer Tools console!'} />
import type { Example } from './example';import type { ExampleResponse } from './example-response';
export function exampleBodyAdapter(body: ExampleResponse): Example { return body;}
export interface ExampleResponse { id: number; title: string; description: string;}
export interface Example { id: number; title: string; description: string;}
Reference
Section titled “Reference”httpClient (factory)
Section titled “httpClient (factory)”The httpClient
function is a factory that creates HttpClient
instances with the desired options that will be applied to any request made by the instance created.
There are several options defined in the interface HttpClientInitOptions
:
baseUrl
Section titled “baseUrl”baseUrl: (() => string) | string
Defines the base url to use in every request.
beforeRequest
Section titled “beforeRequest”beforeRequest?: (request: Request, requestOptions?: RequestInit) => void
Defines a hook that will be executed before making the request. The request can be modified as desired and the initial requestOptions
can be used to make decisions.
afterResponse
Section titled “afterResponse”afterResponse?: (response: Response, request: Request, requestOptions?: RequestInit) => Response
Defines a hook that will be executed immediately after receiving the response. A new response can be returned with any desired modification.
HttpClient (instance)
Section titled “HttpClient (instance)”The httpClient
factory returns a HttpClient
instance for making the requests and it has several options to configure the request properly defined in the HttpClientOptions<T, K>
interface.
path: string
Defines that request URL path to append to the baseUrl
.
search
Section titled “search”search?: string[][] | Record<string, string> | string | URLSearchParams
It defines the query parameters that will be used to build the request URL.
timeout
Section titled “timeout”timeout?: number
The request will be cancelled after the indicated amount of milliseconds. It uses AbortController
under the hood.
requestOptions
Section titled “requestOptions”requestOptions?: RequestInit
It is the default RequestInit
dictionary that fetch
uses. For more details, go to the official documentation.
bodyAdapter
Section titled “bodyAdapter”bodyAdapter?: <T, K>(body: T) => K;
If specified, the HttpClientResponseSuccess<T>
type will automatically type the response with the returned type of the bodyAdapter
function.
throwOnError
Section titled “throwOnError”The throwOnError
can be used to throw an HttpClientError
with the property response: HttpClientResponseError | HttpClientRequestError
.
It can be useful is some cases in which the application has a global error handler and it is not needed a fine grain management of the request result.