5

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

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

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

所以我做这样的事情:

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

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

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

有什么建议么?

4

2 回答 2

6

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

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

您是否需要在不从实体主体中读取任何字节的情况下确定实体是否为空?根据上面的代码,我不认为你这样做。如果是这种情况,您可以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();
    }
}

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

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

于 2013-06-09T15:21:26.173 回答
1

我建议使用该类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);
}

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

于 2013-06-09T15:21:06.047 回答