WIP because: - [x] Some calls set a `content-type` but send no body, can likely remove the header - [x] Need to check whether `charset=utf-8` has any significance on the webauthn calls, I assume not as it is the default for json content. - [x] Maybe `no-restricted-globals` is better for eslint, but will require a lot of duplication in the yaml or moving eslint config to a `.js` extension. - [x] Maybe export `request` as `fetch`, shadowing the global.
Showing the changes to web_src/js/modules (1 of 17 files). Show all
Unified · Split
| @@ -2,17 +2,18 @@ import {isObject} from '../utils.js'; · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | const {csrfToken} = window.config; |
| 4 | 4 | |
| 5 | +// safe HTTP methods that don't need a csrf token | |
| 6 | +const safeMethods = new Set(['GET', 'HEAD', 'OPTIONS', 'TRACE']); | |
| 7 | + | |
| 5 | 8 | // fetch wrapper, use below method name functions and the `data` option to pass in data |
| 6 | −// which will automatically set an appropriate content-type header. For json content, | |
| 7 | −// only object and array types are currently supported. | |
| 8 | −function request(url, {headers, data, body, ...other} = {}) { | |
| 9 | +// which will automatically set an appropriate headers. For json content, only object | |
| 10 | +// and array types are currently supported. | |
| 11 | +export function request(url, {method = 'GET', headers = {}, data, body, ...other} = {}) { | |
| 9 | 12 | let contentType; |
| 10 | 13 | if (!body) { |
| 11 | 14 | if (data instanceof FormData) { |
| 12 | − contentType = 'multipart/form-data'; | |
| 13 | 15 | body = data; |
| 14 | 16 | } else if (data instanceof URLSearchParams) { |
| 15 | − contentType = 'application/x-www-form-urlencoded'; | |
| 16 | 17 | body = data; |
| 17 | 18 | } else if (isObject(data) || Array.isArray(data)) { |
| 18 | 19 | contentType = 'application/json'; |
| @@ -20,12 +21,18 @@ function request(url, {headers, data, body, ...other} = {}) { · 1 unmodified line | ||
| 20 | 21 | } |
| 21 | 22 | } |
| 22 | 23 | |
| 24 | + const headersMerged = new Headers({ | |
| 25 | + ...(!safeMethods.has(method.toUpperCase()) && {'x-csrf-token': csrfToken}), | |
| 26 | + ...(contentType && {'content-type': contentType}), | |
| 27 | + }); | |
| 28 | + | |
| 29 | + for (const [name, value] of Object.entries(headers)) { | |
| 30 | + headersMerged.set(name, value); | |
| 31 | + } | |
| 32 | + | |
| 23 | 33 | return fetch(url, { |
| 24 | − headers: { | |
| 25 | − 'x-csrf-token': csrfToken, | |
| 26 | − ...(contentType && {'content-type': contentType}), | |
| 27 | − ...headers, | |
| 28 | − }, | |
| 34 | + method, | |
| 35 | + headers: headersMerged, | |
| 29 | 36 | ...(body && {body}), |
| 30 | 37 | ...other, |
| 31 | 38 | }); |