1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// SPDX-License-Identifier: Apache-2.0
//! Axum router for the Maven 2/3 protocol.
//!
//! The mount point is conventionally `/repository/{repo}` so `FerroRepo`
//! can host many named Maven repositories side-by-side. The wildcard
//! `{*path}` captures the complete Maven layout path below that.
//!
//! Spec: Maven Repository Layout —
//! <https://maven.apache.org/repository/layout.html>.
use BTreeMap;
use Arc;
use Router;
use DefaultBodyLimit;
use get;
use BlobStore;
use RwLock;
use crate;
use crateMavenMetadata;
/// Shape of a metadata cache key.
///
/// The first two entries are always `(repo, groupPath, artifactId)`;
/// the optional `baseVersion` — when present — scopes the entry to
/// version-level SNAPSHOT metadata at
/// `{groupPath}/{artifactId}/{baseVersion}-SNAPSHOT/maven-metadata.xml`.
pub type MetadataKey = ;
/// `MetadataKey` → [`MavenMetadata`] cache.
pub type MetadataCache = ;
/// `(repo, groupPath, artifactId, baseVersion)` → monotonic build
/// number.
pub type SnapshotCounter = ;
/// Shared state held by every Maven handler.
///
/// Wraps a content-addressed [`BlobStore`] and three in-memory indices:
///
/// - `layout`: maps the Maven layout path (e.g.
/// `com/example/foo/1.0/foo-1.0.jar`) to a
/// `ferro_blob_store::Digest`, so incoming `GET`s can find the right
/// blob.
/// - `metadata`: caches the parsed [`MavenMetadata`] for each
/// `{repo}/{groupPath}/{artifactId}` so regeneration on `PUT` does
/// not need a full scan.
/// - `snapshot_counter`: monotonic per-base-version build numbers for
/// SNAPSHOT timestamping.
/// Maximum accepted size, in bytes, of a Maven artifact `PUT` body
/// (256 MiB).
///
/// R5-2: Axum's [`DefaultBodyLimit`] is 2 MiB, which silently rejects
/// (`413 Payload Too Large`) any artifact larger than that — and real
/// Maven artifacts (fat/uber JARs, WARs, EARs, native bundles) routinely
/// exceed 2 MiB. Without an explicit limit, `mvn deploy` of such an
/// artifact fails unless the embedder happens to override the default.
///
/// 256 MiB is a Maven-appropriate cap: it comfortably covers the vast
/// majority of published artifacts (Maven Central's own per-file ceiling
/// is well under this) while still bounding memory, since [`handle_put`]
/// buffers the whole body as [`bytes::Bytes`]. It sits between the
/// cargo registry's 20 MiB tarball cap and the OCI server's 512 MiB blob
/// cap, reflecting that Maven artifacts are larger than crate tarballs
/// but smaller than container image layers.
///
/// [`handle_put`]: crate::handlers::handle_put
pub const MAX_ARTIFACT_BODY_BYTES: usize = 256 * 1024 * 1024;
/// Build the Maven Axum router.
///
/// Routes all HTTP verbs on `/repository/{repo}/{*path}` to the
/// appropriate handler.
///
/// The `PUT` body limit is raised to [`MAX_ARTIFACT_BODY_BYTES`] above
/// Axum's 2 MiB default so normal Maven artifacts are accepted.