Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 18 additions & 13 deletions src/routes/file_cdn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ use crate::utils::app::AppState;
use crate::utils::file_cdn_load_balance::select_cdn_endpoint;

pub fn config(cfg: &mut web::ServiceConfig) {
cfg
.service(get_modrinth_file)
cfg.service(get_modrinth_file)
.service(get_curseforge_file)
.service(get_curseforge_avatar)
.service(get_curseforge_avatar_thumbnail)
Expand Down Expand Up @@ -37,11 +36,14 @@ pub async fn get_curseforge_file(
data: web::Data<AppState>,
) -> impl Responder {
let (file_id1, file_id2, file_name) = path.into_inner();

if data.file_cdn_enabled == false {
let url = format!(
"{}/files/{}/{}/{}",
data.curseforge_file_cdn_fallback_url.clone(), file_id1, file_id2, file_name
data.curseforge_file_cdn_fallback_url.clone(),
file_id1,
file_id2,
file_name
);
return Redirect::to(url).temporary();
}
Expand Down Expand Up @@ -89,7 +91,10 @@ pub async fn get_modrinth_file(
if data.file_cdn_enabled == false {
let url = format!(
"{}/data/{}/versions/{}/{}",
data.modrinth_file_cdn_fallback_url.clone(), project_id, version_id, file_name
data.modrinth_file_cdn_fallback_url.clone(),
project_id,
version_id,
file_name
);
return Redirect::to(url).temporary();
}
Expand Down Expand Up @@ -138,7 +143,8 @@ pub async fn get_curseforge_avatar(
if data.file_cdn_enabled == false {
let url = format!(
"{}/avatars/{}",
data.curseforge_avatar_cdn_fallback_url.clone(), avatar_path
data.curseforge_avatar_cdn_fallback_url.clone(),
avatar_path
);
return Redirect::to(url).temporary();
}
Expand Down Expand Up @@ -184,7 +190,8 @@ pub async fn get_curseforge_avatar_thumbnail(
if data.file_cdn_enabled == false {
let url = format!(
"{}/avatars/{}",
data.curseforge_avatar_cdn_fallback_url.clone(), avatar_path
data.curseforge_avatar_cdn_fallback_url.clone(),
avatar_path
);
return Redirect::to(url).temporary();
}
Expand Down Expand Up @@ -213,11 +220,7 @@ pub async fn get_curseforge_avatar_thumbnail(
description = "Modrinth Icon CDN",
tag = "File CDN"
)]
#[route(
"/data/{project_id}/{file_name}",
method = "GET",
method = "HEAD"
)]
#[route("/data/{project_id}/{file_name}", method = "GET", method = "HEAD")]
pub async fn get_modrinth_avatar(
path: web::Path<(String, String)>,
data: web::Data<AppState>,
Expand All @@ -226,7 +229,9 @@ pub async fn get_modrinth_avatar(
if data.file_cdn_enabled == false {
let url = format!(
"{}/data/{}/{}",
data.modrinth_avatar_cdn_fallback_url.clone(), project_id, file_name
data.modrinth_avatar_cdn_fallback_url.clone(),
project_id,
file_name
);
return Redirect::to(url).temporary();
}
Expand Down
10 changes: 7 additions & 3 deletions src/utils/file_cdn_load_balance.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
use rand::Rng;

/// 根据百分比选择 URL
///
///
/// # Arguments
/// * `primary_url` - 主要 endpoint
/// * `fallback_url` - 回退 endpoint
/// * `primary_percentage` - 主要 endpoint 的流量百分比 (0-100)
pub fn select_cdn_endpoint(primary_endpoint: String, fallback_endpoint: String, primary_percentage: u8) -> String {
pub fn select_cdn_endpoint(
primary_endpoint: String,
fallback_endpoint: String,
primary_percentage: u8,
) -> String {
let mut rng = rand::rng();
let random_value: u8 = rng.random_range(0..100);

Expand All @@ -15,4 +19,4 @@ pub fn select_cdn_endpoint(primary_endpoint: String, fallback_endpoint: String,
} else {
fallback_endpoint.to_string()
}
}
}
2 changes: 1 addition & 1 deletion src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pub mod app;
pub mod file_cdn_load_balance;
pub mod redis_cache;
pub mod file_cdn_load_balance;
6 changes: 2 additions & 4 deletions tests/file_cdn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,7 @@ async fn test_curseforge_avatar_cdn() {
#[actix_web::test]
async fn test_modrinth_avatar_cdn() {
let app = init_service(create_test_app().await).await;
let sample_avatars = &[
"/data/AANobbMI/295862f4724dc3f78df3447ad6072b2dcd3ef0c9_96.webp"
];
let sample_avatars = &["/data/AANobbMI/295862f4724dc3f78df3447ad6072b2dcd3ef0c9_96.webp"];
for url in sample_avatars.iter() {
let req = TestRequest::get().uri(url).to_request();
let resp = app.call(req).await.unwrap();
Expand All @@ -86,4 +84,4 @@ async fn test_modrinth_avatar_cdn() {
url
);
}
}
}