Java中的分块HTTP解码?

6
我正在解码HTTP数据包。遇到了分块问题。 当我收到一个HTTP数据包时,它有头部和正文。 当传输编码是分块的时候,我不知道该怎么做?
在JAVA中是否有用的API或类可以解除数据块?
如果有经验的HTTP解码人员,请告诉我如何解决这个问题?
4个回答

12

使用一个完整的HTTP客户端,例如Apache HttpComponents Client或者Java SE提供的java.net.URLConnection这里有个小教程)。两者都会自动处理并返回一个"普通"的InputStream。HttpClient还提供了一个ChunkedInputStream类,您可以将其与InputStream结合使用。

如果您坚持要编写自己的库,则建议创建一个类似于ChunkedInputStream extends InputStream 的类,并相应地编写逻辑。 您可以在这篇维基百科文章中找到更多解析信息。


实际上,我正在进行离线HTTP解码,我只有HTTP数据包的头部和正文。我将对该数据包进行解码。但是我需要一个API,它可以获取头部和正文,并为我提供解码后的数据。 是否有这样的API? - CodingForever
维基百科文章详细介绍了块的外观。你可以基本上只在CRLF(\r\n)上分割。它们是10和13字节。第一部分是头,表示十六进制块长度。第二部分是块数据本身。你只需收集并连接所有这些块。ChunkedInputStream正是这样做的。 - BalusC
抱歉,有两个ChunkedInputStream类:第一个:http://jigsaw.w3.org/Doc/Programmer/api/org/w3c/www/http/ChunkedInputStream.html第二个:http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/ChunkedInputStream.html哪一个是正确的?您是否有关于如何使用ChunkedInputStream的任何信息? - CodingForever
我的回答中的ChunkedInputStream部分是可点击的(就像所有其他蓝色部分一样)。它是一个InputStream,你可以用它来装饰另一个InputStream。例如:InputStream input = new ChunkedInputStream(originalInput); - BalusC
首先感谢您的回答,它们确实帮助了我。但我有另一个问题:ChunkedInputStream构造函数获取SessionInputBuffer(接口),我该如何将字符串(分块主体)转换为此格式? - CodingForever
哦,它已经根据HttpClient 4.x进行了更改。好吧,要么选择使用接受“InputStream”的HttpClient 3.x,要么自己编写一个。确定分块主体非常简单。只需在CRLF上拆分并执行逻辑计算即可。 - BalusC

1
如果您正在寻找一种简单的API,请尝试使用Jodd Http库(http://jodd.org/doc/http.html)。它会为您处理分块传输编码,并将整个正文作为字符串返回。
从文档中得知:
HttpRequest httpRequest = HttpRequest.get("http://jodd.org");
HttpResponse response = httpRequest.send();

System.out.println(response);

1

我将对离线的HTTP解码(已捕获的数据包),我只有一个头和一个主体。 因此,我需要一个API,它只获取头和主体,并为我提供解码后的数据。 是否有这样的API? - CodingForever

0

这里有一个快速而简单的替代方案,除了Oracle JRE之外不需要任何依赖项:

private static byte[] unchunk(byte[] content) throws IOException {
    ByteArrayInputStream bais = new ByteArrayInputStream(content);
    ChunkedInputStream cis = new ChunkedInputStream(bais, new HttpClient() {}, null);
    return readFully(cis);
}

它使用与java.net.HttpURLConnection背后的sun.net.www.http.ChunkedInputStream相同的内容。

此实现不会提供有关错误内容格式的详细异常(行号)。

它适用于Java 8,但在下一个版本中可能会失败。你已经被警告了。

虽然对于原型设计可能很有用。

您可以从Convert InputStream to byte array in Java中选择任何readFully实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接