Jetty: Как я могу использовать FilterHolder для «мониторинга» содержимого входящего HTTP-запроса POST? - PullRequest
1 голос
/ 03 августа 2011

Я пытался сделать ...

Источник

FilterHolder myHolder
    = new FilterHolder(new Filter() {
        public void init(FilterConfig fc) throws ServletException {
        }

        public void doFilter(ServletRequest req, ServletResponse resp,
                FilterChain fc) throws IOException, ServletException {
            HttpServletRequest httpReq = (HttpServletRequest) req;
            HttpServletResponse httpResp = (HttpServletResponse) resp;

            // HERE:
            InputStream is = httpReq.getInputStream();
            // (read is to a string and output it, works,
            // but swallows all data forever)

            fc.doFilter(httpReq, httpResp);
        }

        public void destroy() {
        }
    });

... но проглатывает все данные, а реальные сервлеты ничего не получают.

Я просто хочу "прочитать" POST-запрос содержимое и вывести их для отладки.

ПРИМЕЧАНИЕ 1. Я не хочу «перехватывать» запросы, они должны проходить, как раньше.

ПРИМЕЧАНИЕ 2. Дополнительный совет: как сделать то же самое с POST-ответами будет очень любезно.

РЕДАКТИРОВАТЬ Заменить Reader на InputStream. Reader вообще не работал.

Ответы [ 3 ]

2 голосов
/ 04 августа 2011

Понял!Я использую оболочку для InputStream и OutputStream каждый.
Протестировано.Работает в обоих направлениях.

HttpRequestCopyFilter

final class HttpRequestCopyFilter implements Filter {

private final OutputStream copyOutput;

public HttpRequestCopyFilter(OutputStream copyOutput) {
    this.copyOutput = copyOutput;
}

public void init(FilterConfig arg0) throws ServletException {
}

public void destroy() {
}

private void flushCopy() throws IOException {
    copyOutput.flush();
}

public void doFilter(ServletRequest req, ServletResponse resp,
        FilterChain fc) throws IOException, ServletException {
    HttpServletRequest httpReq = (HttpServletRequest) req;
    HttpServletResponse httpResp = (HttpServletResponse) resp;

    HttpServletRequestWrapper requestWrapper =
            new HttpServletRequestWrapper(httpReq) {

                @Override
                public ServletInputStream getInputStream()
                        throws IOException {
                    final ServletInputStream original =
                            super.getInputStream();

                    return new ServletInputStream() {

                        @Override
                        public int read() throws IOException {
                            int c = original.read();
                            if (c >= 0) {
                                copyOutput.write(c);
                                flushCopy();
                            }
                            return c;
                        }

                        @Override
                        public int read(byte[] b) throws IOException {
                            int count = original.read(b);
                            if (count >= 0) {
                                copyOutput.write(b, 0, count);
                                flushCopy();
                            }
                            return count;
                        }

                        @Override
                        public int read(byte[] b, int off, int len)
                                throws IOException {
                            int count = original.read(b, off, len);
                            if (count >= 0) {
                                copyOutput.write(b, off, count);
                                flushCopy();
                            }
                            return count;
                        }
                    };
                }
            };

    fc.doFilter(requestWrapper, httpResp);
}
}

HttpResponseCopyFilter

final class HttpResponseCopyFilter implements Filter {

private final OutputStream copyOutput;

public HttpResponseCopyFilter(OutputStream copyOutput) {
    this.copyOutput = copyOutput;
}

public void init(FilterConfig arg0) throws ServletException {
}

public void destroy() {
}

public void doFilter(ServletRequest req, ServletResponse resp,
        FilterChain fc) throws IOException, ServletException {
    HttpServletRequest httpReq = (HttpServletRequest) req;
    HttpServletResponse httpResp = (HttpServletResponse) resp;

    HttpServletResponseWrapper responseWrapper =
            new HttpServletResponseWrapper(httpResp) {

                @Override
                public ServletOutputStream getOutputStream()
                        throws IOException {
                    final ServletOutputStream original =
                            super.getOutputStream();
                    return new ServletOutputStream() {

                        @Override
                        public void write(int b) throws IOException {
                            original.write(b);
                            copyOutput.write(b);
                            flush();
                        }

                        @Override
                        public void write(byte[] b) throws IOException {
                            original.write(b);
                            copyOutput.write(b);
                            flush();
                        }

                        @Override
                        public void write(byte[] b, int off, int len)
                                throws IOException {
                            original.write(b, off, len);
                            copyOutput.write(b, off, len);
                            flush();
                        }

                        @Override
                        public void flush() throws IOException {
                            original.flush();
                            copyOutput.flush();
                            super.flush();
                        }

                        @Override
                        public void close() throws IOException {
                            original.close();
                            copyOutput.flush(); // DON'T CLOSE COPY-OUTPUT !!!
                            super.close();
                        }
                    };
                }
            };

    fc.doFilter(httpReq, responseWrapper);
}
}
0 голосов
/ 03 августа 2011

Если сообщения хранят свои пары ключ = значение в теле, которое может быть прочитано с использованием InputStream, сам процесс чтения InputStream может потреблять его, то есть IS пуст, когда реальный сервлет пытается это проверить.*

0 голосов
/ 03 августа 2011

В спецификации сервлета указано, что getInputStream может мешать, например, getParameter(String name), см. this .Поэтому после вызова getInputStream вы, возможно, не сможете использовать функции «объектов более высокого уровня» для объектов запроса.

Вы можете настроить Регистрация запросов Jetty и использовать logback вместе с TeeFilter.Кажется, вы реализуете необходимое вам поведение (никогда не использовали его).

...