Move web router to separate module
This commit is contained in:
parent
3adc3035f6
commit
7a4fbaf74a
116
src/bin/web.rs
116
src/bin/web.rs
@ -1,82 +1,15 @@
|
||||
use anyhow::{
|
||||
Context,
|
||||
};
|
||||
use askama::Template;
|
||||
use axum::{
|
||||
extract::{
|
||||
Path,
|
||||
State,
|
||||
},
|
||||
http::{
|
||||
StatusCode,
|
||||
},
|
||||
response::{
|
||||
IntoResponse,
|
||||
Response,
|
||||
},
|
||||
Router,
|
||||
routing::{
|
||||
get,
|
||||
},
|
||||
};
|
||||
use flake_tracker::{
|
||||
storage::{
|
||||
Storage,
|
||||
},
|
||||
templates::{
|
||||
FlakeListTemplate,
|
||||
FlakeTemplate,
|
||||
IndexTemplate,
|
||||
RevisionTemplate,
|
||||
web::{
|
||||
make_router,
|
||||
},
|
||||
};
|
||||
|
||||
struct AppError(anyhow::Error);
|
||||
|
||||
impl std::fmt::Display for AppError {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(&self.0, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for AppError {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Debug::fmt(&self.0, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoResponse for AppError {
|
||||
fn into_response(self) -> Response {
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
format!("Internal server error:\n{:?}", self),
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> From<E> for AppError where E: Into<anyhow::Error> {
|
||||
fn from(err: E) -> Self {
|
||||
Self(err.into())
|
||||
}
|
||||
}
|
||||
|
||||
fn render_template<T: Template>(t: &T) -> anyhow::Result<Response> {
|
||||
let body = t.render()
|
||||
.context("Failed to render template")?;
|
||||
|
||||
Ok((
|
||||
[
|
||||
("Content-Type", T::MIME_TYPE),
|
||||
],
|
||||
body,
|
||||
).into_response())
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct AppState {
|
||||
storage: Storage,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
@ -84,16 +17,8 @@ async fn main() -> anyhow::Result<()> {
|
||||
.await
|
||||
.context("Failed to connect to database")?;
|
||||
|
||||
let state = AppState {
|
||||
storage,
|
||||
};
|
||||
|
||||
let app = Router::new()
|
||||
.route("/", get(route_index))
|
||||
.route("/flakes", get(route_flakes))
|
||||
.route("/f/{uri}", get(route_flake))
|
||||
.route("/r/{revision_uri}", get(route_revision))
|
||||
.with_state(state);
|
||||
let app = make_router(storage)?;
|
||||
|
||||
let listener = tokio::net::TcpListener::bind("[::]:3000")
|
||||
.await
|
||||
@ -105,38 +30,3 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn route_index() -> Result<impl IntoResponse, AppError> {
|
||||
Ok(render_template(&IndexTemplate {})?)
|
||||
}
|
||||
|
||||
async fn route_flakes(
|
||||
State(state): State<AppState>,
|
||||
) -> Result<impl IntoResponse, AppError> {
|
||||
Ok(render_template(&FlakeListTemplate {
|
||||
flakes: state.storage.flakes().await?,
|
||||
})?)
|
||||
}
|
||||
|
||||
async fn route_flake(
|
||||
State(state): State<AppState>,
|
||||
Path(uri): Path<String>,
|
||||
) -> Result<impl IntoResponse, AppError> {
|
||||
Ok(render_template(&FlakeTemplate {
|
||||
uri: uri.clone(),
|
||||
revisions: state.storage.revisions_from_flake(&uri).await?,
|
||||
current_inputs: state.storage.current_inputs_for_flake(&uri).await?,
|
||||
})?)
|
||||
}
|
||||
|
||||
async fn route_revision(
|
||||
State(state): State<AppState>,
|
||||
Path(revision_uri): Path<String>,
|
||||
) -> Result<impl IntoResponse, AppError> {
|
||||
|
||||
Ok(render_template(&RevisionTemplate {
|
||||
revision_uri: revision_uri.clone(),
|
||||
inputs: state.storage.inputs_for_revision(&revision_uri).await?,
|
||||
input_of: state.storage.input_of_for_revision(&revision_uri).await?,
|
||||
})?)
|
||||
}
|
||||
|
@ -2,3 +2,4 @@ pub mod flake;
|
||||
pub mod storage;
|
||||
pub mod templates;
|
||||
pub mod utils;
|
||||
pub mod web;
|
||||
|
129
src/web.rs
Normal file
129
src/web.rs
Normal file
@ -0,0 +1,129 @@
|
||||
use anyhow::{
|
||||
Context,
|
||||
};
|
||||
use askama::Template;
|
||||
use axum::{
|
||||
extract::{
|
||||
Path,
|
||||
State,
|
||||
},
|
||||
http::{
|
||||
StatusCode,
|
||||
},
|
||||
response::{
|
||||
IntoResponse,
|
||||
Response,
|
||||
},
|
||||
Router,
|
||||
routing::{
|
||||
get,
|
||||
},
|
||||
};
|
||||
use crate::{
|
||||
storage::{
|
||||
Storage,
|
||||
},
|
||||
templates::{
|
||||
FlakeListTemplate,
|
||||
FlakeTemplate,
|
||||
IndexTemplate,
|
||||
RevisionTemplate,
|
||||
},
|
||||
};
|
||||
|
||||
struct AppError(anyhow::Error);
|
||||
|
||||
impl std::fmt::Display for AppError {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(&self.0, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for AppError {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Debug::fmt(&self.0, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoResponse for AppError {
|
||||
fn into_response(self) -> Response {
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
format!("Internal server error:\n{:?}", self),
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> From<E> for AppError where E: Into<anyhow::Error> {
|
||||
fn from(err: E) -> Self {
|
||||
Self(err.into())
|
||||
}
|
||||
}
|
||||
|
||||
fn render_template<T: Template>(t: &T) -> anyhow::Result<Response> {
|
||||
let body = t.render()
|
||||
.context("Failed to render template")?;
|
||||
|
||||
Ok((
|
||||
[
|
||||
("Content-Type", T::MIME_TYPE),
|
||||
],
|
||||
body,
|
||||
).into_response())
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct AppState {
|
||||
storage: Storage,
|
||||
}
|
||||
|
||||
pub fn make_router(storage: Storage) -> anyhow::Result<Router> {
|
||||
let state = AppState {
|
||||
storage,
|
||||
};
|
||||
|
||||
let app = Router::new()
|
||||
.route("/", get(route_index))
|
||||
.route("/flakes", get(route_flakes))
|
||||
.route("/f/{uri}", get(route_flake))
|
||||
.route("/r/{revision_uri}", get(route_revision))
|
||||
.with_state(state);
|
||||
|
||||
Ok(app)
|
||||
}
|
||||
|
||||
async fn route_index() -> Result<impl IntoResponse, AppError> {
|
||||
Ok(render_template(&IndexTemplate {})?)
|
||||
}
|
||||
|
||||
async fn route_flakes(
|
||||
State(state): State<AppState>,
|
||||
) -> Result<impl IntoResponse, AppError> {
|
||||
Ok(render_template(&FlakeListTemplate {
|
||||
flakes: state.storage.flakes().await?,
|
||||
})?)
|
||||
}
|
||||
|
||||
async fn route_flake(
|
||||
State(state): State<AppState>,
|
||||
Path(uri): Path<String>,
|
||||
) -> Result<impl IntoResponse, AppError> {
|
||||
Ok(render_template(&FlakeTemplate {
|
||||
uri: uri.clone(),
|
||||
revisions: state.storage.revisions_from_flake(&uri).await?,
|
||||
current_inputs: state.storage.current_inputs_for_flake(&uri).await?,
|
||||
})?)
|
||||
}
|
||||
|
||||
async fn route_revision(
|
||||
State(state): State<AppState>,
|
||||
Path(revision_uri): Path<String>,
|
||||
) -> Result<impl IntoResponse, AppError> {
|
||||
|
||||
Ok(render_template(&RevisionTemplate {
|
||||
revision_uri: revision_uri.clone(),
|
||||
inputs: state.storage.inputs_for_revision(&revision_uri).await?,
|
||||
input_of: state.storage.input_of_for_revision(&revision_uri).await?,
|
||||
})?)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user