1#![feature(async_closure)]
2#![feature(or_patterns)]
3#![feature(exclusive_range_pattern)]
4
5mod body;
6mod request;
7mod response;
8mod router;
9mod server;
10
11use async_std::{fs, io::ReadExt, task};
12use router::{Middleware, Path, Route, Router};
13use std::{future::Future, pin::Pin, str, sync::Arc};
14
15pub use body::ChunkedBody;
16pub use request::{Encoding, Method, Request};
17pub use response::{Response, Status};
18pub use router::Ctx;
19
20pub(crate) const BUF_LEN: usize = 2;
21pub(crate) const KEEP_ALIVE_TIMEOUT: u64 = 10;
22
23pub(crate) type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
24pub(crate) type Sender<T> = futures::channel::mpsc::Sender<T>;
25pub(crate) type Receiver<T> = futures::channel::mpsc::Receiver<T>;
26pub(crate) type BoxFuture<'a, Response> = Pin<Box<dyn Future<Output = Response> + Send + 'static>>;
27
28pub struct App<Routes> {
29 router: Router<Routes>,
30}
31
32impl App<()> {
33 pub fn new() -> App<()> {
34 Self::with_routes(())
35 }
36 pub fn run(self, port: u32) -> Result<()> {
37 let router = Arc::new(self.router);
38 task::block_on(server::accept_loop("127.0.0.1", port, router))
39 }
40 pub fn get(&mut self, path: &'static str, handler: impl Route) -> &Self {
41 self.add_route(Path::new(Method::Get, path.to_owned()), handler);
42 self
43 }
44 pub fn post(&mut self, path: &'static str, handler: impl Route) -> &Self {
45 self.add_route(Path::new(Method::Post, path.to_owned()), handler);
46 self
47 }
48 pub fn put(&mut self, path: &'static str, handler: impl Route) -> &Self {
49 self.add_route(Path::new(Method::Put, path.to_owned()), handler);
50 self
51 }
52 pub fn delete(&mut self, path: &'static str, handler: impl Route) -> &Self {
53 self.add_route(Path::new(Method::Delete, path.to_owned()), handler);
54 self
55 }
56 pub fn middleware(&mut self, path: &'static str, middleware: impl Middleware) -> &Self {
57 self.add_middleware(Path::all(path.to_owned()), middleware);
58 self
59 }
60 pub fn get_middleware(&mut self, path: &'static str, middleware: impl Middleware) -> &Self {
61 self.add_middleware(Path::new(Method::Get, path.to_owned()), middleware);
62 self
63 }
64 pub fn post_middleware(&mut self, path: &'static str, middleware: impl Middleware) -> &Self {
65 self.add_middleware(Path::new(Method::Post, path.to_owned()), middleware);
66 self
67 }
68 pub fn put_middleware(&mut self, path: &'static str, middleware: impl Middleware) -> &Self {
69 self.add_middleware(Path::new(Method::Put, path.to_owned()), middleware);
70 self
71 }
72 pub fn delete_middleware(&mut self, path: &'static str, middleware: impl Middleware) -> &Self {
73 self.add_middleware(Path::new(Method::Delete, path.to_owned()), middleware);
74 self
75 }
76 pub fn files(&mut self, path: &'static str, src: &'static str) -> &Self {
77 self.add_middleware(
78 Path::new(Method::Get, path.to_owned()),
79 Files::new(path, src),
80 );
81 self
82 }
83 fn add_route(&mut self, route: Path, handler: impl Route) {
84 self.router.routes.insert(route, Box::new(handler));
85 }
86 fn add_middleware(&mut self, route: Path, middleware: impl Middleware) {
87 self.router.middleware.push((route, Arc::new(middleware)));
88 }
89}
90
91impl<Routes: Send + Sync + Copy + 'static> App<Routes> {
92 pub fn with_routes(routes: Routes) -> App<Routes> {
93 App {
94 router: Router::new(routes),
95 }
96 }
97}
98
99async fn not_found(_req: Request) -> Response {
100 Response::with_status(Status::NotFound)
101}
102
103pub struct Files {
104 pub path: &'static str,
105 pub src: &'static str,
106}
107
108impl Files {
109 pub fn new(path: &'static str, src: &'static str) -> Files {
110 Files { path, src }
111 }
112}
113
114impl Middleware for Files {
115 fn handle(&self, ctx: Ctx) -> BoxFuture<Response> {
116 let filepath = ctx.req.path.replace(&self.path, "");
117 let src = self.src.clone();
118 Box::pin(async move {
119 let path = format!("{}{}", src, filepath);
120 match fs::canonicalize(path).await {
121 Ok(path) => match async_std::fs::File::open(path).await {
122 Ok(mut file) => {
123 let mut res = Response::with_status(Status::Ok);
124 let mut buf = vec![];
125 let res = match file.read_to_end(&mut buf).await {
126 Ok(_) => {
127 let mime = mime_guess::from_path(filepath)
128 .first()
129 .unwrap_or(mime::APPLICATION_OCTET_STREAM);
130
131 res.set_bytes(buf, mime);
132 res
133 }
134 Err(_) => Response::with_status(Status::NotFound),
135 };
136 res
137 }
138 Err(_) => Response::with_status(Status::NotFound),
139 },
140 Err(_) => Response::with_status(Status::NotFound),
141 }
142 })
143 }
144}