fix: pre-fetch bincio wheel via RN networking to avoid ATS blocking HTTP in WKWebView
WKWebView blocks HTTP requests (ATS) even when NSAllowsLocalNetworking is set for the app's own networking — so fetch(http://192.168.x.x/api/wheel/download) inside the WebView always fails with 'Load failed' on iOS. - extractActivity.ts: rename wheelUrl param to wheelBase64; WebView now receives the wheel as pre-fetched base64 bytes rather than a URL to fetch itself - PyodideWebView.tsx: decode wheelBase64 → Uint8Array → Blob → blob URL for micropip.install; fix baseUrl '' → 'https://localhost' (null origin blocks fetch on iOS) - import.tsx: add fetchWheelBase64() that resolves the wheel URL via /api/wheel/version then fetches with native networking (HTTP works); caches result in memory so repeated imports in one session don't re-download
This commit is contained in:
@@ -87,10 +87,10 @@ var initError = null;
|
||||
})();
|
||||
|
||||
window._bincioExtract = async function(params) {
|
||||
var reqId = params.reqId;
|
||||
var filename = params.filename;
|
||||
var base64 = params.base64;
|
||||
var wheelUrl = params.wheelUrl;
|
||||
var reqId = params.reqId;
|
||||
var filename = params.filename;
|
||||
var base64 = params.base64;
|
||||
var wheelBase64 = params.wheelBase64; // pre-fetched by React Native (avoids ATS/HTTP issues)
|
||||
|
||||
function post(m) { _post(Object.assign({}, m, { reqId: reqId })); }
|
||||
|
||||
@@ -108,13 +108,14 @@ window._bincioExtract = async function(params) {
|
||||
}
|
||||
if (initError) throw new Error(initError);
|
||||
|
||||
// Install bincio wheel on first extraction (lazy: keeps startup fast)
|
||||
// Install bincio wheel on first extraction.
|
||||
// Wheel bytes arrive pre-fetched from the React Native side as base64,
|
||||
// so the WebView never needs to make an HTTP request (avoids ATS blocks).
|
||||
if (!wheelReady) {
|
||||
post({ type: 'progress', msg: 'Loading Bincio…' });
|
||||
var resp = await fetch(wheelUrl);
|
||||
if (!resp.ok) throw new Error('Failed to fetch Bincio wheel (' + resp.status + ')');
|
||||
var wheelBlob = new Blob([await resp.arrayBuffer()]);
|
||||
var blobUrl = URL.createObjectURL(wheelBlob);
|
||||
var wheelBytes = Uint8Array.from(atob(wheelBase64), function(c) { return c.charCodeAt(0); });
|
||||
var wheelBlob = new Blob([wheelBytes]);
|
||||
var blobUrl = URL.createObjectURL(wheelBlob);
|
||||
pyodide.globals.set('_blobUrl', blobUrl);
|
||||
await pyodide.runPythonAsync(_PY_INSTALL_WHEEL);
|
||||
URL.revokeObjectURL(blobUrl);
|
||||
@@ -158,7 +159,7 @@ export function PyodideWebView() {
|
||||
return (
|
||||
<WebView
|
||||
ref={pyodideRef}
|
||||
source={{ html: PYODIDE_HTML, baseUrl: '' }}
|
||||
source={{ html: PYODIDE_HTML, baseUrl: 'https://localhost' }}
|
||||
style={styles.hidden}
|
||||
onMessage={handleWebViewMessage}
|
||||
javaScriptEnabled
|
||||
|
||||
@@ -54,10 +54,12 @@ export function handleWebViewMessage(e: WebViewMessageEvent): void {
|
||||
}
|
||||
}
|
||||
|
||||
// wheelBase64 is the bincio .whl file pre-fetched by the React Native side
|
||||
// (native networking supports HTTP on local network; WKWebView does not).
|
||||
export function extractFile(
|
||||
filename: string,
|
||||
base64: string,
|
||||
wheelUrl: string,
|
||||
wheelBase64: string,
|
||||
onStatus: (msg: string) => void = () => {},
|
||||
): Promise<ExtractionResult> {
|
||||
if (isExtracting) return Promise.reject(new Error('Another extraction is already in progress'));
|
||||
@@ -67,7 +69,7 @@ export function extractFile(
|
||||
|
||||
isExtracting = true;
|
||||
const reqId = String(++reqCounter);
|
||||
const args = JSON.stringify({ reqId, filename, base64, wheelUrl });
|
||||
const args = JSON.stringify({ reqId, filename, base64, wheelBase64 });
|
||||
|
||||
return new Promise<ExtractionResult>((resolve, reject) => {
|
||||
pending.set(reqId, {
|
||||
|
||||
Reference in New Issue
Block a user