在OkHttp中使用请求正文获取请求

时间:2017-04-07 23:00:26

标签: java okhttp okhttp3

我正在尝试将OkHttp 3.6.0与Elasticsearch一起使用,而且我一直坚持向Elasticsearch Multi GET API发送请求。

它需要使用请求正文发送HTTP GET请求。不幸的是,如果我自己尝试构建请求,OkHttp并不支持开箱即用并抛出异常。

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();

是否有机会在OkHttp中使用请求正文构建GET请求?

相关问题:

6 个答案:

答案 0 :(得分:2)

经过几次尝试,我找到了解决该问题的方法。也许有人觉得它有用。

我使用了“ Httpurl.Builder”。

HttpUrl mySearchUrl = new HttpUrl.Builder()
       .scheme("https")
       .host("www.google.com")
       .addPathSegment("search")
       .addQueryParameter("q", "polar bears")
       .build();

您的获取请求网址将完全按照这种方式发生:

https://www.google.com/search?q=polar%20bears

在构建了网址之后,您必须像这样构建请求:

Request request = new Request.Builder()
                        .url(mySearchUrl)
                        .addHeader("Accept", "application/json")
                        .method("GET", null)
                        .build();

以下是来源:https://square.github.io/okhttp/3.x/okhttp/okhttp3/HttpUrl.html

答案 1 :(得分:0)

我试图实现相同的目标,但不幸的是,如果没有我个人喜欢的肮脏技巧,这是不可能完成的,但是我不想在我的生产代码中看到。

基本上,您可以使用构建器创建POST方法,并在以后使用反射将其方法字段设置为“ GET”。这可以解决问题。

类似这样的东西:

Builder builder = new Request.Builder().url(mySearchUrl).method("POST", body).build();
Field field = Builder.class.getField("method");
field.setAccessible(true);
field.setValue(builder, "GET");

答案 2 :(得分:0)

技术上的 RFC https://tools.ietf.org/html/rfc2616#section-9.3 说你可以在 get 请求中使用正文。

在切换到另一个客户端库之前我尝试了什么

  1. 我尝试使用网络拦截器重写请求

  2. 我尝试了反射来改变方法

        Field field = originalRequest.getClass().getDeclaredField("method");
        field.setAccessible(true);
        field.set(originalRequest, "GET");
    

结论: 您将需要更改库,OKHttp 不支持带有请求正文的 GET 请求,需要使用 apache 客户端或任何其他支持此功能的客户端。

答案 3 :(得分:0)

基于@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;
    }
}

然后,而不是做

new Request.Builder().get(getBody(input))

我们可以做到

new GetBodyBuilder().get(getBody(input))

它不漂亮,但很管用

答案 4 :(得分:-1)

如果基本API允许查询参数,则将所有正文参数作为queryparams发送。它像一种魅力。虽然OKHttp允许查询参数,但不允许带有Get调用的正文以避免缓存不一致。

答案 5 :(得分:-1)

两者都做。 (按顺序)

Request request = new Request.Builder()
                  .url("http://example.com")
                  .post(requestBody)
                  .get()
                  .build();