Skip to content

Commit

Permalink
Auto merge of #22616 - jdm:google-decode, r=nox
Browse files Browse the repository at this point in the history
Fix brotli decoding

This replaces our current decoding setup by https://github.com/seanmonstar/reqwest/blob/master/src/async_impl/decoder.rs, and integrates brotli and deflate decoding to maintain our existing support.

---
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #22228
- [x] There are tests for these changes

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/22616)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Jan 15, 2019
2 parents 2e439fa + 047a6b3 commit bc3832f
Show file tree
Hide file tree
Showing 11 changed files with 12,997 additions and 12,593 deletions.
33 changes: 27 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions components/net/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ crossbeam-channel = "0.3"
devtools_traits = {path = "../devtools_traits"}
embedder_traits = { path = "../embedder_traits" }
flate2 = "1"
futures = "0.1"
headers-core = "0.0.1"
headers-ext = "0.0.3"
http = "0.1"
Expand All @@ -31,6 +32,7 @@ hyper-openssl = "0.7"
immeta = "0.4"
ipc-channel = "0.11"
lazy_static = "1"
libflate = "0.1"
log = "0.4"
malloc_size_of = { path = "../malloc_size_of" }
malloc_size_of_derive = "0.1"
Expand Down
106 changes: 1 addition & 105 deletions components/net/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,14 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::hosts::replace_host;
use crate::http_loader::Decoder;
use flate2::read::GzDecoder;
use hyper::body::Payload;
use hyper::client::connect::{Connect, Destination};
use hyper::client::HttpConnector as HyperHttpConnector;
use hyper::rt::Future;
use hyper::{Body, Client};
use hyper_openssl::HttpsConnector;
use openssl::ssl::{SslConnector, SslConnectorBuilder, SslMethod, SslOptions};
use openssl::x509;
use std::io::{Cursor, Read};
use tokio::prelude::future::Executor;
use tokio::prelude::{Async, Stream};

pub const BUF_SIZE: usize = 32768;

Expand Down Expand Up @@ -47,105 +42,6 @@ impl Connect for HttpConnector {
}

pub type Connector = HttpsConnector<HttpConnector>;
pub struct WrappedBody {
pub body: Body,
pub decoder: Decoder,
}

impl WrappedBody {
pub fn new(body: Body) -> Self {
Self::new_with_decoder(body, Decoder::Plain)
}

pub fn new_with_decoder(body: Body, decoder: Decoder) -> Self {
WrappedBody { body, decoder }
}
}

impl Payload for WrappedBody {
type Data = <Body as Payload>::Data;
type Error = <Body as Payload>::Error;
fn poll_data(&mut self) -> Result<Async<Option<Self::Data>>, Self::Error> {
self.body.poll_data()
}
}

impl Stream for WrappedBody {
type Item = <Body as Stream>::Item;
type Error = <Body as Stream>::Error;
fn poll(&mut self) -> Result<Async<Option<Self::Item>>, Self::Error> {
self.body.poll().map(|res| {
res.map(|maybe_chunk| {
if let Some(chunk) = maybe_chunk {
match self.decoder {
Decoder::Plain => Some(chunk),
Decoder::Gzip(Some(ref mut decoder)) => {
let mut buf = vec![0; BUF_SIZE];
decoder.get_mut().get_mut().extend(chunk.as_ref());
let len = decoder.read(&mut buf).ok()?;
buf.truncate(len);
Some(buf.into())
},
Decoder::Gzip(None) => {
let mut buf = vec![0; BUF_SIZE];
let mut decoder = GzDecoder::new(Cursor::new(chunk.into_bytes()));
let len = decoder.read(&mut buf).ok()?;
buf.truncate(len);
self.decoder = Decoder::Gzip(Some(decoder));
Some(buf.into())
},
Decoder::Deflate(ref mut decoder) => {
let mut buf = vec![0; BUF_SIZE];
decoder.get_mut().get_mut().extend(chunk.as_ref());
let len = decoder.read(&mut buf).ok()?;
buf.truncate(len);
Some(buf.into())
},
Decoder::Brotli(ref mut decoder) => {
let mut buf = vec![0; BUF_SIZE];
decoder.get_mut().get_mut().extend(chunk.as_ref());
let len = decoder.read(&mut buf).ok()?;
buf.truncate(len);
Some(buf.into())
},
}
} else {
// Hyper is done downloading but we still have uncompressed data
match self.decoder {
Decoder::Gzip(Some(ref mut decoder)) => {
let mut buf = vec![0; BUF_SIZE];
let len = decoder.read(&mut buf).ok()?;
if len == 0 {
return None;
}
buf.truncate(len);
Some(buf.into())
},
Decoder::Deflate(ref mut decoder) => {
let mut buf = vec![0; BUF_SIZE];
let len = decoder.read(&mut buf).ok()?;
if len == 0 {
return None;
}
buf.truncate(len);
Some(buf.into())
},
Decoder::Brotli(ref mut decoder) => {
let mut buf = vec![0; BUF_SIZE];
let len = decoder.read(&mut buf).ok()?;
if len == 0 {
return None;
}
buf.truncate(len);
Some(buf.into())
},
_ => None,
}
}
})
})
}
}

pub fn create_ssl_connector_builder(certs: &str) -> SslConnectorBuilder {
// certs include multiple certificates. We could add all of them at once,
Expand Down Expand Up @@ -189,7 +85,7 @@ pub fn create_ssl_connector_builder(certs: &str) -> SslConnectorBuilder {
pub fn create_http_client<E>(
ssl_connector_builder: SslConnectorBuilder,
executor: E,
) -> Client<Connector, WrappedBody>
) -> Client<Connector, Body>
where
E: Executor<Box<dyn Future<Error = (), Item = ()> + Send + 'static>> + Sync + Send + 'static,
{
Expand Down
Loading

0 comments on commit bc3832f

Please sign in to comment.