Пользовательский фильтр Zuul — тело запроса журнала

У меня есть собственный (предварительный) фильтр zuul, в котором я хочу регистрировать requestBody запроса на API (API доступен в службе, которая зарегистрирована в Eureka), но когда я использую приведенный ниже код в ZUUL

HttpServletRequest request.getReader(); or RequestContext.getCurrentContext().getRequest().getInputStream();

Я могу зарегистрировать requestBody, но -

Проблема: служба, имеющая API, не может получить requestBody, потому что невозможно снова вызвать getReader для того же запроса. Я понимаю, что мне нужно иметь что-то, что расширяет HttpServletRequestWrapper и переопределяет метод getReader(), но я не уверен, как обрабатывать в контексте ZUUL, как перенаправить запрос вместе с requestBody в службу из ZUUL после его регистрации.

Любое предложение будет полезно.


person Vijaykumar Arumugam    schedule 23.03.2016    source источник
comment
Мне удалось решить эту проблему с помощью HttpServletRequestWrapper, опубликую код.   -  person Vijaykumar Arumugam    schedule 23.03.2016


Ответы (1)


Вы можете напрямую обернуть входящий запрос в экземпляр HttpServletRequestWrapper. Вот пример кода. Надеюсь это поможет.

package com.example.edge.filter.pre;

import com.google.common.io.CharStreams;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.HttpServletRequestWrapper;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Component
public class RequestPayloadLoggingFilter extends ZuulFilter {

    private static Logger log = LoggerFactory.getLogger(RequestPayloadLoggingFilter.class);

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 2;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = new HttpServletRequestWrapper(ctx.getRequest());

        log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));

        String requestData = null;
        JSONParser jsonParser = new JSONParser();
        JSONObject requestJson = null;

        try {
            if (request.getContentLength() > 0 ) {
                requestData = CharStreams.toString(request.getReader());
            }

            if (requestData == null) {
                return null;
            }
            requestJson = (JSONObject) jsonParser.parse(requestData);
        } catch (Exception e) {
            log.error("Error parsing JSON request", e);
            return null;
        }
        log.info(String.format("%s request payload %s", request.getMethod(), requestJson.toJSONString()));
        return null;
    }
}
person ymkale    schedule 06.05.2018
comment
Любая идея, как зарегистрировать как тело запроса, так и ответ на вызов API через шлюз Zuul? Похоже, я могу зарегистрировать либо запрос, либо ответ, но не оба, в одном и том же фильтре. Я хотел бы иметь что-то вроде журнала доступа для всех моих вызовов API, включая код ответа. - person Kevin M; 24.06.2020