java HttpClient:确定响应中的空实体

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17011023/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 00:42:41  来源:igfitidea点击:

HttpClient: Determine empty entity in response

javaandroidhttpclient

提问by sockeqwe

I'm wondering how to determine an empty http response. With empty http response I mean, that the http response will only have set some headers, but contains an empty http body.

我想知道如何确定一个空的 http 响应。对于空的 http 响应,我的意思是,http 响应将只设置一些标头,但包含一个空的 http 正文。

For example: I do a HTTP POST to an webserver, but the webserver will only return an status code for my HTTP POST and nothing else.

例如:我对网络服务器执行 HTTP POST,但网络服务器只会返回我的 HTTP POST 的状态代码,而不会返回其他任何内容。

The problem is, that I have written a little http framework on top of apache HttpClient to do auto json parsing etc. So the default use case of this framework is to make a request and parse the response. However if the response does not contain data, like mentioned in the example above, I will ensure that my framework skip json parsing.

问题是,我在 apache HttpClient 之上编写了一个小的 http 框架来进行自动 json 解析等。所以这个框架的默认用例是发出请求并解析响应。但是,如果响应不包含数据,如上面示例中所述,我将确保我的框架跳过 json 解析。

So I do something like this:

所以我做这样的事情:

HttpResponse response = httpClient.execute(uriRequest);
HttpEntity entity = response.getEntity();
if (entity != null){
    InputStream in = entity.getContent();
    // json parsing
}

However entity is always != null. And also the retrieved inputstream is != null. Is there a simple way to determine if the http body is empty or not?

然而实体总是 != null。并且检索到的输入流也是 != null。有没有一种简单的方法来确定 http 正文是否为空?

The only way I see is that the server response contains the Content-Length header field set to 0. But not every server set this field.

我看到的唯一方法是服务器响应包含设置为 0 的 Content-Length 标头字段。但并非每个服务器都设置此字段。

Any suggestions?

有什么建议?

回答by sigpwned

In HttpClient, getEntity()canreturn null. See the latest samples.

HttpClientgetEntity()可以返回null。查看最新样本

However, there's a difference between an emptyentity, and noentity. Sounds like you've got an emptyentity. (Sorry to be pedantic -- it's just that HTTP is pedantic. :) With respect to detecting empty entities, have you tried reading from the entity input stream? If the response is an empty entity, you should get an immediate EOF.

但是,实体和没有实体之间是有区别的。听起来你有一个实体。(抱歉,太迂腐——只是 HTTP 是迂腐的。:) 关于检测空实体,您是否尝试过从实体输入流中读取数据?如果响应是空实体,您应该立即获得 EOF。

Do you need to determine if the entity is empty without reading any bytes from the entity body? Based on the code above, I don't think you do. If that's the case, you can just wrap the entity InputStreamwith a PushbackInputStreamand check:

您是否需要在不从实体主体中读取任何字节的情况下确定实体是否为空?根据上面的代码,我认为你不会。如果是这种情况,您可以InputStream用 a包裹实体PushbackInputStream并检查:

HttpResponse response = httpClient.execute(uriRequest);
HttpEntity entity = response.getEntity();
if(entity != null) {
    InputStream in = new PushbackInputStream(entity.getContent());
    try {
        int firstByte=in.read();
        if(firstByte != -1) {
            in.unread(firstByte);
            // json parsing
        }
        else {
            // empty
        }
    }
    finally {
        // Don't close so we can reuse the connection
        EntityUtils.consumeQuietly(entity);
        // Or, if you're sure you won't re-use the connection
        in.close();
    }
}

It's best not to read the entire response into memory just in case it's large. This solution will test for emptiness using constant memory (4 bytes :).

最好不要将整个响应读入内存,以防它很大。此解决方案将使用常量内存(4 个字节 :) 来测试是否为空。

EDIT: <pedantry>In HTTP, if a request has no Content-Lengthheader, then there should be a Transfer-Encoding: chunkedheader. If there is no Transfer-Encoding: chunkedheader either, then you should have noentity as opposed to an emptyentity. </pedantry>

编辑<pedantry>在 HTTP 中,如果请求没有Content-Length标头,则应该有Transfer-Encoding: chunked标头。如果也没有Transfer-Encoding: chunked标题,那么您应该没有实体而不是实体。</pedantry>

回答by namero999

I would suggest to use the class EntityUtilsto get the response as String. If it returns the empty string, then the response is empty.

我建议使用该类EntityUtils以字符串形式获取响应。如果它返回空字符串,则响应为空。

String resp = EntityUtils.toString(client.execute(uriRequest).getEntity())
if (resp == null || "".equals(resp)) {
    // no entity or empty entity
} else {
    // got something
    JSON.parse(resp);
}

The assumption here is that, for sake of code simplicity and manutenibility, you don't care to distinguish between empty entity and no entity, and that if there is a response, you need to read it anyway.

这里的假设是,为了代码的简单性和可操作性,您不关心区分空实体和无实体,并且如果有响应,您无论如何都需要阅读它。