不使用第 3 方库(Core Java)从 HTTP 请求字符串解析 HTTP 标头的最佳方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11989651/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best way to parse HTTP headers from HTTP request String using no 3rd party libs (Core Java)
提问by Zugdud
Given an HTTP request header, does anyone have suggestions or know of existing code to properly parse the header? I am trying to do this with Core Java only, no third party libs
给定一个 HTTP 请求标头,有没有人有建议或知道正确解析标头的现有代码?我正在尝试仅使用 Core Java 来执行此操作,没有第三方库
Edit:
编辑:
Trying to find key fields from this String for example:
尝试从该字符串中查找关键字段,例如:
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: /
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: /
Want to parse out the Method and method
想解析出Method和方法
回答by parsifal
Start by reading and understanding the HTTP specification.
首先阅读和理解HTTP 规范。
The request line and headers are separated by CR LF sequences (bytes with decimal value 13 and 10), so you can read the stream and separate out each line. I believethat the headers must be encoded in US-ASCII, so you can simply convert bytes to characters and append to a StringBuilder
(but check the spec: it may allow ISO-8859-1 or another encoding).
请求行和标头由 CR LF 序列(十进制值为 13 和 10 的字节)分隔,因此您可以读取流并分离出每一行。我相信标头必须以 US-ASCII 编码,因此您可以简单地将字节转换为字符并附加到 a StringBuilder
(但请检查规范:它可能允许 ISO-8859-1 或其他编码)。
The end of the headers is signified by CR LF CR LF.
报头的结束由 CR LF CR LF 表示。
回答by Jin Kwon
Your concatenated one-line string is not a HTTP header.
您连接的单行字符串不是 HTTP 标头。
A proper HTTP request message should be look like this (not always)
正确的 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
See here http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html
请参阅此处http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html
If you want implement a HTTP server without any help of Sevlets, JavaEE Containers, you should use Sockets.
如果你想在没有任何 Sevlets、JavaEE Containers 帮助的情况下实现一个 HTTP 服务器,你应该使用 Sockets。
- Read the first line [Request-Line = Method SP Request-URI SP HTTP-Version CRLF]
- Read the request header line by line till you got the blank line
- For each header line you can parse [fieldName: fieldValue]
- Read the entity body.
- 读取第一行【Request-Line = Method SP Request-URI SP HTTP-Version CRLF】
- 逐行读取请求头,直到出现空行
- 对于每个标题行,您可以解析 [fieldName: fieldValue]
- 读取实体主体。
This is NOT the only case for HTTP message contracts.
这不是 HTTP 消息契约的唯一情况。
回答by Renato
I wrote a library, RawHTTP, whose only purpose is to parse HTTP messages (requests and responses).
我写了一个库RawHTTP,它的唯一目的是解析 HTTP 消息(请求和响应)。
If you don't want to use a library, you could copy the source into your own code base, starting form this: https://github.com/renatoathaydes/rawhttp/blob/a6588b116a4008e5b5840d4eb66374c0357b726d/rawhttp-core/src/main/java/com/athaydes/rawhttp/core/RawHttp.java#L52
如果你不想使用库,你可以将源代码复制到你自己的代码库中,从这个开始:https: //github.com/renatoathydes/rawhttp/blob/a6588b116a4008e5b5840d4eb66374c0357b726d/rawhttp-core/src/main/ java/com/asaydes/rawhttp/core/RawHttp.java#L52
This will split the lines of the HTTP message all the way to the end of the metadata sections (start-line + headers).
这会将 HTTP 消息的行一直拆分到元数据部分的末尾(起始行 + 标头)。
With the list of metadata lines at hand, you can then call the parseHeaders
method, which will create the headers for you. You can easily adapt that to just return a Map<String, List<String>>
to avoid having to also import the header classes.
有了手头的元数据行列表,您就可以调用该parseHeaders
方法,该方法将为您创建标题。您可以轻松地将其调整为仅返回 aMap<String, List<String>>
以避免还必须导入头类。
That said... RawHTTP has no dependencies, so I would just use it instead :) but up to you.
也就是说...... RawHTTP 没有依赖项,所以我会用它来代替 :) 但取决于你。
回答by amadib
I'm using the guava library to include preconditions for my methods. You can remove them in favor of null checks.
我正在使用番石榴库为我的方法包含先决条件。您可以删除它们以支持空检查。
/**
* @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;
}