Okhttp请求重定向检测

HttpURLConnection的重定向处理

我们都知道一般的网络框架都是可以在内部自动处理重定向,比如常见的HttpURLConnection,当我们使用HttpURLConnection来处理重定向时,HttpURLConnection提供给一个 ,setInstanceFollowRedirects(true|false)来设置当前的HttpURLConnection是否在内部处理重定向请求

设置为true

内部处理重定向,返回最终的响应结果,调用方得到最终的code为200

设置为false

内部不处理重定向,只返回第一次响应的结果,调用方得到的是301或者302的状态码,调用方需要自己去处理重定向

在某些业务中,业务方需要知道一个链接是否有过重定向,或者业务方有部分请求需要自己处理重定向时,业务方可以自己在构建HttpURLConnection时,灵活的设置setInstanceFollowRedirects

代码如下

URL url = new URL(openurl);                                                                                  
//得到connection对象。                                                                                            
HttpURLConnection connection = (HttpURLConnection) url.openConnection();                                     
//设置请求方式                                                                                                     
connection.setRequestMethod(GET);                                                                            
connection.setConnectTimeout(TurboConstant.OKHTTP_DEFAULT_CONNET_TIMEOUT);                                   
connection.setReadTimeout(TurboConstant.OKHTTP_DEFAULT_REQ_TIMEOUT);                                         
connection.setInstanceFollowRedirects(false);                                                                
//连接                                                                                                         
connection.connect();                                                                                        
//得到响应码                                                                                                      
int responseCode = connection.getResponseCode();                                                             
if (responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP) {
    if (WebTurboConfiguration.getInstance().showAllLog()) {                                                  
        String redirectUrl = connection.getHeaderField("Location");                                          
        TLog.d(TAG, "发现 重定向链接  openurl = " + openurl + "  redirectUrl = " + redirectUrl);                    
    } else {                                                                                                 
        TLog.d(TAG, "find redirect link");                                                                   
    }                                                                                                                                                                           
} else if (responseCode == HttpURLConnection.HTTP_OK) {                                                      
                                                                    
}
connection.disconnect();                                                                                                   

OkHttp的重定向处理

尽管现在Android系统提供的HttpURLConnection底层是使用OKhttp实现的,但是如果我们单独使用OKhttp来实现自己的网络请求的化,重定向方面的代码逻辑与HttpURLConnection差异比较大

Okhttp提供了followRedirects(true|false)方法来进行重定向的处理配置,但是followRedirects(true|false)方法是 OkHttpClient实例提供的方法

如图所示

OkHttpClient client = new OkHttpClient.Builder()
.followRedirects(true)
.build();

正常来讲,业务方在使用Okhttp的时候,都会将OkHttpClient做为一个全局的单例来使用,followRedirects做为OkHttpClient提供的方法,一旦设置,就会全局处理或者不处理重定向,这不一定能满足需求

查看OKHttp负责重定向的源码

为了方便理解,我们将核心逻辑提取出来并稍作修改,方便让大家看的更清楚

RetryAndFollowUpInterceptor.java

public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    RealInterceptorChain realChain = (RealInterceptorChain) chain;

//核心逻辑是一个循环体
    while (true) {

        //获取网络的数据
        Response response = realChain.proceed(request, transmitter, null);

        // 判断上一个Response是否有效,如果有效就合入到当前准备返回的Response中
        if (priorResponse != null) {
            response = response.newBuilder()
            .priorResponse(priorResponse.newBuilder()
            .body(null)
            .build())
            .build();
        }
        //检查是否是一个重定向请求
        Request followUp = followUpRequest(response, route);

        //不是重定向请求直接返回Response
        if (followUp == null) {
            return response;
        } else {
            //是重定向请求,将当前Response保存为priorResponse,在下一个循环
            request = followUp;
            priorResponse = response;
        }
    }
}

从RetryAndFollowUpInterceptor.java拦截器的核心逻辑可以看出以下几点

1、当检测到重定向时,RetryAndFollowUpInterceptor保存了重定向发生时的Response,并且命名为priorResponse

2、当重定向后的请求发起后,priorResponse被当成一个参数放入到最终的Response中

因此我们只要在Response中取出priorResponse即可知道曾经发生过什么

因此

我么可以使用如下方法来判断一次请求是否发生过重定向

    /**
     * 判断是否曾经发生过重定向
     * priorResponse是重定向之前产生的response,里面有重定向信息
     *
     * @param response 响应
     * @return 是否发生过重定向
     */
    private static boolean isRedirected(Response response) {
        Response priorResponse = response.priorResponse();
        if (priorResponse != null) {
            int priorResponseCode = priorResponse.code();
            return priorResponseCode == HttpURLConnection.HTTP_MOVED_PERM || priorResponseCode == HttpURLConnection.HTTP_MOVED_TEMP;
        }
        return false;
    }

在RetryAndFollowUpInterceptor的循环体中,如果一个url请求包含多次重定向,那么包含了priorResponse的Response又会被做为一个新的priorResponse保存起来,因此只要逐级的取出priorResponse就可以得到整个网络请求过程中发生的若干次重定向数据

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值