| /*- |
| * ============LICENSE_START======================================================= |
| * SDC |
| * ================================================================================ |
| * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. |
| * ================================================================================ |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * ============LICENSE_END========================================================= |
| */ |
| |
| import _extend from 'lodash/extend.js'; |
| import _clone from 'lodash/clone.js'; |
| import _defaults from 'lodash/defaults.js'; |
| import $ from 'jquery'; |
| import uuid from 'uuid-js'; |
| import md5 from 'md5'; |
| |
| import store from 'sdc-app/AppStore.js'; |
| import {actionTypes as LoaderConstants} from 'nfvo-components/loader/LoaderConstants.js'; |
| import Configuration from 'sdc-app/config/Configuration.js'; |
| import errorResponseHandler from './ErrorResponseHandler.js'; |
| |
| const methodMap = { |
| 'create': 'POST', |
| 'update': 'PUT', |
| 'delete': 'DELETE', |
| 'read': 'GET' |
| }; |
| const AUTHORIZATION_HEADER = 'X-AUTH-TOKEN'; |
| const STORAGE_AUTH_KEY = 'sdc-auth-token'; |
| const REQUEST_ID_HEADER = 'X-ECOMP-RequestID'; |
| const CONTENT_MD5_HEADER = 'Content-MD5'; |
| const namedParam = /{(\w+)}/g; |
| const queryParamsNames = { |
| pageStart: 'pageStart', |
| pageSize: 'pageSize', |
| sortField: 'sortField', |
| sortDir: 'sortDir', |
| filtering: 'filter' |
| }; |
| |
| |
| // jQuery binary transport to download files through XHR |
| // http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/ |
| // https://github.com/henrya/js-jquery/tree/master/BinaryTransport |
| $.ajaxTransport('+binary', function (options/*, originalOptions , jqXHR*/) { |
| // check for conditions and support for blob / arraybuffer response type |
| if (window.FormData && ((options.dataType && (options.dataType === 'binary')) || |
| (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || |
| (window.Blob && options.data instanceof Blob)))) |
| ) { |
| return { |
| // create new XMLHttpRequest |
| send: function (headers, callback) { |
| // setup all variables |
| var xhr = new XMLHttpRequest(), |
| url = options.url, |
| type = options.type, |
| async = options.async || true, |
| // blob or arraybuffer. Default is blob |
| dataType = options.responseType || 'blob', |
| data = options.data || null, |
| username = options.username || null, |
| password = options.password || null; |
| |
| xhr.addEventListener('load', function () { |
| var data = {}; |
| data[options.dataType] = xhr.response; |
| // make callback and send data |
| callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders()); |
| }); |
| |
| xhr.open(type, url, async, username, password); |
| |
| // setup custom headers |
| for (var i in headers) { |
| xhr.setRequestHeader(i, headers[i]); |
| } |
| |
| xhr.responseType = dataType; |
| xhr.send(data); |
| }, |
| abort: function () { |
| } |
| }; |
| } |
| }); |
| |
| $(document).ajaxStart(()=> store.dispatch({type: LoaderConstants.SHOW})); |
| $(document).ajaxStop(()=> store.dispatch({type: LoaderConstants.HIDE})); |
| |
| function urlError() { |
| throw new Error('A "url" property or function must be specified'); |
| }; |
| |
| export function makeQueryParams(options) { |
| var qParams = {}; |
| if (options.pagination) { |
| qParams[queryParamsNames.pageStart] = options.pagination.pageStart; |
| qParams[queryParamsNames.pageSize] = options.pagination.pageSize; |
| } |
| if (options.sorting) { |
| qParams[queryParamsNames.sortField] = options.sorting.sortField; |
| qParams[queryParamsNames.sortDir] = options.sorting.sortDir; |
| } |
| if (options.filtering) { |
| qParams[queryParamsNames.filtering] = JSON.stringify(options.filtering); |
| } |
| |
| return _defaults(qParams, options.qParams); |
| } |
| |
| function appendQueryParam(p, value) { |
| var str = ''; |
| |
| if (value instanceof Array) { |
| if (value.length === 1) { |
| str = appendQueryParam(p, value[0]); |
| } else if (value.length > 1) { |
| str = appendQueryParam(p, value.shift()) + '&' + appendQueryParam(p, value); |
| } |
| } else { |
| str = p + '=' + encodeURIComponent(value); |
| } |
| |
| return str; |
| } |
| |
| function appendQueryString(url, qParams) { |
| var str = ''; |
| for (var param in qParams) { |
| str += (str ? '&' : '') + appendQueryParam(param, qParams[param]); |
| } |
| return url + (str ? '?' : '') + str; |
| } |
| |
| function composeURL(baseUrl, options) { |
| var url = baseUrl || urlError(); |
| if (options.url) { |
| delete options.url; |
| } |
| |
| var qParams = makeQueryParams(options); |
| url = appendQueryString(url, qParams); |
| |
| var matches = url.match(namedParam); |
| if (matches) { |
| for (var i = 0; i < matches.length; i++) { |
| var param = matches[i].substring(1, matches[i].length - 1); |
| var value = (options.params && options.params[param]); |
| |
| if (value === undefined) { |
| value = options[param]; |
| } |
| url = url.replace(matches[i], encodeURIComponent(value)); |
| } |
| } |
| |
| return url; |
| } |
| |
| function applyMD5Header(options, data) { |
| if (options.md5) { |
| let headers = options.headers; |
| headers[CONTENT_MD5_HEADER] = window.btoa(md5(JSON.stringify(data)).toLowerCase()); |
| } |
| } |
| |
| function applySecurity(options, data) { |
| var headers = options.headers || (options.headers = {}); |
| |
| var authToken = localStorage.getItem(STORAGE_AUTH_KEY); |
| if (authToken) { |
| headers[AUTHORIZATION_HEADER] = authToken; |
| } |
| |
| var attApiHeaders = Configuration.get('ATTApiHeaders'), |
| attUidHeader = attApiHeaders && attApiHeaders.userId; |
| if (attUidHeader) { |
| headers[attUidHeader.name] = attUidHeader.value; |
| } |
| |
| headers[REQUEST_ID_HEADER] = uuid.create().toString(); |
| |
| applyMD5Header(options, data); |
| } |
| |
| function handleResponse(options) { |
| var authToken = options.xhr.getResponseHeader(AUTHORIZATION_HEADER); |
| var prevToken = options.headers && options.headers[AUTHORIZATION_HEADER]; |
| if (authToken && authToken !== prevToken) { |
| if (authToken === 'null') { |
| localStorage.removeItem(STORAGE_AUTH_KEY); |
| } else { |
| localStorage.setItem(STORAGE_AUTH_KEY, authToken); |
| } |
| } |
| } |
| |
| function sync(baseUrl, method, options, data) { |
| |
| options = options ? _clone(options) : {}; |
| |
| var type = methodMap[method]; |
| _defaults(options || (options = {})); |
| var params = { |
| type: type, |
| dataType: 'json' |
| }; |
| params.url = composeURL(baseUrl, options); |
| |
| if ((method === 'create' || method === 'update') && data instanceof FormData) { |
| params.contentType = 'multipart/form-data'; |
| params.data = data; |
| } |
| else if (method === 'create' || method === 'update') { |
| params.contentType = 'application/json'; |
| params.data = JSON.stringify(data); |
| } |
| |
| if (params.type !== 'GET') { |
| params.processData = false; |
| } |
| var success = options.success; |
| options.success = function (resp) { |
| if (success) { |
| handleResponse(options); |
| success.call(options.context, _clone(resp), resp, options); |
| } |
| }; |
| |
| options.error = options.error || errorResponseHandler; |
| |
| if (typeof options.progressCallback === 'function' && options.fileSize) { |
| const {fileSize} = options; |
| options.xhrFields = { |
| // add listener to XMLHTTPRequest object directly for progress (jquery doesn't have this yet) |
| onprogress: function (progress) { |
| // calculate upload progress |
| let percentage = Math.floor((progress.loaded / fileSize) * 100); |
| // log upload progress to console |
| //console.log('progress', percentage); |
| options.progressCallback(percentage); |
| if (percentage === 100) { |
| console.log('DONE!'); |
| } |
| } |
| }; |
| } |
| |
| applySecurity(options, data); |
| |
| if (DEBUG) { |
| console.log('--> Making REST call (' + type + '): ' + params.url); |
| } |
| var xhr = options.xhr = $.ajax(_extend(params, options)); |
| return xhr; |
| } |
| |
| export default { |
| |
| fetch(baseUrl, options) { |
| return sync(baseUrl, 'read', options); |
| }, |
| |
| save(baseUrl, data, options) { |
| return sync(baseUrl, 'update', options, data); |
| }, |
| |
| create(baseUrl, data, options) { |
| return sync(baseUrl, 'create', options, data); |
| }, |
| |
| destroy(baseUrl, options) { |
| return sync(baseUrl, 'delete', options); |
| } |
| |
| }; |