DataHttpClientModule
Custom http client, with the ability to customize requests, auto unsubscribe and additional request interceptors.
Table of contents:
First step
Example, if your API base url placed here https://my-server.com/api/***
and have swagger documentation:
Copy import { HttpClientModule } from '@angular/common/http' ;
import { DataHttpClientModule } from '@angular-ru/cdk/http' ;
@ NgModule ({
imports : [
// ...
HttpClientModule ,
DataHttpClientModule .forRoot ([ApiUsersClient] , {
hostUrl : 'https://my-server.com/api/'
})
] ,
declarations : [AppComponent] ,
bootstrap : [AppComponent]
})
export class AppModule {}
Create your http client for your api controller
Copy export interface User {
id : number ;
name : string ;
}
Copy import { Delete , Get , Patch , PathVariable , RequestBody , Put , RestClient } from '@angular-ru/cdk/http/decorators' ;
import { DataHttpClient } from '@angular-ru/cdk/http' ;
import { Injectable } from '@angular/core' ;
import { Observable } from 'rxjs' ;
@ Injectable ()
@ RestClient ( '/users' )
export class ApiUsersClient extends DataHttpClient {
@ Get ()
public findAllUsers () : Observable < User []> {
return this .restTemplate ();
}
@ Post ()
public createUser (@ RequestBody () _body : User ) : Observable < void > {
return this .restTemplate ();
}
@ Get ( '/{id}' )
public findByIdUser (@ PathVariable ( 'id' ) _id : number ) : Observable < User > {
return this .restTemplate ();
}
@ Put ( '/{id}' )
public updateUser (@ PathVariable ( 'id' ) _id : number , @ RequestBody () _body : User ) : Observable < void > {
return this .restTemplate ();
}
@ Delete ( '/{id}' )
public deleteByIdUser (@ PathVariable ( 'id' ) _id : number ) : Observable < void > {
return this .restTemplate ();
}
@ Patch ( '/{id}' )
public mutateUser (@ PathVariable ( 'id' ) _id : number , @ RequestBody () _body : Partial < User >) : Observable < void > {
return this .restTemplate ();
}
}
Copy @ Component ({
//...
changeDetection : ChangeDetectionStrategy .OnPush
})
export class UsersComponent {
private readonly users : User [] = [];
constructor ( private readonly users : ApiUsersClient , private readonly cd : ChangeDetectorRef ) {}
public ngOnInit () : void {
this . users .findAllUsers () .subscribe ((users) => {
this .users = users;
this . cd .detectChanges ();
});
}
}
Different use cases
each of these examples works the same
Copy @ Injectable ()
@ RestClient ( '/cities' )
class MyCitiesClient extends DataHttpClient {
@ Put ()
public updateCity (@ RequestBody () _body : CityRecordDto , @ RequestParam ( 'id' ) _id : number ) : Observable < void > {
return this .restTemplate ({ emitSuccess : true });
}
}
Copy @ Injectable ()
@ RestClient ( '/cities' )
class MyCitiesClient extends DataHttpClient {
@ Put ()
public updateCity (body : CityRecordDto , id : number ) : Observable < void > {
return this .restTemplate ({ emitSuccess : true , body , queryParams : { id } });
}
}
Copy @ Injectable ()
@ RestClient ( '/cities' )
class MyCitiesClient extends DataHttpClient {
public updateCity (body : CityRecordDto , id : number ) : Observable < void > {
return this .put ({ emitSuccess : true , body , queryParams : { id } });
}
}
Limiting the number of concurrent requests (optional)
there is almost no limit on the number of requests that can be sent in parallel
Note: various browsers have various limits for maximum connections per host name (Chrome: 6)
but if necessary, you can change it
for example, limitConcurrency: 5
This mean that maximum of 5 requests can be executed in parallel. Next one immediately start only if one of the previous requests is completed
Copy import { DataHttpClientModule } from '@angular-ru/cdk/http' ;
@ NgModule ({
imports : [
// ...
DataHttpClientModule .forRoot ([ApiUsersClient] , {
// ...
limitConcurrency : 5
})
]
// ...
})
export class AppModule {}
@angular-ru/cdk/http/decorators
Copy @ Injectable ()
@ RestClient ( 'my-controller-api-path' )
export class ApiEtcClient extends DataHttpClient {}
Copy @ Injectable ()
@ BaseUrl ( 'nginx-path-controller' )
@ RestClient ( 'my-controller-api-path' )
export class ApiEtcClient extends DataHttpClient {}
Copy @ Injectable ()
@ HostUrl ( '//no-cors.my-api.com' )
@ BaseUrl ( 'nginx-path-controller' )
@ RestClient ( 'my-controller-api-path' )
export class ApiEtcClient extends DataHttpClient {}
@Get(url), @Post(url), @Put(url), @Delete(url), @Patch(url)
Copy @ Injectable ()
@ RestClient ( 'users' )
export class ApiUsersClient extends DataHttpClient {
@ Get ()
public getUsersAll () : Observable < User []> {
return this .restTemplate ();
}
}
Copy @ Injectable ()
@ RestClient ( 'users' )
export class ApiUsersClient extends DataHttpClient {
@ Get ()
public getUsersAllByPagination (
@ RequestParam ( 'size' ) _pageSize : number ,
@ RequestParam ( 'index' ) _pageIndex : number
) : Observable < User []> {
return this .restTemplate ();
}
// ...
}
Copy @ Injectable ()
@ RestClient ( 'users' )
export class ApiUsersClient extends DataHttpClient {
@ Get ( '/{id}' )
public getUserById (@ PathVariable ( 'id' ) _userId : number ) : Observable < User > {
return this .restTemplate ();
}
}
Copy @ Injectable ()
@ RestClient ( 'users' )
export class ApiUsersClient extends DataHttpClient {
@ Post ()
public createUser (@ RequestBody () _body : User ) : Observable < User > {
return this .restTemplate ();
}
}
@angular-ru/cdk/http/utils
Copy expect ( isLocalhost ( 'https://127.0.0.1:4200' )) .toEqual ( true );
expect ( isLocalhost ( 'https://google.com' )) .toEqual ( false );
getPathWithoutQueryParams
Copy expect ( getPathWithoutQueryParams ( 'http://hello/world/todo/1/all?pageSize=10&pageIndex=0' )) .toEqual (
'http://hello/world/todo/1/all'
);
Copy expect ( getUrlSegments ({})) .toEqual ({ hostUrl : 'http://localhost/' , baseUrl : '' });
expect ( getUrlSegments ({ hostUrl : 'http://hello_world' , baseUrl : 'api' })) .toEqual ({
hostUrl : 'http://hello_world/' ,
baseUrl : '/api/'
});
Copy expect ( isAbsolutePath ( '/api' )) .toEqual ( false );
expect ( isAbsolutePath ( '//hello_world' )) .toEqual ( false );
expect ( isAbsolutePath ( 'http://hello_world' )) .toEqual ( true );
Copy expect ( replaceDoubleSlash ( 'https://a///b//c/d/' )) .toEqual ( 'https://a/b/c/d/' );
expect ( replaceDoubleSlash ( '////a///b//c/d/' )) .toEqual ( '/a/b/c/d/' );
replaceLeadingAndTrailingSlashes
Copy expect ( replaceLeadingAndTrailingSlashes ( '/' )) .toEqual ( '' );
expect ( replaceLeadingAndTrailingSlashes ( '//' )) .toEqual ( '' );
expect ( replaceLeadingAndTrailingSlashes ( '//a///b//c/d/' )) .toEqual ( 'a/b/c/d' );
Copy expect ( urlParse ( '////a///b//c/d?quick' , getUrlSegments ({ hostUrl : 'https://127.0.0.0:8030' }))) .toEqual (
'https://127.0.0.0:8030/a/b/c/d'
);
Copy const headers : HttpHeaders = getHttpHeader ({ a : '1' , b : '2' });
expect ( headers .keys ()) .toEqual ([ 'a' , 'b' ]);
expect ( headers .get ( 'a' )) .toEqual ( '1' );
expect ( headers .get ( 'b' )) .toEqual ( '2' );
Copy const queryParams : PlainObject = parseQueryParams ( '/todos/get?pageSize=5&value=2' );
expect (queryParams) .toEqual ({ pageSize : '5' , value : '2' });
Copy const params : HttpParams = getHttpParams ( '/todos/get?pageSize=5&value=2' , { pageIndex : 0 });
expect ( params .keys ()) .toEqual ([ 'pageSize' , 'value' , 'pageIndex' ]);
expect ( params .get ( 'pageSize' )) .toEqual ( '5' );
expect ( params .get ( 'value' )) .toEqual ( '2' );
expect ( params .get ( 'pageIndex' )) .toEqual ( 0 );