Почему reqwest не возвращает длину содержимого в этом запросе? - PullRequest
0 голосов
/ 26 февраля 2019

Я запутался, почему я не получаю никакого контента от следующей функции, которая использует 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"
  }
}

Что такоепроблема с моей функцией в том, что она не предоставляет мне длину контента?

1 Ответ

0 голосов
/ 26 февраля 2019

Документация reqwest для 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 - нет.

HTTP-заголовок Content-Length не является обязательным, поэтому обычно полагаться на его наличие было бы ошибкой.Вы должны прочитать данные из запроса, используя другие 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());
...