Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrofit 2 appending post to requestbody in intercept

I have this:

OkHttpClient client = new OkHttpClient();
client.interceptors().add(new Interceptor() {
    @Override
    public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        HttpUrl url = request.httpUrl().newBuilder()
                     .addQueryParameter("platform", "android")
                     .addQueryParameter("app_version", com.package.BuildConfig.VERSION_NAME)
                     .build();
        Request newRequest = chain.request().newBuilder().url(url).build();
        return chain.proceed(newRequest);
    }
});

but would also like to append an additional post key-value to the request body containing the userkey. This would look something like

    RequestBody newBody = RequestBody.create(request.body().contentType(),request.body().content+ request.addPost("sUserKey","3254345kdskf");
...
...
 Request newRequest = chain.request()
.newBuilder()
.url(url)
.post(newBody)
.build();
like image 328
Nic Capdevila Avatar asked Nov 06 '15 19:11

Nic Capdevila


1 Answers

Appending to the RequestBody is not straight forward. Here is a sketch of a custom RequestBody that will add a post parameter. Couple of caveats -- you will want to add some error checking, like making sure the existing body is not null. The given code also assumes all calls coming to this interceptor are POSTs. If that is not that case, you'll need to check the incoming request type before applying the new body. Also, since this just copies the new parameter into the body, you'll need to make sure the name and body are already url encoded if needed.

class AddPostParamRequestBody extends RequestBody {

    final RequestBody body;
    final String parameter;

    AddPostParamRequestBody(RequestBody body, String name, String value) {
        this.body = body;
        this.parameter = "&" + name + "=" + value;
    }

    @Override
    public long contentLength() throws IOException {
        return body.contentLength() + parameter.length();
    }

    @Override
    public MediaType contentType() {
        return body.contentType();
    }

    @Override
    public void writeTo(BufferedSink bufferedSink) throws IOException {
        body.writeTo(bufferedSink);
        bufferedSink.writeString(parameter, Charset.forName("UTF-8"));
    }

} 

Then you can use in your interceptor --

client.interceptors().add(new Interceptor() {
    @Override
    public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        HttpUrl url = request.httpUrl().newBuilder().addQueryParameter("added", "param").build();
        AddPostParamRequestBody newBody = new AddPostParamRequestBody(request.body(), "sUserKey","3254345kdskf");
        Request newRequest = request.newBuilder().post(newBody).url(url).build();
        return chain.proceed(newRequest);
    }
});

Your other option is to the include an extra Field annotation in your retrofit definition and pass it in on every call, but I assume you were trying to avoid that.

like image 93
iagreen Avatar answered Sep 23 '22 16:09

iagreen