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 |