Fetch Client
The Aurelia Fetch Client wraps the native browser Fetch API and provides helpers and configuration options to make working with it more "Aurelia friendly"
Aurelia provides a fetch client which wraps the native Fetch API. It allows you to work with Fetch in an Aurelia-style way and provides some helper methods and configuration options to make working with Fetch easier.
Using the Fetch Client
The Fetch client ships with Aurelia and requires no additional installation. To use it, import the HttpClient
from the @aurelia/fetch-client
package.
import { HttpClient } from '@aurelia/fetch-client';
In most cases, you want to inject a new instance of the Fetch client into your application. You can achieve this in a couple of different ways.
The first approach you can take is creating a new instance of the HttpClient
and referencing it like the native Fetch API.
import { HttpClient } from '@aurelia/fetch-client';
const http = new HttpClient();
You can also inject a new instance into your component or service class using the following approach: injecting the Fetch client with the newInstanceOf
decorator. This will ensure our component gets a new instance of the Fetch client.
import { HttpClient } from '@aurelia/fetch-client';
import { newInstanceOf } from '@aurelia/kernel';
import { ICustomElementViewModel } from 'aurelia';
export class MyComponent implements ICustomElementViewModel {
constructor(@newInstanceOf(IHttpClient) readonly http: IHttpClient) {
}
}
Taking a service-based approach to encapsulating your HTTP calls, you might create something like this:
import { HttpClient } from '@aurelia/fetch-client';
import { newInstanceOf } from '@aurelia/kernel';
export class ApiService {
constructor(@newInstanceOf(IHttpClient) readonly http: IHttpClient) {
}
getProducts() {
const request = await this.http.fetch(`/products`);
const response = await request.json();
return response;
}
getProduct(id) {
const request = await this.http.fetch(`/products/${id}`);
const response = await request.json();
return response;
}
}
Configuring the fetch client
Many of the configuration options available to the native Fetch API are also available in the Aurelia Fetch Client. You can set default headers, create interceptors (more on that further down) and more.
import { HttpClient } from '@aurelia/fetch-client';
import { newInstanceOf } from '@aurelia/kernel';
import { ICustomElementViewModel } from 'aurelia';
export class MyComponent implements ICustomElementViewModel {
constructor(@newInstanceOf(IHttpClient) readonly http: IHttpClient) {
http.configure(config =>
config
.withBaseUrl('api/')
.withDefaults({
credentials: 'same-origin',
headers: {
'Accept': 'application/json',
'X-Requested-With': 'Fetch'
}
})
.withInterceptor({
request(request) {
console.log(`Requesting ${request.method} ${request.url}`);
return request;
},
response(response) {
console.log(`Received ${response.status} ${response.url}`);
return response;
}
})
);
}
}
The example above withBaseUrl()
is used to specify a base URL that all fetches will be relative to. The withDefaults()
method allows passing an object that can include any properties described in the optional init
parameter to the Request constructor, and will be merged into the new Request before it is passed to the first request interceptor.
withInterceptor()
enables passing an object which can provide any of these four optional methods: request
, requestError
, response
, and responseError
. Here's an explanation of how each of these methods works:request
takes the Request that will be passed to window.fetch()
after interceptors run. It should return the same Request or create a new one. It can also return a Response to short-circuit the call to fetch()
and complete the request immediately. Interceptors will handle errors thrown in request interceptors.
requestError
acts as a Promise rejection handler during Request creation and request interceptor execution. It will receive the rejection reason and can either re-throw, or recover by returning a valid Request.response
will be run afterfetch()
completes, and will receive the resulting Response . As withrequest
, it can either pass the Response along, return a modified response, or throw.responseError
is similar torequestError
, and acts as a Promise rejection handler for response rejections.
These methods on the interceptor object can also return a Promise
for their respective return values.
Fetch helpers
There are some caveats with the default Fetch implementation around error handling that Aurelia provides helper methods to work with conveniently.
config.rejectErrorResponses()
will add a response interceptor that causes responses with unsuccessful status codes to result in a rejected Promise.config.useStandardConfiguration()
will applyrejectErrorResponses()
, and also configurecredentials: 'same-origin'
as a default on all requests.The Fetch API has no convenient way of sending JSON in the body of a request. Objects must be manually serialized to JSON, and the
Content-Type
header must be set appropriately. the Fetch package includes a helper calledjson
for this.
Posting JSON
import { HttpClient, json } from '@aurelia/fetch-client';
import { newInstanceOf } from '@aurelia/kernel';
import { ICustomElementViewModel } from 'aurelia';
export class MyComponent implements ICustomElementViewModel {
constructor(@newInstanceOf(IHttpClient) readonly http: IHttpClient) {
}
createComment() {
let comment = {
title: 'Awesome!',
content: 'This Fetch client is pretty rad.'
};
this.http.fetch('comments', {
method: 'post',
body: json(comment)
});
}
}
Working with authentication bearer tokens
A common scenario in applications using authentication is to use bearer tokens sent in the headers of each request.
To achieve this, we can use a request interceptor to add the token to the headers of each request. The following example assumes you are getting the bearer token from somewhere (session or local storage, etc.).
import { HttpClient } from '@aurelia/fetch-client';
import { newInstanceOf } from '@aurelia/kernel';
import { ICustomElementViewModel } from 'aurelia';
export class MyComponent implements ICustomElementViewModel {
constructor(@newInstanceOf(IHttpClient) readonly http: IHttpClient) {
http.configure(config =>
config
.withInterceptor({
request(request) {
request.headers.append('Authorization', 'Bearer ' + YOUR_BEARER_TOKEN);
return request;
}
})
);
}
}
Last updated
Was this helpful?