Skip to content

Commit

Permalink
feat(gitlab): Introduce a self-hosted gitlab endpoint
Browse files Browse the repository at this point in the history
This introduces the `/v1/gitlab/:host/:user/:repo` routes, where `:host`
is any GitLab instance (including, possibly, gitlab.com).

Signed-off-by: Gergely Nagy <me@gergo.csillger.hu>
  • Loading branch information
algernon authored and cafkafk committed Oct 30, 2023
1 parent 0c1e780 commit 3dd2c37
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 0 deletions.
51 changes: 51 additions & 0 deletions src/api/v1/gitlab/endpoints/get_repo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-FileCopyrightText: 2023 Gergely Nagy
// SPDX-FileContributor: Gergely Nagy
//
// SPDX-License-Identifier: AGPL-3.0-only

use axum::{
body::Body,
extract::Path,
http::{Request, StatusCode},
response::{IntoResponse, Redirect},
};

#[allow(unused)]
use log::{debug, error, info, trace, warn};

use super::super::utils::gitlab_api_get_latest_tag;

pub async fn get_repo(
Path((host, user, repo)): Path<(String, String, String)>,
request: Request<Body>,
) -> impl IntoResponse {
if repo.ends_with(".tar.gz") {
let tag = gitlab_api_get_latest_tag(
host.clone(),
user.clone(),
repo.clone()
.strip_suffix(".tar.gz")
.expect("couldn't strip .tar.gz suffix")
.to_string(),
)
.await
.expect("failed to await gitlab_api_get_latest_tag");
let result_uri = format!(
"/v1/gitlab/{}/{}/{}/v/{}.tar.gz",
host,
user,
repo.strip_suffix(".tar.gz")
.expect("couldn't strip .tar.gz suffix"),
tag,
);
trace!("{result_uri:#?}");
Redirect::to(&result_uri).into_response()
} else {
let body = format!(
"Hi friend, you probably meant to request {:#?}{}.tar.gz, that should work <3",
request.headers()["host"],
request.uri()
);
(StatusCode::BAD_REQUEST, body).into_response()
}
}
37 changes: 37 additions & 0 deletions src/api/v1/gitlab/endpoints/get_repo_ref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-FileCopyrightText: 2023 Gergely Nagy
// SPDX-FileContributor: Gergely Nagy
//
// SPDX-License-Identifier: AGPL-3.0-only

use axum::{
body::Body,
extract::Path,
http::{Request, StatusCode},
response::{IntoResponse, Redirect},
};

#[allow(unused)]
use log::{debug, error, info, trace, warn};

pub async fn get_repo_ref(
Path((host, user, repo, git_ref)): Path<(String, String, String, String)>,
request: Request<Body>,
) -> impl IntoResponse {
if git_ref.ends_with(".tar.gz") {
let git_ref_name = git_ref
.strip_suffix(".tar.gz")
.expect("couldn't strip .tar.gz suffix");
let uri = format!(
"https://{}/{}/{}/-/archive/{}/{}-{}.tar.gz",
host, user, repo, git_ref_name, repo, git_ref_name,
);
Redirect::to(&uri).into_response()
} else {
let body = format!(
"Hi friend, you probably meant to request {:#?}{}.tar.gz, that should work <3",
request.headers()["host"],
request.uri()
);
(StatusCode::BAD_REQUEST, body).into_response()
}
}
9 changes: 9 additions & 0 deletions src/api/v1/gitlab/endpoints/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-FileCopyrightText: 2023 Gergely Nagy
// SPDX-FileContributor: Gergely Nagy
//
// SPDX-License-Identifier: AGPL-3.0-only

mod get_repo;
pub use self::get_repo::get_repo;
mod get_repo_ref;
pub use self::get_repo_ref::get_repo_ref;
9 changes: 9 additions & 0 deletions src/api/v1/gitlab/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-FileCopyrightText: 2023 Gergely Nagy
// SPDX-FileContributor: Gergely Nagy
//
// SPDX-License-Identifier: AGPL-3.0-only

pub mod routes;

mod endpoints;
mod utils;
19 changes: 19 additions & 0 deletions src/api/v1/gitlab/routes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: 2023 Gergely Nagy
// SPDX-FileContributor: Gergely Nagy
//
// SPDX-License-Identifier: AGPL-3.0-only

use super::endpoints::{get_repo, get_repo_ref};

use axum::{routing::get, Router};

pub fn get_routes() -> Router {
Router::new()
.route("/:host/:user/:repo/b/:branch", get(get_repo_ref))
.route("/:host/:user/:repo/branch/:branch", get(get_repo_ref))
.route("/:host/:user/:repo/v/:version", get(get_repo_ref))
.route("/:host/:user/:repo/version/:version", get(get_repo_ref))
.route("/:host/:user/:repo/t/:version", get(get_repo_ref))
.route("/:host/:user/:repo/tag/:version", get(get_repo_ref))
.route("/:host/:user/:repo", get(get_repo))
}
40 changes: 40 additions & 0 deletions src/api/v1/gitlab/utils/gitlab_api_get_latest_tag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: 2023 Gergely Nagy
// SPDX-FileContributor: Gergely Nagy
//
// SPDX-License-Identifier: AGPL-3.0-only

#[allow(unused)]
use log::{debug, error, info, trace, warn};

pub async fn gitlab_api_get_latest_tag(
host: String,
user: String,
repo: String,
) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
use reqwest::{
header::{ACCEPT, USER_AGENT},
Url,
};
// TODO: The middle part, `{}%2F{}` is really `user/repo` URL-encoded. We
// should do proper URL encoding.
let version_uri = Url::parse(&format!(
"https://{}/api/v4/projects/{}%2F{}/repository/tags",
host, user, repo
))?;
trace!("{:#?}", version_uri);
let client = reqwest::Client::builder().user_agent(USER_AGENT).build()?;
let res = client
.get(version_uri)
.header(ACCEPT, "application/json")
.send()
.await?
.json::<serde_json::Value>()
.await?;

trace!("got:\n {:#?}", res[0]["name"]);

Ok(res[0]["name"]
.as_str()
.expect("failed to get release name as_str()")
.to_string())
}
7 changes: 7 additions & 0 deletions src/api/v1/gitlab/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-FileCopyrightText: 2023 Gergely Nagy
// SPDX-FileContributor: Gergely Nagy
//
// SPDX-License-Identifier: AGPL-3.0-only

mod gitlab_api_get_latest_tag;
pub use self::gitlab_api_get_latest_tag::gitlab_api_get_latest_tag;
1 change: 1 addition & 0 deletions src/api/v1/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ pub mod routes;
mod flakehub;
mod forgejo;
mod github;
mod gitlab;
2 changes: 2 additions & 0 deletions src/api/v1/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use super::flakehub::routes::get_routes as get_flakehub_routes;
use super::forgejo::routes::get_redirect_routes as get_forgejo_redirect_routes;
use super::forgejo::routes::get_routes as get_forgejo_routes;
use super::github::routes::get_routes as get_github_routes;
use super::gitlab::routes::get_routes as get_gitlab_routes;
use axum::Router;

pub fn get_routes() -> Router {
Expand All @@ -15,5 +16,6 @@ pub fn get_routes() -> Router {
.nest("/flakehub", get_flakehub_routes())
.nest("/forgejo", get_forgejo_routes())
.nest("/gitea", get_forgejo_routes())
.nest("/gitlab", get_gitlab_routes())
.merge(get_forgejo_redirect_routes())
}

0 comments on commit 3dd2c37

Please sign in to comment.