安卓端curl请求localhost正常但Java/Kotlin调用返回503错误
问题现象
- 安卓设备本地localhost部署了API服务,通过
adb shell进入设备执行curl命令请求接口可正常响应 - 同设备上使用Java/Kotlin代码发起完全相同的请求时,服务端返回503状态码,附带Squid代理生成的HTML格式错误页面
测试使用的curl命令如下:
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":67}' http://127.0.0.1:8545
错误页面截图:
根因分析
从错误页的标识信息可以直接定位问题:
- 错误页明确标注由
squid/4.4生成,生成主机为lxasmap001.at.inside,记录的客户端IP为内网网段地址10.52.113.145,说明请求根本没有在安卓设备本地走回环网络,而是被转发到了网络上的Squid代理服务器。 - adb shell中执行curl时,默认不读取安卓系统的全局代理配置,请求直接访问设备本地的127.0.0.1:8545,因此可以正常拿到响应。
- Java/Kotlin的网络请求默认会继承系统的代理配置(通常是当前连接WiFi下手动设置的HTTP代理,多为企业内网的Squid缓存代理),请求发往Squid服务器后,代理服务器尝试访问自身的127.0.0.1:8545端口,自然找不到对应服务,最终返回「Connection refused」的503错误。
解决方法
- 方案1(推荐):本地请求强制绕过系统代理
发起本地回环地址请求时明确指定直连,不走任何代理,对其他正常业务请求无影响。
若使用原生HttpURLConnection,在建立连接前添加配置即可:
若使用OkHttp框架,初始化客户端时自定义代理选择器,仅对本地地址走直连:val url = URL("http://127.0.0.1:8545") val connection = url.openConnection(Proxy.NO_PROXY) as HttpURLConnection // 后续正常设置请求方法、请求体即可val client = OkHttpClient.Builder() .proxySelector(object : ProxySelector() { private val defaultSelector = getDefault() override fun select(uri: URI?): MutableList<Proxy> { val host = uri?.host // 访问本地回环地址时强制直连 return if (host == "127.0.0.1" || host == "localhost") { mutableListOf(Proxy.NO_PROXY) } else { defaultSelector.select(uri) } } override fun connectFailed(uri: URI?, sa: SocketAddress?, ioe: IOException?) { defaultSelector.connectFailed(uri, sa, ioe) } }) .build() - 方案2:临时关闭系统代理
进入安卓设备WLAN设置,找到当前连接的WiFi,将代理配置修改为「无」,所有请求将不再经过Squid代理。注意:如果当前网络环境必须通过代理才能访问外网,该方法会导致其他正常网络请求失败,仅适合临时调试使用。 - 方案3:改用设备局域网IP访问
先查看安卓设备在当前局域网下的实际IP(通常是192.168.x.x网段),同时确认本地部署的API服务绑定到0.0.0.0地址(而非仅绑定127.0.0.1),后续请求使用http://<设备局域网IP>:8545作为目标地址即可。该方法不需要修改代理配置,但会将本地服务暴露到局域网,存在安全风险,仅适合受控调试环境使用。
内容的提问来源于stack exchange,提问作者Markusbug
相关产品推荐
相关产品推荐

