/** @file * @author Edouard DUPIN * @copyright 2018, Edouard DUPIN, all right reserved * @license PROPRIETARY (see license file) */ import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders, HttpEventType } from '@angular/common/http'; import { environment } from 'environments/environment'; import { SessionService } from './session'; import { isArrayOfs, isBoolean, isNullOrUndefined, isNumber, isString } from 'common/utils'; export enum HTTPRequestModel { POST = 'POST', GET = 'GET', PUT = 'PUT', DELETE = 'DELETE', PATCH = 'PATCH', } export enum HTTPMimeType { ALL = '*/*', JSON = 'application/json', OCTET_STREAM = 'application/octet-stream', IMAGE = 'image/*', IMAGE_JPEG = 'image/jpeg', IMAGE_PNG = 'image/png', } export type UrlPath = string | boolean | number | (string | boolean | number)[]; export type ProgressCallback = (count: number, total: number) => void; export interface HTTPRequest { server?: string; endPoint: UrlPath; requestType: HTTPRequestModel; accept: HTTPMimeType; contentType: HTTPMimeType; params?: object; body?: any; authorization?: string; // c'est un hook de merde ... disableTocken?: boolean; // progress interface to notify progression of the streaming. progress?: ProgressCallback; } export interface ModelResponseHttp { status: number; data: any; } /** * This service permit to add some data like tocken and authorisation.. ir automatically get the token if needed and retake it if expired... */ @Injectable() export class HttpWrapperService { private displayReturn: boolean = false; constructor(private http: HttpClient, private session: SessionService) { } addTokenIfNeeded(headerOption: any): any { const token = this.session.getToken(); if (!isNullOrUndefined(token)) { if (headerOption.Authorization === undefined) { headerOption.Authorization = `Yota ${token}`; } } return headerOption; } request(properties: HTTPRequest): Promise { //uriRest:string, headerOption:any, params:any): Promise<{status:number, data:any}> { //console.log(`-------------------------------------------------------\nHTTP-wrapper GET '${ properties.endPoint }'\n\t\tparams=${ JSON.stringify(properties, null, 2)}`); let connectionAddresses = this.createRESTCall2({ server: properties.server, api: properties.endPoint, inputOptions: properties.params, }); let headers: any = { Accept: properties.accept, //'Content-Type': properties.contentType, }; if (properties.authorization !== undefined && properties.authorization !== null) { headers['Authorization'] = properties.authorization; } if (properties.requestType !== HTTPRequestModel.GET) { headers['Content-Type'] = properties.contentType; } //console.log(`disble tocken : ${JSON.stringify(properties)} properties.disableTocken=${properties.disableTocken}`); if ( properties.disableTocken === undefined || properties.disableTocken === null || properties.disableTocken === false ) { headers = this.addTokenIfNeeded(headers); } //console.log(`header: ${JSON.stringify(headers)}`); let body = properties.body; if (properties.contentType === HTTPMimeType.JSON) { body = JSON.stringify(properties.body); } console.log(`Call ${connectionAddresses}`) const result = fetch(connectionAddresses, { method: properties.requestType, headers, body, }); return result; } requestJson(properties: HTTPRequest): Promise { return new Promise((resolve, reject) => { this.request(properties) .then((response: Response) => { if (response.status >= 200 && response.status <= 299) { const contentType = response.headers.get('Content-Type'); if (contentType === HTTPMimeType.JSON) { response .json() .then((value: any) => { //console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`); resolve({ status: response.status, data: value }); }) .catch((reason: any) => { reject({ status: 999, data: reason }); }); } else { console.error(`content Type is not Json: ${contentType}`); reject({ status: 999, data: `content Type is not Json: ${contentType}` }); } } else { console.error(`wring correct status: ${response.status}`); reject({ status: 900, data: response }); } }) .catch((error: any) => { reject({ status: error.status, data: error.error }); }); }); } requestImage(properties: HTTPRequest): Promise { return new Promise((resolve, reject) => { this.request(properties) .then((response: Response) => { if (response.status >= 200 && response.status <= 299) { const contentType = response.headers.get('Content-Type'); //console.log(`REICEIVE ==> ${response.status}`); resolve({ status: 900, data: response }); /* resolve({ status:response.status, data:value }); }).catch((reason:any)=> { reject({ status:999, data:reason }); }); } else { console.error(`content Type is not Json: ${contentType}`) reject({ status:999, data:`content Type is not Json: ${contentType}` }); } */ } else { console.error(`wring correct status: ${response.status}`); resolve({ status: 900, data: response }); } }) .catch((error: any) => { reject({ status: error.status, data: error.error }); }); }); } createRESTCall2({ api, server, inputOptions, addURLToken, }: { server?: string; api: UrlPath; inputOptions?: object; addURLToken?: boolean; }) { if (isNullOrUndefined(server)) { server = environment.defaultServer; } const basePage = environment.server[server]; let addressServerRest = basePage; if (!basePage.endsWith('/')) { addressServerRest = `${basePage}/`; } let options = inputOptions; if (isNullOrUndefined(options)) { options = {}; } let out = addressServerRest; if (isArrayOfs(api, isString, isNumber, isBoolean)) { for (let iii = 0; iii < api.length; iii++) { let elem = api[iii]; if (out.endsWith('/')) { out += elem; } else { out += `/${elem}`; } } } else { out += api; } let first = true; let keys = Object.keys(options); for (let iii = 0; iii < keys.length; iii++) { if (first === false) { out = `${out}&`; } else { out = `${out}?`; first = false; } out = out + keys[iii]; if (options[keys[iii]] != null) { out = out + '=' + options[keys[iii]]; } } //console.log(`try to get session : ${this.session.getToken()}`); if (!isNullOrUndefined(this.session.getToken())) { if (addURLToken !== undefined && addURLToken === true) { if (first === false) { out = `${out}&`; } else { out = `${out}?`; } out = out + `Authorization=Yota ${this.session.getToken()}`; } } return out; } // Deprecated ... createRESTCall(api: string, inputOptions?: any) { let basePage = environment.server[environment.defaultServer]; let addressServerRest = `${basePage}/`; let options = inputOptions; if (options === undefined) { options = []; } let out = addressServerRest + api; let first = true; for (let iii = 0; iii < options.length; iii++) { if (first === false) { out = `${out}&`; } else { out = `${out}?`; first = false; } out = out + options[iii]; } return out; } // Deprecated ... old model stream post(uriRest: string, headerOption: any, data: any, progress: ProgressCallback = null) { //console.log(`-------------------------------------------------------\nHTTP-wrapper POST '${ uriRest }'\n\t\theaderOption=${ JSON.stringify(headerOption, null, 2)}\n\t\tdata=${ JSON.stringify(data, null, 2)}`); this.addTokenIfNeeded(headerOption); let connectionAdresse = this.createRESTCall(uriRest, {}); return new Promise((resolve, reject) => { if (this.displayReturn === true) { console.log(`call POST ${connectionAdresse} data=${JSON.stringify(data, null, 2)}`); } let request = this.http.post(connectionAdresse, data, { headers: new HttpHeaders(headerOption), reportProgress: true, observe: 'events', }); let self = this; request.subscribe( (res: any) => { if (self.displayReturn === true) { console.log(`!! data ${JSON.stringify(res, null, 2)}`); } if (res.type === HttpEventType.Sent) { /* res.type === 0 */ //console.log('post : Sent'); } else if (res.type === HttpEventType.UploadProgress) { /* res.type === 1 */ // console.log("post : " + res.loaded + " / " + res.total); progress(res.loaded, res.total); } else if (res.type === HttpEventType.ResponseHeader) { /* res.type === 2 */ //console.log('post : get header'); } else if (res.type === HttpEventType.DownloadProgress) { /* res.type === 3 */ //console.log(`post : get DownloadProgress ${ res.loaded}`); } else if (res.type === HttpEventType.Response) { /* res.type === 4 */ //console.log('post : get response'); if (res.httpCode) { resolve({ status: res.httpCode, data: res }); } else { resolve({ status: 200, data: res }); } } else if (res.type === HttpEventType.User) { /* res.type === 5 */ //console.log('post : get User'); } else { console.log(`post : get unknown ... ${res.type}`); } }, error => { if (self.displayReturn === true) { console.log(`an error occured status: ${error.status}`); console.log(`answer: ${JSON.stringify(error, null, 2)}`); } reject({ status: error.status, data: error.error }); } ); }); } // Deprecated ... old model stream uploadMultipart(base: string, multipart: FormData, progress: ProgressCallback): any { //console.log(`Upload multipart to ${ base}`); let url = base; let self = this; return new Promise((resolve, reject) => { let headers = { // 'Content-Type': 'multipart/form-data', }; // new Headers(); self.post(url, headers, multipart, progress).then( (response: any) => { //console.log(`URL: ${ url }\nRespond(${ response.status }): ${ JSON.stringify(response.data, null, 2)}`); if (response.status >= 200 && response.status <= 299) { resolve(response.data.body); return; } reject('An error occured'); }, (response: any) => { if (typeof response.data === 'undefined') { reject('return ERROR undefined'); } else { reject('return ERROR ...'); // + JSON.stringify(response, null, 2)); } } ); }); } // Complex wrapper to simplify interaction: getSpecific(urlPath: UrlPath): any { return new Promise((resolve, reject) => { this.requestJson({ endPoint: urlPath, requestType: HTTPRequestModel.GET, accept: HTTPMimeType.JSON, contentType: HTTPMimeType.JSON, }).then( (response: ModelResponseHttp) => { //console.log("URL: " + url + "\nRespond(" + response.status + "): " + JSON.stringify(response.data, null, 2)); if (response.status === 200) { resolve(response.data); return; } reject('An error occured'); }, (response: ModelResponseHttp) => { if (isNullOrUndefined(response.data)) { reject('return ERROR undefined'); } else { reject(`return ERROR ${JSON.stringify(response.data, null, 2)}`); } } ); }); } // Complex wrapper to simplify interaction:s putSpecific(urlPath: UrlPath, data: object): Promise { return new Promise((resolve, reject) => { this.request({ endPoint: urlPath, requestType: HTTPRequestModel.PUT, accept: HTTPMimeType.JSON, contentType: HTTPMimeType.JSON, body: data, }) .then((response: Response) => { if (response.status >= 200 && response.status <= 201) { const contentType = response.headers.get('Content-Type'); if (contentType === HTTPMimeType.JSON) { response .json() .then((value: any) => { //console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`); resolve({ status: response.status, data: value }); }) .catch((reason: any) => { reject({ status: 999, data: reason }); }); } else { console.error(`content Type is not Json: ${contentType}`); reject({ status: 998, data: `content Type is not Json: ${contentType}` }); } } else { console.error(`wrong correct status: ${response.status}`); reject({ status: 900, data: response }); } }) .catch((error: any) => { reject({ status: error.status, data: error.error }); }); }); } postSpecific(urlPath: UrlPath, data: object): Promise { return new Promise((resolve, reject) => { this.request({ endPoint: urlPath, requestType: HTTPRequestModel.POST, accept: HTTPMimeType.JSON, contentType: HTTPMimeType.JSON, body: data, }) .then((response: Response) => { if (response.status >= 200 && response.status <= 201) { const contentType = response.headers.get('Content-Type'); if (contentType === HTTPMimeType.JSON) { response .json() .then((value: any) => { //console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`); resolve({ status: response.status, data: value }); }) .catch((reason: any) => { reject({ status: 999, data: reason }); }); } else { console.error(`content Type is not Json: ${contentType}`); reject({ status: 998, data: `content Type is not Json: ${contentType}` }); } } else { console.error(`wrong correct status: ${response.status}`); reject({ status: 900, data: response }); } }) .catch((error: any) => { reject({ status: error.status, data: error.error }); }); }); } deleteSpecific(urlPath: UrlPath): Promise { return new Promise((resolve, reject) => { this.request({ endPoint: urlPath, requestType: HTTPRequestModel.DELETE, accept: HTTPMimeType.JSON, contentType: HTTPMimeType.JSON, }) .then((response: Response) => { if (response.status >= 200 && response.status <= 201) { const contentType = response.headers.get('Content-Type'); if (contentType === HTTPMimeType.JSON) { response .json() .then((value: any) => { //console.log(`REICEIVE ==> ${response.status}=${ JSON.stringify(value, null, 2)}`); resolve({ status: response.status, data: value }); }) .catch((reason: any) => { reject({ status: 999, data: reason }); }); } else { console.error(`content Type is not Json: ${contentType}`); reject({ status: 998, data: `content Type is not Json: ${contentType}` }); } } else { console.error(`wrong correct status: ${response.status}`); reject({ status: 900, data: response }); } }) .catch((error: any) => { reject({ status: error.status, data: error.error }); }); }); } }