Skip to content

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.

Setup

Install the library using your preferred package manager:

npm i -D @astro-tools/http-client

Use

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

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!'} />
Preview
Take a look to the Developer Tools console!

Reference

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

baseUrl: (() => string) | string

Defines the base url to use in every request.

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

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)

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

path: string

Defines that request URL path to append to the baseUrl.

search?: string[][] | Record<string, string> | string | URLSearchParams

It defines the query parameters that will be used to build the request URL.

timeout

timeout?: number

The request will be cancelled after the indicated amount of milliseconds. It uses AbortController under the hood.

requestOptions

requestOptions?: RequestInit

It is the default RequestInit dictionary that fetch uses. For more details, go to the official documentation.

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

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.