如何在没有请求主体和查询参数的情况下进行Feign POST请求?

时间:2017-06-27 06:36:24

标签: http-post apache-httpclient-4.x feign

我正在使用Fe Apache Http Client,我想支持以下jax-rs接口:

@POST
@Path("/do_something")
void doSomething(@QueryParam("arg") String arg);

但是,ApacheHttpClient使用RequestBuilder,它将没有正文/实体的请求的查询参数转换为UrlEncodedFormEntity。

我正在将我的API转换为jax-rs,我不想破坏向后兼容性。有没有办法在不调整我的API的情况下使用Feign? OkHttp或Ribbon客户端是否支持具有查询参数且没有正文/实体的POST?还有另一个支持这个的java jax-rs客户端吗?

此外,RequestBuilder是否有理由将查询参数转换为UrlEncodedFormEntity?在apache-httpclient库中是否有另一个HttpUriRequest构建器不能执行此操作? RequestBuilder的构建方法包含以下代码行:

if (entity == null && (HttpPost.METHOD_NAME.equalsIgnoreCase(method) || HttpPut.METHOD_NAME.equalsIgnoreCase(method))) {
  entity = new UrlEncodedFormEntity(parameters, HTTP.DEF_CONTENT_CHARSET);
} else {
  // omitted expected behavior
}

在切换到Feign之前,我的代码构造了一个类似于以下内容的HttpUriRequest:

URI uri = new URIBuilder()
        .setScheme("https")
        .setHost("localhost")
        .setPath("service/do_something")
        .addParameter("arg", "value")
        .build();
HttpUriRequest request = new HttpPost(uri);

1 个答案:

答案 0 :(得分:0)

如果您愿意稍微破坏API并保持对@QueryParam的支持,那么您可以在假装客户端上定义请求拦截器,为请求添加纯文本实体/主体:

.requestInterceptor(template -> {
  if (template.method().equals(HttpPost.METHOD_NAME) && template.queries().keySet().size() > 0 && template.body() == null) {
    template.body(" ");
  }
})

然后,您的API将更改为以下内容:

@POST
@Consumes(MediaType.TEXT_PLAIN)
@Path("/do_something")
void doSomething(@QueryParam("arg") String arg);

但是,这打破了API,因为服务器现在期望/使用带有纯文本实体/正文的POST消息。

我认为可以在没有requestInterceptor和Feign的@Body模板的情况下完成同样的事情:

@POST
@Consumes(MediaType.TEXT_PLAIN)
@Body(" ")
@Path("/do_something")
void doSomething(@QueryParam("arg") String arg);

但是,这意味着您的API必须包含Feign而不是纯jax-rs注释。