OXYGENHUB

oxy serve takes a push of more than 2 MB (closes #138) e30c081a5064

oxy_server::router set no request limit of its own, so axum's default
of 2 MB applied and a larger push part was cut off: Broken pipe at the
client, nothing in the server's log. BODY_LIMIT is 4 GiB, OxygenHub's
default push_body_limit; a test pushes 3 MB over HTTP.
Author
Andy McCall @andymccall <[email protected]>
via
agent agent:claude@andymccall <[email protected]> · keyless, under your grant for changes,refs,seal · key eeb10df24b16
When
· 2026-10-25 08:03 UTC
Signature
◈ sealed by agent:claude@andymccall
Hash
e30c081a50647168556fe693b88e934f0fff3ec6039a7562af7c18d77080ff61
Depends on
750251b21a96 75167672ebcd b3c5a59a875a e02bf0cd0533
Depended on by
nothing yet
In bookmarks
identical-sides main push-notes subrepo-pin-state
In tags
v0.10.0 v0.11.0 v0.7.0 v0.8.0 v0.9.0
Edits
5 atoms, 0 tree operations, 2 files

Browse the tree at this change

modified crates/oxy-server/src/lib.rs +12 −0
…
334 unchanged lines
335 335
    }
336 336
}
337 337
338 +
/// The largest request `oxy serve` takes: a push part is about
339 +
/// `push.batch-bytes` (64 MiB), but one change can weigh more; OxygenHub's
340 +
/// default `push_body_limit` is the same.
341 +
pub const BODY_LIMIT: usize = if usize::BITS > 32 {
342 +
    4 << 30
343 +
} else {
344 +
    usize::MAX
345 +
};
346 +
338 347
/// The router of `oxy serve`: `/{repo}/oxy/v1/{endpoint}` over a [`DirBackend`].
339 348
pub fn router(cfg: ServerConfig) -> Router {
340 349
    let server = Server::new(DirBackend {
341 350
        root: cfg.root,
342 351
        tokens: cfg.tokens,
343 352
    });
353 +
    // Without a limit of its own a request takes axum's 2 MB, and a larger
354 +
    // push was cut off with no word in the log ("Broken pipe" at the client).
344 355
    Router::new()
345 356
        .route("/{repo}/oxy/v1/{endpoint}", any(dispatch))
357 +
        .layer(axum::extract::DefaultBodyLimit::max(BODY_LIMIT))
346 358
        .with_state(server)
347 359
}
348 360
…
29 unchanged lines
modified crates/oxy-server/tests/http.rs +29 −0
…
113 unchanged lines
114 114
        .contains("404"));
115 115
}
116 116
117 +
/// A push of more than axum's default 2 MB body is taken: `oxy serve`
118 +
/// sets its own limit, as OxygenHub does.
117 119
#[test]
120 +
fn a_push_of_more_than_two_megabytes_is_taken() {
121 +
    hermetic();
122 +
    let dir = tempfile::tempdir().unwrap();
123 +
    let root = dir.path();
124 +
    let served = root.join("served");
125 +
    Repo::init(&served.join("origin")).unwrap();
126 +
    let url = format!("{}/origin", start(&served, vec![]));
127 +
    let a = Repo::clone(&url, &root.join("a")).unwrap();
128 +
    let mut x: u64 = 0x9e3779b97f4a7c15;
129 +
    let noise: Vec<u8> = (0..3 << 20)
130 +
        .map(|_| {
131 +
            x ^= x << 13;
132 +
            x ^= x >> 7;
133 +
            x ^= x << 17;
134 +
            (x >> 24) as u8
135 +
        })
136 +
        .collect();
137 +
    write(&root.join("a"), "big.bin", &noise);
138 +
    let h = a.commit("three megabytes", &[]).unwrap();
139 +
    let r = a.push("origin", false).unwrap();
140 +
    assert!(r[0].ok, "{}", r[0].reason);
141 +
    let b = Repo::clone(&url, &root.join("b")).unwrap();
142 +
    assert_eq!(b.bookmark_heads().unwrap(), vec![h]);
143 +
    assert_eq!(fs::read(root.join("b/big.bin")).unwrap(), noise);
144 +
}
145 +
146 +
#[test]
118 147
fn objects_endpoint_serves_lazy_blobs() {
119 148
    hermetic();
120 149
    let dir = tempfile::tempdir().unwrap();
…
397 unchanged lines