summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/error.rs26
-rw-r--r--src/lib.rs6
-rw-r--r--src/main.rs18
-rw-r--r--src/routes.rs69
-rw-r--r--src/state.rs1
5 files changed, 120 insertions, 0 deletions
diff --git a/src/error.rs b/src/error.rs
new file mode 100644
index 0000000..1f4b354
--- /dev/null
+++ b/src/error.rs
@@ -0,0 +1,26 @@
+use axum::{
+ http::StatusCode,
+ response::{IntoResponse, Response},
+ Json,
+};
+
+pub type Result<T, E = Error> = std::result::Result<T, E>;
+
+#[derive(thiserror::Error, Debug)]
+pub enum Error {
+ #[error("IO error: {0}")]
+ IO(#[from] std::io::Error),
+
+ #[error("Axum Error: {0:?}")]
+ Axum(#[from] axum::Error),
+}
+
+impl IntoResponse for Error {
+ fn into_response(self) -> Response {
+ let body = Json(serde_json::json!({
+ "error": self.to_string(),
+ }));
+
+ (StatusCode::INTERNAL_SERVER_ERROR, body).into_response()
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..d899368
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,6 @@
+pub use error::{Error, Result};
+pub use routes::serve;
+
+pub mod error;
+pub mod routes;
+pub mod state;
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..7b5d3c2
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,18 @@
+use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
+
+#[tokio::main]
+#[tracing::instrument]
+async fn main() -> Result<(), unnamed_server::Error> {
+ tracing_subscriber::registry()
+ .with(
+ tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| {
+ "example_tracing_aka_logging=debug,tower_http=debug,axum::rejection=trace".into()
+ }),
+ )
+ .with(tracing_subscriber::fmt::layer())
+ .init();
+
+ let socket_addr = std::net::SocketAddr::from(([127, 0, 0, 1], 30000));
+
+ unnamed_server::serve(socket_addr).await
+}
diff --git a/src/routes.rs b/src/routes.rs
new file mode 100644
index 0000000..3625eff
--- /dev/null
+++ b/src/routes.rs
@@ -0,0 +1,69 @@
+use axum::Router;
+use axum_extra::routing::{RouterExt, TypedPath};
+use tokio::{
+ net::{TcpListener, ToSocketAddrs},
+ signal,
+};
+
+use crate::Error;
+
+#[derive(TypedPath)]
+#[typed_path("/ping")]
+pub struct Ping;
+
+/// # Test endpoint
+///
+/// Returns "pong"
+#[tracing::instrument(ret)]
+pub async fn ping(_: Ping) -> &'static str {
+ "pong"
+}
+
+#[derive(TypedPath)]
+#[typed_path("/")]
+pub struct Root;
+
+#[tracing::instrument(ret)]
+pub async fn root(_: Root) -> &'static str {
+ "Hello, World!"
+}
+
+pub async fn serve<A>(addr: A) -> Result<(), Error>
+where
+ A: ToSocketAddrs,
+{
+ let app = Router::new().typed_get(root).typed_get(ping);
+
+ let listener = TcpListener::bind(addr).await?;
+
+ tracing::info!("Server listening on http://{}", listener.local_addr()?);
+
+ axum::serve(listener, app)
+ .with_graceful_shutdown(shutdown_signal())
+ .await
+ .map_err(From::from)
+}
+
+async fn shutdown_signal() {
+ let ctrl_c = async {
+ signal::ctrl_c()
+ .await
+ .expect("failed to install Ctrl+C handler");
+ };
+
+ #[cfg(unix)]
+ let terminate = async {
+ signal::unix::signal(signal::unix::SignalKind::terminate())
+ .expect("failed to install signal handler")
+ .recv()
+ .await;
+ };
+
+ #[cfg(not(unix))]
+ let terminate = std::future::pending::<()>();
+
+ tokio::select! {
+ _ = ctrl_c => {},
+ _ = terminate => {},
+ }
+}
diff --git a/src/state.rs b/src/state.rs
new file mode 100644
index 0000000..78a6654
--- /dev/null
+++ b/src/state.rs
@@ -0,0 +1 @@
+pub struct AppState;