logique de base

This commit is contained in:
thatscringebro
2026-05-06 16:18:30 -04:00
parent 990c10c75f
commit 89a8237bfe
3 changed files with 146 additions and 36 deletions

View File

@@ -2,11 +2,16 @@ use askama::Template;
use axum::{ use axum::{
Router, Router,
body::Bytes, body::Bytes,
extract::{self, MatchedPath}, extract::{self, MatchedPath, State},
http::{HeaderMap, Request, StatusCode}, http::{HeaderMap, Request, StatusCode},
response::{Html, IntoResponse, Response}, response::{Html, IntoResponse, Response},
routing::get, routing::get,
}; };
use std::{
collections::HashMap,
path::{Path, PathBuf},
sync::{Arc, RwLock},
};
use tokio::time::Duration; use tokio::time::Duration;
use tower_http::{classify::ServerErrorsFailureClass, trace::TraceLayer}; use tower_http::{classify::ServerErrorsFailureClass, trace::TraceLayer};
use tracing::{Span, info_span}; use tracing::{Span, info_span};
@@ -28,43 +33,52 @@ async fn main() {
} }
fn app() -> Router { fn app() -> Router {
Router::new().route("/greet/{name}", get(greet)).layer( // Idée: chaque fois qu'on lit repos, on regarde c'est quand le dernier reload. Si plus de 5 min, reload
TraceLayer::new_for_http() let state = Arc::new(AppState {
.make_span_with(|request: &Request<_>| { repos: load_repos(),
let matched_path = request });
.extensions() Router::new()
.get::<MatchedPath>() .route("/", get(index))
.map(MatchedPath::as_str); .route("/{name}", get(repo_summary))
let path = &request.uri().to_string(); .route("/greet/{name}", get(greet))
.layer(
TraceLayer::new_for_http()
.make_span_with(|request: &Request<_>| {
let matched_path = request
.extensions()
.get::<MatchedPath>()
.map(MatchedPath::as_str);
let path = &request.uri().to_string();
info_span!( info_span!(
"http_request", "http_request",
method = ?request.method(), method = ?request.method(),
matched_path, matched_path,
path, path,
some_other_field = tracing::field::Empty, 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_failure(
.on_request(|_request: &Request<_>, _span: &Span| { |_error: ServerErrorsFailureClass, _latency: Duration, _span: &Span| {
tracing::debug!("started processing request") tracing::error!("something went wrong")
}) },
.on_response(|_response: &Response, _latency: Duration, _span: &Span| { ),
tracing::debug!("finished processing request") )
}) .with_state(state)
.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")
},
),
)
} }
async fn greet(extract::Path(name): extract::Path<String>) -> impl IntoResponse { async fn greet(extract::Path(name): extract::Path<String>) -> impl IntoResponse {
@@ -72,6 +86,65 @@ async fn greet(extract::Path(name): extract::Path<String>) -> impl IntoResponse
HtmlTemplate(template) HtmlTemplate(template)
} }
async fn index(State(state): State<Arc<AppState>>) -> impl IntoResponse {
let template = IndexTemplate {
repos: state.repos.clone(),
};
HtmlTemplate(template)
}
async fn repo_summary(
extract::Path(name): extract::Path<String>,
State(state): State<Arc<AppState>>,
) -> 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<Repo> {
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<Repo>,
}
#[derive(Template)]
#[template(path = "repo_summary.html")]
struct RepoSummaryTemplate {
repo: Repo,
}
#[derive(Template)] #[derive(Template)]
#[template(path = "hello.html")] #[template(path = "hello.html")]
struct HelloTemplate { struct HelloTemplate {
@@ -94,3 +167,14 @@ where
} }
} }
} }
#[derive(Clone)]
struct Repo {
name: String,
desc: String,
lastcommit: String,
}
struct AppState {
repos: Vec<Repo>,
}

24
templates/index.html Normal file
View File

@@ -0,0 +1,24 @@
<!doctype html>
<html>
<head><meta charset="utf-8"><title>Repositories</title></head>
<body>
<h2>Repositories</h2>
<hr>
<table>
<tbody>
<tr>
<th>Name</th>
<th>Description</th>
<th>Last commit</th>
</tr>
{% for r in repos %}
<tr>
<td><a href="{{ r.name }}">{{ r.name }}</a></td>
<td>{{ r.desc }}</td>
<td>{{ r.lastcommit }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>

View File

@@ -0,0 +1,2 @@
<h1>hello {{ repo.name }}</h1>