android - Retrofit/OkHttp3: Create and access custom RequestBody with an Interceptor -
i posting backend. service looks this:
public interface thingservice { @post("thing/") @headers("content-type: application/json") single<result<thing>> postthing(@body @nonnull requestbody body); }
and interceptor this:
public class thinginterceptor implements interceptor { @override public response intercept(@nonnull chain chain) throws ioexception { return chain.proceed(getthingedrequest(chain.request())); } @nonnull private request getthingedrequest(request request) { string thing = getthing(request.body()); httpurl newurl = request.url().newbuilder() .addqueryparameter("thing", thing) .build(); return request.newbuilder().url(newurl).build(); } private string getthing(requestbody body) { thingrequestbody thingbody = (thingrequestbody) body; // no good, see below return thingbody.getthing(); } }
here's thingrequestbody
:
public static final class thingrequestbody extends requestbody { private final requestbody delegate; private final string thing; public thingrequestbody(@nonnull requestbody delegate, @nonnull string thing) { this.delegate = delegate; this.thing = thing; } // why want own requestbody, can attach metadata later // via thinginterceptor @nonnull public string getthing() { return body; } // boilerplate omitted }
and measure, create instance of thingrequestbody
so:
@nonnull public requestbody build() { mediatype json = mediatype.parse("application/json; charset=utf-8"); gson gson = gsonadapterfactory.getgson(); string body = gson.tojson(things); // list of things requestbody delegate = requestbody.create(json, body); return new thingrequestbody(delegate, body); // in case not clear, `body` here string representation of // `content` byte-encoded inside requestbody delegate }
this approach falls flat on face, because okhttp3, in class requestbuilder
, wrap thingrequestbody
in instance of contenttypeoverridingrequestbody
, assigning thingrequestbody
private delegate
field. unfortunately, contenttypeoverridingrequestbody
private, , delegate
. can access them via reflection.
i can think of 2 solutions: 1. make contenttypeoverridingrequestbody
public , expose delegate
, or 2. change design.
edit
quick update, have discovered easy way access string representation of encoded body via okio's buffer (try/catch boilderplate omitted):
buffer buffer = new buffer(); body.writeto(buffer); json = buffer.readstring(charset.forname("utf-8"));
and guess that's fine, why okhttp3 force use of internal private contenttypeoverridingrequestbody
class?
Comments
Post a Comment