使用 Retrofit/OkHttp 时修改 POST 请求正文
Modifying POST request Body when using Retrofit/OkHttp
到目前为止,我一直在使用 OkHttp 进行网络请求,但现在我想使用 Retrofit (v2)。
我正在与之通信的服务器需要 AuthToken 作为 Url(GET 请求)或内部 Body(POST 请求)的一部分。
我还需要将请求创建与执行分开,顺便说一句,这是 Retrofit 非常好的功能,即我可以稍后传递 Call 对象和 execute/enqueue 它。
困难的部分是创建请求时 AuthToken 可能不可用,我需要在执行之前修改它。到目前为止,我一直在创建时添加一个虚拟 authToken 并在执行前替换它。
这对于 GET 请求来说非常简单,因为我可以将拦截器添加到 OkHttpClient 中以修改请求 Url 但是修改 POST 请求的主体是我正在努力的事情。
那么,Retrofit/OkHttp是否支持这个用例?
一些不起作用的示例代码几乎可以解决问题(尝试始终在可用时添加 authToken,结果是:java.lang.IllegalStateException:无法在没有分块编码或已知内容长度的情况下流式传输请求正文!
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();
}
};
}
});
目前不支持我要求的用例,因此我为 Retrofit 创建了关于它的新问题,请参阅 Argument pre-processor, deserialized post-processor #816
到目前为止,我一直在使用 OkHttp 进行网络请求,但现在我想使用 Retrofit (v2)。 我正在与之通信的服务器需要 AuthToken 作为 Url(GET 请求)或内部 Body(POST 请求)的一部分。 我还需要将请求创建与执行分开,顺便说一句,这是 Retrofit 非常好的功能,即我可以稍后传递 Call 对象和 execute/enqueue 它。
困难的部分是创建请求时 AuthToken 可能不可用,我需要在执行之前修改它。到目前为止,我一直在创建时添加一个虚拟 authToken 并在执行前替换它。 这对于 GET 请求来说非常简单,因为我可以将拦截器添加到 OkHttpClient 中以修改请求 Url 但是修改 POST 请求的主体是我正在努力的事情。
那么,Retrofit/OkHttp是否支持这个用例?
一些不起作用的示例代码几乎可以解决问题(尝试始终在可用时添加 authToken,结果是:java.lang.IllegalStateException:无法在没有分块编码或已知内容长度的情况下流式传输请求正文!
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();
}
};
}
});
目前不支持我要求的用例,因此我为 Retrofit 创建了关于它的新问题,请参阅 Argument pre-processor, deserialized post-processor #816