From 3afff9f83428cb4ec3700287aacff1191335a543 Mon Sep 17 00:00:00 2001 From: fuxiaohei Date: Mon, 3 Jun 2024 18:09:17 +0800 Subject: [PATCH] feat(apiserver): init api server --- Cargo.lock | 29 +++++++++--- Cargo.toml | 2 +- crates/core-service/src/httputil/response.rs | 46 +++++++++++++++++++ land-apiserver/Cargo.toml | 16 +++++++ land-apiserver/src/main.rs | 47 ++++++++++++++++++++ land-apiserver/src/server.rs | 29 ++++++++++++ land-apiserver/src/v1/mod.rs | 9 ++++ land-apiserver/src/v1/tokens.rs | 31 +++++++++++++ 8 files changed, 201 insertions(+), 8 deletions(-) create mode 100644 land-apiserver/Cargo.toml create mode 100644 land-apiserver/src/main.rs create mode 100644 land-apiserver/src/server.rs create mode 100644 land-apiserver/src/v1/mod.rs create mode 100644 land-apiserver/src/v1/tokens.rs diff --git a/Cargo.lock b/Cargo.lock index cee83be2..5ffb931a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2196,6 +2196,21 @@ dependencies = [ "simple_asn1", ] +[[package]] +name = "land-apiserver" +version = "0.3.12" +dependencies = [ + "anyhow", + "axum", + "clap", + "land-common", + "land-core-service", + "land-dao", + "serde", + "tokio", + "tracing", +] + [[package]] name = "land-cli" version = "0.3.12" @@ -4477,9 +4492,9 @@ dependencies = [ [[package]] name = "spdx" -version = "0.10.4" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ef1a0fa1e39ac22972c8db23ff89aea700ab96aa87114e1fb55937a631a0c9" +checksum = "47317bbaf63785b53861e1ae2d11b80d6b624211d42cb20efcd210ee6f8a14bc" dependencies = [ "smallvec", ] @@ -5880,9 +5895,9 @@ dependencies = [ [[package]] name = "wast" -version = "209.0.0" +version = "209.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "796916a29f4a8454655b7af3aa2d0e40532d07b4d3b8abdb78e4cb6b84c00586" +checksum = "8fffef2ff6147e4d12e972765fd75332c6a11c722571d4ab7a780d81ffc8f0a4" dependencies = [ "bumpalo", "leb128", @@ -5893,11 +5908,11 @@ dependencies = [ [[package]] name = "wat" -version = "1.209.0" +version = "1.209.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ecc135c1bdf98ef1c818b80996897ab23dff91391149e8c22d8278796b743e9" +checksum = "42203ec0271d113f8eb1f77ebc624886530cecb35915a7f63a497131f16e4d24" dependencies = [ - "wast 209.0.0", + "wast 209.0.1", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ef266b98..e06eac7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ members = [ "crates/sdk-macro", "crates/wasm", "crates/wasm-gen", - "crates/worker-server", + "crates/worker-server", "land-apiserver", "land-cli", "land-controller", "land-server", diff --git a/crates/core-service/src/httputil/response.rs b/crates/core-service/src/httputil/response.rs index b49dd45b..12818790 100644 --- a/crates/core-service/src/httputil/response.rs +++ b/crates/core-service/src/httputil/response.rs @@ -1,5 +1,6 @@ use axum::body::Body; use axum::response::{IntoResponse, Response}; +use axum::Json; use reqwest::StatusCode; /// response_redirect returns a redirect response @@ -11,6 +12,51 @@ pub fn response_redirect(url: &str) -> impl IntoResponse { .unwrap() } +pub struct ServerJsonError(pub StatusCode, pub anyhow::Error); + +impl Clone for ServerJsonError { + fn clone(&self) -> Self { + Self(self.0, anyhow::anyhow!(self.1.to_string())) + } +} + +impl ServerJsonError { + pub fn status_code(code: StatusCode, msg: &str) -> Self { + Self(code, anyhow::anyhow!(msg.to_string())) + } +} + +#[derive(serde::Serialize)] +pub struct ServerJsonResponse { + pub message: String, +} + +impl IntoResponse for ServerJsonError { + fn into_response(self) -> Response { + let mut resp = ( + self.0, + Json(ServerJsonResponse { + message: self.1.to_string(), + }), + ) + .into_response(); + let exts = resp.extensions_mut(); + exts.insert(self); + resp + } +} + +// This enables using `?` on functions that return `Result<_, anyhow::Error>` to turn them into +// `Result<_, AppError>`. That way you don't need to do that manually. +impl From for ServerJsonError +where + E: Into, +{ + fn from(err: E) -> Self { + Self(StatusCode::INTERNAL_SERVER_ERROR, err.into()) + } +} + // Make our own error that wraps `anyhow::Error`. pub struct ServerError(pub StatusCode, pub anyhow::Error); diff --git a/land-apiserver/Cargo.toml b/land-apiserver/Cargo.toml new file mode 100644 index 00000000..15af7470 --- /dev/null +++ b/land-apiserver/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "land-apiserver" +version = { workspace = true } +edition = { workspace = true } +authors = { workspace = true } + +[dependencies] +anyhow = { workspace = true } +axum = { workspace = true } +clap = { workspace = true } +land-common = { workspace = true } +land-dao = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } +land-core-service = { workspace = true } +serde = { workspace = true } diff --git a/land-apiserver/src/main.rs b/land-apiserver/src/main.rs new file mode 100644 index 00000000..0173085e --- /dev/null +++ b/land-apiserver/src/main.rs @@ -0,0 +1,47 @@ +use anyhow::Result; +use clap::Parser; +use land_common::tracing::TraceArgs; +use land_common::version; + +mod server; +mod v1; + +#[derive(Parser, Debug)] +#[clap(author, version)] +#[clap(disable_version_flag = true)] // handled manually +#[clap( + name = env!("CARGO_PKG_NAME"), + about = concat!(env!("CARGO_PKG_NAME")," ",env!("CARGO_PKG_VERSION")), +)] +struct Args { + /// Print version info and exit. + #[clap(short = 'V', long)] + version: bool, + #[clap(flatten)] + output: TraceArgs, + /// Address to listen on. + #[clap(long, default_value("0.0.0.0:9814"))] + address: String, + #[clap(flatten)] + dbargs: land_dao::db::DBArgs, +} + +#[tokio::main] +async fn main() -> Result<()> { + let args = Args::parse(); + if args.version { + version::print(env!("CARGO_PKG_NAME"), args.output.verbose); + return Ok(()); + } + + // Initialize tracing + land_common::tracing::init(args.output.verbose); + + // Connect to database + args.dbargs.connect().await?; + + // Start the server + server::start(args.address.parse()?).await?; + + Ok(()) +} diff --git a/land-apiserver/src/server.rs b/land-apiserver/src/server.rs new file mode 100644 index 00000000..0abd85a8 --- /dev/null +++ b/land-apiserver/src/server.rs @@ -0,0 +1,29 @@ +use anyhow::Result; +use axum::routing::get; +use axum::Router; +use std::net::SocketAddr; +use tracing::info; + +use crate::v1; + +pub async fn start(addr: SocketAddr) -> Result<()> { + // routes + let app = Router::new() + .route("/", get(index)) + .nest("/v1", v1::router()?); + + info!("Starting server on {}", addr); + + // with connect info + let app = app.into_make_service_with_connect_info::(); + + // run server + let listener = tokio::net::TcpListener::bind(addr).await?; + axum::serve(listener, app).await?; + + Ok(()) +} + +async fn index() -> &'static str { + "Hello, World!" +} diff --git a/land-apiserver/src/v1/mod.rs b/land-apiserver/src/v1/mod.rs new file mode 100644 index 00000000..e881a5c5 --- /dev/null +++ b/land-apiserver/src/v1/mod.rs @@ -0,0 +1,9 @@ +use anyhow::Result; +use axum::routing::post; +use axum::Router; + +pub mod tokens; + +pub fn router() -> Result { + Ok(Router::new().route("/token", post(tokens::create))) +} diff --git a/land-apiserver/src/v1/tokens.rs b/land-apiserver/src/v1/tokens.rs new file mode 100644 index 00000000..cb3ece44 --- /dev/null +++ b/land-apiserver/src/v1/tokens.rs @@ -0,0 +1,31 @@ +use axum::response::IntoResponse; +use axum::Json; +use land_core_service::httputil::ServerJsonError; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug)] +pub struct CreateTokenUserParam { + pub first_name: String, + pub last_name: String, + pub email: String, + pub image_url: String, + pub has_image: bool, + pub identifier: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct CreateTokenSessionParam { + pub id: String, + pub value: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct CreateTokenParam { + pub user: CreateTokenUserParam, + pub session: CreateTokenSessionParam, +} + +pub async fn create(Json(j): Json) -> Result { + println!("{:?}", j); + Ok(Json("abc")) +}