Jetty:我如何使用FilterHolder“监控”传入的HTTP POST请求内容?

时间:2011-08-03 11:41:10

标签: java http servlets post jetty

我试着做...

来源

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() {
        }
    });

...但是吞下所有数据并且真正的servlet没有得到任何东西。

我只是想“阅读” POST请求内容并将其输出以进行调试。

注1:我不想“拦截”请求,它们应该像以前一样经历。

注意2:另外一个提示,如何对 POST回复做同样的事情会非常友好。

编辑Reader替换InputStreamReader根本不起作用。

3 个答案:

答案 0 :(得分:2)

知道了!我正在使用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);
}
}

答案 1 :(得分:0)

Servlet规范指出getInputStream 可能干扰例如getParameter(String name),请参阅this。因此,在调用getInputStream之后,您可能无法使用请求对象的“更高级别”功能。

您可以配置Jetty's request logging并与TeeFilter一起使用logback。它似乎实现了你需要的行为(从未使用过它)。

答案 2 :(得分:0)

鉴于posts将它们的key = value对存储在正文中,可以使用InputStream读取,你读取InputStream的行为可能会消耗它,这意味着当真正的servlet尝试检查它时IS是空的。