代码之家  ›  专栏  ›  技术社区  ›  Serxipc

如何为java HttpURLConnection流量启用连线日志记录?

  •  39
  • Serxipc  · 技术社区  · 15 年前

    Jakarta commons HttpClient 在另一个项目中,我也希望如此 wire logging 输出,但使用“标准”HttpUrlConnection。

    Fiddler 作为代理,但我想直接从java记录流量。

    捕获连接输入和输出流的内容是不够的,因为HTTP头是由HttpUrlConnection类编写和使用的,所以我将无法记录头。

    8 回复  |  直到 10 年前
        1
  •  59
  •   sleske    7 年前

    Sun's HttpURLConnection source 有一些日志记录支持通过 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 . 但主要是 useful for SSL debugging .

        2
  •  16
  •   L. Cornelius Dol    7 年前

    SSLSocketFactory 在默认值之上。

    这对我来说很有效,因为我们所有的连接都使用HTTPS,我们可以使用该方法设置套接字工厂 HttpsURLConnection.setSSLSocketFactory .

    可以在以下位置找到一个更完整的解决方案,该解决方案支持对所有套接字进行监控: http://www.javaspecialists.eu/archive/Issue169.html 幸亏 Lawrence Dol 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();
                }
            }
        }
    }
    
        3
  •  10
  •   Gladwin Burboz    15 年前

    解决方案#1:使用装饰图案

    你必须使用 Decorator pattern 在…上 HttpURLConnection

    URLConnection.getOutputStream() OutputStream URLConnection.html#getInputStream() InputStream 输出流 输入流

    .

    编写一个简单的http代理服务器 并在应用程序启动和初始化期间在其单独的线程中启动。看见 Example simple proxy server .

    将应用程序配置为 谢谢你的请求。看见 configuring Java to use Proxies .

    您可以访问原始http流 “从客户端到服务器”以及“从服务器返回到客户端”。您必须解释这些原始信息,并根据需要将其记录下来。

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

      == Client System =============================== 
      |                                              | 
      |    ------------------------------            | 
      |   |                              |           | 
      |   |    Java process              |           | 
      |   |                       ----   |           | 
      |   |        ----------    |    |  |           | 
      |   |       |          |    -O  |  |           | 
      |   |       |  Logging |        |  |           | 
      |   |       |   Proxy <---HTTP--   |    -----  | 
      |   |       |  Adapter |           |   |     | | 
      |   |       |  Thread o------------------>   | | 
      |   |       |        o |           |   |     | | 
      |   |        --------|-            |   | Log | | 
      |   |                |             |    -----  | 
      |    ----------------|-------------            | 
      |                    |                         | 
      =====================|========================== 
                           |                           
                           |                           
                         HTTPS                         
                          SSL                          
                           |                           
      == Server System ====|========================== 
      |                    |                         | 
      |    ----------------|----------------         | 
      |   |                V                |        | 
      |   |                                 |        | 
      |   |   Web Server                    |        | 
      |   |                                 |        | 
      |    ---------------------------------         | 
      |                                              | 
      ================================================ 
    
        4
  •  6
  •   weberjn    9 年前

    在Linux中,您可以在strace下运行VM:

        5
  •  3
  •   pl.square    6 年前

    要使用Java 8环境刷新,请执行以下操作:

    下面是@sleske的答案

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

    对我来说,这是开箱即用的。

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

    所有其他的代码技巧对我来说都不起作用,但可能不够努力。

        6
  •  2
  •   Adam Batkin    15 年前

    我不认为您可以自动地这样做,但您可以子类化 FilterOutputStream FilterInputStream HttpUrlConnection

        7
  •  2
  •   danpaq    15 年前

    使用AspectJ插入切入点以在方法周围添加日志记录建议怎么样?我相信AspectJ可以将它编织成私有/受保护的方法。

    sun.net.www.protocol.http.HttpURLConnection.writeRequest可能会调用sun.net.www.http.HttpClient.writeRequest,它将MessageHeader对象作为输入,从而成为您的目标。

        8
  •  2
  •   beny23    15 年前

    偶尔,你只对网络上的内容感兴趣(标题、正文等),你可能想给出 wireshark a开始。