(url, options = {})
| 331 | * @return {Promise<VMReq.Response>} |
| 332 | */ |
| 333 | export async function request(url, options = {}) { |
| 334 | // fetch supports file:// since Chrome 99 but we use XHR for consistency |
| 335 | if (url.startsWith('file:')) return requestLocalFile(url, options); |
| 336 | const { body, headers, [kResponseType]: responseType } = options; |
| 337 | const isBodyObj = body && body::({}).toString() === '[object Object]'; |
| 338 | const [, scheme, auth, hostname, urlTail] = url.match(/^([-\w]+:\/\/)([^@/]*@)?([^/]*)(.*)|$/); |
| 339 | // Avoiding LINK header prefetch of js in 404 pages which cause CSP violations in our console |
| 340 | // TODO: toggle a webRequest/declarativeNetRequest rule to strip LINK headers |
| 341 | const accept = (hostname === 'greasyfork.org' || hostname === 'sleazyfork.org') |
| 342 | && 'application/javascript, text/plain, text/css'; |
| 343 | const init = Object.assign({}, !isRemote(url) && NO_CACHE, options, { |
| 344 | body: isBodyObj ? JSON.stringify(body) : body, |
| 345 | headers: isBodyObj || accept || auth |
| 346 | ? Object.assign({}, |
| 347 | headers, |
| 348 | isBodyObj && { 'Content-Type': 'application/json' }, |
| 349 | auth && { Authorization: `Basic ${btoa(decodeURIComponent(auth.slice(0, -1)))}` }, |
| 350 | accept && { accept }) |
| 351 | : headers, |
| 352 | }); |
| 353 | let status = -1; |
| 354 | let result = { url }; |
| 355 | try { |
| 356 | const urlNoAuth = auth ? scheme + hostname + urlTail : url; |
| 357 | const resp = await fetch(urlNoAuth, init); |
| 358 | const loadMethod = { |
| 359 | arraybuffer: 'arrayBuffer', |
| 360 | blob: 'blob', |
| 361 | json: 'json', |
| 362 | }[responseType] || 'text'; |
| 363 | // status for `file:` protocol will always be `0` |
| 364 | status = resp.status || 200; |
| 365 | result.headers = resp.headers; |
| 366 | result.data = await resp[loadMethod](); |
| 367 | } catch (err) { |
| 368 | result = Object.assign(err, result); |
| 369 | result.message += (status > 0 ? ` (HTTP ${status})` : ' (could not connect)') + '\n' + url; |
| 370 | } |
| 371 | result.status = status; |
| 372 | if (status < 0 || status > 300) throw result; |
| 373 | return result; |
| 374 | } |
| 375 | |
| 376 | // Used by `injected` |
| 377 | const SIMPLE_VALUE_TYPE = { |
no test coverage detected