Skip to content

Commit

Permalink
feat(apiserver): init api server
Browse files Browse the repository at this point in the history
  • Loading branch information
fuxiaohei committed Jun 3, 2024
1 parent 1aa446b commit 3afff9f
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 8 deletions.
29 changes: 22 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
46 changes: 46 additions & 0 deletions crates/core-service/src/httputil/response.rs
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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<E> From<E> for ServerJsonError
where
E: Into<anyhow::Error>,
{
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);

Expand Down
16 changes: 16 additions & 0 deletions land-apiserver/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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 }
47 changes: 47 additions & 0 deletions land-apiserver/src/main.rs
Original file line number Diff line number Diff line change
@@ -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(())
}
29 changes: 29 additions & 0 deletions land-apiserver/src/server.rs
Original file line number Diff line number Diff line change
@@ -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::<SocketAddr>();

// run server
let listener = tokio::net::TcpListener::bind(addr).await?;
axum::serve(listener, app).await?;

Ok(())
}

async fn index() -> &'static str {
"Hello, World!"
}
9 changes: 9 additions & 0 deletions land-apiserver/src/v1/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use anyhow::Result;
use axum::routing::post;
use axum::Router;

pub mod tokens;

pub fn router() -> Result<Router> {
Ok(Router::new().route("/token", post(tokens::create)))
}
31 changes: 31 additions & 0 deletions land-apiserver/src/v1/tokens.rs
Original file line number Diff line number Diff line change
@@ -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<CreateTokenParam>) -> Result<impl IntoResponse, ServerJsonError> {
println!("{:?}", j);
Ok(Json("abc"))
}

0 comments on commit 3afff9f

Please sign in to comment.