Compare commits

...

10 Commits

Author SHA1 Message Date
9dd40e1a6b Merge pull request '[RELEASE] Version 0.0.7' (#9) from feature/version-0.0.7 into main
All checks were successful
Cargo Build & Test / Test publish (push) Successful in 22s
Reviewed-on: #9
2024-08-21 14:04:26 +00:00
69d71d6588
Add ability to run async functions in blocking mode
All checks were successful
Cargo Build & Test / Tests (pull_request) Successful in 14s
Cargo Build & Test / check-cargo-version (pull_request) Successful in 6s
Cargo Build & Test / Test publish (pull_request) Successful in 22s
2024-08-21 15:55:25 +02:00
91cc658d86
Add example and change some code
All checks were successful
Cargo Build & Test / Test publish (pull_request) Successful in 32s
Cargo Build & Test / Tests (pull_request) Successful in 36s
Cargo Build & Test / check-cargo-version (pull_request) Successful in 5s
2024-08-21 14:55:30 +02:00
036c6f873e
Change logic of the router 2024-08-21 12:42:52 +02:00
132917c616
Add controllers
All checks were successful
Cargo Build & Test / Tests (pull_request) Successful in 11s
Cargo Build & Test / Test publish (pull_request) Successful in 12s
Cargo Build & Test / check-cargo-version (pull_request) Successful in 5s
2024-08-21 08:12:12 +02:00
a392734d59 Add ability to render templates
All checks were successful
Cargo Build & Test / Tests (pull_request) Successful in 12s
Cargo Build & Test / Test publish (pull_request) Successful in 12s
Cargo Build & Test / check-cargo-version (pull_request) Successful in 6s
2024-08-20 22:40:04 +02:00
aaa062db31 Add some more Response types
All checks were successful
Cargo Build & Test / Tests (pull_request) Successful in 19s
Cargo Build & Test / check-cargo-version (pull_request) Successful in 5s
Cargo Build & Test / Test publish (pull_request) Successful in 16s
2024-08-20 22:11:40 +02:00
55fb3a196e Add function to add a route
All checks were successful
Cargo Build & Test / Tests (pull_request) Successful in 9s
Cargo Build & Test / Test publish (pull_request) Successful in 10s
Cargo Build & Test / check-cargo-version (pull_request) Successful in 7s
2024-08-20 21:58:14 +02:00
97d7946554 Update version
All checks were successful
Cargo Build & Test / Tests (pull_request) Successful in 11s
Cargo Build & Test / Test publish (pull_request) Successful in 10s
Cargo Build & Test / check-cargo-version (pull_request) Successful in 5s
2024-08-20 21:45:36 +02:00
980cc2d42d Remove the default add function
Some checks failed
Cargo Build & Test / Tests (pull_request) Successful in 11s
Cargo Build & Test / Test publish (pull_request) Successful in 9s
Cargo Build & Test / check-cargo-version (pull_request) Failing after 5s
2024-08-20 21:43:09 +02:00
10 changed files with 605 additions and 39 deletions

413
Cargo.lock generated

@ -2,29 +2,129 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "ascii"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
[[package]]
name = "autocfg"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "backtrace"
version = "0.3.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "bytes"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
[[package]]
name = "cc"
version = "1.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48"
dependencies = [
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chunked_transfer"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901"
[[package]]
name = "gimli"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "httpdate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "libc"
version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "loadstar"
version = "0.0.6"
version = "0.0.7"
dependencies = [
"ascii",
"maud",
"tiny_http",
"tokio",
]
[[package]]
name = "lock_api"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
@ -33,6 +133,197 @@ version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "maud"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df518b75016b4289cdddffa1b01f2122f4a49802c93191f3133f6dc2472ebcaa"
dependencies = [
"itoa",
"maud_macros",
]
[[package]]
name = "maud_macros"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa453238ec218da0af6b11fc5978d3b5c3a45ed97b722391a2a11f3306274e18"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "miniz_oxide"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
dependencies = [
"adler",
]
[[package]]
name = "mio"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
dependencies = [
"hermit-abi",
"libc",
"wasi",
"windows-sys",
]
[[package]]
name = "object"
version = "0.36.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9"
dependencies = [
"memchr",
]
[[package]]
name = "parking_lot"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets",
]
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
dependencies = [
"bitflags",
]
[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook-registry"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
dependencies = [
"libc",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "socket2"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "syn"
version = "2.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tiny_http"
version = "0.12.0"
@ -44,3 +335,123 @@ dependencies = [
"httpdate",
"log",
]
[[package]]
name = "tokio"
version = "1.39.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys",
]
[[package]]
name = "tokio-macros"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

@ -2,9 +2,12 @@
name = "loadstar"
description = "A simple web framework for rust"
repository = "https://git.kjan.de/jank/loadstar"
version = "0.0.6"
version = "0.0.7"
license = "GPL-3.0-only"
edition = "2021"
[dependencies]
tiny_http = "0.12.0"
maud = "0.26.0"
ascii = "1.1.0"
tokio = { version = "1.39.3", features = [ "full" ] }

89
examples/hello_world.rs Normal file

@ -0,0 +1,89 @@
use std::{collections::HashMap, sync::Arc, thread::sleep, time::Duration};
use loadstar::{controller::Controller, entities::request::Url, router::Router, template::Template, utilities::{async_block::run_async, responses::{respond_not_found, respond_template}}};
use maud::html;
use tiny_http::Request;
async fn example_async() {
sleep(Duration::from_secs(1));
}
struct MainRouter {
routes: HashMap<String, fn(Request)>
}
impl Router for MainRouter {
fn new() -> Self {
MainRouter {
routes: HashMap::new(),
}
}
fn route(&self, request: Request) {
match self.routes.get(&request.get_url_without_parameters()) {
Some(handler) => handler(request),
None => respond_not_found(request),
}
}
fn add_route(&mut self, route: &str, route_function: fn(Request)) {
self.routes.insert(route.to_string(), route_function as fn(Request));
}
}
struct MainTemplate;
impl Template for MainTemplate {
fn render(&self) -> maud::Markup {
html! {
h1 {"Hello World"}
}
}
}
struct MainController;
impl MainController {
fn index_route(request: Request) {
run_async(example_async());
respond_template(request, MainTemplate {})
}
}
impl Controller for MainController {
fn register_routes(&self, router: &mut impl Router) {
router.add_route("/", MainController::index_route)
}
}
#[tokio::main]
async fn main() {
let server = tiny_http::Server::http("0.0.0.0:8000").unwrap();
let mut main_router = MainRouter::new();
main_router.add_controller(MainController {});
let router = Arc::new(main_router);
loop {
let request = match server.recv() {
Ok(rq) => rq,
Err(e) => {
println!("error: {}", e);
break;
}
};
let router_clone = Arc::clone(&router);
tokio::spawn(async move {
router_clone.route(request);
});
}
}

5
src/controller.rs Normal file

@ -0,0 +1,5 @@
use crate::router::Router;
pub trait Controller {
fn register_routes(&self, router: &mut impl Router);
}

@ -1,18 +1,5 @@
pub mod router;
pub mod controller;
pub mod entities;
pub mod utilities;
pub fn add(left: usize, right: usize) -> usize {
left + right
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
}
pub mod template;

@ -1,26 +1,15 @@
use std::collections::HashMap;
use tiny_http::Request;
use crate::{entities::request::Url, utilities::responses::respond_not_found};
use crate::controller::Controller;
pub struct Router {
routes: HashMap<String, fn(Request)>,
pub trait Router {
fn new() -> Self;
fn route(&self, request: Request);
fn add_controller(&mut self, controller: impl Controller)
where
Self: Sized,
{
controller.register_routes(self);
}
fn add_route(&mut self, route: &str, route_function: fn(Request));
}
impl Router {
pub fn new() -> Self {
let routes = HashMap::new();
Router { routes }
}
pub async fn route(&self, request: Request) {
match self.routes.get(&request.get_url_without_parameters()) {
Some(handler) => handler(request),
None => respond_not_found(request),
}
}
}

5
src/template.rs Normal file

@ -0,0 +1,5 @@
use maud::Markup;
pub trait Template {
fn render(&self) -> Markup;
}

@ -0,0 +1,12 @@
use std::future::Future;
pub fn run_async<T>(async_operation: impl Future<Output = T>) -> T {
// Use `block_in_place` to ensure runtime is dropped in a blocking context
tokio::task::block_in_place(|| {
// Get the current Tokio runtime handle
let handle = tokio::runtime::Handle::current();
// Run the async operation using the handle and wait for it to complete
handle.block_on(async_operation)
})
}

@ -1 +1,2 @@
pub mod responses;
pub mod async_block;

@ -1,7 +1,71 @@
use tiny_http::{Request, Response};
use ascii::AsciiString;
use maud::Markup;
use tiny_http::{Header, Request, Response};
use crate::template::Template;
/// Returns a 404 response
pub fn respond_not_found(request: Request) {
let response = Response::from_string("Not Found").with_status_code(404);
let _ = request.respond(response);
}
/// Renders a template
pub fn respond_template(request: Request, template: impl Template) {
let response = Response::from_string(template.render())
.with_header(Header {
field: "Content-Type".parse().unwrap(),
value: AsciiString::from_ascii("text/html; charset=utf8").unwrap(),
});
let _ = request.respond(response);
}
/// Renders html
pub fn respond_html(request: Request, content: Markup) {
let response = Response::from_string(content);
let response = response.with_header(Header {
field: "Content-Type".parse().unwrap(),
value: AsciiString::from_ascii("text/html; charset=utf8").unwrap(),
});
let _ = request.respond(response);
}
/// Redirects the user to another route
pub fn respond_redirect(request: Request, new_route: &str) {
let response = Response::from_string("Redirect");
let response = response.with_header(Header {
field: "Content-Type".parse().unwrap(),
value: AsciiString::from_ascii("text/html").unwrap(),
});
let response = response.with_header(Header {
field: "Location".parse().unwrap(),
value: AsciiString::from_ascii(new_route).unwrap(),
});
let response = response.with_status_code(302);
let _ = request.respond(response);
}
/// Redirects the user to another route while also adding a cookie
pub fn respond_redirect_cookie(request: Request, new_route: &str, cookie_name: &str, cookie_value: &str) {
let response = Response::from_string("Redirect")
.with_header(Header {
field: "Content-Type".parse().unwrap(),
value: AsciiString::from_ascii("text/html").unwrap(),
})
.with_header(Header {
field: "Location".parse().unwrap(),
value: AsciiString::from_ascii(new_route).unwrap(),
})
.with_header(Header {
field: "Set-Cookie".parse().unwrap(),
value: AsciiString::from_ascii(format!("{}={}", cookie_name, cookie_value)).unwrap(),
})
.with_status_code(302);
let _ = request.respond(response);
}