
重定向
客戶端向服務(wù)器發(fā)送一個(gè)請(qǐng)求,獲取對(duì)應(yīng)的資源,服務(wù)器收到請(qǐng)求后,發(fā)現(xiàn)請(qǐng)求的這個(gè)資源實(shí)際放在另一個(gè)位置,于是服務(wù)器在返回的響應(yīng)頭的Location字段中寫(xiě)入那個(gè)請(qǐng)求資源的正確的URL,并設(shè)置reponse的狀態(tài)碼為30x 。
相關(guān)狀態(tài)碼說(shuō)明

Okhttp代碼中的實(shí)現(xiàn)
在RetryAndFollowUpInterceptor的intercept方法中構(gòu)建了while (true)循環(huán),根據(jù)response重建request:
Request followUp = followUpRequest(response)

判斷是否需要重定向的邏輯在followUpRequest方法中:

1.如果響應(yīng)碼是307 或者308并且請(qǐng)求方法不是 GET 或者 HEAD 請(qǐng)求不進(jìn)行重定向。
2.重定向的地址從響應(yīng)頭中獲取 “Location”。
3.HTTPS 和 HTTP 之間的重定向,需要根據(jù)配置 followSslRedirects 來(lái)判斷。final boolean followSslRedirects; //安全套接層重定向
4.如果請(qǐng)求不是PROPFIND的重定向,重定向后的請(qǐng)求會(huì)轉(zhuǎn)為GET請(qǐng)求。
我們項(xiàng)目中的請(qǐng)求大都是POST請(qǐng)求或者GET請(qǐng)求,有時(shí)候?yàn)榱税踩紤],全部都用POST請(qǐng)求,在遇到重定向的時(shí)候會(huì)被轉(zhuǎn)成GET請(qǐng)求,或者我們的重定向狀態(tài)碼使用的是307,并且請(qǐng)求方法是GET,Okhttp就不支持了。這就不符合我們的要求了。有時(shí)候還可能實(shí)現(xiàn)跨域重定向,如:HTTP -> HTTPS。
既然Okhttp默認(rèn)的實(shí)現(xiàn)不能滿足我們的要求,就需要我們自己去實(shí)現(xiàn),其實(shí)實(shí)現(xiàn)很簡(jiǎn)單,我們只需要自定義一個(gè)攔截器,判斷重定向的響應(yīng)碼,然后從響應(yīng)頭中獲取重定向后的地址,重新請(qǐng)求一遍即可。
重定向處理
//處理重定向的攔截器
public class RedirectInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
okhttp3.Request request = chain.request();
Response response = chain.proceed(request);
int code = response.code();
if (code == 307) {
//獲取重定向的地址
String location = response.headers().get("Location");
LogUtils.e("重定向地址:", "location = " + location);
//重新構(gòu)建請(qǐng)求
Request newRequest = request.newBuilder().url(location).build();
response = chain.proceed(newRequest);
}
return response;
}
}
//使用
OkHttpClient client = new OkHttpClient.Builder()
.followRedirects(false); //禁制OkHttp的重定向操作,我們自己處理重定向
.addInterceptor(new RedirectInterceptor())
.build();