blob: 24734739a2a77f396ac5bd73f56f3b79c050c5d7 [file] [log] [blame]
/*-
* ============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);
}
};