I'm trying to use OkHttp 3.6.0 with Elasticsearch and I'm stuck with sending requests to the Elasticsearch Multi GET API.
It requires sending an HTTP GET request with a request body. Unfortunately OkHttp doesn't support this out of the box and throws an exception if I try to build the request myself.
RequestBody body = RequestBody.create("text/plain", "test");
// No RequestBody supported
Request request = new Request.Builder()
.url("http://example.com")
.get()
.build();
// Throws: java.lang.IllegalArgumentException: method GET must not have a request body.
Request request = new Request.Builder()
.url("http://example.com")
.method("GET", requestBody)
.build();
Is there any chance to build a GET request with request body in OkHttp?
Related questions:
I found a solution for this problem after a few attempts. Maybe someone finds it useful.
I made use of "Httpurl.Builder."
HttpUrl mySearchUrl = new HttpUrl.Builder()
.scheme("https")
.host("www.google.com")
.addPathSegment("search")
.addQueryParameter("q", "polar bears")
.build();
Your get request url will happen exactly this way:
https://www.google.com/search?q=polar%20bears
And after building your url you have to build your request like this:
Request request = new Request.Builder()
.url(mySearchUrl)
.addHeader("Accept", "application/json")
.method("GET", null)
.build();
Here is the source: https://square.github.io/okhttp/3.x/okhttp/okhttp3/HttpUrl.html
Technically RFC https://www.rfc-editor.org/rfc/rfc2616#section-9.3 says you can use the body in the get request.
What I tried before switching to another client library
I tried request rewriting using network interceptor
I tried reflection to change the method
Field field = originalRequest.getClass().getDeclaredField("method");
field.setAccessible(true);
field.set(originalRequest, "GET");
Conclusion: You will need to change the library, OKHttp doesn't have support for GET request with requests body, need to use apache client or any other client which supports this.
Building on the answer from @nilesh-salpe:
static class GetBodyBuilder extends Request.Builder {
public Request.Builder get(RequestBody body) {
this.post(body);
try {
Field field = Request.Builder.class.getDeclaredField("method");
field.setAccessible(true);
field.set(this, "GET");
} catch (IllegalAccessException | NoSuchFieldException e) {
throw new SliceException("Couldn't set dirty reflection", e);
}
return this;
}
}
Then, instead of doing
new Request.Builder().get(getBody(input))
We can do
new GetBodyBuilder().get(getBody(input))
It's not pretty, but it works