gitbeaker/src/infrastructure/RequestHelper.js
Giuseppe Angri 764fdef928 Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	src/infrastructure/RequestHelper.js
2018-06-06 11:29:34 +02:00

135 lines
3.6 KiB
JavaScript

import Humps from 'humps';
import LinkParser from 'parse-link-header';
import QS from 'qs';
import URLJoin from 'url-join';
import StreamableRequest from 'request';
function defaultRequest(
{ url, useXMLHttpRequest },
endpoint,
{
headers,
body,
qs,
formData,
resolveWithFullResponse = false,
},
) {
const params = {
url: URLJoin(url, endpoint),
headers,
json: true,
};
if (body) params.body = Humps.decamelizeKeys(body);
if (qs) {
if (useXMLHttpRequest) {
// The xhr package doesn't have a way of passing in a qs object until v3
params.url = URLJoin(params.url, `?${QS.stringify(Humps.decamelizeKeys(qs))}`);
} else {
params.qs = Humps.decamelizeKeys(qs);
}
}
if (formData) params.formData = formData;
params.resolveWithFullResponse = resolveWithFullResponse;
return params;
}
function getStream(service, endpoint, options = {}) {
if (service.useXMLHttpRequest) {
throw new Error('Cannot use streaming functionality with XMLHttpRequest. Please instantiate without this option to use streaming');
}
const requestOptions = defaultRequest(service, endpoint, {
headers: service.headers,
qs: options,
});
return StreamableRequest.get(requestOptions);
}
async function getPaginated(service, endpoint, options = {}) {
const { showPagination, maxPages, ...queryOptions } = options;
const requestOptions = defaultRequest(service, endpoint, {
headers: service.headers,
qs: queryOptions,
resolveWithFullResponse: true,
});
const response = await service.requester.get(requestOptions);
const links = LinkParser(response.headers.link) || {};
const page = response.headers['x-page'];
const underMaxPageLimit = maxPages ? page < maxPages : true;
let more = [];
let data;
// If not looking for a singular page and still under the max pages limit
// AND their is a next page, paginate
if (!queryOptions.page && underMaxPageLimit && links.next) {
more = await getPaginated(service, links.next.url.replace(service.url, ''), options);
data = [...response.body, ...more];
} else {
data = response.body;
}
const data = Array.isArray(response.body) ? [...response.body, ...more] : response.body;
if (queryOptions.page && showPagination) {
return {
data,
pagination: {
total: response.headers['x-total'],
next: response.headers['x-next-page'] || null,
current: response.headers['x-page'] || null,
previous: response.headers['x-prev-page'] || null,
perPage: response.headers['x-per-page'],
totalPages: response.headers['x-total-pages'],
},
};
}
return data;
}
class RequestHelper {
static async get(service, endpoint, options = {}, { stream = false } = {}) {
if (stream) return getStream(service, endpoint, options);
return getPaginated(service, endpoint, options);
}
static post(service, endpoint, options = {}, form = false) {
const body = form ? 'formData' : 'body';
const requestOptions = defaultRequest(service, endpoint, {
headers: service.headers,
[body]: options,
});
return service.requester.post(requestOptions);
}
static put(service, endpoint, options = {}) {
const requestOptions = defaultRequest(service, endpoint, {
headers: service.headers,
body: options,
});
return service.requester.put(requestOptions);
}
static delete(service, endpoint, options = {}) {
const requestOptions = defaultRequest(service, endpoint, {
headers: service.headers,
qs: options,
});
return service.requester.delete(requestOptions);
}
}
export default RequestHelper;