mirror of
https://github.com/servo/servo.git
synced 2025-09-17 02:18:23 +01:00
Enable the zstd decoder (#36530)
Uses the `zstd` support from `async-compression` to support zstd Content-Encoding. Testing: Covered by wpt tests. Signed-off-by: webbeef <me@webbeef.org>
This commit is contained in:
parent
84465e7768
commit
bc496b08e7
9 changed files with 54 additions and 27 deletions
30
Cargo.lock
generated
30
Cargo.lock
generated
|
@ -1543,6 +1543,8 @@ dependencies = [
|
||||||
"compression-core",
|
"compression-core",
|
||||||
"flate2",
|
"flate2",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
"zstd",
|
||||||
|
"zstd-safe",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -10950,6 +10952,34 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd"
|
||||||
|
version = "0.13.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
|
||||||
|
dependencies = [
|
||||||
|
"zstd-safe",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-safe"
|
||||||
|
version = "7.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
|
||||||
|
dependencies = [
|
||||||
|
"zstd-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-sys"
|
||||||
|
version = "2.0.16+zstd.1.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zune-core"
|
name = "zune-core"
|
||||||
version = "0.4.12"
|
version = "0.4.12"
|
||||||
|
|
|
@ -15,7 +15,7 @@ test = false
|
||||||
doctest = false
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-compression = { version = "0.4.12", default-features = false, features = ["tokio", "brotli", "gzip", "zlib"] }
|
async-compression = { version = "0.4.12", default-features = false, features = ["tokio", "brotli", "gzip", "zlib", "zstd"] }
|
||||||
async-recursion = "1.1"
|
async-recursion = "1.1"
|
||||||
async-tungstenite = { workspace = true }
|
async-tungstenite = { workspace = true }
|
||||||
base = { workspace = true }
|
base = { workspace = true }
|
||||||
|
|
|
@ -21,7 +21,7 @@ use std::fmt;
|
||||||
use std::io::{self};
|
use std::io::{self};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
|
||||||
use async_compression::tokio::bufread::{BrotliDecoder, GzipDecoder, ZlibDecoder};
|
use async_compression::tokio::bufread::{BrotliDecoder, GzipDecoder, ZlibDecoder, ZstdDecoder};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::stream::Peekable;
|
use futures::stream::Peekable;
|
||||||
use futures::task::{Context, Poll};
|
use futures::task::{Context, Poll};
|
||||||
|
@ -51,6 +51,7 @@ enum DecoderType {
|
||||||
Gzip,
|
Gzip,
|
||||||
Brotli,
|
Brotli,
|
||||||
Deflate,
|
Deflate,
|
||||||
|
Zstd,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Inner {
|
enum Inner {
|
||||||
|
@ -62,6 +63,8 @@ enum Inner {
|
||||||
Deflate(FramedRead<ZlibDecoder<StreamReader<Peekable<BodyStream>, Bytes>>, BytesCodec>),
|
Deflate(FramedRead<ZlibDecoder<StreamReader<Peekable<BodyStream>, Bytes>>, BytesCodec>),
|
||||||
/// A `Brotli` decoder will uncompress the brotli-encoded response content before returning it.
|
/// A `Brotli` decoder will uncompress the brotli-encoded response content before returning it.
|
||||||
Brotli(FramedRead<BrotliDecoder<StreamReader<Peekable<BodyStream>, Bytes>>, BytesCodec>),
|
Brotli(FramedRead<BrotliDecoder<StreamReader<Peekable<BodyStream>, Bytes>>, BytesCodec>),
|
||||||
|
/// A `Zstd` decoder will uncompress the zstd-encoded response content before returning it.
|
||||||
|
Zstd(FramedRead<ZstdDecoder<StreamReader<Peekable<BodyStream>, Bytes>>, BytesCodec>),
|
||||||
/// A decoder that doesn't have a value yet.
|
/// A decoder that doesn't have a value yet.
|
||||||
Pending(Pending),
|
Pending(Pending),
|
||||||
}
|
}
|
||||||
|
@ -131,6 +134,8 @@ impl Decoder {
|
||||||
Some(DecoderType::Brotli)
|
Some(DecoderType::Brotli)
|
||||||
} else if enc == HeaderValue::from_static("deflate") {
|
} else if enc == HeaderValue::from_static("deflate") {
|
||||||
Some(DecoderType::Deflate)
|
Some(DecoderType::Deflate)
|
||||||
|
} else if enc == HeaderValue::from_static("zstd") {
|
||||||
|
Some(DecoderType::Zstd)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -182,6 +187,13 @@ impl Stream for Decoder {
|
||||||
None => Poll::Ready(None),
|
None => Poll::Ready(None),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Inner::Zstd(ref mut decoder) => {
|
||||||
|
match futures_core::ready!(Pin::new(decoder).poll_next(cx)) {
|
||||||
|
Some(Ok(bytes)) => Poll::Ready(Some(Ok(bytes.freeze()))),
|
||||||
|
Some(Err(err)) => Poll::Ready(Some(Err(err))),
|
||||||
|
None => Poll::Ready(None),
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,6 +235,11 @@ impl Future for Pending {
|
||||||
BytesCodec::new(),
|
BytesCodec::new(),
|
||||||
DECODER_BUFFER_SIZE,
|
DECODER_BUFFER_SIZE,
|
||||||
)))),
|
)))),
|
||||||
|
DecoderType::Zstd => Poll::Ready(Ok(Inner::Zstd(FramedRead::with_capacity(
|
||||||
|
ZstdDecoder::new(StreamReader::new(body)),
|
||||||
|
BytesCodec::new(),
|
||||||
|
DECODER_BUFFER_SIZE,
|
||||||
|
)))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,7 +184,7 @@ fn set_default_accept_encoding(headers: &mut HeaderMap) {
|
||||||
// TODO(eijebong): Change this once typed headers are done
|
// TODO(eijebong): Change this once typed headers are done
|
||||||
headers.insert(
|
headers.insert(
|
||||||
header::ACCEPT_ENCODING,
|
header::ACCEPT_ENCODING,
|
||||||
HeaderValue::from_static("gzip, deflate, br"),
|
HeaderValue::from_static("gzip, deflate, br, zstd"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1313,7 +1313,7 @@ fn test_fetch_with_devtools() {
|
||||||
|
|
||||||
headers.insert(
|
headers.insert(
|
||||||
header::ACCEPT_ENCODING,
|
header::ACCEPT_ENCODING,
|
||||||
HeaderValue::from_static("gzip, deflate, br"),
|
HeaderValue::from_static("gzip, deflate, br, zstd"),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Append fetch metadata headers
|
// Append fetch metadata headers
|
||||||
|
|
|
@ -189,7 +189,7 @@ fn test_check_default_headers_loaded_in_every_request() {
|
||||||
|
|
||||||
headers.insert(
|
headers.insert(
|
||||||
header::ACCEPT_ENCODING,
|
header::ACCEPT_ENCODING,
|
||||||
HeaderValue::from_static("gzip, deflate, br"),
|
HeaderValue::from_static("gzip, deflate, br, zstd"),
|
||||||
);
|
);
|
||||||
|
|
||||||
headers.typed_insert(Host::from(
|
headers.typed_insert(Host::from(
|
||||||
|
@ -369,7 +369,7 @@ fn test_request_and_response_data_with_network_messages() {
|
||||||
|
|
||||||
headers.insert(
|
headers.insert(
|
||||||
header::ACCEPT_ENCODING,
|
header::ACCEPT_ENCODING,
|
||||||
HeaderValue::from_static("gzip, deflate, br"),
|
HeaderValue::from_static("gzip, deflate, br, zstd"),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Append fetch metadata headers
|
// Append fetch metadata headers
|
||||||
|
@ -1128,7 +1128,7 @@ fn test_load_sets_default_accept_encoding_to_gzip_and_deflate() {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_str()
|
.to_str()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
"gzip, deflate, br"
|
"gzip, deflate, br, zstd"
|
||||||
);
|
);
|
||||||
*response.body_mut() = make_body(b"Yay!".to_vec());
|
*response.body_mut() = make_body(b"Yay!".to_vec());
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,17 +2,11 @@
|
||||||
expected: ERROR
|
expected: ERROR
|
||||||
|
|
||||||
[big-zstd-body.https.any.worker.html]
|
[big-zstd-body.https.any.worker.html]
|
||||||
[large zstd data should be decompressed successfully]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[large zstd data should be decompressed successfully with byte stream]
|
[large zstd data should be decompressed successfully with byte stream]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
||||||
[big-zstd-body.https.any.html]
|
[big-zstd-body.https.any.html]
|
||||||
[large zstd data should be decompressed successfully]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[large zstd data should be decompressed successfully with byte stream]
|
[large zstd data should be decompressed successfully with byte stream]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -2,19 +2,8 @@
|
||||||
expected: ERROR
|
expected: ERROR
|
||||||
|
|
||||||
[zstd-body.https.any.html]
|
[zstd-body.https.any.html]
|
||||||
[fetched zstd data with content type text should be decompressed.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[fetched zstd data with content type octetstream should be decompressed.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
|
|
||||||
[zstd-body.https.any.sharedworker.html]
|
[zstd-body.https.any.sharedworker.html]
|
||||||
expected: ERROR
|
expected: ERROR
|
||||||
|
|
||||||
[zstd-body.https.any.worker.html]
|
[zstd-body.https.any.worker.html]
|
||||||
[fetched zstd data with content type text should be decompressed.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[fetched zstd data with content type octetstream should be decompressed.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[zstd-navigation.https.window.html]
|
|
||||||
[Naigation to zstd encoded page]
|
|
||||||
expected: FAIL
|
|
Loading…
Add table
Add a link
Reference in a new issue