From ac21fc084db05d23cb12ff8d6bb74cf4819c02d1 Mon Sep 17 00:00:00 2001 From: Frank Stellmacher <171614930+Psychotoxical@users.noreply.github.com> Date: Thu, 14 May 2026 22:17:02 +0200 Subject: [PATCH] feat(http): enable gzip + brotli decompression for reqwest clients (#704) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(http): enable gzip + brotli decompression for reqwest clients All Rust-side HTTP clients now advertise Accept-Encoding and transparently decode compressed responses. reqwest auto-decompresses by default once the features are enabled, so this is a pure dependency-feature change with no call-site edits. Added to all five reqwest declarations across the Cargo workspace (top psysonic crate + psysonic-audio / -analysis / -integration / -syncfs). The real wire savings land on JSON payloads — Navidrome native /api, Bandsintown, Radio-Browser, Last.fm — measured at roughly -76% to -93% on earlier curl tests. Crates that only fetch already-compressed audio bytes get the features too for consistency: reqwest just advertises the header there, so there's no runtime cost when the server returns data as-is. Cargo.lock grows additively (async-compression + compression codecs); no other crates moved. * docs(changelog): add entry for HTTP gzip + brotli (#704) --- CHANGELOG.md | 7 ++++ src-tauri/Cargo.lock | 35 +++++++++++++++++++ src-tauri/Cargo.toml | 2 +- src-tauri/crates/psysonic-analysis/Cargo.toml | 2 +- src-tauri/crates/psysonic-audio/Cargo.toml | 2 +- .../crates/psysonic-integration/Cargo.toml | 2 +- src-tauri/crates/psysonic-syncfs/Cargo.toml | 2 +- 7 files changed, 47 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7acd06e4..42d7c6ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,13 @@ Foundational work: faster reviews, narrower diffs, and a safety net under the pa ## Added +### HTTP — gzip + brotli decompression for the Rust-side clients + +**By [@Psychotoxical](https://github.com/Psychotoxical), PR [#704](https://github.com/Psychotoxical/psysonic/pull/704)** + +* Every HTTP client on the Rust side now advertises `Accept-Encoding` and transparently decodes compressed responses. The JSON-heavy endpoints — Navidrome native `/api`, Bandsintown, Radio-Browser, Last.fm — were the gap: the WebView's `axios` calls were already compressed, the Rust clients were not. Earlier curl measurements put the wire savings on those payloads at roughly **76–93 %**. +* Implementation is a dependency-feature change only (`gzip` + `brotli` on `reqwest`) — no behaviour change beyond smaller transfers, and no extra cost on the clients that fetch already-compressed audio. + ### Queue Toolbar — customizable button order + per-button visibility **By [@kveld9](https://github.com/kveld9), PR [#534](https://github.com/Psychotoxical/psysonic/pull/534)** diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 235a126f..18425a7e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -128,6 +128,18 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "async-compression" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79b3f8a79cccc2898f31920fc69f304859b3bd567490f75ebf51ae1c792a9ac" +dependencies = [ + "compression-codecs", + "compression-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "async-executor" version = "1.14.0" @@ -671,6 +683,24 @@ dependencies = [ "memchr", ] +[[package]] +name = "compression-codecs" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce2548391e9c1929c21bf6aa2680af86fe4c1b33e6cea9ac1cfeec0bd11218cf" +dependencies = [ + "brotli", + "compression-core", + "flate2", + "memchr", +] + +[[package]] +name = "compression-core" +version = "0.4.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc14f565cf027a105f7a44ccf9e5b424348421a1d8952a8fc9d499d313107789" + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -5950,13 +5980,18 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ + "async-compression", "bitflags 2.11.1", "bytes", + "futures-core", "futures-util", "http", "http-body", + "http-body-util", "iri-string", "pin-project-lite", + "tokio", + "tokio-util", "tower", "tower-layer", "tower-service", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index b207654c..275dec50 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" rodio = { version = "0.22", default-features = false, features = ["playback", "symphonia-all"] } symphonia = { version = "0.5", default-features = false, features = ["flac", "mp3", "pcm", "aac", "alac", "isomp4", "vorbis", "ogg", "wav", "adpcm"] } -reqwest = { version = "0.13", default-features = false, features = ["stream", "json", "multipart", "query", "form", "rustls", "blocking"] } +reqwest = { version = "0.13", default-features = false, features = ["stream", "json", "multipart", "query", "form", "rustls", "blocking", "gzip", "brotli"] } futures-util = "0.3" md5 = "0.8" tokio = { version = "1", features = ["rt", "time", "sync"] } diff --git a/src-tauri/crates/psysonic-analysis/Cargo.toml b/src-tauri/crates/psysonic-analysis/Cargo.toml index 376d5424..154e911e 100644 --- a/src-tauri/crates/psysonic-analysis/Cargo.toml +++ b/src-tauri/crates/psysonic-analysis/Cargo.toml @@ -12,7 +12,7 @@ tauri = { version = "2" } serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = { version = "1", features = ["rt", "time", "sync"] } -reqwest = { version = "0.13", default-features = false, features = ["stream", "rustls"] } +reqwest = { version = "0.13", default-features = false, features = ["stream", "rustls", "gzip", "brotli"] } futures-util = "0.3" ebur128 = "0.1" md5 = "0.8" diff --git a/src-tauri/crates/psysonic-audio/Cargo.toml b/src-tauri/crates/psysonic-audio/Cargo.toml index b218527c..8e7bbcf8 100644 --- a/src-tauri/crates/psysonic-audio/Cargo.toml +++ b/src-tauri/crates/psysonic-audio/Cargo.toml @@ -13,7 +13,7 @@ tauri = { version = "2" } serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = { version = "1", features = ["rt", "time", "sync"] } -reqwest = { version = "0.13", default-features = false, features = ["stream", "json", "rustls", "blocking"] } +reqwest = { version = "0.13", default-features = false, features = ["stream", "json", "rustls", "blocking", "gzip", "brotli"] } futures-util = "0.3" rodio = { version = "0.22", default-features = false, features = ["playback", "symphonia-all"] } symphonia = { version = "0.5", default-features = false, features = ["flac", "mp3", "pcm", "aac", "alac", "isomp4", "vorbis", "ogg", "wav", "adpcm"] } diff --git a/src-tauri/crates/psysonic-integration/Cargo.toml b/src-tauri/crates/psysonic-integration/Cargo.toml index 664c1cf7..f4bc5715 100644 --- a/src-tauri/crates/psysonic-integration/Cargo.toml +++ b/src-tauri/crates/psysonic-integration/Cargo.toml @@ -12,7 +12,7 @@ tauri = { version = "2" } serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = { version = "1", features = ["rt", "time", "sync"] } -reqwest = { version = "0.13", default-features = false, features = ["stream", "json", "rustls", "blocking"] } +reqwest = { version = "0.13", default-features = false, features = ["stream", "json", "rustls", "blocking", "gzip", "brotli"] } futures-util = "0.3" discord-rich-presence = "1.1" url = "2" diff --git a/src-tauri/crates/psysonic-syncfs/Cargo.toml b/src-tauri/crates/psysonic-syncfs/Cargo.toml index d29d12f3..4b912216 100644 --- a/src-tauri/crates/psysonic-syncfs/Cargo.toml +++ b/src-tauri/crates/psysonic-syncfs/Cargo.toml @@ -16,7 +16,7 @@ tauri-plugin-process = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = { version = "1", features = ["rt", "time", "sync"] } -reqwest = { version = "0.13", default-features = false, features = ["stream", "json", "rustls", "blocking"] } +reqwest = { version = "0.13", default-features = false, features = ["stream", "json", "rustls", "blocking", "gzip", "brotli"] } futures-util = "0.3" sysinfo = { version = "0.38", default-features = false, features = ["disk"] } url = "2"