Как сделать Feign POST-запрос без тела запроса и с параметрами запроса?

Я использую Feign с Apache Http Client, и я хотел бы поддержать следующий интерфейс jax-rs:

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

Но ApacheHttpClient использует RequestBuilder, который преобразует параметры запроса для запросов без тела / сущности в UrlEncodedFormEntity.

Я конвертирую свои API в jax-rs и не хочу нарушать обратную совместимость. Есть ли способ использовать Feign без настройки моего API? Будут ли клиенты 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 ответ

Если вы хотите немного сломать 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's @Body шаблон:

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

Но это означает, что ваш API должен включать в себя Feign, а не чисто jax-rs аннотации.

Другие вопросы по тегам