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成功!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值