patissiere/src/handlers.rs

66 lines
1.8 KiB
Rust

use axum::{
extract::{Form, Path, State},
http::HeaderMap,
http::StatusCode,
response::{Html, IntoResponse, Response},
};
use std::{path::PathBuf, sync::Arc};
use tokio::fs;
use uuid::Uuid;
#[derive(Clone)]
pub struct AppState {
pub paste_dir: Arc<PathBuf>,
}
#[derive(serde::Deserialize)]
pub struct PasteForm {
body: String,
}
pub async fn index() -> Html<&'static str> {
Html(include_str!("../templates/index.html"))
}
pub async fn create_paste(
State(state): State<AppState>,
headers: HeaderMap,
Form(form): Form<PasteForm>,
) -> Response {
let ip = headers
.get("x-real-ip")
.and_then(|v| v.to_str().ok())
.unwrap_or("unknown");
let id = Uuid::new_v4().to_string()[..8].to_string();
let path = state.paste_dir.join(&id);
fs::write(&path, &form.body).await.unwrap();
tracing::info!(
"paste created: id={} size={} bytes ip={}",
id,
&form.body.len(),
ip
);
(StatusCode::SEE_OTHER, [("location", format!("/{id}"))]).into_response()
}
pub async fn get_paste(State(state): State<AppState>, Path(id): Path<String>) -> Response {
let path = state.paste_dir.join(&id);
match fs::read_to_string(&path).await {
Ok(content) => Html(format!(
include_str!("../templates/paste.html"),
id = id,
content = content
))
.into_response(),
Err(_) => (StatusCode::NOT_FOUND, "paste not found").into_response(),
}
}
pub async fn get_paste_raw(State(state): State<AppState>, Path(id): Path<String>) -> Response {
let path = state.paste_dir.join(&id);
match fs::read_to_string(&path).await {
Ok(content) => ([("content-type", "text/plain; charset=utf-8")], content).into_response(),
Err(_) => (StatusCode::NOT_FOUND, "paste not found").into_response(),
}
}