Spring Cloud Gateway - обработка недовольных путей в фильтрах (обработка исключений или обработка ответов) с телом ответа - PullRequest
0 голосов
/ 24 апреля 2020

Каков наилучший (или наиболее эффективный способ) реализации управления несчастными путями с помощью фильтров SCG и ответа с телом? Обработка исключений или перезапись ответов?

Сценарий

Мы реализуем шлюз API с некоторыми сложными фильтрами GatewayFilter (между различными типами регулирования и некоторыми другими поведениями), которые имеют общий несчастный путь, где они заканчиваются обработка цепочки обмена и должна немедленно вернуть ответ 4xx с указанным c общим форматом тела (json / xml на основе заголовка Accept, у нас есть устаревшие требования совместимости).

Первоначальное решение

Первоначально я решил использовать фильтр, а затем попытаться написать ответ с одним из этих параметров:

response.setStatusCode(..);
//set headers
return response.writeAndFlushWith(...);

или

response.setStatusCode(..);
//set headers
return response.writeWith(...);

или даже

response.setStatusCode(..);
exchange.mutate().response(...);
return response.setComplete();

в каждом указанном c фильтре. Но обработка ответа тела кажется довольно многословным процессом, плюс форматирование ошибки, обеспечиваемое фильтром, не должно беспокоить специфицированный c фильтр. Мы хотим разделения интересов, поэтому фильтр должен определять заголовки, статус и сообщение об ошибке, но кто-то другой должен преобразовать это в надлежащий формат ответа.

Так что после долгого (и кровавого :)) обсуждения мы пришли с двумя возможными вариантами. Давайте предположим, что у нас есть 4 фильтра, и наш счастливый путь был бы (с некоторым приближением без учета наложения из глобального порядка фильтров):

(initial global filters) -> 1 -> 2 -> 3 -> 4-> 5 -> (other global filters) -> Routing -> (other global filters) -> 5 -> 4-> 3 -> 2 -> 1 -> 0 -> (initial global filters) -> Response

Вариант 1 - Обработка ошибок

Реализуйте класс java MyErrorHandler extends DefaultErrorWebExceptionHandler и java MyErrorAttributes extends DefaultErrorAttributes, и это делает волхвы c.

Это означает, что в фильтре Speci c выдается исключение, которое расширяет ResponseStatusException или аннотируется @ResponseStatus и направить его в ExceptionHandler. Это имеет преимущество в том, что прерывает всю обработку обмена в фильтрах, если я не ошибаюсь. Например: учитывая 3 фильтра и фильтр 3, создающий исключение, мы имеем ... 1 -> 2 -> 3 -> ExH -> (other global filters) -> Response

Вариант 2 - Запись ответа

Добавить фильтр (фильтр 0) в верхнюю позицию, возможно, один расширяющийся ModifyResponseGatewayFilter который управляет ошибками записи в ответе, просматривая специфицированный c атрибут обмена (например: gateway.error) для bean-компонента и записывает ответ, и имеет фильтр в цепочке, задающий c bean и сгенерируйте ответ с этим.

Это будет иметь следующий поток: ... -> 0 -> 1 -> 2 -> 3 -> 2 -> 1 -> 0 -> (other global filters) -> Response

Проблемы

Опция

  1. Опция 1 кажется опцией короткого замыкания, которая действительно блокирует обработку и основывается на существующих возможностях (ExceptionHandler), но мне говорят, что исключения являются ужасным бременем для эффективности, так как они вынуждены строить всю трассировку стека
  2. Вариант 2, кажется, более эффективный, но тогда ответ пузырится через все «постовые» фильтры, и мы должны убедиться, что никакой другой фильтр не пытается обновить ответ, проверяя специфицируемый c атрибут обмена (например: gateway.error)

RedisRateLimiter, предлагаемый SCG, использует option2, но не переписывает тело и использует response.setComplete(), но это не ' Позволяет переписывать любое тело позже.

Является ли это предпочтительным подходом?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...