5

给定 HTTP 请求标头,是否有人有建议或知道现有代码以正确解析标头?我正在尝试仅使用 Core Java 执行此操作,没有第三方库

编辑:

尝试从此字符串中查找关键字段,例如:

GET / HTTP/1.1User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15Host: localhost:9000Accept: /

想解析出Method和method

4

4 回答 4

4

首先阅读和理解HTTP 规范

请求行和标头由 CR LF 序列(十进制值 13 和 10 的字节)分隔,因此您可以读取流并分离出每一行。我相信标头必须以 US-ASCII 编码,因此您可以简单地将字节转换为字符并附加到 a StringBuilder(但检查规范:它可能允许 ISO-8859-1 或其他编码)。

标题的结尾由 CR LF CR LF 表示。

于 2012-08-16T14:54:12.917 回答
3

我编写了一个库RawHTTP,其唯一目的是解析 HTTP 消息(请求和响应)。

如果您不想使用库,您可以将源代码复制到您自己的代码库中,从以下开始:https ://github.com/renatoathaydes/rawhttp/blob/a6588b116a4008e5b5840d4eb66374c0357b726d/rawhttp-core/src/main/ java/com/athaydes/rawhttp/core/RawHttp.java#L52

这会将 HTTP 消息的行一直拆分到元数据部分的末尾(起始行 + 标头)。

有了手头的元数据行列表,您就可以调用该parseHeaders方法,该方法将为您创建标题。您可以轻松地将其调整为仅返回 aMap<String, List<String>>以避免还必须导入头类。

也就是说... RawHTTP 没有依赖项,所以我会使用它来代替:) 但这取决于你。

于 2018-03-15T17:42:16.610 回答
2

您连接的单行字符串不是 HTTP 标头。

正确的 HTTP 请求消息应如下所示(并非总是如此)

GET / HTTP/1.1 CRLF
Host: localhost:9000 CRLF
User-Agent: curl/7.19.7 blar blar CRLF
Accept: */* CRLF
Content-Length: ?? CRLF
...: ... CRLF
CRLF
octets

见这里http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html

如果你想在没有任何 Sevlets、JavaEE 容器帮助的情况下实现 HTTP 服务器,你应该使用 Sockets。

  1. 阅读第一行 [Request-Line = Method SP Request-URI SP HTTP-Version CRLF]
  2. 逐行读取请求标题,直到得到空行
  3. 对于每个标题行,您可以解析 [fieldName: fieldValue]
  4. 读取实体主体。

这不是 HTTP 消息合约的唯一情况。

于 2012-08-16T14:59:40.187 回答
0

我正在使用 guava 库来包含我的方法的先决条件。您可以删除它们以支持空检查。

  /**
   * @return a string consisting of the HTTP headers, concatenating the keys and values delimited by
   * CFLR (empty line) capable of serialization to the database.
   */
  public static final String httpHeadersToString(final HttpResponse httpResponse) {
    Preconditions.checkNotNull(httpResponse);
    Preconditions.checkNotNull(httpResponse.getAllHeaders());

    final Header[] allHeaders = httpResponse.getAllHeaders();
    StringBuffer sb = new StringBuffer();
    int index = 0;
    while(index < allHeaders.length) {
      Header header = allHeaders[index];

      sb.append(header.getName())
         .append(System.getProperty("line.separator"))
         .append(header.getValue());

      if (++index < allHeaders.length) {
        sb.append(System.getProperty("line.separator"));
      }
    }
    return sb.toString();
  }

  /**
   * @return reconstruct HTTP headers from a string, delimited by CFLR (empty line).
   */
  public final HttpHeaders stringToHttpHeaders(final String headerContents) {
    HttpHeaders httpHeaders = new HttpHeaders();
    final String[] tempHeaderArray = headerContents.split(System.getProperty("line.separator"));
    int i = 0;
    while (i + 1 <= tempHeaderArray.length) {
      httpHeaders.add(tempHeaderArray[i++], tempHeaderArray[i++]);
    }
    return httpHeaders;
  }
于 2015-06-19T11:37:58.163 回答