diff --git a/src/main.rs b/src/main.rs index 5e1f865..957aaf6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,11 +2,16 @@ use askama::Template; use axum::{ Router, body::Bytes, - extract::{self, MatchedPath}, + extract::{self, MatchedPath, State}, http::{HeaderMap, Request, StatusCode}, response::{Html, IntoResponse, Response}, routing::get, }; +use std::{ + collections::HashMap, + path::{Path, PathBuf}, + sync::{Arc, RwLock}, +}; use tokio::time::Duration; use tower_http::{classify::ServerErrorsFailureClass, trace::TraceLayer}; use tracing::{Span, info_span}; @@ -28,43 +33,52 @@ async fn main() { } fn app() -> Router { - Router::new().route("/greet/{name}", get(greet)).layer( - TraceLayer::new_for_http() - .make_span_with(|request: &Request<_>| { - let matched_path = request - .extensions() - .get::() - .map(MatchedPath::as_str); - let path = &request.uri().to_string(); + // Idée: chaque fois qu'on lit repos, on regarde c'est quand le dernier reload. Si plus de 5 min, reload + let state = Arc::new(AppState { + repos: load_repos(), + }); + Router::new() + .route("/", get(index)) + .route("/{name}", get(repo_summary)) + .route("/greet/{name}", get(greet)) + .layer( + TraceLayer::new_for_http() + .make_span_with(|request: &Request<_>| { + let matched_path = request + .extensions() + .get::() + .map(MatchedPath::as_str); + let path = &request.uri().to_string(); - info_span!( - "http_request", - method = ?request.method(), - matched_path, - path, - some_other_field = tracing::field::Empty, + info_span!( + "http_request", + method = ?request.method(), + matched_path, + path, + some_other_field = tracing::field::Empty, + ) + }) + .on_request(|_request: &Request<_>, _span: &Span| { + tracing::debug!("started processing request") + }) + .on_response(|_response: &Response, _latency: Duration, _span: &Span| { + tracing::debug!("finished processing request") + }) + .on_body_chunk(|_chunk: &Bytes, _latency: Duration, _span: &Span| { + tracing::debug!("sending body chunk") + }) + .on_eos( + |_trailers: Option<&HeaderMap>, _stream_duration: Duration, _span: &Span| { + tracing::debug!("stream closed") + }, ) - }) - .on_request(|_request: &Request<_>, _span: &Span| { - tracing::debug!("started processing request") - }) - .on_response(|_response: &Response, _latency: Duration, _span: &Span| { - tracing::debug!("finished processing request") - }) - .on_body_chunk(|_chunk: &Bytes, _latency: Duration, _span: &Span| { - tracing::debug!("sending body chunk") - }) - .on_eos( - |_trailers: Option<&HeaderMap>, _stream_duration: Duration, _span: &Span| { - tracing::debug!("stream closed") - }, - ) - .on_failure( - |_error: ServerErrorsFailureClass, _latency: Duration, _span: &Span| { - tracing::error!("something went wrong") - }, - ), - ) + .on_failure( + |_error: ServerErrorsFailureClass, _latency: Duration, _span: &Span| { + tracing::error!("something went wrong") + }, + ), + ) + .with_state(state) } async fn greet(extract::Path(name): extract::Path) -> impl IntoResponse { @@ -72,6 +86,65 @@ async fn greet(extract::Path(name): extract::Path) -> impl IntoResponse HtmlTemplate(template) } +async fn index(State(state): State>) -> impl IntoResponse { + let template = IndexTemplate { + repos: state.repos.clone(), + }; + HtmlTemplate(template) +} + +async fn repo_summary( + extract::Path(name): extract::Path, + State(state): State>, +) -> impl IntoResponse { + let repo: Option<&Repo> = state.repos.iter().find(|x| x.name == name); + match repo { + Some(r) => { + let template = RepoSummaryTemplate { repo: r.clone() }; + tracing::debug!("here!{}", template.repo.name); + HtmlTemplate(template).into_response() + } + None => StatusCode::NOT_FOUND.into_response(), + } +} + +fn load_repos() -> Vec { + let mut repos = Vec::new(); + repos.push(Repo { + name: "ft_rs".to_string(), + desc: "financial tracker in rust".to_string(), + lastcommit: "2025-01-01".to_string(), + }); + repos.push(Repo { + name: "ft_rs".to_string(), + desc: "financial tracker in rust".to_string(), + lastcommit: "2025-01-01".to_string(), + }); + repos.push(Repo { + name: "ft_rs".to_string(), + desc: "financial tracker in rust".to_string(), + lastcommit: "2025-01-01".to_string(), + }); + repos.push(Repo { + name: "ft_rs".to_string(), + desc: "financial tracker in rust".to_string(), + lastcommit: "2025-01-01".to_string(), + }); + repos +} + +#[derive(Template)] +#[template(path = "index.html")] +struct IndexTemplate { + repos: Vec, +} + +#[derive(Template)] +#[template(path = "repo_summary.html")] +struct RepoSummaryTemplate { + repo: Repo, +} + #[derive(Template)] #[template(path = "hello.html")] struct HelloTemplate { @@ -94,3 +167,14 @@ where } } } + +#[derive(Clone)] +struct Repo { + name: String, + desc: String, + lastcommit: String, +} + +struct AppState { + repos: Vec, +} diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..a1a79ec --- /dev/null +++ b/templates/index.html @@ -0,0 +1,24 @@ + + +Repositories + +

Repositories

+
+ + + + + + + + {% for r in repos %} + + + + + + {% endfor %} + +
NameDescriptionLast commit
{{ r.name }}{{ r.desc }}{{ r.lastcommit }}
+ + diff --git a/templates/repo_summary.html b/templates/repo_summary.html new file mode 100644 index 0000000..37b0a30 --- /dev/null +++ b/templates/repo_summary.html @@ -0,0 +1,2 @@ + +

hello {{ repo.name }}