如何启用为Java HttpURLConnection的业务线记录?(How to enable w

2019-07-18 12:38发布

我使用的Jakarta Commons的HttpClient在另一个项目,我想同样的丝日志输出,但使用“标准” HttpURLConnection类。

我用菲德勒作为代理,但我想直接从Java记录的流量。

捕获由连接输入和输出流发生的事情是不够的,因为HTTP头书面和HttpURLConnection的类消费,所以我将无法登录的头。

Answer 1:

据Sun公司的HttpURLConnection的来源有通过一些日志支持JUL 。

设置(根据需要进行调整路径):

-Djava.util.logging.config.file=/full/path/to/logging.properties

logging.properties:

handlers= java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = FINEST
sun.net.www.protocol.http.HttpURLConnection.level=ALL

这将登录到控制台,按要求,例如日志文件进行调整。

示例输出:

2010-08-07 00:00:31 sun.net.www.protocol.http.HttpURLConnection writeRequests
FIN: sun.net.www.MessageHeader@16caf435 pairs: {GET /howto.html HTTP/1.1: null}{User-Agent: Java/1.6.0_20}{Host: www.rgagnon.com}{Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2}{Connection: keep-alive}
2010-08-07 00:00:31 sun.net.www.protocol.http.HttpURLConnection getInputStream
FIN: sun.net.www.MessageHeader@5ac0728 pairs: {null: HTTP/1.1 200 OK}{Date: Sat, 07 Aug 2010 04:00:33 GMT}{Server: Apache}{Accept-Ranges: bytes}{Content-Length: 17912}{Keep-Alive: timeout=5, max=64}{Connection: Keep-Alive}{Content-Type: text/html}

请注意,这仅打印头无身。

见http://www.rgagnon.com/javadetails/java-debug-HttpURLConnection-problem.html了解详情。

还有系统属性-Djavax.net.debug=all 。 但它主要是用于SSL调试有用 。



Answer 2:

我已经能够登录实现我自己的所有SSL流量的SSLSocketFactory上默认的顶部。

这为我工作,因为我们所有的连接都使用HTTPS,我们可以设置套接字工厂与方法HttpsURLConnection.setSSLSocketFactory 。

更完整的解决方案,使所有的插座监控,可以发现http://www.javaspecialists.eu/archive/Issue169.html感谢劳伦斯·多尔在使用的指向正确的方向Socket.setSocketImplFactory

这是我没有准备好生产代码:

public class WireLogSSLSocketFactory extends SSLSocketFactory {

    private SSLSocketFactory delegate;

    public WireLogSSLSocketFactory(SSLSocketFactory sf0) {
        this.delegate = sf0;
    }

    public Socket createSocket(Socket s, String host, int port,
            boolean autoClose) throws IOException {
        return new WireLogSocket((SSLSocket) delegate.createSocket(s, host, port, autoClose));
    }

    /*
    ...
    */

    private static class WireLogSocket extends SSLSocket {

        private SSLSocket delegate;

        public WireLogSocket(SSLSocket s) {
            this.delegate = s;
        }

        public OutputStream getOutputStream() throws IOException {
            return new LoggingOutputStream(delegate.getOutputStream());
        }

        /*
        ...
        */

        private static class LoggingOutputStream extends FilterOutputStream {
            private static final Logger logger = Logger.getLogger(WireLogSocket.LoggingOutputStream.class);
            //I'm using a fixed charset because my app always uses the same. 
            private static final String CHARSET = "ISO-8859-1";
            private StringBuffer sb = new StringBuffer();

            public LoggingOutputStream(OutputStream out) {
                super(out);
            }

            public void write(byte[] b, int off, int len)
                    throws IOException {
                sb.append(new String(b, off, len, CHARSET));
                logger.info("\n" + sb.toString());
                out.write(b, off, len);
            }

            public void write(int b) throws IOException {
                sb.append(b);
                logger.info("\n" + sb.toString());
                out.write(b);
            }

            public void close() throws IOException {
                logger.info("\n" + sb.toString());
                super.close();
            }
        }
    }
}


Answer 3:

解决方案#1:使用装饰模式

你将不得不使用Decorator模式上HttpURLConnection的类来扩展它的功能。 然后覆盖所有HttpURLConnection的方法(或多个)和委托操作元器件指针以及捕获所需的信息和记录它。

另外,还要确保你覆盖父类URLConnection.getOutputStream() : 为OutputStream和URLConnection.html#的getInputStream() : InputStream的方法,以返回装饰的OutputStream和InputStream的对象以及。

解决方案2:使用自定义,在内存中的http代理

编写一个简单的HTTP代理服务器 ,并将它开始在它的在应用程序启动和初始化单独的线程。 请参见以下是一个简单的代理服务器 。

必须配置为使用上面的所有请求的HTTP代理应用程序。 请参阅配置Java使用代理 。

现在,所有的流量正在经历上面的代理,就像它在小提琴手是如何发生的。 因此,你可以访问原始HTTP流 “从客户端到服务器”以及“回从服务器到客户端”。 你将不得不解释这个原始信息,并记录它的要求。

更新:使用HTTP代理作为适配器基于SSL的Web服务器。

  == Client System =============================== 
  |                                              | 
  |    ------------------------------            | 
  |   |                              |           | 
  |   |    Java process              |           | 
  |   |                       ----   |           | 
  |   |        ----------    |    |  |           | 
  |   |       |          |    -O  |  |           | 
  |   |       |  Logging |        |  |           | 
  |   |       |   Proxy <---HTTP--   |    -----  | 
  |   |       |  Adapter |           |   |     | | 
  |   |       |  Thread o------------------>   | | 
  |   |       |        o |           |   |     | | 
  |   |        --------|-            |   | Log | | 
  |   |                |             |    -----  | 
  |    ----------------|-------------            | 
  |                    |                         | 
  =====================|========================== 
                       |                           
                       |                           
                     HTTPS                         
                      SSL                          
                       |                           
  == Server System ====|========================== 
  |                    |                         | 
  |    ----------------|----------------         | 
  |   |                V                |        | 
  |   |                                 |        | 
  |   |   Web Server                    |        | 
  |   |                                 |        | 
  |    ---------------------------------         | 
  |                                              | 
  ================================================ 


Answer 4:

在Linux中,你可以在strace的运行VM:

strace的-o strace.out -s -e 4096一丝=网络-f java的...



Answer 5:

我不认为你可以自动做到这一点,但你可以继承FilterOutputStream中和FilterInputStream中与HttpUrlConnection作为参数的输出和输入流。 然后,随着字节写入/读取,记录它们,以及通过将它们传递到底层流。



Answer 6:

怎么样使用AspectJ插入一个切入点来绕方法添加日志记录的建议? 我相信的AspectJ可以编织它的方式进入私人/保护方法。

看来,sun.net.www.protocol.http.HttpURLConnection.writeRequest可致电sun.net.www.http.HttpClient.writeRequest它接受的MessageHeader对象作为输入所以这将是你的目标。

最后,这可能会奏效,但将是非常脆弱的,只有在Sun JVM工作; 真的,你只能相信你正在使用的确切版本。



Answer 7:

在关闭的机会,你是只在上线(头,体等)的含量越来越有兴趣,你可能想给Wireshark的一展身手。

这并没有改变任何代码,但如果能够通过代码记录了你以后,这个答案是不适用的优势。



Answer 8:

与Java 8环境刷新:

继@sleske答案

System.setProperty("javax.net.debug","all");

为我工作开箱。

也就是@weberjn建议

strace -o strace.out -s 4096 -e trace=network -f java

但如果与SSL流量处理,因为它转储编码流没有用的。

所有其它代码的技巧并没有为我工作,但也许并不想努力不够。



文章来源: How to enable wire logging for a java HttpURLConnection traffic?