【问题标题】:Why isn't reqwest returning the content length in this request?为什么 reqwest 不返回此请求中的内容长度?
【发布时间】:2019-02-26 10:27:16
【问题描述】:

我很困惑为什么我没有从以下使用reqwest的函数返回任何内容:

  fn try_get() {
      let wc = reqwest::Client::new();
      wc.get("https://httpbin.org/json").send().map(|res| {
          println!("{:?}", res);
          println!("length {:?}", res.content_length());
      });
  }

我希望这个函数显示响应对象,然后给我内容长度。它做了第一个但不是第二个:

Response { url: "https://httpbin.org/json", status: 200, headers: {"access-control-allow-credentials": "true", "access-control-allow-origin": "*", "connection": "keep-alive", "content-type": "application/json", "date": "Tue, 26 Feb 2019 00:52:47 GMT", "server": "nginx"} }
length None

这很令人困惑,因为如果我使用 cURL 访问同一个端点,它会给我一个预期的正文:

$ curl -i https://httpbin.org/json
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Content-Type: application/json
Date: Tue, 26 Feb 2019 00:54:57 GMT
Server: nginx
Content-Length: 429
Connection: keep-alive

{
  "slideshow": {
    "author": "Yours Truly",
    "date": "date of publication",
    "slides": [
      {
        "title": "Wake up to WonderWidgets!",
        "type": "all"
      },
      {
        "items": [
          "Why <em>WonderWidgets</em> are great",
          "Who <em>buys</em> WonderWidgets"
        ],
        "title": "Overview",
        "type": "all"
      }
    ],
    "title": "Sample Slide Show"
  }
}

我的函数没有为我提供内容长度的问题是什么?

【问题讨论】:

    标签: rust reqwest


    【解决方案1】:

    reqwest documentation for content_length() 始终是一个不错的起点。它指出

    获取响应的内容长度(如果已知)。

    可能不知道的原因:

    • 服务器未发送内容长度标头。
    • 响应被压缩并自动解码(从而改变实际解码长度)。

    查看您的示例curl 输出,它包含Content-Length: 429,因此涵盖了第一种情况。所以现在让我们尝试禁用 gzip:

    let client = reqwest::Client::builder()
      .gzip(false)
      .build()
      .unwrap();
    
    client.get("https://httpbin.org/json").send().map(|res| {
      println!("{:?}", res);
      println!("length {:?}", res.content_length());
    });
    

    哪些日志

    length Some(429)
    

    所以第二种情况是问题所在。默认情况下,reqwest 似乎会自动处理压缩后的内容,而curl 则不会。

    Content-Length HTTP 标头完全是可选的,因此通常依赖它的存在是错误的。您应该使用其他reqwest API 从请求中读取数据,然后计算数据本身的长度。例如,您可以使用.text()

    let wc = reqwest::Client::new();
    let mut response = wc.get("https://httpbin.org/json").send().unwrap();
    let text = response.text().unwrap();
    
    println!("text: {} => {}", text.len(), text);
    

    同样,对于二进制数据,您可以使用.copy_to()

    let wc = reqwest::Client::new();
    let mut response = wc.get("https://httpbin.org/json").send().unwrap();
    
    let mut data = vec![];
    response.copy_to(&mut data).unwrap();
    
    println!("data: {}", data.len());
    

    【讨论】:

    • 谢谢。在这种情况下,我如何才能确定内容长度实际上是多少并分配一个缓冲区来读取它?
    • 使用.text() 并且只使用返回的String 可能是最简单的,而不是尝试在某处预分配缓冲区。 Content-Length 不是请求中的必需标头,因此依赖它是错误的。
    • 是的,但是我的一些查询不是文本而是二进制的。 text 可以工作吗?如果没有,我想我仍然需要用缓冲区读取它。
    • 我在回答中添加了更多示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    • 2017-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    相关资源
    最近更新 更多