Series Overview
This article belongs to a broader series on the HttpClient API:
- The new Angular
HttpClientAPI - Testing with the Angular
[HttpClientTesting](https://medium.com/netscape/testing-with-the-angular-httpclient-api-648203820712)API
The HttpClient API landed in version 4.3.0 and serves as the successor to the older HTTP module. It ships in its own dedicated package called @angular/common/http. This post walks through the primary capabilities this new client brings to the table. For a deeper dive into the internals of HttpClient, refer to Insider’s guide into interceptors and HttpClient mechanics in Angular.
A standout shift is that the response object is now parsed as JSON out of the box, eliminating the need for explicit parsing. This means you can write:
// HttpClient
this.http.get('https://api.github.com/users')
.subscribe(data => console.log(data));
Instead of having to do:
// Http
this.users = this.http.get('https://api.github.com/users')
.map(response => response.json())
.subscribe(data => console.log(data));
That said, if you still want access to the full Response object, you can use the observe option:
// HttpClient
this.http.get('…', { observe: 'response' });
Managing Query Parameters
A point that may catch you off guard is how query parameters are handled. You cannot simply supply a Plain Old JavaScript Object (POJO) and expect the client to automatically treat it as query parameters the way other options in the GET call’s options object behave.
import { HttpParams } from '@angular/common/http';
const params = new HttpParams().set('q', 'cironunes');
this.http.get('...', { params });
The syntax here is somewhat cumbersome. Fortunately, there is already a pull request that aims to allow the use of object maps for parameters and headers in GET requests.
Response Type Checking
With the help of TypeScript Generics, the type of the response will match the type you specify when calling the HTTP method:
interface LoginResponse {
accessToken: string;
accessExpiration: number;
}
this.http.post<LoginResponse>('api/login', {
login: 'foo',
password: 'bar'
}).subscribe(data => {
console.log(data.accessToken, data.accessExpiration);
});
Handling Non-JSON Data
While JSON is the typical format, you’ll occasionally encounter other data types. The responseType property covers this scenario.
this.http.get('...', { responseType: 'text' });
responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'
In such cases, there’s no need to explicitly type the response, since responseType already handles that.
Interceptors
The most compelling addition in HttpClient is the arrival of Interceptors, which allow you to insert middleware logic directly into the request pipeline. Here’s a quick rundown of how they operate.
To begin, you’ll need to build an interceptor. This involves implementing the HttpInterceptor interface, which in turn requires an intercept method.
interface HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>;
}
The intercept method takes an HttpRequest and returns a stream of HttpEvent typed as HttpResponse. Given that both Request and Response objects are immutable — a design choice that simplifies predictability and testing — the clone method is used to modify the Response object.
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpEventType } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
export class AuthInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<HttpEventType.Response>> {
const authReq = req.clone({
setHeaders: { Authorization: `Bearer authtest` }
});
return next.handle(authReq);
}
}
Registration is done this way:
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
@NgModule({
imports: [],
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
]
})
export class AppModule {}
To register several interceptors, simply add more entries to the providers array.
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: First, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: Second, multi: true }
]
Tracking Progress
Another handy feature is the ability to subscribe to events such as upload or download progress using the reportProgress option. For a file upload scenario, it would look like:
const req = new HttpRequest('POST', 'upload/file', file, {
reportProgress: true
});
this.http.request(req)
.subscribe(event => {
if (event.type === HttpEventType.UploadProgress) {
console.log(event.total, event.loaded);
}
});
Final Thoughts
The HttpClient API is a significant improvement. Beyond prioritizing the most frequent use cases, it further reinforces the framework’s commitment to Observables and immutable objects where applicable. This makes the library not only easier to work with but also more straightforward to test.
Up Next
The following post will delve into testing with the HttpClientTestingModule. Stay tuned.
