From 4455ad3d17241b26731427cd55a056c6c6971fd9 Mon Sep 17 00:00:00 2001 From: wujian <353981613@qq.com> Date: Mon, 27 May 2024 16:16:46 +0800 Subject: [PATCH 1/2] init gemini code --- Cargo.toml | 1 + gateway/Cargo.toml | 1 + gateway/src/lib.rs | 2 +- gateway/src/relay_server.rs | 100 +++++++++++++++++++++++++++++ gemini/Cargo.toml | 15 +++++ gemini/src/http/handler.rs | 14 ++++ gemini/src/http/mod.rs | 1 + gemini/src/lib.rs | 1 + mega/src/commands/service/mod.rs | 10 ++- mega/src/commands/service/relay.rs | 21 ++++++ 10 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 gateway/src/relay_server.rs create mode 100644 gemini/Cargo.toml create mode 100644 gemini/src/http/handler.rs create mode 100644 gemini/src/http/mod.rs create mode 100644 gemini/src/lib.rs create mode 100644 mega/src/commands/service/relay.rs diff --git a/Cargo.toml b/Cargo.toml index a9706ddc4..862424132 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ jupiter = { path = "jupiter" } venus = { path = "venus" } ceres = { path = "ceres" } callisto = { path = "jupiter/callisto" } +gemini = { path = "gemini" } anyhow = "1.0.83" serde = "1.0.201" serde_json = "1.0.117" diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index ef95d2e9e..63f688e38 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -14,6 +14,7 @@ common = { workspace = true } jupiter = { workspace = true } callisto = { workspace = true } ceres = { workspace = true } +gemini = { workspace = true } venus = { workspace = true } mercury = { workspace = true } anyhow = { workspace = true } diff --git a/gateway/src/lib.rs b/gateway/src/lib.rs index b3b349635..f7b616955 100644 --- a/gateway/src/lib.rs +++ b/gateway/src/lib.rs @@ -1,10 +1,10 @@ - mod api_service; mod git_protocol; pub mod https_server; pub mod init; mod lfs; mod model; +pub mod relay_server; pub mod ssh_server; #[cfg(test)] diff --git a/gateway/src/relay_server.rs b/gateway/src/relay_server.rs new file mode 100644 index 000000000..b44288d12 --- /dev/null +++ b/gateway/src/relay_server.rs @@ -0,0 +1,100 @@ +use std::net::SocketAddr; +use std::str::FromStr; + +use axum::body::Body; +use axum::extract::{Query, State}; +use axum::http::{Response, StatusCode, Uri}; +use axum::routing::get; +use axum::Router; +use clap::Args; +use common::config::Config; +use common::model::{CommonOptions, GetParams}; +use jupiter::context::Context; +use regex::Regex; +use tower::ServiceBuilder; +use tower_http::cors::{Any, CorsLayer}; +use tower_http::decompression::RequestDecompressionLayer; +use tower_http::trace::TraceLayer; + +use crate::api_service; +use crate::api_service::router::ApiServiceState; + +#[derive(Args, Clone, Debug)] +pub struct RelayOptions { + #[clap(flatten)] + pub common: CommonOptions, + + #[arg(long, default_value_t = 8001)] + pub http_port: u16, +} + +pub async fn http_server(config: Config, options: RelayOptions) { + let RelayOptions { + common: CommonOptions { host }, + http_port, + } = options; + + let app = app(config, host.clone(), http_port).await; + + let server_url = format!("{}:{}", host, http_port); + + let addr = SocketAddr::from_str(&server_url).unwrap(); + let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); + axum::serve(listener, app.into_make_service()) + .await + .unwrap(); +} + +#[derive(Clone)] +pub struct AppState { + pub context: Context, + pub host: String, + pub port: u16, +} + +pub async fn app(config: Config, host: String, port: u16) -> Router { + let state = AppState { + host, + port, + context: Context::new(config.clone()).await, + }; + + let api_state = ApiServiceState { + context: Context::new(config).await, + }; + + // add RequestDecompressionLayer for handle gzip encode + // add TraceLayer for log record + // add CorsLayer to add cors header + Router::new() + .nest( + "/api/v1", + api_service::router::routers().with_state(api_state), + ) + .route( + "/*path", + get(get_method_router), // .post(post_method_router) + // .put(put_method_router), + ) + .layer(ServiceBuilder::new().layer(CorsLayer::new().allow_origin(Any))) + .layer(TraceLayer::new_for_http()) + .layer(RequestDecompressionLayer::new()) + .with_state(state) +} + +async fn get_method_router( + _state: State, + Query(params): Query, + uri: Uri, +) -> Result, (StatusCode, String)> { + if Regex::new(r"/hello$").unwrap().is_match(uri.path()) { + return gemini::http::handler::hello_gemini(params).await; + } + return Err(( + StatusCode::NOT_FOUND, + String::from("Operation not supported\n"), + )); +} + +#[cfg(test)] +mod tests {} diff --git a/gemini/Cargo.toml b/gemini/Cargo.toml new file mode 100644 index 000000000..3a952139c --- /dev/null +++ b/gemini/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "gemini" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "gemini" +path = "src/lib.rs" + + +[dependencies] +common = { workspace = true } +axum = { workspace = true } \ No newline at end of file diff --git a/gemini/src/http/handler.rs b/gemini/src/http/handler.rs new file mode 100644 index 000000000..6a0f93d26 --- /dev/null +++ b/gemini/src/http/handler.rs @@ -0,0 +1,14 @@ +use axum::{ + body::Body, + http::{Response, StatusCode}, +}; +use common::model::GetParams; + +pub async fn hello_gemini(_params: GetParams) -> Result, (StatusCode, String)> { + return Ok(Response::builder() + .body(Body::from("hello gemini")) + .unwrap()); +} + +#[cfg(test)] +mod tests {} diff --git a/gemini/src/http/mod.rs b/gemini/src/http/mod.rs new file mode 100644 index 000000000..062ae9d9b --- /dev/null +++ b/gemini/src/http/mod.rs @@ -0,0 +1 @@ +pub mod handler; diff --git a/gemini/src/lib.rs b/gemini/src/lib.rs new file mode 100644 index 000000000..3883215fc --- /dev/null +++ b/gemini/src/lib.rs @@ -0,0 +1 @@ +pub mod http; diff --git a/mega/src/commands/service/mod.rs b/mega/src/commands/service/mod.rs index 4d12d1fde..fa20dcb4b 100644 --- a/mega/src/commands/service/mod.rs +++ b/mega/src/commands/service/mod.rs @@ -10,12 +10,19 @@ use common::{config::Config, errors::MegaResult}; mod http; mod https; mod multi; +mod relay; mod ssh; // This function generates the CLI for the 'service' command. // It includes subcommands for each server type. pub fn cli() -> Command { - let subcommands = vec![http::cli(), https::cli(), ssh::cli(), multi::cli()]; + let subcommands = vec![ + http::cli(), + https::cli(), + ssh::cli(), + multi::cli(), + relay::cli(), + ]; Command::new("service") .about("Start different kinds of server: for example https or ssh") .subcommands(subcommands) @@ -37,6 +44,7 @@ pub(crate) async fn exec(config: Config, args: &ArgMatches) -> MegaResult { "https" => https::exec(config, subcommand_args).await, "ssh" => ssh::exec(config, subcommand_args).await, "multi" => multi::exec(config, subcommand_args).await, + "relay" => relay::exec(config, subcommand_args).await, _ => Ok(()), } } diff --git a/mega/src/commands/service/relay.rs b/mega/src/commands/service/relay.rs new file mode 100644 index 000000000..754b7269a --- /dev/null +++ b/mega/src/commands/service/relay.rs @@ -0,0 +1,21 @@ +use clap::{ArgMatches, Args, Command, FromArgMatches}; + +use common::{config::Config, errors::MegaResult}; +use gateway::relay_server::{self, RelayOptions}; + +pub fn cli() -> Command { + RelayOptions::augment_args_for_update(Command::new("relay").about("Start Mega RELAY server")) +} + +pub(crate) async fn exec(config: Config, args: &ArgMatches) -> MegaResult { + let relay_matchers = RelayOptions::from_arg_matches(args) + .map_err(|err| err.exit()) + .unwrap(); + + tracing::info!("{relay_matchers:#?}"); + relay_server::http_server(config, relay_matchers).await; + Ok(()) +} + +#[cfg(test)] +mod tests {} From d112cf305371ee351add2e9b1099b3c0088e4a07 Mon Sep 17 00:00:00 2001 From: wujian <353981613@qq.com> Date: Mon, 27 May 2024 16:53:47 +0800 Subject: [PATCH 2/2] remove useless return statement --- gateway/src/relay_server.rs | 4 ++-- gemini/src/http/handler.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gateway/src/relay_server.rs b/gateway/src/relay_server.rs index b44288d12..715c92c2e 100644 --- a/gateway/src/relay_server.rs +++ b/gateway/src/relay_server.rs @@ -90,10 +90,10 @@ async fn get_method_router( if Regex::new(r"/hello$").unwrap().is_match(uri.path()) { return gemini::http::handler::hello_gemini(params).await; } - return Err(( + Err(( StatusCode::NOT_FOUND, String::from("Operation not supported\n"), - )); + )) } #[cfg(test)] diff --git a/gemini/src/http/handler.rs b/gemini/src/http/handler.rs index 6a0f93d26..e4750284c 100644 --- a/gemini/src/http/handler.rs +++ b/gemini/src/http/handler.rs @@ -5,9 +5,9 @@ use axum::{ use common::model::GetParams; pub async fn hello_gemini(_params: GetParams) -> Result, (StatusCode, String)> { - return Ok(Response::builder() + Ok(Response::builder() .body(Body::from("hello gemini")) - .unwrap()); + .unwrap()) } #[cfg(test)]