I'm trying to write a mobile app via Capacitor that makes use of PouchDB. When I run the app in the emulator via Android Studio the connection to the remote CouchDB instance fails. I've tracked this down to a failure in the fetch
API for certain URLs when running on Android.
To debug I made a minimal web application and wrapped it using Capacitor to run on Android. The app includes the following code
const testFetch = (url) => {
console.log("Testing fetch", url)
fetch(url)
.then((response) => response.text())
.then((t) => {
console.log("Respose from fetch:", url)
console.log(t)
console.log("that was it")
})
.catch((reason) => {
console.log("FETCH FAILED", url, reason)
})
}
I then have three tests:
testFetch("https://jsonplaceholder.typicode.com/todos/1"); // just some JSON
testFetch("http://10.0.2.2:5984/simple"); // local pouchdb instance
testFetch("http://10.0.2.2:8080/sample.json"); // local http server + CORS
The second two use the IP address that is an alias for the development machine when running in the Android emulator. I confirmed that I can access all of these URLs from the browser on the emulator but the app succeeds on the first and fails on the second two (error: TypeError: Failed to fetch
). When running the base web app in the browser, all succeed (with localhost instead of 10.0.2.2).
CORS headers are in place on all URLs. As far as I can see the app doesn't even try to access the two servers that fail - no HEAD requests for example. I've also tried various other URLs and can't see a pattern to the failures -- eg. it's not the port number != 80.
Any clues as to what is going on would be appreciated.
So the thing I didn't notice that the failing URLs had in common was http rather than https. It turns out that fetch
silently fails to work for any http URL, just giving the error 'Failed to fetch'.
I'm not sure whether this is a feature of the Android web view or of Capacitor itself. The Capacitor docs suggest that using https
is a good idea but not that http
won't work.
This policy doesn't get altered by setting a Content Security Policy in the main page header.
The original goal was to connect a local PouchDB database to a remote CouchDB instance. This now works as long as the CouchDB instance is served via https
. Without that you just get silent failure to sync.