An HTTP client based on the Fetch API. The project aims to embrace and expose the new Fetch API, while providing features important in web applications: default configuration of request parameters, interceptors, and centralized request tracking.
This library relies on the Fetch API, which is not yet supported by all popular browsers. This library does not include a polyfill for Fetch. If you need to support browsers that haven't implemented Fetch, you will need to install a polyfill like GitHub's Fetch polyfill
import 'fetch';
import {HttpClient} from 'aurelia-fetch-client';
import {HttpClient} from 'aurelia-fetch-client';
let httpClient = new HttpClient();
httpClient.fetch('package.json')
.then(response => response.json())
.then(data => {
console.log(data.description);
});
HttpClient.fetch()
has the same signature as window.fetch()
. The difference is that HttpClient
will apply default configuration values, execute any registered interceptors, and track the number of active requests.
httpClient.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; // you can return a modified Request, or you can short-circuit the request by returning a Response
},
response(response) {
console.log(`Received ${response.status} ${response.url}`);
return response; // you can return a modified Response
}
});
});
-
The
defaults
object can include any properties described in the optionalinit
parameter to the Request constructor, and will be merged into the new Request before it is passed to the first request interceptor. -
Interceptors can be any object providing any of the four optional methods:
request
,requestError
,response
, andresponseError
.request
takes the Request that will be passed towindow.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 tofetch()
and complete the request immediately. Errors thrown in request interceptors will be handled byrequestError
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.
The Fetch API has a couple gotchas, documented by the GitHub Fetch polyfill docs. aurelia-fetch-client provides configuration helpers to apply the changes suggested by the polyfill docs.
-
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 to sending JSON in the body of a request. Objects must be manually serialized to JSON, and the
Content-Type
header set appropriately. aurelia-fetch-client includes a helper calledjson
for this.
import {HttpClient, json} from 'aurelia-fetch-client';
...
let comment = { title: 'Awesome!', content: 'This Fetch client is pretty rad.' };
httpClient.fetch('comments', {
method: 'post',
body: json(comment)
});
- This library does not include a polyfill for Fetch. If you need to support browsers that haven't implemented Fetch, you will need to install a polyfill like GitHub's Fetch polyfill.
- This library does not work around any of the existing limitations in the Fetch API, including:
- Fetch does not currently support aborting requests or specifying request timeouts.
- Fetch does not currently support progress reporting.
- JSONP support is not currently provided by this library.
- The Request constructor provides its own default values, so if a Request is created before invoking
HttpClient.fetch
(eg, theHttpClient.fetch(request)
signature is used instead of theHttpClient.fetch(url, params)
signature), there is no way for the client to know which default values to merge into the Request. The base URL and headers can be merged, but currently no other defaults will be applied in this case.
Fixed with interceptor:
return response.json().then(Promise.reject.bind(Promise));