提交 e3c2b9da 编写于 作者: J jessyan

improve RequestInterceptor

上级 6d9193b2
......@@ -6,6 +6,7 @@ import android.text.TextUtils;
import com.jess.arms.base.BaseApplication;
import com.jess.arms.di.module.GlobeConfigModule;
import com.jess.arms.http.GlobeHttpHandler;
import com.jess.arms.http.RequestInterceptor;
import com.jess.arms.utils.UiUtils;
import com.squareup.leakcanary.LeakCanary;
import com.squareup.leakcanary.RefWatcher;
......@@ -82,6 +83,7 @@ public class WEApplication extends BaseApplication {
/**
* 将AppComponent返回出去,供其它地方使用, AppComponent接口中声明的方法返回的实例,在getAppComponent()拿到对象后都可以直接使用
*
* @return
*/
public AppComponent getAppComponent() {
......@@ -93,6 +95,7 @@ public class WEApplication extends BaseApplication {
* app的全局配置信息封装进module(使用Dagger注入到需要配置信息的地方)
* GlobeHttpHandler是在NetworkInterceptor中拦截数据
* 如果想将请求参数加密,则必须在Interceptor中对参数进行处理,GlobeConfigModule.addInterceptor可以添加Interceptor
*
* @return
*/
@Override
......@@ -107,7 +110,7 @@ public class WEApplication extends BaseApplication {
//这里可以先客户端一步拿到每一次http请求的结果,可以解析成json,做一些操作,如检测到token过期后
//重新请求token,并重新执行请求
try {
if (!TextUtils.isEmpty(httpResult)) {
if (!TextUtils.isEmpty(httpResult) && RequestInterceptor.isJson(response.body())) {
JSONArray array = new JSONArray(httpResult);
JSONObject object = (JSONObject) array.get(0);
String login = object.getString("login");
......
package com.jess.arms.http;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.util.ContentLengthInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import okhttp3.Call;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
/**
* Created by jess on 10/04/2017 17:38
* Contact with jess.yan.effort@gmail.com
* Fetches an {@link InputStream} using the okhttp3library.
*/
public class OkHttpStreamFetcher implements DataFetcher<InputStream> {
private final Call.Factory client;
private final GlideUrl url;
private InputStream stream;
private ResponseBody responseBody;
private volatile Call call;
public OkHttpStreamFetcher(Call.Factory client, GlideUrl url) {
this.client = client;
this.url = url;
}
@Override
public InputStream loadData(Priority priority) throws Exception {
Request.Builder requestBuilder = new Request.Builder().url(url.toStringUrl());
for (Map.Entry<String, String> headerEntry : url.getHeaders().entrySet()) {
String key = headerEntry.getKey();
requestBuilder.addHeader(key, headerEntry.getValue());
}
Request request = requestBuilder.build();
Response response;
call = client.newCall(request);
response = call.execute();
responseBody = response.body();
if (!response.isSuccessful()) {
throw new IOException("Request failed with code: " + response.code());
}
long contentLength = responseBody.contentLength();
stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength);
return stream;
}
@Override
public void cleanup() {
try {
if (stream != null) {
stream.close();
}
} catch (IOException e) {
// Ignored
}
if (responseBody != null) {
responseBody.close();
}
}
@Override
public String getId() {
return url.getCacheKey();
}
@Override
public void cancel() {
Call local = call;
if (local != null) {
local.cancel();
}
}
}
package com.jess.arms.http;
import android.content.Context;
import com.bumptech.glide.load.data.DataFetcher;
import com.bumptech.glide.load.model.GenericLoaderFactory;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.load.model.ModelLoaderFactory;
import java.io.InputStream;
import okhttp3.Call;
import okhttp3.OkHttpClient;
/**
* Created by jess on 10/04/2017 17:37
* Contact with jess.yan.effort@gmail.com
* A simple model loader for fetching media over http/https using OkHttp.
*/
public class OkHttpUrlLoader implements ModelLoader<GlideUrl, InputStream> {
private final Call.Factory client;
public OkHttpUrlLoader(Call.Factory client) {
this.client = client;
}
@Override
public DataFetcher<InputStream> getResourceFetcher(GlideUrl model, int width, int height) {
return new OkHttpStreamFetcher(client, model);
}
/**
* The default factory for {@link OkHttpUrlLoader}s.
*/
public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
private static volatile Call.Factory internalClient;
private Call.Factory client;
/**
* Constructor for a new Factory that runs requests using a static singleton client.
*/
public Factory() {
this(getInternalClient());
}
/**
* Constructor for a new Factory that runs requests using given client.
*
* @param client this is typically an instance of {@code OkHttpClient}.
*/
public Factory(Call.Factory client) {
this.client = client;
}
private static Call.Factory getInternalClient() {
if (internalClient == null) {
synchronized (Factory.class) {
if (internalClient == null) {
internalClient = new OkHttpClient();
}
}
}
return internalClient;
}
@Override
public ModelLoader<GlideUrl, InputStream> build(Context context, GenericLoaderFactory factories) {
return new OkHttpUrlLoader(client);
}
@Override
public void teardown() {
// Do nothing, this instance doesn't own the client.
}
}
}
package com.jess.arms.http;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.jess.arms.utils.CharactorHandler;
import com.jess.arms.utils.ZipHelper;
import java.io.EOFException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Singleton;
......@@ -26,6 +29,7 @@ import timber.log.Timber;
/**
* Created by jess on 7/1/16.
* Contact with jess.yan.effort@gmail.com
*/
@Singleton
public class RequestInterceptor implements Interceptor {
......@@ -40,28 +44,60 @@ public class RequestInterceptor implements Interceptor {
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
boolean hasRequestBody = request.body() != null;
Buffer requestbuffer = new Buffer();
if (request.body() != null) {
if (hasRequestBody) {
request.body().writeTo(requestbuffer);
}
//打印url信息
//打印请求信息
Timber.tag(getTag(request, "Request_Info")).w("Params : 「 %s 」%nConnection : 「 %s 」%nHeaders : %n「 %s 」"
, request.body() != null ? parseParams(request.body(), requestbuffer) : "null"
, hasRequestBody ? parseParams(request.body(), requestbuffer) : "Null"
, chain.connection()
, request.headers());
long t1 = System.nanoTime();
Response originalResponse = chain.proceed(request);
Response originalResponse;
try {
originalResponse = chain.proceed(request);
} catch (Exception e) {
Timber.w("Http Error: " + e);
throw e;
}
long t2 = System.nanoTime();
//打印响应时间
Timber.tag(getTag(request, "Response_Info")).w("Received response in [ %.1fms ]%n%s", (t2 - t1) / 1e6d, originalResponse.headers());
String bodySize = originalResponse.body().contentLength() != -1 ? originalResponse.body().contentLength() + "-byte" : "unknown-length";
//打印响应时间以及响应头
Timber.tag(getTag(request, "Response_Info")).w("Received response in [ %d-ms ] , [ %s ]%n%s"
, TimeUnit.NANOSECONDS.toMillis(t2 - t1), bodySize, originalResponse.headers());
//打印响应结果
String bodyString = printResult(request, originalResponse);
if (mHandler != null)//这里可以比客户端提前一步拿到服务器返回的结果,可以做一些操作,比如token超时,重新获取
return mHandler.onHttpResultResponse(bodyString, chain, originalResponse);
return originalResponse;
}
/**
* 打印响应结果
*
* @param request
* @param originalResponse
* @return
* @throws IOException
*/
@Nullable
private String printResult(Request request, Response originalResponse) throws IOException {
//读取服务器返回的结果
ResponseBody responseBody = originalResponse.body();
String bodyString = null;
if (isJson(responseBody)) {
if (isParseable(responseBody)) {
BufferedSource source = responseBody.source();
source.request(Long.MAX_VALUE); // Buffer the entire body.
Buffer buffer = source.buffer();
......@@ -77,21 +113,17 @@ public class RequestInterceptor implements Interceptor {
//解析response content
bodyString = parseContent(responseBody, encoding, clone);
Timber.tag(getTag(request, "Response_Result")).w(CharactorHandler.jsonFormat(bodyString));
Timber.tag(getTag(request, "Response_Result")).w(isJson(responseBody) ? CharactorHandler.jsonFormat(bodyString) : bodyString);
} else {
Timber.tag(getTag(request, "Response_Result")).w("The result isn't json");
Timber.tag(getTag(request, "Response_Result")).w("This result isn't parsed");
}
if (mHandler != null)//这里可以比客户端提前一步拿到服务器返回的结果,可以做一些操作,比如token超时,重新获取
return mHandler.onHttpResultResponse(bodyString, chain, originalResponse);
return originalResponse;
return bodyString;
}
public String getTag(Request request, String tag) {
return "「 " + request.url() + " 」" + tag;
private String getTag(Request request, String tag) {
return String.format(" [%s] 「 %s 」>>> %s", request.method(), request.url().toString(), tag);
}
......@@ -120,13 +152,48 @@ public class RequestInterceptor implements Interceptor {
@NonNull
public static String parseParams(RequestBody body, Buffer requestbuffer) throws UnsupportedEncodingException {
if (body.contentType() != null && !body.contentType().toString().contains("multipart")) {
return URLDecoder.decode(requestbuffer.readUtf8(), "UTF-8");
if (isPlaintext(requestbuffer)) {
Charset charset = Charset.forName("UTF-8");
MediaType contentType = body.contentType();
if (contentType != null) {
charset = contentType.charset(charset);
}
return URLDecoder.decode(requestbuffer.readString(charset), "UTF-8");
}
return "null";
return "This Params isn't Text";
}
public static boolean isParseable(ResponseBody responseBody) {
if (responseBody.contentLength() == 0) return false;
return responseBody.contentType().toString().contains("text") || isJson(responseBody);
}
public boolean isJson(ResponseBody responseBody) {
public static boolean isJson(ResponseBody responseBody) {
return responseBody.contentType().toString().contains("json");
}
/**
* Returns true if the body in question probably contains human readable text. Uses a small sample
* of code points to detect unicode control characters commonly used in binary file signatures.
*/
static boolean isPlaintext(Buffer buffer) {
try {
Buffer prefix = new Buffer();
long byteCount = buffer.size() < 64 ? buffer.size() : 64;
buffer.copyTo(prefix, 0, byteCount);
for (int i = 0; i < 16; i++) {
if (prefix.exhausted()) {
break;
}
int codePoint = prefix.readUtf8CodePoint();
if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) {
return false;
}
}
return true;
} catch (EOFException e) {
return false; // Truncated UTF-8 sequence.
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册