import { Injectable } from '@angular/core' ; import { HttpClient , HttpHeaders , HttpResponse } from '@angular/common/http' ; import { Observable } from 'rxjs/Rx' ; import { HttpHeader } from './http-header.model' ; import { CookieStore } from './cookie-store.service' ; import { IRequestInterceptor } from './request-interceptor.interface' ; import { IResponseInterceptor } from './response-interceptor.interface' ; import { HttpError } from './http-error.model' ; import { DEFAULT_REQUEST_OPTIONS , RequestOptions } from './request-options.interface' ; export interface Func < T , T1 , T2 , TResult > { ( item , item1 , item2 ) : TResult ; } @ Injectable ( ) export class CoolHttp { private _cookieStore : CookieStore = new CookieStore ( ) ; private _globalHeaders : HttpHeader [ ] = [ ] ; private _requestInterceptors : IRequestInterceptor [ ] = [ ] ; private _responseInterceptors : IResponseInterceptor [ ] = [ ] ; private _customCookieToHeaders = [ ] ; private _baseUrl ; private _withCredentials ; constructor ( private _http ) { } public get baseUrl ( ) : string { return this . _baseUrl ; } public registerBaseUrl ( baseUrl ) { this . _baseUrl = baseUrl ; if ( this . _baseUrl [ this . _baseUrl . length - 1 ] !== '/' ) { this . _baseUrl += '/' ; } } public deRegisterBaseUrl ( ) { this . _baseUrl = null ; } public setWithCredentials ( status ) { this . _withCredentials = status ; } public registerGlobalHeader ( header ) { this . deregisterGlobalHeader ( header . key ) ; this . _globalHeaders . push ( header ) ; } public deregisterGlobalHeader ( headerKey ) { const indexOfHeader = this . _globalHeaders . findIndex ( header => header . key === headerKey ) ; if ( indexOfHeader === - 1 ) { return false ; } this . _globalHeaders . splice ( indexOfHeader , 1 ) ; return true ; } public removeAllRegisteredGlobalHeaders ( ) { this . _globalHeaders . length = 0 ; } public registerRequestInterceptor ( requestInterceptor ) { this . _requestInterceptors . push ( requestInterceptor ) ; } public deregisterRequestInterceptor ( requestInterceptor ) { let indexOfItem = this . _requestInterceptors . indexOf ( requestInterceptor ) ; if ( indexOfItem === - 1 ) { return false ; } this . _requestInterceptors . splice ( indexOfItem , 1 ) ; return true ; } public registerResponseInterceptor ( responseInterceptor ) { this . _responseInterceptors . push ( responseInterceptor ) ; } public deregisterResponseInterceptor ( responseInterceptor ) { let indexOfItem = this . _responseInterceptors . indexOf ( responseInterceptor ) ; if ( indexOfItem === - 1 ) { return false ; } this . _responseInterceptors . splice ( indexOfItem , 1 ) ; return true ; } public sendCookieValueInCustomHeader ( cookieName , customHeaderName ) { this . _customCookieToHeaders . push ( { cookieName : cookieName , customHeaderName : customHeaderName } ) ; } public async getAsync < T = any > ( url , options = DEFAULT_REQUEST_OPTIONS ) { let that = this ; return await that . _requestCoreAsync < T > ( url , 'GET' , null , options , ( url , data , modOptions ) => { return that . _http . get ( url , modOptions ) ; } ) ; } public async postAsync < T = any > ( url , data ? , options = DEFAULT_REQUEST_OPTIONS ) { let that = this ; return await that . _requestCoreAsync < T > ( url , 'POST' , data , options , ( url , data , modOptions ) => { return that . _http . post ( url , data , modOptions ) ; } ) ; } public async putAsync < T = any > ( url , data ? , options = DEFAULT_REQUEST_OPTIONS ) { let that = this ; return await that . _requestCoreAsync < T > ( url , 'PUT' , data , options , ( url , data , modOptions ) => { return that . _http . put ( url , data , modOptions ) ; } ) ; } public async deleteAsync < T = any > ( url , options = DEFAULT_REQUEST_OPTIONS ) { let that = this ; return await that . _requestCoreAsync < T > ( url , 'DELETE' , null , options , ( url , data , modOptions ) => { return that . _http [ 'delete' ] ( url , modOptions ) ; } ) ; } public async patchAsync < T = any > ( url , data ? , options = DEFAULT_REQUEST_OPTIONS ) { let that = this ; return await that . _requestCoreAsync < T > ( url , 'PATCH' , data , options , ( url , data , modOptions ) => { return that . _http . patch ( url , data , modOptions ) ; } ) ; } public async headAsync < T = any > ( url , options = DEFAULT_REQUEST_OPTIONS ) { let that = this ; return await that . _requestCoreAsync < T > ( url , 'HEAD' , null , options , ( url , data , modOptions ) => { return that . _http . head ( url , modOptions ) ; } ) ; } private async _requestCoreAsync < T = any > ( url , method , data , options , action ) { options . headers = options . headers || new HttpHeaders ( ) ; options . observe = 'response' ; options . responseType = 'text' ; url = this . _convertUrl ( url ) ; options . headers = this . _appendGlobalHeaders ( < HttpHeaders > options . headers ) ; options . headers = this . _tryAppendRegisteredCookiesToCustomHeaders ( < HttpHeaders > options . headers ) ; this . _modifyOptions ( options ) ; let clientHeaders = this . _convertAngularHeadersToHttpClientHeaders ( < HttpHeaders > options . headers ) ; let shouldIntercept = await this . _invokeRequestInterceptorsAsync ( url , method , data , clientHeaders ) ; if ( shouldIntercept ) { return ; } options . headers = this . _updateAngularHeadersFromHttpClientHeaders ( clientHeaders , < HttpHeaders > options . headers ) ; let response ; try { response = await action ( url , data , options ) . toPromise ( ) ; } catch ( errorResponse ) { response = errorResponse ; } shouldIntercept = await this . _invokeResponseInterceptorsAsync ( response , url , method , data , clientHeaders ) ; if ( shouldIntercept ) { return ; } if ( ! response . ok ) { throw new HttpError ( method , url , response . status , response . statusText , JSON . stringify ( response . body ) ) ; } let returnValue ; try { returnValue = JSON . parse ( response . body ) ; } catch ( e ) { returnValue = { data : response . body } ; } return < T > returnValue ; } public getObservable < T = any > ( url , options = DEFAULT_REQUEST_OPTIONS ) { let that = this ; return that . _requestCoreObservable < T > ( url , 'GET' , null , options , ( url , data , modOptions ) => { return that . _http . get ( url , modOptions ) ; } ) ; } public postObservable < T = any > ( url , data , options = DEFAULT_REQUEST_OPTIONS ) { let that = this ; return that . _requestCoreObservable < T > ( url , 'POST' , data , options , ( url , data , modOptions ) => { return that . _http . post ( url , data , modOptions ) ; } ) ; } public putObservable < T = any > ( url , data , options = DEFAULT_REQUEST_OPTIONS ) { let that = this ; return that . _requestCoreObservable < T > ( url , 'PUT' , data , options , ( url , data , modOptions ) => { return that . _http . put ( url , data , modOptions ) ; } ) ; } public deleteObservable < T = any > ( url , options = DEFAULT_REQUEST_OPTIONS ) { let that = this ; return that . _requestCoreObservable < T > ( url , 'DELETE' , null , options , ( url , data , modOptions ) => { return that . _http [ 'delete' ] ( url , modOptions ) ; } ) ; } public patchObservable < T = any > ( url , data , options = DEFAULT_REQUEST_OPTIONS ) { let that = this ; return that . _requestCoreObservable < T > ( url , 'PATCH' , data , options , ( url , data , modOptions ) => { return that . _http . patch ( url , data , modOptions ) ; } ) ; } public headObservable < T = any > ( url , options = DEFAULT_REQUEST_OPTIONS ) { let that = this ; return that . _requestCoreObservable < T > ( url , 'HEAD' , null , options , ( url , data , modOptions ) => { return that . _http . head ( url , modOptions ) ; } ) ; } private _requestCoreObservable < T = any > ( url , method , data , options , action ) { return Observable . fromPromise ( this . _requestCoreAsync ( url , method , data , options , action ) ) ; } private _convertUrl ( url ) { let returnUrl = url ; if ( this . _baseUrl ) { returnUrl = this . _baseUrl + returnUrl ; } return returnUrl ; } private _modifyOptions ( options ) { if ( this . _withCredentials ) { options . withCredentials = true ; } } private _appendGlobalHeaders ( headers ) { let newHeaders = headers ; for ( const registeredHeader of this . _globalHeaders ) { newHeaders = headers . set ( registeredHeader . key , registeredHeader . value ) ; } return newHeaders ; } private _tryAppendRegisteredCookiesToCustomHeaders ( headers ) { let newHeaders = headers ; for ( const cookieToHeader of this . _customCookieToHeaders ) { const cookieValue = this . _cookieStore . getCookie ( cookieToHeader . cookieName ) ; if ( cookieValue ) { newHeaders = headers . set ( cookieToHeader . customHeaderName , cookieValue ) ; } } return newHeaders ; } private async _invokeRequestInterceptorsAsync ( url , method , data , headers ) { for ( const requestInterceptor of this . _requestInterceptors ) { const shouldIntercept = await requestInterceptor . beforeRequestAsync ( url , method , data , headers ) ; if ( shouldIntercept ) { return true ; } } return false ; } private async _invokeResponseInterceptorsAsync ( response , url , method , data , headers ) { for ( const responseInterceptor of this . _responseInterceptors ) { const shouldIntercept = await responseInterceptor . afterResponseAsync ( response , url , method , data , headers ) ; if ( shouldIntercept ) { return true ; } } return false ; } private _convertAngularHeadersToHttpClientHeaders ( headers ) { return headers . keys ( ) . map ( headerKey => { const httpClientHeader = new HttpHeader ( ) ; httpClientHeader . key = headerKey ; httpClientHeader . value = headers . get ( headerKey ) ; return httpClientHeader ; } ) ; } private _updateAngularHeadersFromHttpClientHeaders ( httpClientHeaders , headers ) { let newHeaders = headers ; for ( const clientHeader of httpClientHeaders ) { const headerValue = headers . get ( clientHeader . key ) ; if ( headerValue !== clientHeader . value ) { newHeaders = headers . set ( clientHeader . key , clientHeader . value ) ; } } return newHeaders ; } }