Download app/src/browser-http.mjs from Mike0021/MiniCPM5-2B-WebGPU-Pi-HTTP: direct link, hf CLI and curl.
- Browser
- Download file 3.54 kB
-
https://huggingface.co/spaces/Mike0021/MiniCPM5-2B-WebGPU-Pi-HTTP/resolve/main/app/src/browser-http.mjs
- Command line
-
hf download hf://spaces/Mike0021/MiniCPM5-2B-WebGPU-Pi-HTTP/app/src/browser-http.mjs
-
curl -L -o browser-http.mjs https://huggingface.co/spaces/Mike0021/MiniCPM5-2B-WebGPU-Pi-HTTP/resolve/main/app/src/browser-http.mjs
3.54 kB
| // just-bash's curl uses this browser transport. There is no proxy/server. | |
| export const HTTP_METHODS = Object.freeze(['GET', 'HEAD', 'POST']); | |
| export const HTTP_LIMIT = 1024 * 1024; | |
| export const HTTP_TIMEOUT = 8_000; | |
| export function createBrowserFetch({ transport = globalThis.fetch, | |
| timeoutMs = HTTP_TIMEOUT, maxBytes = HTTP_LIMIT } = {}) { | |
| return async (input, options = {}) => { | |
| const url = new URL(input); | |
| if (url.protocol !== 'https:') throw Error('Only HTTPS URLs are supported. Use https:// instead.'); | |
| if (url.username || url.password) throw Error('Credentials in URLs are unsupported. Use an explicit Authorization header if needed.'); | |
| const method = (options.method ?? 'GET').toUpperCase(); | |
| if (!HTTP_METHODS.includes(method)) throw Error(`HTTP method ${method} is not enabled. Use GET, HEAD, or POST.`); | |
| const requestedTimeout = options.timeoutMs > 0 ? options.timeoutMs : timeoutMs; | |
| const controller = new AbortController(); | |
| const deadline = Math.min(requestedTimeout, timeoutMs); | |
| const timer = setTimeout(() => controller.abort(new DOMException(`HTTP request timed out after ${deadline} ms.`, 'TimeoutError')), deadline); | |
| const signal = options.signal ? AbortSignal.any([options.signal, controller.signal]) : controller.signal; | |
| let reader; | |
| try { | |
| signal.throwIfAborted(); | |
| const response = await transport(url.href, { method, headers: options.headers, | |
| body: ['GET', 'HEAD'].includes(method) ? undefined : options.body, | |
| mode: 'cors', credentials: 'omit', redirect: 'manual', referrerPolicy: 'no-referrer', signal }); | |
| // Browsers hide both the Location header and status on manual redirects. | |
| // Following automatically would skip the HTTPS check at intermediate hops. | |
| if (response.type === 'opaqueredirect' || (response.status >= 300 && response.status < 400 && response.status !== 304)) { | |
| throw Error('HTTP redirect cannot be followed safely in this browser shell. Use the final HTTPS URL directly (including exact capitalization).'); | |
| } | |
| if (response.status === 0 || response.type === 'opaque') throw Error('HTTP response is unreadable. The destination must allow browser access with CORS.'); | |
| if (method !== 'HEAD' && Number(response.headers.get('content-length')) > maxBytes) { | |
| await response.body?.cancel(); | |
| throw Error(`HTTP response exceeds the ${maxBytes}-byte limit.`); | |
| } | |
| const chunks = []; let size = 0; | |
| if (response.body) { | |
| reader = response.body.getReader(); | |
| while (true) { | |
| const { done, value } = await reader.read(); | |
| signal.throwIfAborted(); | |
| if (done) break; | |
| size += value.byteLength; | |
| if (size > maxBytes) { await reader.cancel(); throw Error(`HTTP response exceeds the ${maxBytes}-byte limit.`); } | |
| chunks.push(value); | |
| } | |
| } | |
| const body = new Uint8Array(size); let offset = 0; | |
| for (const chunk of chunks) { body.set(chunk, offset); offset += chunk.byteLength; } | |
| return { status: response.status, statusText: response.statusText, | |
| headers: Object.fromEntries(response.headers.entries()), body, url: response.url || url.href }; | |
| } catch (error) { | |
| if (signal.aborted) throw signal.reason; | |
| if (error instanceof TypeError) throw Error('HTTP request failed: the server may block browser requests (CORS), or the connection failed. No proxy is used.'); | |
| throw error; | |
| } finally { clearTimeout(timer); reader?.releaseLock(); } | |
| }; | |
| } | |