wip
This commit is contained in:
56
Cargo.lock
generated
56
Cargo.lock
generated
@@ -541,6 +541,15 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.8"
|
version = "1.4.8"
|
||||||
@@ -622,6 +631,7 @@ name = "templateServe"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"bytes",
|
||||||
"http-body-util",
|
"http-body-util",
|
||||||
"hyper",
|
"hyper",
|
||||||
"macro_rules_attribute",
|
"macro_rules_attribute",
|
||||||
@@ -630,6 +640,7 @@ dependencies = [
|
|||||||
"smol",
|
"smol",
|
||||||
"smol-hyper",
|
"smol-hyper",
|
||||||
"smol-macros",
|
"smol-macros",
|
||||||
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -655,6 +666,45 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.9.11+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde_core",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_parser",
|
||||||
|
"toml_writer",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.7.5+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_parser"
|
||||||
|
version = "1.0.6+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44"
|
||||||
|
dependencies = [
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_writer"
|
||||||
|
version = "1.0.6+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.44"
|
version = "0.1.44"
|
||||||
@@ -694,3 +744,9 @@ checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.7.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.100"
|
anyhow = "1.0.100"
|
||||||
|
bytes = "1.11.0"
|
||||||
http-body-util = "0.1.3"
|
http-body-util = "0.1.3"
|
||||||
hyper = { version = "1.8.1", features = ["http1", "http2", "server"] }
|
hyper = { version = "1.8.1", features = ["http1", "http2", "server"] }
|
||||||
macro_rules_attribute = "0.2.2"
|
macro_rules_attribute = "0.2.2"
|
||||||
@@ -15,3 +16,4 @@ serde = { version = "1.0.228", features = ["derive"] }
|
|||||||
smol = "2.0.2"
|
smol = "2.0.2"
|
||||||
smol-hyper = "0.1.1"
|
smol-hyper = "0.1.1"
|
||||||
smol-macros = "0.1.1"
|
smol-macros = "0.1.1"
|
||||||
|
toml = "0.9.11"
|
||||||
|
|||||||
44
bleh.txt
Normal file
44
bleh.txt
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
- templete-serve
|
||||||
|
- config.toml
|
||||||
|
- home
|
||||||
|
- id: "MAINHOME"
|
||||||
|
- type: root
|
||||||
|
- assets
|
||||||
|
- pngs & mp4's
|
||||||
|
- base
|
||||||
|
- config.toml
|
||||||
|
- id: "base"
|
||||||
|
- title: ""
|
||||||
|
- type: page
|
||||||
|
- path: Empty, Not meant to be visited
|
||||||
|
- comment: "Base page that others can extend from"
|
||||||
|
- include: [style.css] // <- FEATURE FOR LATER
|
||||||
|
- extras
|
||||||
|
- index.html
|
||||||
|
- home
|
||||||
|
- config.toml
|
||||||
|
- id: "mainHome"
|
||||||
|
- title: "home"
|
||||||
|
- type: page
|
||||||
|
- path: "/"
|
||||||
|
- extras
|
||||||
|
- web stamps
|
||||||
|
- extra data yk
|
||||||
|
- index.html
|
||||||
|
- second
|
||||||
|
- config.toml
|
||||||
|
- id: "secondPage"
|
||||||
|
- title: "bleh"
|
||||||
|
- type: page
|
||||||
|
- path: "/"
|
||||||
|
- extras
|
||||||
|
- web stamps
|
||||||
|
- extra data yk
|
||||||
|
- index.html
|
||||||
|
- 404
|
||||||
|
- config.toml
|
||||||
|
- id: "404page"
|
||||||
|
- title: "home"
|
||||||
|
- type: page
|
||||||
|
- path: "/404"
|
||||||
|
- index.html
|
||||||
83
src/loader.rs
Normal file
83
src/loader.rs
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
use std::future::IntoFuture;
|
||||||
|
|
||||||
|
use crate::AppState;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use minijinja::Value;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use smol::{
|
||||||
|
fs::{self, DirEntry},
|
||||||
|
stream::StreamExt,
|
||||||
|
};
|
||||||
|
use toml::Table;
|
||||||
|
|
||||||
|
pub struct Page {
|
||||||
|
header: Header,
|
||||||
|
content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub enum PageType {
|
||||||
|
// If root, the dir contains all the pages, if there are no dirs within the root, we can assume
|
||||||
|
// its empty
|
||||||
|
Root,
|
||||||
|
// Contains a single html
|
||||||
|
Page,
|
||||||
|
// Is template
|
||||||
|
Base,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct Header {
|
||||||
|
id: String,
|
||||||
|
// r#type: PageType,
|
||||||
|
r#type: String,
|
||||||
|
title: Option<String>,
|
||||||
|
path: Option<String>,
|
||||||
|
// TODO impl this later
|
||||||
|
// extras: Table,
|
||||||
|
}
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct Root {
|
||||||
|
id: String,
|
||||||
|
// r#type: PageType,
|
||||||
|
r#type: String,
|
||||||
|
title: Option<String>,
|
||||||
|
path: Option<String>,
|
||||||
|
// TODO impl this later
|
||||||
|
// extras: Table,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppState<'_> {
|
||||||
|
pub async fn load_from_fs(&mut self) -> anyhow::Result<()> {
|
||||||
|
let mut dir = fs::read_dir("./template-serve").await?;
|
||||||
|
|
||||||
|
// Find config.toml from within dir
|
||||||
|
let config = dir
|
||||||
|
.find(|x| x.as_ref().unwrap().file_name().eq("config.toml"))
|
||||||
|
.await
|
||||||
|
.unwrap()?;
|
||||||
|
|
||||||
|
while let Some(Ok(entry)) = dir.next().await {
|
||||||
|
if entry.file_type().await?.is_dir() {
|
||||||
|
let entry_opened = fs::read_dir(entry.path()).await?;
|
||||||
|
println!("Opened {}", entry.file_name().to_str().unwrap());
|
||||||
|
} else {
|
||||||
|
println!("Not parsing {}", entry.file_name().to_str().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let config_file = fs::read(config.path()).await?;
|
||||||
|
|
||||||
|
let config_parsed: Root = toml::from_slice(config_file.as_slice())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl From<Table> for Value {
|
||||||
|
// fn from(value: Table) -> Self {
|
||||||
|
// Value {
|
||||||
|
// ..Default::default()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
80
src/main.rs
80
src/main.rs
@@ -1,56 +1,78 @@
|
|||||||
use std::net::{TcpListener, TcpStream};
|
use std::net::{TcpListener, TcpStream};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
use std::string;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use bytes::Bytes;
|
||||||
use http_body_util::Full;
|
use http_body_util::Full;
|
||||||
use hyper::body::Incoming;
|
use hyper::body::Incoming;
|
||||||
use hyper::service::service_fn;
|
use hyper::service::service_fn;
|
||||||
use hyper::{Request, Response, Uri};
|
use hyper::{Request, Response};
|
||||||
use macro_rules_attribute::apply;
|
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_hyper::rt::{FuturesIo, SmolTimer};
|
||||||
use smol_macros::main;
|
use smol_macros::main;
|
||||||
|
|
||||||
/// Serves a request and returns a response.
|
mod loader;
|
||||||
async fn serve(req: Request<Incoming>) -> Result<Response<Full<&'static [u8]>>> {
|
use crate::loader::*;
|
||||||
println!("Serving {}", req.uri());
|
|
||||||
let path = req.uri().path();
|
struct AppState<'a> {
|
||||||
let reply = match path {
|
pages: Vec<Page>,
|
||||||
"/" => "mreow",
|
env: Environment<'a>,
|
||||||
_ => "Invalid path!",
|
|
||||||
};
|
|
||||||
Ok(Response::new(Full::new(reply.as_bytes())))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle a new client.
|
/// Serves a request and returns a response.
|
||||||
async fn handle_client(client: Async<TcpStream>) -> Result<()> {
|
async fn serve(req: Request<Incoming>, state: Arc<AppState<'_>>) -> Result<Response<Full<Bytes>>> {
|
||||||
// Wrap it in TLS if necessary.
|
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);
|
let client = SmolStream::Plain(client);
|
||||||
|
|
||||||
// Build the server.
|
|
||||||
hyper::server::conn::http1::Builder::new()
|
hyper::server::conn::http1::Builder::new()
|
||||||
.timer(SmolTimer::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?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Listens for incoming connections and serves them.
|
/// 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.
|
// Format the full host address.
|
||||||
// println!("Listening on {}", host);
|
// println!("Listening on {}", host);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Wait for a new client.
|
// Wait for a new client.
|
||||||
let (client, _) = listener.accept().await?;
|
let (client, _) = listener.accept().await?;
|
||||||
|
let cloned_state = state.clone();
|
||||||
|
|
||||||
// Spawn a task to handle this connection.
|
// Spawn a task to handle this connection.
|
||||||
ex.spawn({
|
ex.spawn({
|
||||||
async move {
|
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);
|
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!)]
|
#[apply(main!)]
|
||||||
async fn main(ex: &Arc<Executor<'static>>) -> Result<()> {
|
async fn main(ex: &Arc<Executor<'static>>) -> Result<()> {
|
||||||
// Start HTTP and HTTPS servers.
|
let mut state = init().await?;
|
||||||
let _ = listen(ex, Async::<TcpListener>::bind(([127, 0, 0, 1], 8000))?).await;
|
|
||||||
print!("mroew");
|
let _ = listen(
|
||||||
|
ex,
|
||||||
|
Async::<TcpListener>::bind(([127, 0, 0, 1], 8000))?,
|
||||||
|
Arc::new(state),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
template-serve/config.toml
Normal file
2
template-serve/config.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
id = "mainhome"
|
||||||
|
type = "Root"
|
||||||
0
template-serve/home/config.toml
Normal file
0
template-serve/home/config.toml
Normal file
Reference in New Issue
Block a user