Skip to content

Commit 8319853

Browse files
committed
Implement legacy api
1 parent e22c6d4 commit 8319853

File tree

10 files changed

+235
-32
lines changed

10 files changed

+235
-32
lines changed

Cargo.lock

Lines changed: 24 additions & 21 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 & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ publish = { workspace = true }
2121

2222
[dependencies]
2323
actix-web = { version = "4.11.0", features = ["http2"] }
24-
anyhow = "1.0.98"
2524
base16ct = { version = "0.2.0", features = ["std"] }
2625
clap = { version = "4.5.41", features = ["derive", "env"] }
2726
documented = "0.9.2"
@@ -33,6 +32,7 @@ reqwest = { version = "0.12.22", default-features = false, features = ["charset"
3332
semver = "1.0.26"
3433
serde = { workspace = true }
3534
serde_json = { workspace = true }
35+
serde_variant = "0.1.3"
3636
sha2 = "0.11.0-rc.0"
3737
thiserror = "2.0.12"
3838
tokio = { version = "1.46.1", features = ["macros", "rt-multi-thread"] }

maven/src/parsing/maven.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use chrono::{DateTime, Utc};
44
use serde::Deserialize;
55

66
pub type ParseError = quick_xml::DeError;
7+
pub type Timestamp = DateTime<Utc>;
78

89
#[derive(Debug, Deserialize)]
910
#[serde(rename_all = "camelCase")]

rustfmt.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ combine_control_expr = false
44
condense_wildcard_suffixes = true
55
control_brace_style = "AlwaysSameLine"
66
empty_item_single_line = true
7-
error_on_line_overflow = true
7+
error_on_line_overflow = false
88
fn_single_line = true
99
force_multiline_blocks = false
1010
format_code_in_doc_comments = true
@@ -34,3 +34,4 @@ use_small_heuristics = "Default"
3434
use_try_shorthand = true
3535
where_single_line = false
3636
wrap_comments = true
37+
tab_spaces = 4

src/api/legacy/endpoint.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use actix_web::{HttpResponse, Responder, get, web};
2+
use tokio::try_join;
3+
4+
use crate::api::{
5+
common::data::ApiData,
6+
legacy::{
7+
types::{
8+
LegacyArtifactsErrorResponse,
9+
LegacyArtifactsResponse,
10+
LegacyLoader,
11+
LegacyVersion
12+
},
13+
utils::get_latest_artifact
14+
}
15+
};
16+
17+
const ONECONFIG_GROUP: &str = "cc.polyfrost";
18+
19+
#[get("/oneconfig/{version}-{loader}")]
20+
async fn oneconfig(
21+
state: web::Data<ApiData>,
22+
path: web::Path<(LegacyVersion, LegacyLoader)>
23+
) -> Result<impl Responder, LegacyArtifactsErrorResponse> {
24+
let version = serde_variant::to_variant_name(&path.0)
25+
.map_err(LegacyArtifactsErrorResponse::EnumVariantSerialization)?;
26+
let loader = serde_variant::to_variant_name(&path.1)
27+
.map_err(LegacyArtifactsErrorResponse::EnumVariantSerialization)?;
28+
let loader_type = path.1.get_loader_type();
29+
30+
let oneconfig_artifact = format!("oneconfig-{version}-{loader}");
31+
let loader_artifact = format!("oneconfig-loader-{loader_type}");
32+
33+
let ((release, release_ts), (snapshot, snapshot_ts), (loader, _)) = try_join!(
34+
get_latest_artifact(
35+
&state,
36+
"releases",
37+
ONECONFIG_GROUP,
38+
&oneconfig_artifact,
39+
Some("full")
40+
),
41+
get_latest_artifact(
42+
&state,
43+
"snapshots",
44+
ONECONFIG_GROUP,
45+
&oneconfig_artifact,
46+
None
47+
),
48+
get_latest_artifact(&state, "releases", ONECONFIG_GROUP, &loader_artifact, None)
49+
)?;
50+
51+
// Replace snapshot with release if it is newer
52+
let snapshot = if release_ts > snapshot_ts {
53+
release.clone()
54+
} else {
55+
snapshot
56+
};
57+
58+
let res = HttpResponse::Ok().json(LegacyArtifactsResponse {
59+
release,
60+
snapshot,
61+
loader
62+
});
63+
64+
Ok(res)
65+
}

src/api/legacy/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1+
use actix_web::web::ServiceConfig;
12

3+
pub mod endpoint;
4+
pub mod types;
5+
pub mod utils;
6+
7+
pub fn configure(config: &mut ServiceConfig) { config.service(endpoint::oneconfig); }

src/api/legacy/types.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use actix_web::{ResponseError, http::StatusCode};
2+
use serde::{Deserialize, Serialize};
3+
use thiserror::Error;
4+
5+
#[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq, Clone)]
6+
pub enum LegacyVersion {
7+
#[serde(rename = "1.8.9")]
8+
OneEightNine,
9+
#[serde(rename = "1.12.2")]
10+
OneTwelveTwo
11+
}
12+
13+
#[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq, Clone)]
14+
#[serde(rename_all = "lowercase")]
15+
pub enum LegacyLoader {
16+
Forge
17+
}
18+
19+
impl LegacyLoader {
20+
pub fn get_loader_type(&self) -> &'static str {
21+
match self {
22+
LegacyLoader::Forge => "launchwrapper"
23+
}
24+
}
25+
}
26+
27+
#[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq, Clone)]
28+
pub struct LegacyArtifact {
29+
pub url: String,
30+
pub sha256: String
31+
}
32+
33+
#[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq, Clone)]
34+
pub struct LegacyArtifactsResponse {
35+
pub release: LegacyArtifact,
36+
pub snapshot: LegacyArtifact,
37+
pub loader: LegacyArtifact
38+
}
39+
40+
#[derive(Debug, Error)]
41+
pub enum LegacyArtifactsErrorResponse {
42+
#[error("unable to serialize serde enum variant name: {0}")]
43+
EnumVariantSerialization(#[source] serde_variant::UnsupportedType),
44+
#[error("unable to connect to maven: {0}")]
45+
MavenFetch(#[source] reqwest::Error),
46+
#[error("maven request returned non-2xx status code: {0}")]
47+
MavenResponse(#[source] reqwest::Error),
48+
#[error("decoding maven metadata response failed: {0}")]
49+
MavenMetadataDecoding(#[source] reqwest::Error),
50+
#[error("parsing maven metadata response as XML failed: {0}")]
51+
MavenMetadataParsing(#[source] maven::parsing::maven::ParseError)
52+
}
53+
54+
impl ResponseError for LegacyArtifactsErrorResponse {
55+
fn status_code(&self) -> StatusCode { StatusCode::INTERNAL_SERVER_ERROR }
56+
57+
// TODO: Implement RFC9457 problem details
58+
}

src/api/legacy/utils.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use actix_web::web;
2+
use maven::{
3+
parsing::{MavenArtifactMetadata, maven::Timestamp},
4+
types::ArtifactCoordinate
5+
};
6+
7+
use crate::api::{
8+
common::data::ApiData,
9+
legacy::types::{LegacyArtifact, LegacyArtifactsErrorResponse}
10+
};
11+
12+
pub async fn get_latest_artifact(
13+
state: &web::Data<ApiData>,
14+
repository: &str,
15+
group_id: &str,
16+
artifact_id: &str,
17+
classifier: Option<&str>
18+
) -> Result<(LegacyArtifact, Timestamp), LegacyArtifactsErrorResponse> {
19+
let internal_repository_url = state.internal_maven_url.clone() + repository;
20+
let public_repository_url = state.public_maven_url.clone() + repository;
21+
22+
let res = state
23+
// Fetch metadata with HTTP
24+
.client
25+
.get(MavenArtifactMetadata::get_metadata_url(&internal_repository_url, group_id, artifact_id))
26+
.send()
27+
.await
28+
.map_err(LegacyArtifactsErrorResponse::MavenFetch)?
29+
// Error on non-2xx response codes
30+
.error_for_status()
31+
.map_err(LegacyArtifactsErrorResponse::MavenResponse)?
32+
// Decode response
33+
.text()
34+
.await
35+
.map_err(LegacyArtifactsErrorResponse::MavenMetadataDecoding)?;
36+
37+
let parsed = MavenArtifactMetadata::parse_from_str(&res)
38+
.map_err(LegacyArtifactsErrorResponse::MavenMetadataParsing)?;
39+
40+
let coordinate =
41+
ArtifactCoordinate::new(group_id, artifact_id, parsed.versioning.latest);
42+
let coordinate = if let Some(classifier) = classifier {
43+
coordinate.with_classifier(classifier)
44+
} else {
45+
coordinate
46+
};
47+
48+
let checksum = state
49+
.client
50+
// Fetch sha256 url
51+
.get(coordinate.to_sha256_url(&internal_repository_url))
52+
.send()
53+
.await
54+
.map_err(LegacyArtifactsErrorResponse::MavenFetch)?
55+
// Error on non-2xx response codes
56+
.error_for_status()
57+
.map_err(LegacyArtifactsErrorResponse::MavenResponse)?
58+
// Decode response as UTF8
59+
.text()
60+
.await
61+
.map_err(LegacyArtifactsErrorResponse::MavenMetadataDecoding)?;
62+
63+
Ok((
64+
LegacyArtifact {
65+
url: coordinate.to_artifact_url(&public_repository_url),
66+
sha256: checksum
67+
},
68+
parsed.versioning.last_updated
69+
))
70+
}

src/api/v1/responses.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,7 @@ pub enum ArtifactErrorResponse {
4646
}
4747

4848
impl ResponseError for ArtifactErrorResponse {
49-
fn status_code(&self) -> StatusCode {
50-
match self {
51-
_ => StatusCode::INTERNAL_SERVER_ERROR
52-
}
53-
}
49+
fn status_code(&self) -> StatusCode { StatusCode::INTERNAL_SERVER_ERROR }
5450

5551
// TODO: Implement RFC9457 problem details
5652
}

0 commit comments

Comments
 (0)