2019-10-19 16:38:07 +02:00
|
|
|
import { contextPath } from './urls';
|
|
|
|
|
import {
|
|
|
|
|
createBackendError,
|
|
|
|
|
ForbiddenError,
|
|
|
|
|
isBackendError,
|
|
|
|
|
UnauthorizedError,
|
|
|
|
|
} from './errors';
|
|
|
|
|
import { BackendErrorContent } from './errors';
|
2018-07-04 16:43:46 +02:00
|
|
|
|
2019-10-19 16:38:07 +02:00
|
|
|
const applyFetchOptions: (p: RequestOptions) => RequestOptions = o => {
|
|
|
|
|
o.credentials = 'same-origin';
|
2019-09-04 14:47:13 +02:00
|
|
|
o.headers = {
|
2019-10-19 16:38:07 +02:00
|
|
|
Cache: 'no-cache',
|
2019-03-12 13:55:34 +01:00
|
|
|
// identify the request as ajax request
|
2019-10-19 16:38:07 +02:00
|
|
|
'X-Requested-With': 'XMLHttpRequest',
|
2019-09-04 14:47:13 +02:00
|
|
|
};
|
|
|
|
|
return o;
|
2018-07-04 16:43:46 +02:00
|
|
|
};
|
|
|
|
|
|
2018-11-15 21:39:08 +01:00
|
|
|
function handleFailure(response: Response) {
|
2018-07-04 16:43:46 +02:00
|
|
|
if (!response.ok) {
|
2018-11-15 21:39:08 +01:00
|
|
|
if (isBackendError(response)) {
|
2019-10-19 16:38:07 +02:00
|
|
|
return response.json().then((content: BackendErrorContent) => {
|
|
|
|
|
throw createBackendError(content, response.status);
|
|
|
|
|
});
|
2018-11-15 21:39:08 +01:00
|
|
|
} else {
|
2019-02-25 17:40:53 +01:00
|
|
|
if (response.status === 401) {
|
2019-10-19 16:38:07 +02:00
|
|
|
throw new UnauthorizedError('Unauthorized', 401);
|
2019-03-04 11:49:12 +01:00
|
|
|
} else if (response.status === 403) {
|
2019-10-19 16:38:07 +02:00
|
|
|
throw new ForbiddenError('Forbidden', 403);
|
2019-02-25 17:40:53 +01:00
|
|
|
}
|
2019-03-04 11:49:12 +01:00
|
|
|
|
2019-10-19 16:38:07 +02:00
|
|
|
throw new Error('server returned status code ' + response.status);
|
2018-07-04 16:43:46 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return response;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-12 08:22:27 +02:00
|
|
|
export function createUrl(url: string) {
|
2019-10-19 16:38:07 +02:00
|
|
|
if (url.includes('://')) {
|
2018-07-11 12:02:53 +02:00
|
|
|
return url;
|
|
|
|
|
}
|
2018-07-12 08:22:27 +02:00
|
|
|
let urlWithStartingSlash = url;
|
2019-10-19 16:38:07 +02:00
|
|
|
if (url.indexOf('/') !== 0) {
|
|
|
|
|
urlWithStartingSlash = '/' + urlWithStartingSlash;
|
2018-07-11 22:01:36 +02:00
|
|
|
}
|
2018-10-01 17:22:03 +02:00
|
|
|
return `${contextPath}/api/v2${urlWithStartingSlash}`;
|
2018-07-04 16:43:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ApiClient {
|
2018-07-11 12:02:53 +02:00
|
|
|
get(url: string): Promise<Response> {
|
2019-09-26 15:42:21 +02:00
|
|
|
return fetch(createUrl(url), applyFetchOptions({})).then(handleFailure);
|
2018-07-04 16:43:46 +02:00
|
|
|
}
|
|
|
|
|
|
2019-10-19 16:38:07 +02:00
|
|
|
post(url: string, payload: any, contentType: string = 'application/json') {
|
|
|
|
|
return this.httpRequestWithJSONBody('POST', url, contentType, payload);
|
2018-07-04 16:43:46 +02:00
|
|
|
}
|
|
|
|
|
|
2019-10-19 16:38:07 +02:00
|
|
|
postBinary(url: string, fileAppender: (p: FormData) => void) {
|
2019-08-29 16:37:57 +02:00
|
|
|
let formData = new FormData();
|
2019-08-30 09:11:14 +02:00
|
|
|
fileAppender(formData);
|
2019-08-29 16:37:57 +02:00
|
|
|
|
|
|
|
|
let options: RequestOptions = {
|
2019-10-19 16:38:07 +02:00
|
|
|
method: 'POST',
|
|
|
|
|
body: formData,
|
2019-08-29 16:37:57 +02:00
|
|
|
};
|
2019-08-30 09:11:14 +02:00
|
|
|
return this.httpRequestWithBinaryBody(options, url);
|
2019-08-29 16:37:57 +02:00
|
|
|
}
|
|
|
|
|
|
2019-10-19 16:38:07 +02:00
|
|
|
put(url: string, payload: any, contentType: string = 'application/json') {
|
|
|
|
|
return this.httpRequestWithJSONBody('PUT', url, contentType, payload);
|
2018-07-11 17:02:38 +02:00
|
|
|
}
|
|
|
|
|
|
2018-10-25 13:45:52 +02:00
|
|
|
head(url: string) {
|
|
|
|
|
let options: RequestOptions = {
|
2019-10-19 16:38:07 +02:00
|
|
|
method: 'HEAD',
|
2018-10-25 13:45:52 +02:00
|
|
|
};
|
2019-09-04 14:47:13 +02:00
|
|
|
options = applyFetchOptions(options);
|
2018-11-15 21:39:08 +01:00
|
|
|
return fetch(createUrl(url), options).then(handleFailure);
|
2018-10-15 16:45:44 +02:00
|
|
|
}
|
|
|
|
|
|
2018-07-11 12:02:53 +02:00
|
|
|
delete(url: string): Promise<Response> {
|
2018-07-04 16:43:46 +02:00
|
|
|
let options: RequestOptions = {
|
2019-10-19 16:38:07 +02:00
|
|
|
method: 'DELETE',
|
2018-07-04 16:43:46 +02:00
|
|
|
};
|
2019-09-04 14:47:13 +02:00
|
|
|
options = applyFetchOptions(options);
|
2018-11-15 21:39:08 +01:00
|
|
|
return fetch(createUrl(url), options).then(handleFailure);
|
2018-07-04 16:43:46 +02:00
|
|
|
}
|
|
|
|
|
|
2018-07-11 12:02:53 +02:00
|
|
|
httpRequestWithJSONBody(
|
2018-07-11 17:02:38 +02:00
|
|
|
method: string,
|
2018-08-03 08:36:16 +02:00
|
|
|
url: string,
|
|
|
|
|
contentType: string,
|
2019-10-19 16:38:07 +02:00
|
|
|
payload: any,
|
2018-07-11 12:02:53 +02:00
|
|
|
): Promise<Response> {
|
2018-07-04 16:43:46 +02:00
|
|
|
let options: RequestOptions = {
|
|
|
|
|
method: method,
|
2019-10-19 16:38:07 +02:00
|
|
|
body: JSON.stringify(payload),
|
2018-07-04 16:43:46 +02:00
|
|
|
};
|
2019-08-30 09:11:14 +02:00
|
|
|
return this.httpRequestWithBinaryBody(options, url, contentType);
|
2019-08-29 16:37:57 +02:00
|
|
|
}
|
|
|
|
|
|
2019-10-19 16:38:07 +02:00
|
|
|
httpRequestWithBinaryBody(
|
|
|
|
|
options: RequestOptions,
|
|
|
|
|
url: string,
|
|
|
|
|
contentType?: string,
|
|
|
|
|
) {
|
2019-09-04 14:47:13 +02:00
|
|
|
options = applyFetchOptions(options);
|
2019-08-30 09:11:14 +02:00
|
|
|
if (contentType) {
|
|
|
|
|
// $FlowFixMe
|
2019-10-19 16:38:07 +02:00
|
|
|
options.headers['Content-Type'] = contentType;
|
2019-08-30 09:11:14 +02:00
|
|
|
}
|
2018-07-04 16:43:46 +02:00
|
|
|
|
2018-11-15 21:39:08 +01:00
|
|
|
return fetch(createUrl(url), options).then(handleFailure);
|
2018-07-04 16:43:46 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export let apiClient = new ApiClient();
|