Ng Flex Http Library
Table of Contents
- Important Notes
- Introduction
- Development Instructions
- Building / Publishing Instructions
- Installing
- Usage
- API / Methods
- Models
- Data Timeline
- Testing
- Changelog
Important Notes
As NgFlexHttp
makes use of Angular's HttpClient
, only Angular versions v4.0.3
and after will be able to use the library.
This project uses Angular CLI v6 that comes with library support. Angular versions prior to v6 WILL NOT be able to build the library.
Please read Libary support in Angular CLI 6 for more information.
Introduction
Objective
- The Company - Flex-Solver
To create a clean and standardized format for http requests with the company-related APIs.
The existing Angular HttpClient
proves to be inadequate for the usage for the company when the number of API requests increases. The Angular subscription
methods of handling APIs is unable to cater to the chaining of http requests. For such cases, we had to resort to creating promises for the subscriptions numerous times.
Hence, this library was created to handle such instances by directly returning promises. It also allows easy access of handling headers, tokens, success and error handlers in one place.
Features
- Chaining of requests via promises
- Easy access for handling headers/tokens per request
- Easy access for handling interceptors and per-API success/error maps
Development Instructions
The library is located in projects/ng-flex-http/src/lib
. To test the library, you will have to build the library (see the next section) after any changes you've made. Upon building, the compiled files will be located in the dist
folder. A playground has been created in this project in src/app/app.component
for local testing.
- You can import the module and service locally via
import { NgFlexHttpModule, NgFlexHttpService } from '@flex-solver/ng-flex-http';
Building / Publishing Instructions
To publish the library follow these steps:
npm version xxx
cd projects/ng-flex-http
ng build ng-flex-http --prod
cd dist/ng-flex-http
npm publish
If you've never published a package in npm before, you will need to create a user account. You can read more about publishing on npm here: https://docs.npmjs.com/getting-started/publishing-npm-packages
The --prod
flag should be used when building to publish because it will completely clean the build directory for the library beforehand, removing old code leftover code from previous versions.
Installing
Using npm:
$ npm install @flexsolver/ng-flex-http
Usage
Please check your rxjs version in your package.json
file to use the recommended imports in the next section.
// Importing the Library in app.module.ts
import { NgFlexHttpModule } from '@flexsolver/ng-flex-http';
@NgModule({
...
providers: [
NgFlexHttpModule
]
})
// Importing the Service in your files
import { NgFlexHttpService } from '@flexsolver/ng-flex-http';
constructor(private flexHttp: NgFlexHttpService) { }
// Set your global configurations in app.component.ts
this.flexHttp.init({
rootURL: 'www.flex-solver.com.sg'
});
// In your service files
downloadFile() {
return this.flexHttp
.post({
url: '/download',
body: { id: 10 },
successMap: (response) => {
return response[0];
}
});
}
// Usage in components
this.myService.downloadFile()
.subscribe((response: any) => {
// Returns the default data
// use successMap to manipulate the original response
console.log(response);
}, (error: FlexHttpResponse) => {
// Catch errors
})
There is no need to import the HttpClientModule
. It has already been imported and exported in NgFlexHttpModule
Chaining Requests
- rxjs >= 6
import { flatMap } from 'rxjs/operators';
// Init chaining of request
const httpRequest = this.flexHttp
.get({
url: '/users'
})
.pipe(
flatMap(data => {
this.users = data;
return this.flexHttp.get({
url: '/departments'
});
})
).pipe(
flatMap(data => {
this.departments = data;
});
)
// Run the request
httpRequest.subscribe();
Parallel Requests
- rxjs >= 6
// rxjs >= 6
import { forkJoin } from 'rxjs';
// Init requests
const httpRequests = forkJoin([
this.flexHttp.get({
url: '/users'
}),
this.flexHttp.get({
url: '/departments'
}),
]).subscribe(response => {
var users = response[0];
var departments = response[1];
});
// Run the request
httpRequest.subscribe();
Cancelling a Request
const httpRequest = this.flexHttp.get({
url: '/users'
}).subscribe(...);
httpRequest.unsubscribe();
Methods
Global Config
- init(config: FlexGlobalHttpConfig) { } Initialises the service with params e.g. rootURL: string
Headers
- setGlobalHeaders(headers) { }
- addGlobalHeaders(headers) { }
- clearGlobalHeaders(headers) { }
// E.g. Set authentication token header
headers = { Auth: '12345abc' }
constructor(private flexHttp: FlexHttpService) {
flexHttp.setGlobalHeaders(headers);
}
Requests
- get(config: FlexHttpOptions) { }
- post(config: FlexHttpOptions) { }
- put(config: FlexHttpOptions) { }
- delete(config: FlexHttpOptions) { }
- request(method: string, config: FlexHttpOptions) { }
Models
FlexGlobalHttpConfig
{
rootURL?: string;
timeout?: number = 8.64e+7 // default
autoParseFlexData?: boolean = true; // default
globalHeaders?: object;
successInterceptor?: (res: HttpResponse) => {
// Return to allow continuous journey
return res;
};
errorInterceptor?: (error: HttpErrorResponse) => {
// Return to allow continuous journey
return error;
};
}
Interceptors and Handlers initialised here are applied to ALL Http requests sent via FlexHttpService
-
rootURL
- Specify a
rootURL
to use for all requests. (e.g.https://google.com
, subsequent API requests only requires/search
instead of writinghttps://google.com/search
);
- Specify a
-
timeout
- Set a maximum time before the http request is cancelled.
- In
milliseconds
-
autoParseFlexData
- Defaults to
true
- Returns only the
data
param in allFlexHttpResponse
success calls and aFlexHttpResponse
in all error calls regardless of response type.
- Defaults to
-
successInterceptor
- Should receive and return a
HttpResponse
. - Allow actions before the response is sent to the request promise.
- Return value is not required.
- Should receive and return a
-
errorInterceptor
- Should receive a
HttpErrorResponse
and return anObservable<HttpErrorResponse>
. - Allow actions before the error response is sent to the catch block in the promise.
- Return value is not required.
- Useful for rerouting on particular error codes.
- Should receive a
FlexHttpOptions
{
url: string;
body?: any;
headers?: HttpHeaders | {
[header: string]: string | string[];
};
observe?: HttpObserve = 'body'; // default
params?: HttpParams | {
[param: string]: string | string[];
};
reportProgress?: boolean = false; // default
responseType?: 'arraybuffer' | 'blob' | 'json' | 'text' = 'json'; // default
withCredentials?: boolean = false; // default
// FlexHttpOptions-specific params
useRootURL?: boolean = true; // default
timeout?: number = 8.64e+7 // default
autoParseFlexData?: boolean = true; // default
successMap?: (data: any) => any;
errorMap?: (data: FlexHttpResponse) => any;
}
// successMap and errorMap are only applied to this request.
-
successMap
- Allows mapping of response before entering the
then
block.
- Allows mapping of response before entering the
-
errorMap
- Allows mapping of the error before entering the
catch
block.
- Allows mapping of the error before entering the
- For other params, please refer to
HttpRequest
FlexHttpResponse
Default response type for requests/errors:
{
status: number;
message: any;
data: any;
}
Data Timeline
- Any headers in
FlexGlobalHttpConfig
will be applied to the Http request. -
requestInterceptor
(if initialised) will be called to make any additional changes to the Http request. - Data is then retreived from the server
- On a successful call (status doesn't return
4xx / 5xx
, ignoring status inFlexHttpResponse
)-
successInterceptor
fromFlexGlobalHttpConfig
will be called - If it returns a
FlexHttpOptions
without a200
status, see section5.2
-
successMap
fromFlexHttpOptions
will be called - Data will then be finally passed to the
then
block of the promise
-
- On a error call (status does returns
4xx / 5xx
, ignoring status inFlexHttpResponse
)-
errorInterceptor
fromFlexGlobalHttpConfig
will be called -
errorMap
fromFlexHttpOptions
will be called - Data will then be finally passed to the
catch
block of the promise
-
Testing
Test cases are located in projects/src/lib/ng-flex-http.service.spect.ts
.
To run the tests, run the following command: ng test ng-flex-http
.
Changelog
v1.0.43
- Remove strict 2xx status codes success handler.
- Throw error only on 4xx/5xx error status codes.
v1.0.42
- Remove request interceptors, fixed error and success interceptors
- Fix global timeout
v1.0.38
- Remove
rxjs-compat
in peer dependencies - Replace rxjs6 imports with rxjs<6 imports. Projects with rxjs > 6 requires installation of
rxjs-compat
- Update documentation
v1.0.3
- Add
rxjs-compat
in peer dependencies - Update documentation for new rxjs operators for
flatMap
andforkJoin
v1.0.0
- Convert all Promises to Observables
- Add timeout configuration
- Add configuration for report progress
- Add documentation for chaining, parallel and cancelling requests
Author: Amanda Ng (@amanduhsays)