2015-10-07 104 views
1

到目前为止,我一直在使用OkHttp来处理我的网络请求,但现在我想要使用Retrofit(v2)。 我与之通信的服务器要求AuthToken作为Url(GET请求)的一部分或Body(POST请求)的一部分。 我还需要将请求创建与执行分开,这是一个很好的改进功能,即我可以传递Call对象并稍后执行/排队。使用Retrofit/OkHttp修改POST请求正文

最难的部分是AuthToken在创建请求时可能不可用,我需要在它执行之前对其进行修改。到目前为止,我一直在创建时添加一个虚拟authToken,并在执行之前进行替换。 对于GET请求,这非常简单,因为我可以将Interceptor添加到OkHttpClient中来修改请求Url,但修改POST请求的正文是我努力的事情。

那么,在Retrofit/OkHttp中是否支持这个用例呢? java.lang.IllegalStateException:

一些没有工作的示例代码,几乎会做的伎俩(尝试添加的authToken总是可用的时候,用结束!无分块编码或已知的内容长度不能流的请求体

client.networkInterceptors().add(new Interceptor() { 
     @Override 
     public Response intercept(Chain chain) throws IOException { 
      Request request = chain.request(); 

      if (request.body() == null) { 
       return chain.proceed(request); 
      } 

      Request authorizedRequest = request.newBuilder() 
        .method(request.method(), replaceDummyAuth(request.body())) 
        .build(); 
      return chain.proceed(authorizedRequest); 
     } 

     private RequestBody replaceDummyAuth(final RequestBody body) { 
      return new RequestBody() { 
       @Override 
       public MediaType contentType() { 
        return body.contentType(); 
       } 

       @Override 
       public long contentLength() throws IOException { 
        return -1; 
       } 

       @Override 
       public void writeTo(BufferedSink sink) throws IOException { 
        ParametersMap map = new ParametersMap(); 

        BufferedSink authSink = Okio.buffer(sink); 
        body.writeTo(authSink); 

        String authToken = SessionManager.getAuthToken(); 
        if(StringUtils.hasText(authToken)) { 
         map.put("authToken", authToken); 
         String paramString = map.getParameterString(); 
         authSink.write(paramString.getBytes("UTF-8")); 
        } 
        authSink.close(); 
       } 
      }; 
     } 
    }); 
+0

为什么内容长度为-1?难道gzip压缩? –

+0

不,这不是gzipped,我只是不知道如何实现contentLength()。如果我把:return body.contentLength();我ge t“java.net.ProtocolException:期望的0字节但收到111” – pmellaaho

回答