最近这两天遇到一个问题,找到了一个公有的开放的API,但是通过Retrofit默认请求得到的结果是code = 400, message = Bad Request。看别人写的用Volley,完全没有问题。

添加Headers

开始我以为是头文件信息不对导致的。在ApiServer里面添加了注释

 @Headers({
            "Content-Type: application/json; charset=utf-8",
            "Accept: application/json"
    })
    @GET("xxxxx")
    Call<ResponseBody> getxxxData();

配置Charles

请求后,通过Charles抓包,得到的结果是个乱码。,。根据Charles的提示,应该是SSL没有配置导致的

  • 手机去下载一个Charles的CA,点击这里
  • 下载完毕后,在Charles中「Proxy -> SSL Proxying -> 勾选Enable SSL Proxying」
  • 将需要访问的Https网址加入到下面的Location里面

配置Charles的SSL成功后,再次请求,发现Header的信息是正常的,但是返回的仍然是400。我猜想应该是UA没有发送导致的。

添加UA

在Android API17之后,可以用下面的方法获取User-Agent

WebSettings.getDefaultUserAgent(getApplicationContext())

接下来就需要将这个UA添加到okHttp的请求当中了。我们自己构造一个OkHttpClient来实现这个。

private OkHttpClient getOkHttpClient() {
        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();

        httpClientBuilder.addInterceptor(new Interceptor() {
            @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
            @Override
            public okhttp3.Response intercept(Chain chain) throws IOException {
                Request request = chain.request()
                        .newBuilder()
                        .removeHeader("User-Agent")//移除旧的
                        .addHeader("User-Agent", WebSettings.getDefaultUserAgent(getApplicationContext()))//添加真正的头部
                        .build();
                return chain.proceed(request);
            }
        });
        return httpClientBuilder.build();
    }

再次测试,成功的获取了该API返回的数据。

添加HttpLoggingInterceptor

在日常网络发起请求的时候,添加一个Http的Log信息很有必要,能看到网络交互的时候一些关键信息,所以我们将上面的OkHttpClient改造一下。

private OkHttpClient getOkHttpClient() {
        //显示级别
        HttpLoggingInterceptor.Level level = HttpLoggingInterceptor.Level.BODY;

        //新建拦截器log
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                Log.d("OKHTTP====Message", message);
            }
        });
        loggingInterceptor.setLevel(level);

        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();

        httpClientBuilder.addInterceptor(new Interceptor() {
            @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
            @Override
            public okhttp3.Response intercept(Chain chain) throws IOException {
                Request request = chain.request()
                        .newBuilder()
                        .removeHeader("User-Agent")//移除旧的
                        .addHeader("User-Agent", WebSettings.getDefaultUserAgent(getApplicationContext()))//添加真正的头部
                        .build();
                return chain.proceed(request);
            }
        });

        httpClientBuilder.addInterceptor(loggingInterceptor);

        return httpClientBuilder.build();
    }