diff options
author | Cara Salter <cara@devcara.com> | 2022-05-27 23:13:52 -0400 |
---|---|---|
committer | Cara Salter <cara@devcara.com> | 2022-05-27 23:13:52 -0400 |
commit | 372b484e8a6366346d52ff44bbdaa6aad1cc2daa (patch) | |
tree | 29b9f5c2dcd07c54057fc86a8f0cc5861b8c0a6d /src | |
parent | ca5c737f047119f31e42a8700b8ae1ad4fabd17a (diff) | |
download | homeworld-372b484e8a6366346d52ff44bbdaa6aad1cc2daa.tar.gz homeworld-372b484e8a6366346d52ff44bbdaa6aad1cc2daa.zip |
initial axum scaffold
Diffstat (limited to 'src')
-rw-r--r-- | src/errors.rs | 27 | ||||
-rw-r--r-- | src/main.rs | 64 |
2 files changed, 89 insertions, 2 deletions
diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 0000000..70b1a43 --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,27 @@ +use axum::{response::{Response, IntoResponse}, body::{boxed, self}}; +use hyper::StatusCode; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum ServiceError { + #[error("Solarlib error: {0}")] + Solarlib(#[from] solarlib::errors::Error), + + #[error("Axum error: {0}")] + Axum(#[from] axum::Error), +} + +pub type StringResult<T = &'static str> = Result<T, ServiceError>; + +pub type JsonResult<T> = Result<T, ServiceError>; + +impl IntoResponse for ServiceError { + fn into_response(self) -> Response { + let body = body::boxed(body::Full::from(self.to_string())); + + Response::builder() + .status(StatusCode::INTERNAL_SERVER_ERROR) + .body(body) + .unwrap() + } +} diff --git a/src/main.rs b/src/main.rs index e7a11a9..ba319d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,63 @@ -fn main() { - println!("Hello, world!"); +use axum::{ + error_handling::HandleErrorLayer, + http::StatusCode, + response::IntoResponse, + routing::get, + Json, Router +}; + +use serde::{Deserialize, Serialize}; +use std::{net::SocketAddr, time::Duration, str::FromStr}; + +use tower::{BoxError, ServiceBuilder}; +use tower_http::trace::TraceLayer; + +use tracing_subscriber::prelude::*; + +mod errors; + +mod handlers; + +#[tokio::main] +async fn main() { + kankyo::init(); + color_eyre::install().unwrap(); + tracing_subscriber::registry() + .with(tracing_subscriber::EnvFilter::new( + std::env::var("RUST_LOG") + .unwrap_or_else(|_| "waifud=info,tower_http=debug".into()), + )) + .with(tracing_subscriber::fmt::layer()) + .init(); + + let app = Router::new() + .route("/health", get(health_check)) + .route("/waifus/list", get(handlers::waifus::list)) + .layer( ServiceBuilder::new() + .layer(HandleErrorLayer::new(|error: BoxError| async move { + if error.is::<tower::timeout::error::Elapsed>() { + Ok(StatusCode::REQUEST_TIMEOUT) + } else { + Err(( + StatusCode::INTERNAL_SERVER_ERROR, + format!("Unhandled internal error: {}", error), + )) + } + })) + .timeout(Duration::from_secs(10)) + .layer(TraceLayer::new_for_http()) + .into_inner(), + ); + + let addr = SocketAddr::from_str(std::env::var("BIND_ADDR").unwrap().as_str().into()).unwrap(); + tracing::info!("Listening on {}", addr); + + axum::Server::bind(&addr) + .serve(app.into_make_service()) + .await + .unwrap(); +} + +async fn health_check() -> &'static str { + "OK" } |