client/services/http-service.js (77 lines of code) (raw):
// Copyright (c) 2021-2024 Uber Technologies Inc.
//
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import { getQueryStringFromObject } from '~helpers';
const DEFAULT_FETCH_OPTIONS = {
credentials: 'same-origin',
headers: {
Accept: 'application/json',
},
};
class HttpService {
constructor() {
this.origin = window.location.origin;
}
handleResponse(response) {
return response.status >= 200 && response.status < 300
? response.json().catch(() => {})
: response.json().then(
json => Promise.reject(Object.assign(response, { json })),
() => Promise.reject(response)
);
}
async request(baseUrl, { query, ...options } = {}) {
const { origin } = this;
const fetch = this.fetchOverride ? this.fetchOverride : window.fetch;
const queryString = getQueryStringFromObject(query);
const path = queryString ? `${baseUrl}${queryString}` : baseUrl;
const hasOrigin = baseUrl.startsWith('http');
const url = hasOrigin ? path : `${origin}${path}`;
const isCrossOrigin = !url.startsWith(window.location.origin);
const requestOptions = {
...DEFAULT_FETCH_OPTIONS,
...options,
...(isCrossOrigin && {
credentials: 'include',
mode: 'cors',
}),
};
return fetch(url, requestOptions).then(this.handleResponse);
}
requestWithBody(url, body, options = {}) {
return this.request(url, {
...options,
body: JSON.stringify(body),
headers: {
...options.headers,
...(body && { 'Content-Type': 'application/json' }),
},
});
}
delete(url, body, options = {}) {
return this.requestWithBody(url, body, {
...options,
method: 'delete',
});
}
get(url, options = {}) {
return this.request(url, { ...options, method: 'get' });
}
post(url, body, options = {}) {
return this.requestWithBody(url, body, {
...options,
method: 'post',
});
}
put(url, body, options = {}) {
return this.requestWithBody(url, body, {
...options,
method: 'put',
});
}
setFetch(fetch) {
this.fetchOverride = fetch;
}
setOrigin(origin) {
this.origin = origin;
}
}
const httpService = new HttpService();
export default httpService;