This commit is contained in:
2026-01-12 14:50:20 +00:00
parent a059b91327
commit a5659dda04
7 changed files with 245 additions and 22 deletions

View File

@@ -1,56 +1,78 @@
use std::net::{TcpListener, TcpStream};
use std::pin::Pin;
use std::string;
use std::sync::Arc;
use std::task::{Context, Poll};
use anyhow::Result;
use bytes::Bytes;
use http_body_util::Full;
use hyper::body::Incoming;
use hyper::service::service_fn;
use hyper::{Request, Response, Uri};
use hyper::{Request, Response};
use macro_rules_attribute::apply;
use smol::{future, io, prelude::*, Async, Executor};
use minijinja::{context, Environment};
use smol::{fs, io, prelude::*, Async, Executor};
use smol_hyper::rt::{FuturesIo, SmolTimer};
use smol_macros::main;
/// Serves a request and returns a response.
async fn serve(req: Request<Incoming>) -> Result<Response<Full<&'static [u8]>>> {
println!("Serving {}", req.uri());
let path = req.uri().path();
let reply = match path {
"/" => "mreow",
_ => "Invalid path!",
};
Ok(Response::new(Full::new(reply.as_bytes())))
mod loader;
use crate::loader::*;
struct AppState<'a> {
pages: Vec<Page>,
env: Environment<'a>,
}
/// Handle a new client.
async fn handle_client(client: Async<TcpStream>) -> Result<()> {
// Wrap it in TLS if necessary.
/// Serves a request and returns a response.
async fn serve(req: Request<Incoming>, state: Arc<AppState<'_>>) -> Result<Response<Full<Bytes>>> {
println!("Serving {}", req.uri());
let tmpl = state.env.get_template("hello").unwrap();
let guh = tmpl.render(context!(name => "meowmeowmeowmeow!")).unwrap();
let guh2 = state.env.get_template("meow").unwrap();
let guh3 = guh2.render(context!(meow => "meow")).unwrap();
let path = req.uri().path();
let reply: Bytes = match path {
"/" => guh.into(),
"/mreow" => guh3.into(),
_ => "Invalid path!".into(),
};
Ok(Response::new(Full::new(reply)))
}
async fn handle_client(client: Async<TcpStream>, state: Arc<AppState<'_>>) -> Result<()> {
let client = SmolStream::Plain(client);
// Build the server.
hyper::server::conn::http1::Builder::new()
.timer(SmolTimer::new())
.serve_connection(FuturesIo::new(client), service_fn(serve))
.serve_connection(
FuturesIo::new(client),
service_fn(move |req| serve(req, state.clone())),
)
.await?;
Ok(())
}
/// Listens for incoming connections and serves them.
async fn listen(ex: &Arc<Executor<'static>>, listener: Async<TcpListener>) -> Result<()> {
async fn listen(
ex: &Arc<Executor<'static>>,
listener: Async<TcpListener>,
state: Arc<AppState<'static>>,
) -> Result<()> {
// Format the full host address.
// println!("Listening on {}", host);
loop {
// Wait for a new client.
let (client, _) = listener.accept().await?;
let cloned_state = state.clone();
// Spawn a task to handle this connection.
ex.spawn({
async move {
if let Err(e) = handle_client(client).await {
if let Err(e) = handle_client(client, cloned_state).await {
println!("Error while handling client: {}", e);
}
}
@@ -59,11 +81,25 @@ async fn listen(ex: &Arc<Executor<'static>>, listener: Async<TcpListener>) -> Re
}
}
async fn init<'a>() -> Result<AppState<'a>> {
let mut env = Environment::new();
let mut pages: Vec<Page> = Vec::new();
let mut state: AppState = AppState { pages, env };
state.load_from_fs().await?;
Ok(state)
}
#[apply(main!)]
async fn main(ex: &Arc<Executor<'static>>) -> Result<()> {
// Start HTTP and HTTPS servers.
let _ = listen(ex, Async::<TcpListener>::bind(([127, 0, 0, 1], 8000))?).await;
print!("mroew");
let mut state = init().await?;
let _ = listen(
ex,
Async::<TcpListener>::bind(([127, 0, 0, 1], 8000))?,
Arc::new(state),
)
.await;
Ok(())
}