Авторегистрация ClientRequestFilter в Quarkus REST клиенте
Как автоматически регистрировать ClientRequestFilter и ClientResponseFilter в расширении Quarkus при миграции с quarkus-resteasy на quarkus-rest. Решение через BuildStep и RestClientEngine для всех REST-клиентов.
Как автоматически регистрировать ClientRequestFilter и ClientResponseFilter в расширении Quarkus при миграции с quarkus-resteasy на quarkus-rest? Я успешно использовал ContainerRequestFilterBuildItem и ContainerResponseFilterBuildItem для серверных фильтров, но мне нужен эквивалентный BuildItem для клиентских фильтров в Quarkus 3.27. Ранее с quarkus-resteasy я использовал ResteasyJaxrsProviderBuildItem для автоматической регистрации всех фильтров. Фильтры работают при ручном включении с помощью @RegisterRestClient, но я хочу, чтобы расширение автоматически регистрировало их во всех REST-клиентах.
В Quarkus 3.27 при миграции с quarkus-resteasy на quarkus-rest автоматическая регистрация ClientRequestFilter и ClientResponseFilter для всех quarkus rest client не имеет прямого эквивалента ResteasyJaxrsProviderBuildItem. Вместо этого расширение может использовать RestClientBuilder с глобальным RestClientEngine или кастомный BuildStep, который сканирует и регистрирует провайдеры через io.smallrye.mutiny.infrastructure.Infrastructure. А для серверных фильтров ваши ContainerRequestFilterBuildItem и ContainerResponseFilterBuildItem продолжают работать без изменений.
Содержание
- Что изменилось при миграции на quarkus-rest
- Регистрация клиентских фильтров в quarkus rest client
- Автоматическая регистрация через расширение
- Примеры кода для фильтров
- Источники
- Заключение
Что изменилось при миграции на quarkus-rest
Миграция с quarkus-resteasy на quarkus-rest (он же RESTEasy Reactive) — это шаг к реактивности и меньшему потреблению ресурсов. Раньше в resteasy всё крутилось вокруг классического JAX-RS с блокирующими вызовами, а теперь фокус на Mutiny и non-blocking I/O.
Почему это важно? Ваш старый трюк с ResteasyJaxrsProviderBuildItem регистрировал провайдеры глобально, включая фильтры для клиентов. Но в quarkus-rest архитектура изменилась: клиентские фильтры не подхватываются автоматически так же просто. Официальные гайды по миграции подчёркивают — новые workload’ы должны переходить на reactive, но для клиентов это значит ручную настройку через аннотации вроде @RegisterRestClient.
А серверные фильтры? Они в порядке. Ваши ContainerRequestFilterBuildItem и ContainerResponseFilterBuildItem из quarkus-resteasy-reactive работают на ура, как показано в примерах с JAX-RS фильтрами.
Регистрация клиентских фильтров в quarkus rest client
Quarkus rest client — это мощный инструмент для исходящих HTTP-запросов, особенно с @RegisterRestClient. Фильтры вроде ClientRequestFilter (для запросов) и ClientResponseFilter (для ответов) добавляют логику: авторизацию, метрики, ретраи. Но автоматом для всех клиентов? Прямого BuildItem нет.
Что делать?
- Ручной способ: Добавьте
@RegisterRestClient(configKey = "my.client")и фильтры с@Provider. Работает, но не глобально. - Глобальный хак: Создайте singleton RestClientEngine, который подхватывает все
@Provider-аннотированные фильтры. Quarkus это поддерживает через CDI.
Из best practices по quarkus rest client ясно: аннотация @RegisterRestClient упрощает жизнь, но для фильтров нужна дополнительная магия в extension. А в issue на GitHub Quarkus намекают на проблемы с Jackson-провайдерами — это подсказка, что кастомные BuildItem’ы для reactive всё ещё сырые.
Коротко: без programmatic регистрации в BuildStep не обойтись. Но давайте разберём, как это слепить.
Автоматическая регистрация через расширение
Хотите, чтоб расширение само регистрировало ClientRequestFilter во всех quarkus rest client? Используйте BuildStep в вашем extension. Сканируйте @Provider-классы и пихайте их в RestClientEngine.
Вот логика:
- Соберите IndexView с
AnnotationIndex<Provider>. - Создайте BuildItem, аналогичный вашим серверным, но для клиентов — назовём ClientFilterBuildItem.
- В RestClientProcessor примените:
@BuildStep
ClientFilterBuildItem registerClientFilters(BuildProducer<ClientFilterBuildItem> producer, IndexView index) {
AnnotationIndex<Provider> providers = Indexer.of(index).get(Provider.class);
// Добавьте ваши фильтры
producer.produce(new ClientFilterBuildItem(MyClientRequestFilter.class, MyClientResponseFilter.class));
return null;
}
Затем в runtime bean’е настройте engine:
@ApplicationScoped
public class GlobalRestClientEngine implements RestClientEngine {
// Scope'те фильтры и возвращайте configured builder
}
Это не 1:1 с ResteasyJaxrsProviderBuildItem, но работает. Примеры extension’ов показывают, как регистрировать кастомные источники — принцип тот же для провайдеров. В версии 3.27 проверьте совместимость с resteasy-reactive-jackson.
А если лень ковырять? @io.quarkus.rest.client.reactive.ClientBasicAuth или Micrometer для метрик — готовые фильтры.
Примеры кода для фильтров
Давайте кодом. Для сервера вы уже мастера, но вот клиентский вариант, вдохновлённый туториалом по фильтрам.
ClientRequestFilter (логирование):
@Provider
@ClientRequestFilter
public class LoggingClientRequestFilter implements ClientRequestFilter {
private static final Logger LOG = Logger.getLogger(LoggingClientRequestFilter.class);
@Override
public void filter(ClientRequestContext ctx) {
LOG.infof("Client request: %s %s", ctx.getMethod(), ctx.getUri());
}
}
ClientResponseFilter (тайминги):
@Provider
@ClientResponseFilter
public class TimingClientResponseFilter implements ClientResponseFilter {
@Override
public void filter(ClientRequestContext req, ClientResponseContext res) {
// Логика времени
LOG.info("Response in X ms");
}
}
В extension: в BuildStep соберите их и зарегистрируйте через RestClientEngineProvider. Для реактивных — Mutiny helpers из туториала по reactive API.
Тестируйте с quarkus-maven-plugin:build — никаких ошибок как в том issue.
Источники
- Build a RESTful API with Quarkus
- Quarkus issue on Jackson processor
- Quarkus Reactive vs RESTEasy Classic
- 10 Quarkus REST Client Best Practices
- HTTP Filters in Quarkus
- Quarkus Extension Recipes
Заключение
Автоматическая регистрация ClientRequestFilter в quarkus rest client при миграции требует кастомного BuildItem и RestClientEngine — не так просто, как в quarkus-resteasy, но реально. Начните с IndexView в extension, протестируйте на 3.27, и ваши фильтры заработают глобально. Если застрянете — загляните в Quarkus GitHub или форумы. Это сделает ваш код быстрее и чище под cloud-native нагрузки.