Skip to content

Instantly share code, notes, and snippets.

@devotox
Created November 17, 2017 10:53
Show Gist options
  • Save devotox/cec5dc185f1470f29f6f20c101a1f42b to your computer and use it in GitHub Desktop.
Save devotox/cec5dc185f1470f29f6f20c101a1f42b to your computer and use it in GitHub Desktop.
import Ember from 'ember';
import fetch from 'fetch';
const { FormData } = window;
import { debug } from '@ember/debug';
import Service, { inject } from '@ember/service';
import config from '../config/environment';
const { host, namespace } = config.authentication;
export default Service.extend({
host,
namespace,
store: inject(),
crypto: inject(),
fastboot: inject(),
authentication: inject(),
put() {
return this.request('put', ...arguments);
},
post() {
return this.request('post', ...arguments);
},
head() {
return this.request('head', ...arguments);
},
fetch() {
return this.request('get', ...arguments);
},
patch() {
return this.request('patch', ...arguments);
},
delete() {
return this.request('delete', ...arguments);
},
params(data = []) {
let e = encodeURIComponent;
let qs = Object.keys(data).map(
(k) => `${e(k)}=${e(data[k])}`
).join('&').trim();
return qs && qs.length ? `?${qs}` : '';
},
createHeaders(accessToken, headers, contentType) {
headers = Object.assign({
'Content-Type': contentType
}, accessToken, headers);
Object.keys(headers).forEach(
(key) => !headers[key] && delete headers[key]
);
return headers;
},
async request(method, api, data = {}, headers = {},
{ form, apiURL, contentType, responseType } = {}) {
method = method.toLowerCase();
responseType = responseType || 'json';
contentType = contentType || 'application/json; charset=utf-8';
let dataType = method !== 'get' ? 'body' : 'params';
let accessToken = this.get('authentication').getAccessToken();
debug('[API]', 'Access Token:', accessToken);
let url = this.createApiUrl(api, method, data, apiURL);
headers = this.createHeaders(accessToken, headers, contentType);
data = method === 'get' ? data
: form ? new FormData(form)
: JSON.stringify(data || {});
let request = {
headers,
contentType,
mode: 'cors',
[dataType]: data,
method: method.toUpperCase()
};
try {
let response = await fetch(url, request);
return this.finish(response, responseType);
}
catch(error) {
this.error(error);
}
},
finish(response, type = 'json') {
if (!response.ok) {
return this.error(response);
}
try {
return response
&& response[type]
&& response[type]();
}
catch(e) {
return response;
}
},
async error(response) {
let fromBlob = async() => {
if (!response.blob) { return; }
let blob = await response.blob();
return await this.get('crypto').fromBlob(blob);
};
let message = response.message
|| response.statusText
|| await fromBlob();
Logger.error('======== API ERROR ========');
Logger.error('Error:', message);
Logger.error('===========================');
let error = new Error(message);
error.code = response.code || response.statusCode || 505;
if (this.get('fastboot.isFastBoot')) {
return this.set('fastboot.response.statusCode', error.code);
}
throw error;
},
createApiUrl(api, method, data, apiURL) {
let qs = this.params(data);
let host = this.get('host');
let namespace = this.get('namespace');
if (this.get('fastboot.isFastBoot')) {
host = this.get('fastboot.request.host');
host = `https://${host}`;
}
if (!api) {
throw new Error('No API Specified');
}
else if (namespace) {
api = api.replace(new RegExp(`^(/+)?(${namespace})?(/+)?`), '');
}
apiURL = apiURL || `${host}/${namespace}`;
apiURL = apiURL && apiURL.replace(/\/$/, '');
apiURL = apiURL ? `${apiURL}/${api}` : api;
return method !== 'get' ? apiURL : `${apiURL}${qs}`;
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment