android http请求时自动设置method为post而不是get的原因

最近发现一个有意思的bug:

明明已经设置了http请求的方式是get,但是实际请求时自动变成了post


debug过程如下:

1、我们先看一下出问题的http设置代码:

public static void loadToken(Context context, checkTokenFinishListener listener) throws Exception {
        HttpURLConnection connection = null;
        try {
            URL url = new URL(getLoadTokenUrl());
            connection = (HttpURLConnection) url.openConnection();
            HttpsURLConnection.setFollowRedirects(false);
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setConnectTimeout(CYFileUploaderByQiniu.getConnTimeout());
            connection.setReadTimeout(CYFileUploaderByQiniu.getReadTimeout());
            //这里明确地设置了http的RequestMethod是GET方式
            connection.setRequestMethod("GET");
            connection.connect();
            //处理请求结果
            ......

可以看到很明显的,设置了这个http请求的方式为GET。那为什么设置了还是会变成post呢?

打断点发现只要connect()执行了以后就会自动变成post,说明在connect()里有修改请求方式的处理。
进去发现是个URLConnection的抽象方法,如图:
这里写图片描述
说明肯定是在某个继承了URLConnection的子类里实现了connect()的逻辑,我们现在需要找到是哪个子类实现了这个connect()方法。

2、首先回去看一下最上面出问题的代码,发现使用了HttpURLConnection这个类。

但是它虽然继承了URLConnection,但是也没实现connect(),猜测是:

某个HttpURLConnection的子类(实现类)  实现的该方法。


3、那怎么看是哪个HttpURLConnection实现类呢

看最上面的代码,发现是通过url.openConnection()获取的。

 connection = (HttpURLConnection) url.openConnection();

我们进入openConnection()方法看一下,发现是URL类。
它的openConnection()方法代码如下:

public URLConnection openConnection() throws IOException {
    return streamHandler.openConnection(this);
}

发现这个openConnection这个方法调用了一个streamHandler类的openConnection方法。
点击进streamHandler的openConnection方法发现又是个抽象方法,如图:
这里写图片描述

4、现在,需要找到streamHandler.openConnection时使用了哪个streamHandler子类(实现类)

在URL类里搜索,发现是在初始化时,设置了个默认的streamHandler类,代码如图:
这里写图片描述
具体的设置在setupStreamHandler()这个函数里。

点击进去,看看函数写了什么。
在函数底部发现了我们要找的那个streamHandler实现类
在http情况下用的是com.android.okhttp.HttpHandler这个类,
代码如图:
这里写图片描述

5、好,现在我们找到了第4步里要找的streamHandler实现类

这个类就是com.android.okhttp.HttpHandler。
但是这个类在项目里是看不了的,得去android源码库里看。

我们去android源码库androidxref,点击查看,选择一个android版本。
我用的测试机是5.1.0的,选择后如图:
这里写图片描述

在第二行Definition里输入HttpHandler,
在右侧的搜索范围(In Project)里选择select all ,
然后点击底部的search按钮,查看结果,如图:
这里写图片描述

第一个结果就是我们要找的okHttp的HttpHandler类,点击进去看看代码。
发现HttpHandler的openConnection()方法里调用的是newOkHttpClient(proxy)的open(url)方法,如图:
这里写图片描述

点击newOkHttpClient类,再看看open方法干了什么,如图:
这里写图片描述
发现这个open方法,返回了个HttpURLConnectionImpl实例。


6、终于,找到了第3步里要找的HttpURLConnection子类

快看看有没有connect()的具体实现。
http自动修改请求方法的秘密就在那里!

果然,有connect()的具体实现,里面有个设置http的方法

initHttpEngine()

点击进去看到http的设置代码逻辑,如图:
这里写图片描述


7、原来connect()时会判断是否设置了doOutput为true。如果设置为true,会自动将get方式改为post方式!!


8、回到最开始有问题的代码,看看是不是设置了doOutput?

如图:
这里写图片描述

果然设置为true了!答案找到了!

9、修改doOutput的设置为false,再去请求。发现请求类型变为get了。debug成功!

您好,Android 可以使用 HttpURLConnection 类来进行 HTTP 请求的发送,以下是一个简单的封装示例: ```java import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class HttpUtil { public static String sendHttpRequest(String urlStr, String method, String data) { HttpURLConnection connection = null; BufferedReader reader = null; try { URL url = new URL(urlStr); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod(method); connection.setConnectTimeout(5000); connection.setReadTimeout(5000); connection.setDoInput(true); connection.setDoOutput(true); if (method.equals("POST")) { OutputStream outputStream = connection.getOutputStream(); outputStream.write(data.getBytes()); outputStream.flush(); outputStream.close(); } InputStream inputStream = connection.getInputStream(); reader = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } return response.toString(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } if (connection != null) { connection.disconnect(); } } return null; } } ``` 您可以使用 `sendHttpRequest` 方法来发送 HTTP 请求,需要传入请求的 URL、请求方法(GET 或 POST)以及请求数据(如果是 POST 请求)。方法会返回响应的数据。例如,发送一个 GET 请求: ```java String response = HttpUtil.sendHttpRequest("http://www.example.com/api", "GET", null); ``` 发送一个 POST 请求: ```java String data = "param1=value1&param2=value2"; String response = HttpUtil.sendHttpRequest("http://www.example.com/api", "POST", data); ``` 当然,上面的代码只是一个简单的封装示例,实际应用需要进行更多的参数校验、错误处理等。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值