Local file webview and CORS

Hello. I’m loading a local HTML file using file:// source in a webview. The file loads fine, but scripts in the file fail to request external URLs (API responses and fonts) with

Access to XMLHttpRequest at 'https://[redacted]' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I can’t find any WebView prop to ignore CORS rendering file:// pages:

  • allowFileAccess={true} nor mixedContentMode='always' change anything
  • onShouldStartLoadWithRequest doesn’t seem like a relevant prop

Am I missing something? What’s an expected handling of CORS/HTTP requests from a file:// in a webview?

WebView code:

<View style={styles.container}>
	<WebView
		// headers: {},
		ref={webRef}
		source={{
			uri: 'file:///pkg/assets/webview/index.html',
		}}
		hasTVPreferredFocus={true}
		javaScriptEnabled={true}
		domStorageEnabled={true}
		allowSystemKeyEvents={true}
		mediaPlaybackRequiresUserAction={false}
		thirdPartyCookiesEnabled={true}
		allowFileAccess={true}
		onLoadStart={(event) => {
			console.log('onLoadStart url: ', event.nativeEvent.url);
		}}
		onLoad={(event) => {
			console.log('onLoad url: ', event.nativeEvent.url);
		}}
		onError={(event) => {
			console.log('onError url: ', event.nativeEvent.url);
		}}
	/>
</View>

App Name: Not yet submitted
App Link on Amazon Appstore (found through Developer Console > Actions column in App List > View on Amazon.com): Not yet submitted

Hi @zemlanin,

Welcome to Amazon Developer Community!!

Thank you for your question about CORS and local file loading in WebView.

This is a known limitation with file:// protocol in WebView - the browser treats the origin as null, which causes CORS blocking.

Could you try out these workarounds and let us know if they work?

  1. Message Bridge approach - Make HTTP requests from your React Native layer and pass data to the WebView using the message bridge pattern

  2. Local HTTP server - Serve your HTML through http://localhost instead of file://

  3. Bundle resources locally - For fonts and static assets, include them in /pkg/assets/ with relative paths

Our team is looking into this limitation and will provide an update as soon as we have more information.

Getting Started:

Thanks for helping us improve the Vega platform.

Warm regards,
Aishwarya

Thank you for a quick response!

We probably could make that work, although it won’t be trivial. Pages in the WebView are already used on other platforms and make requests predominantly through @tanstack/query and I can see only two approaches of using a bridge:

  • RN makes requests on its own (based on WebView’s URL) and pushes the data into query’s cache
    • A lot of duplication and tight coupling between RN and WebView’s contents
  • Replace WebView’s API calls (XHR via axios and HLS.js) with postMessage+onMessage (+injectJavaScript?)
    • Maintaining the same Promise-based API when multiple in-flight requests would be a challenge
    • Won’t help with the fonts, but that’s minor as we indeed could keep using bundled fonts (instead of overwriting them with the latest remote version)

That would require (production) API endpoints to accept localhost requests, which I’m hesitant about. Although that localhost server could probably also be a proxy for API requests?..

All and all, the approach seems the most promising but wasteful (but maybe it’s common in RN ecosystem? Vega is the first time I’m dabbling in RN)

Won’t work for API requests…

For now, going to load a remote URL as the initial WebView’s source

If it fails to load, I’ll be changing the source to a bundled (file://) error page URL that doesn’t do any API requests