Java Apache HTTP组件大小限制响应?

Java Apache HTTP组件大小限制响应?,java,memory,jvm,dos,apache-httpcomponents,Java,Memory,Jvm,Dos,Apache Httpcomponents,我连接到juts返回非有限“A”流的服务器。即:这个 $ nc 1.2.3.4 9001 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

我连接到juts返回非有限“A”流的服务器。即:这个

$ nc 1.2.3.4 9001
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA^C
apache http组件库似乎只是从服务器获取整个响应,然后进行解析。如何限制大小,使JVM不会崩溃

这是我的代码:

w/fluent API:

public static void main(String[] args) throws ClientProtocolException, IOException {
    Request.Get(url).execute().discardContent();
}
w/低级别API:

public static void main(String[] args) throws ClientProtocolException, IOException {
    String url = "http://1.2.3.4:9001/";
    DefaultHttpClient httpclient = new DefaultHttpClient();
    System.out.println("A");
    HttpGet request = new HttpGet(url);
    System.out.println("B");
    HttpResponse hr = httpclient.execute(request);
    System.out.println("C");
}
给我这个:

A
B
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at org.apache.http.util.ByteArrayBuffer.expand(ByteArrayBuffer.java:62)
    at org.apache.http.util.ByteArrayBuffer.append(ByteArrayBuffer.java:92)
    at org.apache.http.impl.io.AbstractSessionInputBuffer.readLine(AbstractSessionInputBuffer.java:278)
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:92)
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:62)
    at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:254)
    at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:289)
    at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:252)
    at org.apache.http.impl.conn.ManagedClientConnectionImpl.receiveResponseHeader(ManagedClientConnectionImpl.java:191)
    at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:300)
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:127)
    at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:712)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:517)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
    at com.dudebro.WhatHappen.main(WhatHappen.java:103)

注:与此无关,我甚至没有向API请求响应体,它仍然崩溃。

从堆栈跟踪中可以清楚地看到发生了什么:
BufferedReader.readLine()
不断增加其缓冲区,因为它找不到行终止符来开始解析响应状态行,直到JVM内存耗尽。您可以将代码包装在
try
块中,并捕获
OutOfMemoryError
,甚至可以向Apache维护人员提交补丁,但我认为您不应该在实际应用程序中考虑这个问题

该服务器不符合HTTP,因为“A”的无限流肯定不是有效的HTTP响应状态行。通常情况下,服务器的设计对其接受的内容是自由的,对其发送的内容是严格的,也就是说,它们应该考虑到可能存在不兼容的客户端

另一方面,客户机开发人员通常认为服务器实现得很好,因为如果没有实现,那么运行服务器的企业将无法获得任何客户机

在这种情况下,很明显,目标服务器没有提供任何有价值的服务,因为它甚至都不符合协议,所以没有人可以从中获取任何东西,谷歌无法索引它,那么谁会将公共URL传播到这样的应用程序?我认为客户端在您的开发机器上崩溃是好的,因为它告诉您服务器程序不工作。如果它在您的控制下,您可以修复它,否则您将切换服务提供商。同样,这在现实世界中是不会发生的,因为如此糟糕的服务将使其所有客户端崩溃,并且没有人会使用它


在评论中,您说这是一个接受用户提交的URL的服务器应用程序。在这种情况下,您应该为行长度设置一个限制,以避免恶意用户导致服务器停机。

您可以尝试设置以下参数:

MAX_LINE_LENGTH = "http.connection.max-line-length"
MAX_HEADER_COUNT = "http.connection.max-header-count"

我认为第一个的默认值是-1,这意味着没有限制。

BufferedReader.readLine()不断增加其缓冲区,我认为有一种方法可以绕过它而不修改库。没有人100%不同意这篇文章的其余部分。不希望整个虚拟机和一切崩溃只是因为一个(100)服务器是坏的。为每个连接购买一台单独的机器或虚拟机是愚蠢的,并没有理由服务器应该首先发送虚假的垃圾。“对他们所接受的东西开明”并不意味着崩溃,也不意味着没有头脑服务器在开发客户机时应该对他们所接受的东西开明服务器说,这意味着服务器开发人员必须警惕行为不端的客户机。当然,客户机也不应该崩溃,您可以防止这种情况发生,但我指出,出于显而易见的原因,这不是一个常见的问题。我不知道你们的应用程序是做什么的,所以我不能告诉你们的客户端使用了100台服务器。如果1/100服务器是邪恶的,这并不意味着客户端应该停止功能。客户机不依赖于1/100服务器,因此不应中断此连接,我并不是说您的客户机应该崩溃。我要说的是,由于我不了解您的环境和需求,我无法判断这是否真的是一个有价值的问题。请尝试理解我的答案:您需要一个公共URL来访问服务器,如果该服务器不提供任何服务,为什么会有人要求该URL?唯一感兴趣的用户可能是恶意用户,因此我声明,根据您的应用程序,这些用户可能是一个问题,或者不是。在这种情况下,有一个有效的理由来检查线路长度谢谢兄弟。“http.connection.max line length”修复它。我猜这件事可能也接受非有限头,最好检查一下。