Spring Boot добавить тело запроса в объекте ответа об ошибке - PullRequest
0 голосов
/ 23 февраля 2019

У меня есть собственный обработчик исключений, который расширяет ResponseEntityExceptionHandler

Я могу зафиксировать ошибку, но тело запроса на момент создания ответа об ошибке пусто

override fun handleHttpMessageNotReadable(e:HttpMessageNotReadableException, headers:HttpHeaders , status:HttpStatus , webRequest: WebRequest):ResponseEntity<Any>{
        val rsp = ErrResponse(
                Data(
                        HttpStatus.BAD_REQUEST.name,
                        e.message!!
                ),**REQUEST-BODY-NEEDED**[customFilter.payload])
        return super.handleExceptionInternal(e, rsp,headers, HttpStatus.BAD_REQUEST, webRequest)
    }

Итак, у меня естьиспользовал customRequestfilter, чтобы получить тело и захватил тело там, но приоритет для заказа низкий для customRequestFilter, он будет выполнен только после запроса.Так есть ли способ захватить тело запроса на ответ об ошибке?

CustomRequestFilter

@Component
public class CustomRequestFilter extends OncePerRequestFilter{

 public String payload;
    public Map<String, Object> reqLog =null;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);

        int status = HttpStatus.BAD_REQUEST.value();

        filterChain.doFilter(wrappedRequest, response);
        if (status == response.getStatus()) {
            reqLog = getTrace(wrappedRequest, status);
            payload = getBody(wrappedRequest, reqLog);/** ITS CAPTURING THE BODY HERE SUCCESSFULLY**/
            logTrace(wrappedRequest, reqLog); 
        }

    }

1 Ответ

0 голосов
/ 23 февраля 2019

Ого, это было сложно!В любом случае ...

Создайте свой пользовательский HttpInputMessage, который будет делегироваться к исходному.

class CachedHttpInputMessage implements HttpInputMessage {
    private final HttpInputMessage httpInputMessage;
    private ByteArrayOutputStream outputStream;

    CachedHttpInputMessage(final HttpInputMessage httpInputMessage) {
        this.httpInputMessage = httpInputMessage;
    }

    @Override
    public InputStream getBody() throws IOException {
        if (outputStream == null) {
            outputStream = new ByteArrayOutputStream();

            final InputStream body = httpInputMessage.getBody();
            final byte[] buffer = new byte[1024];

            while (true) {
                final int length;
                if (!((length = body.read(buffer)) > -1)) {
                    break;
                }

                outputStream.write(buffer, 0, length);
            }

            outputStream.flush();
        }

        return new ByteArrayInputStream(outputStream.toByteArray());
    }

    @Override
    public HttpHeaders getHeaders() {
        return httpInputMessage.getHeaders();
    }
}

Создайте свой пользовательский HttpMessageConverter, расширяя нужный на основе используемых в настоящее времяодин (Jackson, Gson и т. д.) и зарегистрируйте его как первый.

class CustomHttpMessageConverter extends MappingJackson2HttpMessageConverter {
    @Override
    public Object read(
            final Type type,
            final Class<?> contextClass,
            final HttpInputMessage inputMessage) throws IOException {
        return super.read(type, contextClass, new CachedHttpInputMessage(inputMessage));
    }

    @Override
    protected Object readInternal(
            final Class<?> clazz,
            final HttpInputMessage inputMessage) throws IOException {
        return super.readInternal(clazz, new CachedHttpInputMessage(inputMessage));
    }
}

(в качестве альтернативы вы можете создать универсальную оболочку, как в CachedHttpInputMessage, и обернуть каждуюнастроен HttpMessageConverter, просто обновите список, переданный в качестве ввода, до extendMessageConverters)


@Configuration
class WebConfiguration implements WebMvcConfigurer {
    @Override
    public void extendMessageConverters(final List<HttpMessageConverter<?>> converters) {
        converters.add(0, new CustomHttpMessageConverter());
    }

    ...
 }

Выбросьте пользовательский Filter, а внутри ExceptionHandler прочитайте тело, используя

final HttpInputMessage inputMessage = e.getHttpInputMessage();
final InputStream body = inputMessage.getBody();

Готово!
Не забудьте немного очистить код и обработать все возможные исключения.

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