Skip to content

Commit 4bc7c69

Browse files
max-wittigjdalrymple
authored andcommitted
fix: obey rate limits for all request types correctly (#170)
Fixes #165
1 parent 86960c4 commit 4bc7c69

File tree

1 file changed

+66
-57
lines changed

1 file changed

+66
-57
lines changed

src/infrastructure/RequestHelper.js

Lines changed: 66 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -68,39 +68,41 @@ async function getPaginated(service, endpoint, options = {}) {
6868
resolveWithFullResponse: true,
6969
});
7070

71-
try {
72-
const response = await service.requester.get(requestOptions);
73-
const links = LinkParser(response.headers.link) || {};
74-
const page = response.headers['x-page'];
75-
const underMaxPageLimit = maxPages ? page < maxPages : true;
76-
let more = [];
77-
let data;
78-
79-
// If not looking for a singular page and still under the max pages limit
80-
// AND their is a next page, paginate
81-
if (!queryOptions.page && underMaxPageLimit && links.next) {
82-
more = await getPaginated(service, links.next.url.replace(service.url, ''), options);
83-
data = [...response.body, ...more];
84-
} else {
85-
data = response.body;
86-
}
71+
const response = await service.requester.get(requestOptions);
72+
const links = LinkParser(response.headers.link) || {};
73+
const page = response.headers['x-page'];
74+
const underMaxPageLimit = maxPages ? page < maxPages : true;
75+
let more = [];
76+
let data;
77+
78+
// If not looking for a singular page and still under the max pages limit
79+
// AND their is a next page, paginate
80+
if (!queryOptions.page && underMaxPageLimit && links.next) {
81+
more = await getPaginated(service, links.next.url.replace(service.url, ''), options);
82+
data = [...response.body, ...more];
83+
} else {
84+
data = response.body;
85+
}
8786

88-
if (queryOptions.page && showPagination) {
89-
return {
90-
data,
91-
pagination: {
92-
total: response.headers['x-total'],
93-
next: response.headers['x-next-page'] || null,
94-
current: response.headers['x-page'] || null,
95-
previous: response.headers['x-prev-page'] || null,
96-
perPage: response.headers['x-per-page'],
97-
totalPages: response.headers['x-total-pages'],
98-
},
99-
};
100-
}
87+
if (queryOptions.page && showPagination) {
88+
return {
89+
data,
90+
pagination: {
91+
total: response.headers['x-total'],
92+
next: response.headers['x-next-page'] || null,
93+
current: response.headers['x-page'] || null,
94+
previous: response.headers['x-prev-page'] || null,
95+
perPage: response.headers['x-per-page'],
96+
totalPages: response.headers['x-total-pages'],
97+
},
98+
};
99+
}
100+
101+
return data;
102+
}
101103

102-
return data;
103-
} catch (err) {
104+
class RequestHelper {
105+
static async handleRequestError(err) {
104106
if (
105107
!err.response
106108
|| !err.response.headers
@@ -111,46 +113,53 @@ async function getPaginated(service, endpoint, options = {}) {
111113
const sleepTime = parseInt(err.response.headers['retry-after'], 10);
112114

113115
if (!sleepTime) throw err;
114-
115-
await wait(sleepTime * 1000);
116-
117-
return getPaginated(service, endpoint, options);
116+
return wait(sleepTime * 1000);
118117
}
119-
}
120-
121-
class RequestHelper {
122-
static async get(service, endpoint, options = {}, { stream = false } = {}) {
123-
if (stream) return getStream(service, endpoint, options);
124118

125-
return getPaginated(service, endpoint, options);
119+
static get(service, endpoint, options = {}, { stream = false } = {}) {
120+
return RequestHelper.request('get', service, endpoint, options, stream);
126121
}
127122

128-
static post(service, endpoint, options = {}, form = false) {
129-
const body = form ? 'formData' : 'body';
123+
static async request(type, service, endpoint, options = {}, form = false, stream = false) {
130124
const requestOptions = defaultRequest(service, endpoint, {
131125
headers: service.headers,
132-
[body]: options,
133126
});
134127

135-
return service.requester.post(requestOptions);
128+
try {
129+
switch (type) {
130+
case 'get':
131+
if (stream) return await getStream(service, endpoint, options);
132+
return await getPaginated(service, endpoint, options);
133+
case 'post': {
134+
const body = form ? 'formData' : 'body';
135+
requestOptions[body] = options;
136+
return await service.requester.post(requestOptions);
137+
}
138+
case 'put':
139+
requestOptions.body = options;
140+
return await service.requester.put(requestOptions);
141+
case 'delete':
142+
requestOptions.qs = options;
143+
return await service.requester.delete(requestOptions);
144+
default:
145+
throw new Error(`Unknown request type ${type}`);
146+
}
147+
} catch (err) {
148+
await RequestHelper.handleRequestError(err);
149+
return RequestHelper.request(type, service, endpoint, options, form, stream);
150+
}
136151
}
137152

138-
static put(service, endpoint, options = {}) {
139-
const requestOptions = defaultRequest(service, endpoint, {
140-
headers: service.headers,
141-
body: options,
142-
});
153+
static post(service, endpoint, options = {}, form = false) {
154+
return RequestHelper.request('post', service, endpoint, options, form);
155+
}
143156

144-
return service.requester.put(requestOptions);
157+
static put(service, endpoint, options = {}) {
158+
return RequestHelper.request('put', service, endpoint, options);
145159
}
146160

147161
static delete(service, endpoint, options = {}) {
148-
const requestOptions = defaultRequest(service, endpoint, {
149-
headers: service.headers,
150-
qs: options,
151-
});
152-
153-
return service.requester.delete(requestOptions);
162+
return RequestHelper.request('delete', service, endpoint, options);
154163
}
155164
}
156165

0 commit comments

Comments
 (0)