【问题标题】:Read gzip response with Hyper and Flate2使用 Hyper 和 Flate2 读取 gzip 响应
【发布时间】:2016-10-28 14:47:30
【问题描述】:

Hyper 具有 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> 功能,可将 HTTP 响应的内容读取到提供的 &mut [u8] 中。

Flate2 可以gunzip:

let mut d = GzDecoder::new("...".as_bytes()).unwrap();
let mut s = String::new();
d.read_to_string(&mut s).unwrap();
println!("{}", s);

我试着把这两件事放在一起:

fn gunzip(r: &Response) -> String {
    let mut zs: &mut [u8] = &mut[];
    r.read(zs);
    let mut d = GzDecoder::new(zs).unwrap();
    let mut s = String::new();
    d.read_to_string(&mut s).unwrap();
    s
}

我得到了错误:

error[E0277]: the trait bound `[u8]: std::io::Read` is not satisfied
   --> tests/integration.rs:232:21
    |
232 |         let mut d = GzDecoder::new(zs).unwrap();
    |                     ^^^^^^^^^^^^^^ trait `[u8]: std::io::Read` not satisfied
    |
    = help: the following implementations were found:
    = help:   <&'a [u8] as std::io::Read>
    = note: required because of the requirements on the impl of `std::io::Read` for `&mut [u8]`
    = note: required by `<flate2::read::DecoderReader<R>>::new`

我哪里错了?


编辑:最终的工作解决方案:

fn gunzip(r: &mut Response) -> String {
    let mut buffer = Vec::new();
    let _ = r.read_to_end(&mut buffer).unwrap();
    let mut d = GzDecoder::new(buffer.as_slice()).unwrap();
    let mut s = String::new();
    d.read_to_string(&mut s).unwrap();
    s
}

【问题讨论】:

  • (回应已删除的评论...)是的,我做到了[尝试&amp;zs]。结果trait '&amp;&amp;mut [u8]: std::io::Read' not satisfied
  • 您可以尝试添加第二个 & 吗? (这听起来很愚蠢,但它适用于 playground
  • GzDecoder::new(&amp;&amp;zs).unwrap() => trait '&amp;&amp;&amp;mut [u8]: std::io::Read' not satisfied.
  • 这很有趣,因为它在操场上确实有效。我还要注意 [] 是一个长度为 0 的数组,不允许增长。这意味着读入它最终将什么也读不到。如果您想阅读所有内容,请使用Vec 试试运气,例如通过read_to_end
  • 您应该能够可变地借用 r 并将其传递给 GzDecoder,因为它接受实现 Read 的类型,而客户端 Response 会这样做。

标签: rust hyper


【解决方案1】:

GzDecoder::new 的参数是用泛型类型定义的,因此 Rust 不会执行一些在预期为固定类型时会发生的转换。

您可以通过取消对可变切片的引用,然后获取对结果的引用,将可变切片转换为不可变切片。

let mut d = GzDecoder::new(&*zs).unwrap();

【讨论】:

    【解决方案2】:

    这是另一种无需使用其他缓冲区即可完成的方法:

    extern crate hyper;
    extern crate flate2;
    
    use std::io::Read;
    
    use hyper::client::Client;
    use hyper::header::{Headers, AcceptEncoding, Encoding, qitem};
    
    use flate2::read::GzDecoder;
    
    fn main() {
        let c = Client::new();
    
        let mut req = c.get("http://httpbin.org/gzip");
        let mut headers = Headers::new();
        headers.set(
            AcceptEncoding(vec![qitem(Encoding::Gzip)])
        );
        req = req.headers(headers);
    
        let res = req.send().unwrap();
        let mut decoder = GzDecoder::new(res).unwrap();
        let mut buf = String::new();
    
        let _ = decoder.read_to_string(&mut buf);
        println!("{}", buf);
    }
    

    此示例使用来自 HTTPBIN 的 gzip 端点来测试 Response 是否可以在 GzDecoder 中使用。

    我的 Cargo 文件中使用的依赖项:

    [dependencies]
    hyper = "0.9"
    flate2 = "0.2"
    

    附: unwrap() 电话是为了简洁起见:)

    【讨论】:

      猜你喜欢
      • 2010-10-16
      • 2018-12-16
      • 2021-08-14
      • 1970-01-01
      • 2019-09-12
      • 1970-01-01
      • 2011-05-08
      • 2013-01-16
      相关资源
      最近更新 更多