【问题标题】:Parsing raw HTTP Request解析原始 HTTP 请求
【发布时间】:2012-10-26 16:14:40
【问题描述】:

我正在研究由完整的 POST 和 GET 请求组成的 HTTP 流量数据集,如下所示。我已经在 java 中编写了代码,将这些请求中的每一个分开并将其保存为数组列表中的字符串元素。 现在我很困惑如何在 java 中解析这些原始 HTTP 请求,有没有比手动解析更好的方法?

GET http://localhost:8080/tienda1/imagenes/3.gif/ HTTP/1.1
User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.8 (like Gecko)
Pragma: no-cache
Cache-control: no-cache
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Encoding: x-gzip, x-deflate, gzip, deflate
Accept-Charset: utf-8, utf-8;q=0.5, *;q=0.5
Accept-Language: en
Host: localhost:8080
Cookie: JSESSIONID=FB018FFB06011CFABD60D8E8AD58CA21
Connection: close

【问题讨论】:

  • 你需要在哪里解析这些?在 Servlet 或类似技术(或)普通 Java 类中?
  • 数据从何而来?你需要解析什么?
  • 如果您绝对必须直接执行 HTTP 并且这不是针对课程的,我强烈建议使用 Apache Commons HttpClient 之类的东西。自己做有很多陷阱。 (例如分块传输编码)
  • @AliAhmad - 你到底想完成什么?如果您使用的是 HttpClient 类,则无需手动解析 HTTP 数据流。
  • 您已经询问过如何解析 HTTP,但这可能意味着很多事情,具体取决于您尝试从原始流中提取的内容。在没有说明你的最终目标的情况下,这个问题对于 SO 来说几乎是“没有建设性的”。

标签: java http-headers


【解决方案1】:

如果您只想按原样发送原始请求,这非常简单,只需使用 TCP 套接字发送实际的字符串!

类似这样的:

    Socket socket = new Socket(host, port);

    BufferedWriter out = new BufferedWriter(
            new OutputStreamWriter(socket.getOutputStream(), "UTF8"));

    for (String line : getContents(request)) {
        System.out.println(line);
        out.write(line + "\r\n");
    }

    out.write("\r\n");
    out.flush();

查看 JoeJag 的 blog post 获取完整代码。

更新

我开始了一个项目,RawHTTP 为请求、响应、标头等提供 HTTP 解析器......结果非常好,它使得在其上编写 HTTP 服务器和客户端变得非常容易。如果您正在寻找低级别的东西,请查看它。

【讨论】:

    【解决方案2】:

    为了您的方便,这里有一个适用于所有方法类型(GET、POST 等)的通用 Http 请求解析器:

        package util.dpi.capture;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.StringReader;
    import java.util.Hashtable;
    
    /**
     * Class for HTTP request parsing as defined by RFC 2612:
     * 
     * Request = Request-Line ; Section 5.1 (( general-header ; Section 4.5 |
     * request-header ; Section 5.3 | entity-header ) CRLF) ; Section 7.1 CRLF [
     * message-body ] ; Section 4.3
     * 
     * @author izelaya
     *
     */
    public class HttpRequestParser {
    
        private String _requestLine;
        private Hashtable<String, String> _requestHeaders;
        private StringBuffer _messagetBody;
    
        public HttpRequestParser() {
            _requestHeaders = new Hashtable<String, String>();
            _messagetBody = new StringBuffer();
        }
    
        /**
         * Parse and HTTP request.
         * 
         * @param request
         *            String holding http request.
         * @throws IOException
         *             If an I/O error occurs reading the input stream.
         * @throws HttpFormatException
         *             If HTTP Request is malformed
         */
        public void parseRequest(String request) throws IOException, HttpFormatException {
            BufferedReader reader = new BufferedReader(new StringReader(request));
    
            setRequestLine(reader.readLine()); // Request-Line ; Section 5.1
    
            String header = reader.readLine();
            while (header.length() > 0) {
                appendHeaderParameter(header);
                header = reader.readLine();
            }
    
            String bodyLine = reader.readLine();
            while (bodyLine != null) {
                appendMessageBody(bodyLine);
                bodyLine = reader.readLine();
            }
    
        }
    
        /**
         * 
         * 5.1 Request-Line The Request-Line begins with a method token, followed by
         * the Request-URI and the protocol version, and ending with CRLF. The
         * elements are separated by SP characters. No CR or LF is allowed except in
         * the final CRLF sequence.
         * 
         * @return String with Request-Line
         */
        public String getRequestLine() {
            return _requestLine;
        }
    
        private void setRequestLine(String requestLine) throws HttpFormatException {
            if (requestLine == null || requestLine.length() == 0) {
                throw new HttpFormatException("Invalid Request-Line: " + requestLine);
            }
            _requestLine = requestLine;
        }
    
        private void appendHeaderParameter(String header) throws HttpFormatException {
            int idx = header.indexOf(":");
            if (idx == -1) {
                throw new HttpFormatException("Invalid Header Parameter: " + header);
            }
            _requestHeaders.put(header.substring(0, idx), header.substring(idx + 1, header.length()));
        }
    
        /**
         * The message-body (if any) of an HTTP message is used to carry the
         * entity-body associated with the request or response. The message-body
         * differs from the entity-body only when a transfer-coding has been
         * applied, as indicated by the Transfer-Encoding header field (section
         * 14.41).
         * @return String with message-body
         */
        public String getMessageBody() {
            return _messagetBody.toString();
        }
    
        private void appendMessageBody(String bodyLine) {
            _messagetBody.append(bodyLine).append("\r\n");
        }
    
        /**
         * For list of available headers refer to sections: 4.5, 5.3, 7.1 of RFC 2616
         * @param headerName Name of header
         * @return String with the value of the header or null if not found.
         */
        public String getHeaderParam(String headerName){
            return _requestHeaders.get(headerName);
        }
    }
    

    【讨论】:

      【解决方案3】:

      我 [正在] 处理 [an] HTTP 流量数据集,该数据集由完整的 POST 和 GET 请求[s] 组成

      所以你想解析一个包含多个 HTTP 请求的文件或列表。你想提取什么数据?总之here是一个Java HTTP解析类,它可以读取请求行中使用的方法、版本和URI,并将所有的headers读入一个Hashtable。

      如果您想重新发明轮子,您可以使用它或自己编写一个。查看RFC 以了解请求的外观以便正确解析它:

      Request       = Request-Line              ; Section 5.1
                          *(( general-header        ; Section 4.5
                           | request-header         ; Section 5.3
                           | entity-header ) CRLF)  ; Section 7.1
                          CRLF
                          [ message-body ]          ; Section 4.3
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-12-29
        • 1970-01-01
        • 2021-12-23
        • 1970-01-01
        • 2011-06-08
        • 2014-01-06
        • 2021-01-18
        相关资源
        最近更新 更多