Skip to content

Commit f2e25a5

Browse files
committed
feat(api,platform): enable gzip compression for outbound connections
1 parent 4e67e5c commit f2e25a5

6 files changed

Lines changed: 77 additions & 4 deletions

File tree

Cargo.lock

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ default = [
108108
"lettre/smtp-transport",
109109
"lettre/tokio1-rustls-tls",
110110
"postcard/use-std",
111+
"reqwest/gzip",
111112
"reqwest/json",
112113
"reqwest-middleware/json",
113114
"reqwest-retry/tracing",

dev/docker/nginx-e2e.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ server {
1313
try_files $uri $uri/ $uri.html /index.html;
1414
}
1515

16-
location ^~ /api/ {
16+
location ~ ^/(api/|api-docs) {
1717
proxy_pass http://secutils_api:7070;
1818
proxy_set_header Host $host;
1919
proxy_set_header X-Real-IP $remote_addr;

src/js_runtime/op_proxy_request.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub trait PublicUrlValidator: Send + Sync {
2525
/// Each script execution creates its own `ProxyState` (and thus its own
2626
/// `reqwest::Client` instances). This is critical because each script runs on
2727
/// a dedicated `CurrentThread` tokio runtime that is dropped when the script
28-
/// finishes. A static/shared `reqwest::Client` would keep pooled connections
28+
/// finishes. A static/shared `reqwest::Client` would keep pooled connections
2929
/// whose hyper background tasks are bound to the *previous* runtime, causing
3030
/// "dispatch task is gone" errors on the next invocation.
3131
#[derive(Clone)]
@@ -64,7 +64,8 @@ impl ProxyState {
6464
cell.get_or_init(|| {
6565
let mut builder = reqwest::Client::builder()
6666
.redirect(RedirectPolicy::none())
67-
.http1_only();
67+
.http1_only()
68+
.no_gzip();
6869
if insecure {
6970
builder = builder.danger_accept_invalid_certs(true);
7071
}

src/network.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,42 @@ pub mod tests {
133133

134134
pub use super::dns_resolver::tests::*;
135135

136+
/// Gzip-compresses the given bytes.
137+
fn gzip_encode(data: &[u8]) -> Vec<u8> {
138+
use flate2::{Compression, write::GzEncoder};
139+
use std::io::Write;
140+
let mut encoder = GzEncoder::new(Vec::new(), Compression::fast());
141+
encoder.write_all(data).unwrap();
142+
encoder.finish().unwrap()
143+
}
144+
145+
#[tokio::test]
146+
async fn http_client_negotiates_gzip_compression() -> anyhow::Result<()> {
147+
let server = httpmock::MockServer::start();
148+
let body = serde_json::json!({"message": "hello from gzip"});
149+
let body_bytes = serde_json::to_vec(&body)?;
150+
let compressed = gzip_encode(&body_bytes);
151+
152+
let mock = server.mock(|when, then| {
153+
when.method(httpmock::Method::GET)
154+
.path("/gzip-test")
155+
.header_exists("accept-encoding");
156+
then.status(200)
157+
.header("Content-Type", "application/json")
158+
.header("Content-Encoding", "gzip")
159+
.body(compressed);
160+
});
161+
162+
let client = Client::builder().build()?;
163+
let response = client.get(server.url("/gzip-test")).send().await?;
164+
let json: serde_json::Value = response.json().await?;
165+
166+
mock.assert();
167+
assert_eq!(json, body);
168+
169+
Ok(())
170+
}
171+
136172
#[tokio::test]
137173
async fn correctly_checks_public_web_urls() -> anyhow::Result<()> {
138174
let public_network = Network::new(

0 commit comments

Comments
 (0)