ERR_CONNECTION_REFUSED despite access origin=* and correct content-secutiy-policy
Closed this issue · 2 comments
Bug Report
Problem
No matter what I do, I get net::ERR_CONNECTION_REFUSED
when making a fetch()
call to a domain running on http://localhost:8002
What is expected to happen?
fetch('http://localhost:8002') .then(response => { return response.text() }).then(response => alert(response));
should alert hello world
What does actually happen?
I get an error Failed to load resource: net::ERR_CONNECTION_REFUSED
Information
Command or Code
index.html
<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<html>
<head>
<meta charset="utf-8">
<!--
Customize this policy to fit your own app's needs. For more guidance, please refer to the docs:
https://cordova.apache.org/docs/en/latest/
Some notes:
* https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
* Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
* Enable inline JS: add 'unsafe-inline' to default-src
-->
<meta http-equiv="Content-Security-Policy" content="default-src 'self' http://localhost:8002 data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
<meta name="color-scheme" content="light dark">
<link rel="stylesheet" href="css/index.css">
<title>Hello World</title>
</head>
<body>
<div class="app">
<h1>Apache Cordova</h1>
<div id="deviceready" class="blink">
<p class="event listening">Connecting to Device</p>
<p class="event received">Device is Ready</p>
</div>
</div>
<script src="cordova.js"></script>
<script src="js/index.js"></script>
</body>
</html>
index.js
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// Wait for the deviceready event before using any of Cordova's device APIs.
// See https://cordova.apache.org/docs/en/latest/cordova/events/events.html#deviceready
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady() {
// Cordova is now initialized. Have fun!
console.log('Running cordova-' + cordova.platformId + '@' + cordova.version);
document.getElementById('deviceready').classList.add('ready');
fetch('http://localhost:8002')
.then(response => {
return response.text()
}).then(response => alert(response));
}
config.xml
<?xml version='1.0' encoding='utf-8'?>
<!-- <widget id="io.cordova.hellocordova" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:android="http://schemas.android.com/apk/res/android" > -->
<widget id="com.onegini.ExampleAppCordova" version="8.1.0" xmlns="http://www.w3.org/ns/widgets" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<name>HelloCordova</name>
<description>Sample Apache Cordova App</description>
<author email="dev@cordova.apache.org" href="https://cordova.apache.org">
Apache Cordova Team
</author>
<content src="index.html" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<plugin name="cordova-plugin-whitelist" spec="1" />
<access origin="*" />
<!-- -->
<platform name="android">
<access origin="*" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<preference name="android-minSdkVersion" value="23" />
<!-- Necessary to make sure that the deep app linking works properly -->
<preference name="AndroidLaunchMode" value="singleTask" />
<!-- <preference name="hostname" value="localhost" />
<preference name="AndroidInsecureFileModeEnabled" value="true" /> -->
<edit-config file="AndroidManifest.xml" target="/manifest" mode="merge">
<manifest xmlns:tools="http://schemas.android.com/tools" />
</edit-config>
<edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application">
<application android:usesCleartextTraffic="true" />
</edit-config>
<plugin name="cordova-plugin-whitelist" spec="1" />
<!-- <resource-file src="google-services.json" target="app/google-services.json" /> -->
</platform>
<!-- -->
</widget>
Environment, Platform, Device
package.json
{
"name": "io.cordova.hellocordova",
"displayName": "HelloCordova",
"version": "1.0.0",
"description": "A sample Apache Cordova application that responds to the deviceready event.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"ecosystem:cordova"
],
"author": "Apache Cordova Team",
"license": "Apache-2.0",
"devDependencies": {
"cordova-android": "^10.1.2",
"cordova-browser": "^6.0.0",
"cordova-plugin-whitelist": "1"
},
"cordova": {
"platforms": [
"browser",
"android"
],
"plugins": {
"cordova-plugin-whitelist": {}
}
}
}
- The command I'm using:
cordova run android
It returnsCONNECTION_REFUSED
forcordova_plugins.js
as well, it's not really the issue as far as I know but I feel like it might give insight.
Version information
- Output from
cordova -version
: 11.0.0 - Operating System: Ubuntu 20.04.5
- No other frameworks
- The only plugin I'm using would be
cordova-plugin-whitelist
but as I understand it's been integrated
Checklist
- I searched for existing GitHub issues
- I updated all Cordova tooling to most recent version
- I included all the necessary information above
Things I've Tried
- Running
cordova prepare android
followed bycordova build android
followed bycordova run android
- Replacing localhost with my private IP address and placing the API at the doc root
- Running on browser platform which functions as it should and alerts "hello world" without any connection refused errors
- Using the following two lines inside the android platform config
<preference name="hostname" value="localhost" /> <preference name="AndroidInsecureFileModeEnabled" value="true" />
- Several different
cordova-android
versions
I ended up fixing this, part of the problem was that because the app was launched with https, I couldn't access localhost as it was only capable of http so I installed an ssl cert and also used https://10.0.0.2
which on android emulators directs to the hosts doc root and it seems to be working now.
Just for context, Android emulators are full virtual machines with their own virtual network stack. Therefore localhost
will resolve to itself, the virtual machine, rather than the host machine. Physical devices will work the same way.
Additionally, if you're using schemes via <preference name="hostname" value="localhost" />
then the webview will (in simple terms) intercept http://localhost
or (https://localhost
if scheme
is set to https
) and remap urls to load from the local file system. It somewhat behaves like a virtual webserver that only the process itself can have access to.
That is why changing the url to use a private IP https://10.0.0.2
works. On mac/linux, you can look up your private ip using the ifconfig
command, most home networks uses a 192.168.x.x
ip scheme