【问题标题】:Jetty: How could I use FilterHolder to "monitor" incoming HTTP POST request contents?Jetty:如何使用 FilterHolder 来“监控”传入的 HTTP POST 请求内容?
【发布时间】:2011-10-19 01:04:23
【问题描述】:

我试着做...

来源

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 根本不起作用。

【问题讨论】:

  • @Maurício Linhares -- Reader 导致异常,替换为 InputStream

标签: java http servlets post jetty


【解决方案1】:

知道了!我为 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);
}
}

【讨论】:

    【解决方案2】:

    Servlet 规范声明 getInputStream 可能 干扰例如getParameter(String name),见this。所以在调用getInputStream 之后,你可能无法使用请求对象的“更高级别”功能。

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-21
        • 2018-04-15
        • 1970-01-01
        相关资源
        最近更新 更多