8

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:

joschi
  • 11,459
  • 4
  • 40
  • 47

5 Answers5

3

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

  • 3
    I don't see how this would send an HTTP request body in an HTTP GET request. – joschi Aug 24 '18 at 20:23
  • I'm sorry my friend. I'm looking to find a solution particularly for elasticsearch. But i couldn't how to customize "curl" with HttpUrl.Builder. I thought you can put your keys and values with in addQueryParameter("q", "polar bears") method instead of request body. Or may be you can make use of addPathSegment("search") method when build your url for your request. But i was wrong. It doesn't solves curl issues. – Mustafa Karcıoğlu Aug 25 '18 at 00:48
0

I tried to achieve the same, but unfortunately, it cannot be done without dirty tricks I personally admire as an exercise but don't want to see in my production code.

Basically, you can create POST method with a builder and set its method field to "GET" later using the reflection. This will do the trick.

Something like this:

Builder builder = new Request.Builder().url(mySearchUrl).method("POST", body).build();
Field field = Builder.class.getField("method");
field.setAccessible(true);
field.setValue(builder, "GET");
Mikhail Aksenov
  • 231
  • 2
  • 7
0

Technically RFC https://tools.ietf.org/html/rfc2616#section-9.3 says you can use the body in the get request.

What I tried before switching to another client library

  1. I tried request rewriting using network interceptor

  2. 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.

NILESH SALPE
  • 95
  • 2
  • 10
-1

If the base API allow query params, send all the body params as queryparams. It works like a charm. While OKHttp allow the query params but will not allow body with Get calls to avoid cache inconsistencies.

YSJaitawat
  • 47
  • 1
  • It doesn't, see [Multi Get API](https://www.elastic.co/guide/en/elasticsearch/reference/5.3/docs-multi-get.html). If query parameters were supported, I wouldn't have to ask the question. Also, the length of query parameters is limited, the size of a HTTP request body is not (within reasonable bounds). – joschi Nov 11 '20 at 06:51
-1

do both. (in order)

Request request = new Request.Builder()
                  .url("http://example.com")
                  .post(requestBody)
                  .get()
                  .build();
Guy
  • 1
  • This will reset the previously added request body: https://github.com/square/okhttp/blob/parent-3.6.0/okhttp/src/main/java/okhttp3/Request.java#L203 – joschi Mar 26 '21 at 12:38