Skip to content

Instantly share code, notes, and snippets.

@cravindra
Last active November 7, 2017 12:03
Show Gist options
  • Save cravindra/698cfe36a68c9d116eaaa8eee8ffaafa to your computer and use it in GitHub Desktop.
Save cravindra/698cfe36a68c9d116eaaa8eee8ffaafa to your computer and use it in GitHub Desktop.
A wrapper around fetch to do common ajax operations on the server and client
require('../../vendor/js/fetch');
/**
* The defaultOptions properties used in fetching API
* @typedef {Object} defaultOptions
* @property {string} method - Indicates the http request method
* @property {string} url - request Url
* @property {Object|null} body - holds the http request body information to be used in post or put request
*/
const fetchConfig = {
headers: {
'Accept': 'application/json, text/plain',
'Content-Type': 'application/json'
},
credentials: 'same-origin'
};
function getErrorMessage(statusCode) {
let message = '';
switch (statusCode) {
case 400:
message = 'error.send400Error';
break;
case 401:
message = 'error.send401Error';
break;
case 403:
message = 'error.send403Error';
break;
case 404:
message = 'error.send404Error';
break;
case 500:
message = 'error.send500Error';
break;
case 502:
message = 'error.send502Error';
break;
case 503:
message = 'error.send503Error';
break;
case 504:
message = 'error.send504Error';
break;
default:
message = 'error.serverError';
}
return message;
}
/**
* Sanitiser Factory that encapsulates original request data and sends log info
* @param {string} url - The Request URL
* @param {Object| null} data - The data required for the current request
* @param {Object} options - The custom options required for fetch
* @returns {function} returns a sanitiser to handle HTTP errors if any and normalize the response
*/
function sanitiserFactory(url, data, options) {
return function sanitiser(response) {
if (response.status >= 200 && response.status <= 299) {
//This is a successful response
return response.json().then(function (jsonBody) {
return Promise.resolve({
response: jsonBody,
success: true,
statusCode: response.status,
statusText: response.statusText,
message: response.message
});
});
}
else {
//Not a 'OK' Response
return response.json().then(function (jsonBody) {
return Promise.reject({
response: jsonBody,
success: false,
statusCode: response.status,
statusText: response.statusText,
message: getErrorMessage(response.status)
});
}, function () {
return response.text().then(function (textBody) {
_sdk.log.silly({url, data, options, textBody});
return Promise.reject({
response: textBody,
success: false,
statusCode: response.status,
statusText: response.statusText,
message: getErrorMessage(response.status)
});
});
}).catch(function () {
_sdk.log.silly(`AJAX: ${response.status} response`, {url, data, options, response});
return Promise.reject({
response: response,
success: false,
statusCode: response.status,
statusText: response.statusText,
message: getErrorMessage(response.status)
});
});
}
};
}
/**
* Function to allow HTTP GET REQUEST
* @param {string} url - The Request URL
* @param {Object} options - The custom options required for fetch
* @returns {Promise} returns response object, if present , else an error object
*/
function get (url, options) {
const defaultOptions = {
method: 'get',
url: url
};
let mergedOptions = {};
Object.assign(mergedOptions, fetchConfig, defaultOptions, options);
_sdk.log.silly('AJAX.get', url, mergedOptions);
return fetch(url, mergedOptions)
.then(sanitiserFactory(url, null, mergedOptions))
.catch(error => {
_sdk.log.silly('AJAX.get', error);
return Promise.reject(error);
});
}
/**
* Function to allow HTTP POST REQUEST
* @param {string} url - The Request URL
* @param {Object} data - The data required for the current request
* @param {Object} options - The custom options required for fetch
* @returns {Promise} returns response object, if present , else an error object
*/
function post(url, data, options) {
const defaultOptions = {
method: 'post',
url: url,
body: JSON.stringify(data)
};
let mergedOptions = {};
Object.assign(mergedOptions, fetchConfig, defaultOptions, options);
_sdk.log.silly('AJAX.post', url, data, mergedOptions);
return fetch(url, mergedOptions)
.then(sanitiserFactory(url, data, mergedOptions))
.catch(error => {
return Promise.reject(error);
});
}
/**
* Function to allow HTTP PUT REQUEST
* @param {string} url - The Request URL
* @param {Object} data - The data required for the current request
* @param {Object} options - The custom options required for fetch
* @returns {Promise} returns response object, if present , else an error object
*/
function put(url, data, options) {
const defaultOptions = {
method: 'put',
url: url,
body: JSON.stringify(data)
};
let mergedOptions = {};
Object.assign(mergedOptions, fetchConfig, defaultOptions, options);
_sdk.log.silly('AJAX.put', url, data, mergedOptions);
return fetch(url, mergedOptions)
.then(sanitiserFactory(url, data, mergedOptions))
.catch(error => {
return Promise.reject(error);
});
}
/**
* Function to allow HTTP DELETE REQUEST
* @param {string} url - The Request URL
* @param {Object} options - The custom options required for fetch
* @returns {Promise} returns response object, if present , else an error object
*/
function deleteAjax(url, options) {
const defaultOptions = {
method: 'delete',
url: url
};
let mergedOptions = {};
Object.assign(mergedOptions, fetchConfig, defaultOptions, options);
_sdk.log.silly('AJAX.delete', url, mergedOptions);
return fetch(url, mergedOptions)
.then(sanitiserFactory(url, null, options))
.catch(error => {
return Promise.reject(error);
});
}
module.exports = {
get: get,
post: post,
put: put,
delete: deleteAjax
};
'use strict';
const _ = require('lodash');
const fetch = require('node-fetch');
/**
* The defaultOptions properties used in fetching API
* @typedef {Object} defaultOptions
* @property {string} method - Indicates the http request method
* @property {string} url - request Url
* @property {Object|null} body - holds the http request body information to be used in post or put request
*/
/****** TODO: move fetchConfig to config *************/
const fetchConfig = {
options: {
timeout: 20000
}
};
function getErrorMessage(statusCode) {
let message = '';
switch (statusCode) {
case 400:
message = 'error.send400Error';
break;
case 401:
message = 'error.send401Error';
break;
case 403:
message = 'error.send403Error';
break;
case 404:
message = 'error.send404Error';
break;
case 500:
message = 'error.send500Error';
break;
case 502:
message = 'error.send502Error';
break;
case 503:
message = 'error.send503Error';
break;
case 504:
message = 'error.send504Error';
break;
default:
message = 'error.serverError';
}
return message;
}
/**
* Sanitiser Factory that encapsulates original request data and sends log info
* @param {string} url - The Request URL
* @param {Object| null} data - The data required for the current request
* @param {Object} options - The custom options required for fetch
* @returns {response} returns response object, when status is [200-299], else an error object
*/
function sanitiserFactory(url, data, options) {
return function sanitiser(response) {
if (response.status >= 200 && response.status <= 299) {
return response.json().then(function (jsonBody) {
log.trace({ url, data, options, jsonBody });
return Promise.resolve({
response: jsonBody,
success: true,
statusCode: response.status,
statusText: response.statusText,
message: response.message
});
});
}
else {
return response.json().then(function (jsonBody) {
log.trace({ url, data, options, jsonBody });
return Promise.reject({
response: jsonBody,
success: false,
statusCode: response.status,
statusText: response.statusText,
message: getErrorMessage(response.status)
});
}, function (err) {
return response.text().then(function (textBody) {
log.trace({ url, data, options, textBody });
return Promise.reject({
response: textBody,
success: false,
statusCode: response.status,
statusText: response.statusText,
message: getErrorMessage(response.status)
});
});
}).catch(function () {
log.warn(`AJAX: ${response.status} response`, { url, data, options, response });
return Promise.reject({
response: response,
success: false,
statusCode: response.status,
statusText: response.statusText,
message: getErrorMessage(response.status)
});
});
}
};
}
/**
* Function to allow HTTP GET REQUEST
* @param {string} url - The Request URL
* @param {Object} options - The custom options required for fetch
* @returns {response} returns response object, if present , else an error object
*/
function get(url, options) {
const defaultOptions = {
method: 'get',
url: url
};
let mergedOptions = {};
_.merge(mergedOptions, fetchConfig.options, defaultOptions, options);
log.trace('AJAX.get', url, mergedOptions);
return fetch(url, mergedOptions)
.then(sanitiserFactory(url, null, mergedOptions))
.catch(error => {
log.warn('AJAX.get', error);
return Promise.reject(error);
});
}
/**
* Function to allow HTTP POST REQUEST
* @param {string} url - The Request URL
* @param {Object} data - The data required for the current request
* @param {Object} options - The custom options required for fetch
* @returns {response} returns response object, if present , else an error object
*/
function post(url, data, options) {
const defaultOptions = {
method: 'post',
url: url,
body: JSON.stringify(data)
};
let mergedOptions = {};
_.merge(mergedOptions, fetchConfig.options, defaultOptions, options);
log.trace('AJAX.post', url, data, mergedOptions);
return fetch(url, mergedOptions)
.then(sanitiserFactory(url, data, options))
.catch(error => {
log.warn('AJAX.post', error);
return Promise.reject(error);
});
}
/**
* Function to allow HTTP PUT REQUEST
* @param {string} url - The Request URL
* @param {Object} data - The data required for the current request
* @param {Object} options - The custom options required for fetch
* @returns {response} returns response object, if present , else an error object
*/
function put(url, data, options) {
const defaultOptions = {
method: 'put',
url: url,
body: JSON.stringify(data)
};
let mergedOptions = {};
_.merge(mergedOptions, fetchConfig.options, defaultOptions, options);
log.trace('AJAX.put', url, data, mergedOptions);
return fetch(url, mergedOptions)
.then(sanitiserFactory(url, data, mergedOptions))
.catch(error => {
log.warn('AJAX.put', error);
return Promise.reject(error);
});
}
/**
* Function to allow HTTP DELETE REQUEST
* @param {string} url - The Request URL
* @param {Object} options - The custom options required for fetch
* @returns {response} returns response object, if present , else an error object
*/
function deleteAjax(url, options) {
const defaultOptions = {
method: 'delete',
url: url
};
let mergedOptions = {};
_.merge(mergedOptions, fetchConfig.options, defaultOptions, options);
log.trace('AJAX.delete', url, mergedOptions);
return fetch(url, mergedOptions)
.then(sanitiserFactory(url, null, mergedOptions))
.catch(error => {
log.warn('AJAX.delete', error);
return Promise.reject(error);
});
}
module.exports = {
get: get,
post: post,
put: put,
delete: deleteAjax
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment