]> BookStack Code Mirror - bookstack/blob - resources/js/services/http.js
added additional color settings into UI
[bookstack] / resources / js / services / http.js
1
2 /**
3  * Perform a HTTP GET request.
4  * Can easily pass query parameters as the second parameter.
5  * @param {String} url
6  * @param {Object} params
7  * @returns {Promise<{headers: Headers, original: Response, data: (Object|String), redirected: boolean, statusText: string, url: string, status: number}>}
8  */
9 async function get(url, params = {}) {
10     return request(url, {
11         method: 'GET',
12         params,
13     });
14 }
15
16 /**
17  * Perform a HTTP POST request.
18  * @param {String} url
19  * @param {Object} data
20  * @returns {Promise<{headers: Headers, original: Response, data: (Object|String), redirected: boolean, statusText: string, url: string, status: number}>}
21  */
22 async function post(url, data = null) {
23     return dataRequest('POST', url, data);
24 }
25
26 /**
27  * Perform a HTTP PUT request.
28  * @param {String} url
29  * @param {Object} data
30  * @returns {Promise<{headers: Headers, original: Response, data: (Object|String), redirected: boolean, statusText: string, url: string, status: number}>}
31  */
32 async function put(url, data = null) {
33     return dataRequest('PUT', url, data);
34 }
35
36 /**
37  * Perform a HTTP PATCH request.
38  * @param {String} url
39  * @param {Object} data
40  * @returns {Promise<{headers: Headers, original: Response, data: (Object|String), redirected: boolean, statusText: string, url: string, status: number}>}
41  */
42 async function patch(url, data = null) {
43     return dataRequest('PATCH', url, data);
44 }
45
46 /**
47  * Perform a HTTP DELETE request.
48  * @param {String} url
49  * @param {Object} data
50  * @returns {Promise<{headers: Headers, original: Response, data: (Object|String), redirected: boolean, statusText: string, url: string, status: number}>}
51  */
52 async function performDelete(url, data = null) {
53     return dataRequest('DELETE', url, data);
54 }
55
56 /**
57  * Perform a HTTP request to the back-end that includes data in the body.
58  * Parses the body to JSON if an object, setting the correct headers.
59  * @param {String} method
60  * @param {String} url
61  * @param {Object} data
62  * @returns {Promise<{headers: Headers, original: Response, data: (Object|String), redirected: boolean, statusText: string, url: string, status: number}>}
63  */
64 async function dataRequest(method, url, data = null) {
65     const options = {
66         method: method,
67         body: data,
68     };
69
70     if (typeof data === 'object' && !(data instanceof FormData)) {
71         options.headers = {'Content-Type': 'application/json'};
72         options.body = JSON.stringify(data);
73     }
74
75     return request(url, options)
76 }
77
78 /**
79  * Create a new HTTP request, setting the required CSRF information
80  * to communicate with the back-end. Parses & formats the response.
81  * @param {String} url
82  * @param {Object} options
83  * @returns {Promise<{headers: Headers, original: Response, data: (Object|String), redirected: boolean, statusText: string, url: string, status: number}>}
84  */
85 async function request(url, options = {}) {
86     if (!url.startsWith('http')) {
87         url = window.baseUrl(url);
88     }
89
90     if (options.params) {
91         const urlObj = new URL(url);
92         for (let paramName of Object.keys(options.params)) {
93             const value = options.params[paramName];
94             if (typeof value !== 'undefined' && value !== null) {
95                 urlObj.searchParams.set(paramName, value);
96             }
97         }
98         url = urlObj.toString();
99     }
100
101     const csrfToken = document.querySelector('meta[name=token]').getAttribute('content');
102     options = Object.assign({}, options, {
103         'credentials': 'same-origin',
104     });
105     options.headers = Object.assign({}, options.headers || {}, {
106         'baseURL': window.baseUrl(''),
107         'X-CSRF-TOKEN': csrfToken,
108     });
109
110     const response = await fetch(url, options);
111     const content = await getResponseContent(response);
112     return {
113         data: content,
114         headers: response.headers,
115         redirected: response.redirected,
116         status: response.status,
117         statusText: response.statusText,
118         url: response.url,
119         original: response,
120     }
121 }
122
123 /**
124  * Get the content from a fetch response.
125  * Checks the content-type header to determine the format.
126  * @param response
127  * @returns {Promise<Object|String>}
128  */
129 async function getResponseContent(response) {
130     const responseContentType = response.headers.get('Content-Type');
131     const subType = responseContentType.split('/').pop();
132
133     if (subType === 'javascript' || subType === 'json') {
134         return await response.json();
135     }
136
137     return await response.text();
138 }
139
140 export default {
141     get: get,
142     post: post,
143     put: put,
144     patch: patch,
145     delete: performDelete,
146 };