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;
    }

}