+/**
+ * Perform a HTTP GET request.
+ * Can easily pass query parameters as the second parameter.
+ * @param {String} url
+ * @param {Object} params
+ * @returns {Promise<{headers: Headers, original: Response, data: (Object|String), redirected: boolean, statusText: string, url: string, status: number}>}
+ */
+async function get(url, params = {}) {
+ return request(url, {
+ method: 'GET',
+ params,
+ });
+}
+
+/**
+ * Perform a HTTP POST request.
+ * @param {String} url
+ * @param {Object} data
+ * @returns {Promise<{headers: Headers, original: Response, data: (Object|String), redirected: boolean, statusText: string, url: string, status: number}>}
+ */
+async function post(url, data = null) {
+ return dataRequest('POST', url, data);
+}
+
+/**
+ * Perform a HTTP PUT request.
+ * @param {String} url
+ * @param {Object} data
+ * @returns {Promise<{headers: Headers, original: Response, data: (Object|String), redirected: boolean, statusText: string, url: string, status: number}>}
+ */
+async function put(url, data = null) {
+ return dataRequest('PUT', url, data);
+}
+
+/**
+ * Perform a HTTP PATCH request.
+ * @param {String} url
+ * @param {Object} data
+ * @returns {Promise<{headers: Headers, original: Response, data: (Object|String), redirected: boolean, statusText: string, url: string, status: number}>}
+ */
+async function patch(url, data = null) {
+ return dataRequest('PATCH', url, data);
+}
+
+/**
+ * Perform a HTTP DELETE request.
+ * @param {String} url
+ * @param {Object} data
+ * @returns {Promise<{headers: Headers, original: Response, data: (Object|String), redirected: boolean, statusText: string, url: string, status: number}>}
+ */
+async function performDelete(url, data = null) {
+ return dataRequest('DELETE', url, data);
+}
+
+/**
+ * Perform a HTTP request to the back-end that includes data in the body.
+ * Parses the body to JSON if an object, setting the correct headers.
+ * @param {String} method
+ * @param {String} url
+ * @param {Object} data
+ * @returns {Promise<{headers: Headers, original: Response, data: (Object|String), redirected: boolean, statusText: string, url: string, status: number}>}
+ */
+async function dataRequest(method, url, data = null) {
+ const options = {
+ method: method,
+ body: data,
+ };
+
+ if (typeof data === 'object') {
+ options.headers = {'Content-Type': 'application/json'};
+ options.body = JSON.stringify(data);
+ }
+
+ return request(url, options)
+}
+
+/**
+ * Create a new HTTP request, setting the required CSRF information
+ * to communicate with the back-end. Parses & formats the response.
+ * @param {String} url
+ * @param {Object} options
+ * @returns {Promise<{headers: Headers, original: Response, data: (Object|String), redirected: boolean, statusText: string, url: string, status: number}>}
+ */
+async function request(url, options = {}) {
+ if (!url.startsWith('http')) {
+ url = window.baseUrl(url);
+ }
+
+ if (options.params) {
+ const urlObj = new URL(url);
+ for (let paramName of Object.keys(options.params)) {
+ const value = options.params[paramName];
+ if (typeof value !== 'undefined' && value !== null) {
+ urlObj.searchParams.set(paramName, value);
+ }