retrofit 基于okhttp。使用retrofit /okhttp时候,这些都会wifi
直连的,不走系统的wifi设置,代理是抓不到包的。所以如果
想抓包那么抓网卡吧,打印请求或者添加公共参数或者签名之类的话,可以使用拦截器来添加。
拦截器这里使用okhttp的应用拦截器,分别对get post添加统一参数和签名
首先实现 interceptor创建自己的拦截器
拦截器的 intercept方法的 Chain 可以获取请求响应 和请求头,可以随意添加参数请求头等等
首先是对请求添加版本号在请求头。可以在实现Interceptor方法的自定义拦截器里面这样写
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
//添加请求头
request = request.newBuilder()
.addHeader("V", "appvesron")
.build()
return chain.proceed(request);
}
这样就添加了一个请求头。v版本号
2 然后是get方法 添加公共参数。比如说客户端类型了,时间戳,版本号等。。方法一样,代码如下
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (request.method().equals("GET")) {
//添加公共参数
HttpUrl httpUrl = request.url()
.newBuilder()
.addQueryParameter("clienttype","1")
.addQueryParameter("imei", "imei")
.addQueryParameter("version", "VersionName")
.addQueryParameter("timestamp", String.valueOf(System.currentTimeMillis()))
.build();
request = request.newBuilder().url(httpUrl).build();
}
return chain.proceed(request);
}
对get请求添加统一封装参数,先从charin里面获取request,然后添加query参数。
3 在说下post方法添加参数,这个稍微麻烦一些
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (request.method().equals("POST")) {
if (request.body() instanceof FormBody) {
FormBody.Builder bodyBuilder = new FormBody.Builder();
FormBody formBody = (FormBody) request.body();
//把原来的参数添加到新的构造器,(因为没找到直接添加,所以就new新的)
for (int i = 0; i < formBody.size(); i++) {
bodyBuilder.addEncoded(formBody.encodedName(i), formBody.encodedValue(i));
}
formBody = bodyBuilder
.addEncoded("clienttype", "1")
.addEncoded("imei", "imei")
.addEncoded("version", "VersionName")
.addEncoded("timestamp", String.valueOf(System.currentTimeMillis()))
.build();
request = request.newBuilder().post(formBody).build();
}
return chain.proceed(request);
}
post方法添加参数的稍微麻烦一下,点了半天,我也没有找到可以直接添加的方法,就新建了一个formbody
这样就可以统一添加 请求和参数,常用的get post都可以了。
下面说一下cookie。
cookie 简答点,就算是请求头里面,和添加头方法一样。
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
//添加cookie
request = request.newBuilder().addHeader("Cookie", "cookie").build();
return chain.proceed(request);
}
我之前项目使用的 AsyncHttpClient。。已经有100多个api了,现在想用 retrofit 和rxjava,被以前的嵌套请求恶心着了。
替换之前的网络请求几乎是不可能了,就同时使用这两个框架。问题来了,cookie一开始搞不定。
cookie是之前AsyncHttpClient 来管理维护的。okhttp 添加的cookie是string串,这个自己拼接了,
取出之前的cookie来拼接好,传给okhttp。格式是实验好久才拼接对的
private static String getCookie(List<Cookie> cookies) {
StringBuilder builder = new StringBuilder();
for (Cookie cookie : cookies) {
builder.append(";"); builder.append(cookie.getName());
builder.append("=");
builder.append(cookie.getValue());
builder.append("; domain=");
builder.append(cookie.getDomain());
// if (cookie.getExpiryDate() != null) {
// builder.append("; expires=");
// calendar.setTime(cookie.getExpiryDate());
// builder.append(DateFormat.format("EEE, dd MMM yyyy hh:mm:ss z", calendar.getTimeInMillis()));
// }
builder.append("; path=");
builder.append(cookie.getPath());
builder.append("; version=");
builder.append(cookie.getVersion());
}
return builder.substring(1, builder.length());
}
如果有多个cookie是通过;来拼接的好像说是通过了。 把这个设置到请求头就行了。
然后还有呢,就是添加签名,添加签名就试试再添加一个参数,不管get post的添加方法前面已经说了,自己再添加要给就行了,
就不单写了。
public class MyInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
//添加请求头
request = request.newBuilder().addHeader("V", MoKaApplication.getInst().VersionName()).build();
// 添加cookie
if (MokaRestClient.getCookies() != null && 0 < MokaRestClient.getCookies().size()) {
request = request.newBuilder().addHeader("Cookie", getCookie(MokaRestClient.getCookies())).build();
}
if (request.method().equals("GET")) {
request = addGetParams(request);
} else if (request.method().equals("POST")) {
request = addPostParams(request);
}
if (!Constants.RELEASE_CLIENT) {
Log.d("mokaNet", URLDecoder.decode(request.url().toString(), "UTF-8"));
Response response = chain.proceed(request);
MediaType mediaType = response.body().contentType();
String content = response.body().string();
Log.d("mokaNet", content);
return response.newBuilder()
.body(okhttp3.ResponseBody.create(mediaType, content))
.build();
} else {
return chain.proceed(request);
}
}
private static String getCookie(List<Cookie> cookies) {
StringBuilder builder = new StringBuilder();
for (Cookie cookie : cookies) {
builder.append(";");
builder.append(cookie.getName());
builder.append("=");
builder.append(cookie.getValue());
builder.append("; domain=");
builder.append(cookie.getDomain());
// if (cookie.getExpiryDate() != null) {
// builder.append("; expires=");
// calendar.setTime(cookie.getExpiryDate());
// builder.append(DateFormat.format("EEE, dd MMM yyyy hh:mm:ss z", calendar.getTimeInMillis()));
// }
builder.append("; path=");
builder.append(cookie.getPath());
builder.append("; version=");
builder.append(cookie.getVersion());
}
return builder.substring(1, builder.length());
}
//get请求 添加公共参数 签名
private static Request addGetParams(Request request) {
//添加公共参数
HttpUrl httpUrl = request.url()
.newBuilder()
.addQueryParameter("clienttype", String.valueOf(NetConstants.CLIENT_TYPE_ANDROID))
.addQueryParameter("version","" )
.addQueryParameter("timestamp", String.valueOf(System.currentTimeMillis()))
.build();
//添加签名
Set<String> nameSet = httpUrl.queryParameterNames();
ArrayList<String> nameList = new ArrayList<>();
nameList.addAll(nameSet);
Collections.sort(nameList);
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < nameList.size(); i++) {
buffer.append("&").append(nameList.get(i)).append("=").append(httpUrl.queryParameterValues(nameList.get(i)) != null &&
httpUrl.queryParameterValues(nameList.get(i)).size() > 0 ? httpUrl.queryParameterValues(nameList.get(i)).get(0) : "");
}
httpUrl = httpUrl.newBuilder()
.addQueryParameter("sign", MD5Util.MD5(buffer.toString()))
.build();
request = request.newBuilder().url(httpUrl).build();
return request;
}
//post 添加签名和公共参数
private Request addPostParams(Request request) throws UnsupportedEncodingException {
if (request.body() instanceof FormBody) {
FormBody.Builder bodyBuilder = new FormBody.Builder();
FormBody formBody = (FormBody) request.body();
//把原来的参数添加到新的构造器,(因为没找到直接添加,所以就new新的)
for (int i = 0; i < formBody.size(); i++) {
bodyBuilder.addEncoded(formBody.encodedName(i), formBody.encodedValue(i));
}
formBody = bodyBuilder
.addEncoded("ctype", String.valueOf(NetConstants.CLIENT_TYPE_ANDROID))
.addEncoded("ver","" )
.addEncoded("time", String.valueOf(System.currentTimeMillis()))
.build();
Map<String, String> bodyMap = new HashMap<>();
List<String> nameList = new ArrayList<>();
for (int i = 0; i < formBody.size(); i++) {
nameList.add(formBody.encodedName(i));
bodyMap.put(formBody.encodedName(i), URLDecoder.decode(formBody.encodedValue(i), "UTF-8"));
}
StringBuilder builder = new StringBuilder();
for (int i = 0; i < nameList.size(); i++) {
builder.append("&").append(nameList.get(i)).append("=")
.append(URLDecoder.decode(bodyMap.get(nameList.get(i)), "UTF-8"));
}
formBody = bodyBuilder.
addEncoded("sign", MD5Util.MD5(builder.toString()))
.build();
request = request.newBuilder().post(formBody).build();
}
return request;
}
}