From 2b824c07f8e381698971c94cbae661cb48789c4a Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Mon, 8 May 2023 21:49:05 +0200
Subject: [PATCH 01/65] Adding threading and general handle of incoming
 requests, as well as returning a standard site

---
 core/http/src/handlers.rs  |  0
 core/http/src/lib.rs       | 78 +++++++++++++++++++++++++++++----
 core/http/src/routing.rs   |  2 +
 core/http/src/threading.rs | 90 ++++++++++++++++++++++++++++++++++++++
 q                          |  0
 site/Cargo.lock            |  7 +++
 site/Cargo.toml            |  1 +
 site/hello.html            | 11 +++++
 site/src/main.rs           |  2 +-
 9 files changed, 181 insertions(+), 10 deletions(-)
 create mode 100644 core/http/src/handlers.rs
 create mode 100644 core/http/src/routing.rs
 create mode 100644 core/http/src/threading.rs
 create mode 100644 q
 create mode 100644 site/hello.html

diff --git a/core/http/src/handlers.rs b/core/http/src/handlers.rs
new file mode 100644
index 0000000..e69de29
diff --git a/core/http/src/lib.rs b/core/http/src/lib.rs
index 7d12d9a..1d8e24d 100644
--- a/core/http/src/lib.rs
+++ b/core/http/src/lib.rs
@@ -1,14 +1,74 @@
-pub fn add(left: usize, right: usize) -> usize {
-    left + right
+use std::{
+    fs,
+    io::{BufRead, BufReader, Write},
+    net::{TcpListener, TcpStream},
+    thread::available_parallelism,
+};
+
+use threading::ThreadPool;
+
+mod handlers;
+mod routing;
+mod threading;
+
+pub struct Config {
+    address: TcpListener,
+    workers: usize,
+    threadpool: ThreadPool,
 }
 
-#[cfg(test)]
-mod tests {
-    use super::*;
+impl Config {
+    pub fn mount(self, mountpoint: &str, routes: Vec<routing::Route>) {}
+    pub fn launch(self) {
+        for stream in self.address.incoming() {
+            let stream = stream.unwrap();
+            self.threadpool.execute(|| handle_connection(stream))
+        }
+    }
+}
+
+fn handle_connection(mut stream: TcpStream) {
+    let buf_reader = BufReader::new(&mut stream);
+    let http_request: Vec<_> = buf_reader
+        .lines()
+        .map(|result| result.unwrap())
+        .take_while(|line| !line.is_empty())
+        .collect();
 
-    #[test]
-    fn it_works() {
-        let result = add(2, 2);
-        assert_eq!(result, 4);
+    let status_line = "HTTP/1.1 200 OK";
+    let contents = fs::read_to_string("hello.html").unwrap();
+    let length = contents.len();
+
+    let response = format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}");
+
+    stream.write_all(response.as_bytes()).unwrap();
+}
+
+pub fn build(ip: &str) -> Config {
+    let listener = TcpListener::bind(ip).unwrap();
+    let ip = ip.splitn(2, ":").collect::<Vec<&str>>();
+    if ip.len() != 2 {
+        panic!("Invalid IP Address");
+    }
+    let port = ip[1];
+    let ip = ip[0];
+    let workers = available_parallelism().unwrap().get();
+    let threadpool = ThreadPool::new(workers);
+    println!(
+        "\x1b[34mâš™ Configuration\x1b[0m
+  >> \x1b[34mIp\x1b[0m: {ip}
+  >> \x1b[34mPort\x1b[0m: {port}
+  >> \x1b[34mWorkers\x1b[0m: {workers}
+\n
+Server has launched from {ip}:{port}.
+"
+    );
+    Config {
+        address: listener,
+        workers,
+        threadpool,
     }
 }
+
+#[cfg(test)]
+mod tests {}
diff --git a/core/http/src/routing.rs b/core/http/src/routing.rs
new file mode 100644
index 0000000..6ae9a73
--- /dev/null
+++ b/core/http/src/routing.rs
@@ -0,0 +1,2 @@
+pub struct Route;
+pub struct RoutInfo;
diff --git a/core/http/src/threading.rs b/core/http/src/threading.rs
new file mode 100644
index 0000000..b59bec8
--- /dev/null
+++ b/core/http/src/threading.rs
@@ -0,0 +1,90 @@
+use std::{
+    sync::{mpsc, Arc, Mutex},
+    thread,
+};
+
+pub struct ThreadPool {
+    workers: Vec<Worker>,
+    sender: Option<mpsc::Sender<Job>>,
+}
+
+type Job = Box<dyn FnOnce() + Send + 'static>;
+
+impl ThreadPool {
+    /// Create a new ThreadPool.
+    ///
+    /// The size is the number of threads in the pool.
+    ///
+    /// # Panics
+    ///
+    /// The `new` function will panic if the size is zero.
+    pub fn new(size: usize) -> ThreadPool {
+        assert!(size > 0);
+
+        let (sender, receiver) = mpsc::channel();
+
+        let receiver = Arc::new(Mutex::new(receiver));
+
+        let mut workers = Vec::with_capacity(size);
+
+        for id in 0..size {
+            workers.push(Worker::new(id, Arc::clone(&receiver)));
+        }
+        ThreadPool {
+            workers,
+            sender: Some(sender),
+        }
+    }
+
+    pub fn execute<F>(&self, f: F)
+    where
+        F: FnOnce() + Send + 'static,
+    {
+        let job = Box::new(f);
+
+        self.sender.as_ref().unwrap().send(job).unwrap();
+    }
+}
+
+impl Drop for ThreadPool {
+    fn drop(&mut self) {
+        drop(self.sender.take());
+
+        for worker in &mut self.workers {
+            println!("Shutting down worker {}", worker.id);
+
+            if let Some(thread) = worker.thread.take() {
+                thread.join().unwrap();
+            }
+        }
+    }
+}
+struct Worker {
+    id: usize,
+    thread: Option<thread::JoinHandle<()>>,
+}
+
+impl Worker {
+    fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
+        let thread = thread::spawn(move || loop {
+            let message = receiver.lock().unwrap().recv();
+
+            match message {
+                Ok(job) => {
+                    println!("Worker {id} got a job; executing.");
+
+                    job();
+                }
+                Err(_) => {
+                    println!("Worker {id} disconnected; shutting down.");
+                    break;
+                }
+            }
+        });
+
+        Worker {
+            id,
+            thread: Some(thread),
+        }
+    }
+}
diff --git a/q b/q
new file mode 100644
index 0000000..e69de29
diff --git a/site/Cargo.lock b/site/Cargo.lock
index d1bf507..fac1130 100644
--- a/site/Cargo.lock
+++ b/site/Cargo.lock
@@ -2,6 +2,13 @@
 # It is not intended for manual editing.
 version = 3
 
+[[package]]
+name = "http"
+version = "0.1.0"
+
 [[package]]
 name = "site"
 version = "0.1.0"
+dependencies = [
+ "http",
+]
diff --git a/site/Cargo.toml b/site/Cargo.toml
index e6a3153..d4e9a4a 100644
--- a/site/Cargo.toml
+++ b/site/Cargo.toml
@@ -6,3 +6,4 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
+http = { path = "../core/http" }
diff --git a/site/hello.html b/site/hello.html
new file mode 100644
index 0000000..ff4f652
--- /dev/null
+++ b/site/hello.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8" />
+    <title>Hello!</title>
+  </head>
+  <body>
+    <h1>Hello!</h1>
+    <p>Hi from Rust</p>
+  </body>
+</html>
diff --git a/site/src/main.rs b/site/src/main.rs
index e7a11a9..435d748 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -1,3 +1,3 @@
 fn main() {
-    println!("Hello, world!");
+    http::build("192.168.179.2:8000").launch();
 }
-- 
GitLab


From a6251e8fc7a44b40119127767a0d04c14e6653c3 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Mon, 8 May 2023 21:52:16 +0200
Subject: [PATCH 02/65] delete random file q

---
 q | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 q

diff --git a/q b/q
deleted file mode 100644
index e69de29..0000000
-- 
GitLab


From d319f18db94db5e534186a1d3345ca7a4547e9bb Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Tue, 9 May 2023 16:51:14 +0200
Subject: [PATCH 03/65] 1. Add SIGNIT graceful shutdown 1. Organize lib.rs in
 modules 1. Setting up basic text-file server functionality 1. Adding some
 test files

---
 core/http/Cargo.lock       | 743 +++++++++++++++++++++++++++++++++++++
 core/http/Cargo.toml       |   2 +
 core/http/src/handlers.rs  |  34 ++
 core/http/src/lib.rs       |  71 +---
 core/http/src/routing.rs   |  63 +++-
 core/http/src/setup.rs     |  85 +++++
 core/http/src/threading.rs |   5 -
 core/http/src/utils/mod.rs |   0
 site/404.html              |  12 +
 site/Cargo.lock            | 743 +++++++++++++++++++++++++++++++++++++
 site/QLC-LS.jpg            | Bin 0 -> 51549 bytes
 site/hello.css             |   4 +
 site/hello.html            |   1 +
 site/src/main.rs           |   2 +-
 14 files changed, 1690 insertions(+), 75 deletions(-)
 create mode 100644 core/http/src/setup.rs
 create mode 100644 core/http/src/utils/mod.rs
 create mode 100644 site/404.html
 create mode 100644 site/QLC-LS.jpg
 create mode 100644 site/hello.css

diff --git a/core/http/Cargo.lock b/core/http/Cargo.lock
index 8490fd5..755ed5e 100644
--- a/core/http/Cargo.lock
+++ b/core/http/Cargo.lock
@@ -2,6 +2,749 @@
 # It is not intended for manual editing.
 version = 3
 
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "base64"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bumpalo"
+version = "3.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8"
+
+[[package]]
+name = "bytes"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
+
+[[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "core-foundation"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
+
+[[package]]
+name = "ctrlc"
+version = "3.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbcf33c2a618cbe41ee43ae6e9f2e48368cd9f9db2896f10167d8d762679f639"
+dependencies = [
+ "nix",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
 [[package]]
 name = "http"
 version = "0.1.0"
+dependencies = [
+ "ctrlc",
+ "quinn",
+]
+
+[[package]]
+name = "js-sys"
+version = "0.3.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.144"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "mio"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
+dependencies = [
+ "libc",
+ "log",
+ "wasi",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "nix"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "libc",
+ "static_assertions",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quinn"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "445cbfe2382fa023c4f2f3c7e1c95c03dcc1df2bf23cebcb2b13e1402c4394d1"
+dependencies = [
+ "bytes",
+ "pin-project-lite",
+ "quinn-proto",
+ "quinn-udp",
+ "rustc-hash",
+ "rustls",
+ "thiserror",
+ "tokio",
+ "tracing",
+ "webpki",
+]
+
+[[package]]
+name = "quinn-proto"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67c10f662eee9c94ddd7135043e544f3c82fa839a1e7b865911331961b53186c"
+dependencies = [
+ "bytes",
+ "rand",
+ "ring",
+ "rustc-hash",
+ "rustls",
+ "rustls-native-certs",
+ "slab",
+ "thiserror",
+ "tinyvec",
+ "tracing",
+ "webpki",
+]
+
+[[package]]
+name = "quinn-udp"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "641538578b21f5e5c8ea733b736895576d0fe329bb883b937db6f4d163dbaaf4"
+dependencies = [
+ "libc",
+ "quinn-proto",
+ "socket2",
+ "tracing",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "ring"
+version = "0.16.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
+dependencies = [
+ "cc",
+ "libc",
+ "once_cell",
+ "spin",
+ "untrusted",
+ "web-sys",
+ "winapi",
+]
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "rustls"
+version = "0.20.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
+dependencies = [
+ "ring",
+ "sct",
+ "webpki",
+]
+
+[[package]]
+name = "rustls-native-certs"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50"
+dependencies = [
+ "openssl-probe",
+ "rustls-pemfile",
+ "schannel",
+ "security-framework",
+]
+
+[[package]]
+name = "rustls-pemfile"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
+dependencies = [
+ "base64",
+]
+
+[[package]]
+name = "schannel"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3"
+dependencies = [
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "sct"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "security-framework"
+version = "2.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254"
+dependencies = [
+ "bitflags",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "socket2"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "spin"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "tokio"
+version = "1.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f"
+dependencies = [
+ "autocfg",
+ "libc",
+ "mio",
+ "pin-project-lite",
+ "socket2",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "tracing"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
+dependencies = [
+ "cfg-if",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
+
+[[package]]
+name = "untrusted"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
+
+[[package]]
+name = "web-sys"
+version = "0.3.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "webpki"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.0",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.0",
+ "windows_aarch64_msvc 0.48.0",
+ "windows_i686_gnu 0.48.0",
+ "windows_i686_msvc 0.48.0",
+ "windows_x86_64_gnu 0.48.0",
+ "windows_x86_64_gnullvm 0.48.0",
+ "windows_x86_64_msvc 0.48.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
diff --git a/core/http/Cargo.toml b/core/http/Cargo.toml
index 8b1c9f1..34a4506 100644
--- a/core/http/Cargo.toml
+++ b/core/http/Cargo.toml
@@ -6,3 +6,5 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
+quinn = "0.9.3"
+ctrlc = "3.2.5"
diff --git a/core/http/src/handlers.rs b/core/http/src/handlers.rs
index e69de29..944f60a 100644
--- a/core/http/src/handlers.rs
+++ b/core/http/src/handlers.rs
@@ -0,0 +1,34 @@
+use std::{
+    fs,
+    io::{BufRead, BufReader, Write},
+    net::TcpStream,
+};
+
+pub fn handle_connection(mut stream: TcpStream) {
+    let buf_reader = BufReader::new(&mut stream);
+    let http_request: Vec<_> = buf_reader
+        .lines()
+        .map(|result| result.unwrap())
+        .take_while(|line| !line.is_empty())
+        .collect();
+
+    let path_elements = http_request[0]
+        .split(" ")
+        .nth(1)
+        .unwrap()
+        .split("/")
+        .filter(|&val| val != ".." && val != "")
+        .collect::<Vec<&str>>();
+    let mut path = String::from("./");
+    path.push_str(&path_elements.join("/"));
+    println!("{:?}", path_elements);
+    println!("{:?}", path);
+
+    let status_line = "HTTP/1.1 200 OK";
+    let contents = fs::read_to_string(path).unwrap_or(fs::read_to_string("404.html").unwrap());
+    let length = contents.len();
+
+    let response = format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}");
+
+    stream.write_all(response.as_bytes()).unwrap();
+}
diff --git a/core/http/src/lib.rs b/core/http/src/lib.rs
index 1d8e24d..0b86db5 100644
--- a/core/http/src/lib.rs
+++ b/core/http/src/lib.rs
@@ -1,74 +1,11 @@
-use std::{
-    fs,
-    io::{BufRead, BufReader, Write},
-    net::{TcpListener, TcpStream},
-    thread::available_parallelism,
-};
-
-use threading::ThreadPool;
-
 mod handlers;
 mod routing;
+mod setup;
 mod threading;
 
-pub struct Config {
-    address: TcpListener,
-    workers: usize,
-    threadpool: ThreadPool,
-}
-
-impl Config {
-    pub fn mount(self, mountpoint: &str, routes: Vec<routing::Route>) {}
-    pub fn launch(self) {
-        for stream in self.address.incoming() {
-            let stream = stream.unwrap();
-            self.threadpool.execute(|| handle_connection(stream))
-        }
-    }
-}
-
-fn handle_connection(mut stream: TcpStream) {
-    let buf_reader = BufReader::new(&mut stream);
-    let http_request: Vec<_> = buf_reader
-        .lines()
-        .map(|result| result.unwrap())
-        .take_while(|line| !line.is_empty())
-        .collect();
-
-    let status_line = "HTTP/1.1 200 OK";
-    let contents = fs::read_to_string("hello.html").unwrap();
-    let length = contents.len();
-
-    let response = format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}");
-
-    stream.write_all(response.as_bytes()).unwrap();
-}
-
-pub fn build(ip: &str) -> Config {
-    let listener = TcpListener::bind(ip).unwrap();
-    let ip = ip.splitn(2, ":").collect::<Vec<&str>>();
-    if ip.len() != 2 {
-        panic!("Invalid IP Address");
-    }
-    let port = ip[1];
-    let ip = ip[0];
-    let workers = available_parallelism().unwrap().get();
-    let threadpool = ThreadPool::new(workers);
-    println!(
-        "\x1b[34mâš™ Configuration\x1b[0m
-  >> \x1b[34mIp\x1b[0m: {ip}
-  >> \x1b[34mPort\x1b[0m: {port}
-  >> \x1b[34mWorkers\x1b[0m: {workers}
-\n
-Server has launched from {ip}:{port}.
-"
-    );
-    Config {
-        address: listener,
-        workers,
-        threadpool,
-    }
-}
+mod utils;
 
 #[cfg(test)]
 mod tests {}
+
+pub use setup::build;
diff --git a/core/http/src/routing.rs b/core/http/src/routing.rs
index 6ae9a73..aee6f8a 100644
--- a/core/http/src/routing.rs
+++ b/core/http/src/routing.rs
@@ -1,2 +1,61 @@
-pub struct Route;
-pub struct RoutInfo;
+pub struct RoutInfo {
+    name: Option<&'static str>,
+    method: Method,
+    path: &'static str,
+    // handler: fn(Request) -> Outcome,
+    format: Option<Format>,
+    rank: Option<isize>,
+}
+
+pub struct Route {
+    name: Option<&'static str>,
+    method: Method,
+    // handler: fn(Request) -> Outcome,
+    uri: &'static str,
+    rank: isize,
+    format: Format,
+}
+
+impl Route {
+    pub fn from(routeinfo: RoutInfo) -> Self {
+        let rank = routeinfo.rank.unwrap_or(0);
+        let format = routeinfo.format.unwrap_or(Format::Plain);
+        Route {
+            name: routeinfo.name,
+            method: routeinfo.method,
+            // handler: routeinfo.handler,
+            uri: routeinfo.path,
+            rank,
+            format,
+        }
+    }
+}
+
+struct Request<'a> {
+    uri: &'a str,
+    headers: Vec<&'a str>,
+}
+
+enum Outcome<S, E, F> {
+    Success(S),
+    Failure(E),
+    Forward(F),
+}
+
+enum Method {
+    Get,
+    Head,
+    Post,
+    Put,
+    Delete,
+    Connect,
+    Options,
+    Trace,
+    Patch,
+}
+
+enum Format {
+    Json,
+    Plain,
+    Html,
+}
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
new file mode 100644
index 0000000..b69bc0f
--- /dev/null
+++ b/core/http/src/setup.rs
@@ -0,0 +1,85 @@
+use std::{
+    net::TcpListener,
+    sync::{
+        atomic::{self, AtomicBool},
+        Arc,
+    },
+    thread::available_parallelism,
+};
+
+use crate::{handlers::handle_connection, routing::Route, threading::ThreadPool};
+
+pub struct PreMountConfig {
+    address: TcpListener,
+    workers: usize,
+    threadpool: ThreadPool,
+}
+impl PreMountConfig {
+    pub fn mount(self, mountpoint: &str, routes: Vec<Route>) -> Config {
+        Config {
+            mountpoint,
+            address: self.address,
+            workers: self.workers,
+            threadpool: self.threadpool,
+            routes,
+        }
+    }
+}
+pub struct Config<'a> {
+    mountpoint: &'a str,
+    address: TcpListener,
+    workers: usize,
+    threadpool: ThreadPool,
+    routes: Vec<Route>,
+}
+
+impl Config<'_> {
+    pub fn launch(self) {
+        let running = Arc::new(AtomicBool::new(true));
+
+        // Clone a reference to `running` to pass to the signal handler closure
+        let running_for_handler = running.clone();
+
+        // Set up a signal handler for SIGINT
+        ctrlc::set_handler(move || {
+            // When the user sends a SIGINT signal (e.g. by pressing CTRL+C),
+            // set the `running` flag to false to initiate a graceful shutdown
+            println!("SIGNIT received, shutting down gracefully");
+            running_for_handler.store(false, atomic::Ordering::SeqCst);
+        })
+        .expect("Error setting Ctrl-C handler");
+
+        for stream in self.address.incoming() {
+            if !running.load(atomic::Ordering::SeqCst) {
+                break;
+            }
+            let stream = stream.unwrap();
+            self.threadpool.execute(|| handle_connection(stream))
+        }
+    }
+}
+pub fn build(ip: &str) -> PreMountConfig {
+    let listener = TcpListener::bind(ip).unwrap();
+    let ip = ip.splitn(2, ":").collect::<Vec<&str>>();
+    if ip.len() != 2 {
+        panic!("Invalid IP Address");
+    }
+    let port = ip[1];
+    let ip = ip[0];
+    let workers = available_parallelism().unwrap().get();
+    let threadpool = ThreadPool::new(workers);
+    println!(
+        "\x1b[34mâš™ Configuration\x1b[0m
+  >> \x1b[34mIp\x1b[0m: {ip}
+  >> \x1b[34mPort\x1b[0m: {port}
+  >> \x1b[34mWorkers\x1b[0m: {workers}
+\n
+Server has launched from {ip}:{port}.
+"
+    );
+    PreMountConfig {
+        address: listener,
+        workers,
+        threadpool,
+    }
+}
diff --git a/core/http/src/threading.rs b/core/http/src/threading.rs
index b59bec8..e743853 100644
--- a/core/http/src/threading.rs
+++ b/core/http/src/threading.rs
@@ -51,8 +51,6 @@ impl Drop for ThreadPool {
         drop(self.sender.take());
 
         for worker in &mut self.workers {
-            println!("Shutting down worker {}", worker.id);
-
             if let Some(thread) = worker.thread.take() {
                 thread.join().unwrap();
             }
@@ -71,12 +69,9 @@ impl Worker {
 
             match message {
                 Ok(job) => {
-                    println!("Worker {id} got a job; executing.");
-
                     job();
                 }
                 Err(_) => {
-                    println!("Worker {id} disconnected; shutting down.");
                     break;
                 }
             }
diff --git a/core/http/src/utils/mod.rs b/core/http/src/utils/mod.rs
new file mode 100644
index 0000000..e69de29
diff --git a/site/404.html b/site/404.html
new file mode 100644
index 0000000..3a6ceb5
--- /dev/null
+++ b/site/404.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8" />
+    <title>404</title>
+    <link rel="stylesheet" href="/hello.css" />
+  </head>
+  <body>
+    <h1>404</h1>
+    <p>Hi from Rust</p>
+  </body>
+</html>
diff --git a/site/Cargo.lock b/site/Cargo.lock
index fac1130..498f9ed 100644
--- a/site/Cargo.lock
+++ b/site/Cargo.lock
@@ -2,9 +2,357 @@
 # It is not intended for manual editing.
 version = 3
 
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "base64"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bumpalo"
+version = "3.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8"
+
+[[package]]
+name = "bytes"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
+
+[[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "core-foundation"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
+
+[[package]]
+name = "ctrlc"
+version = "3.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbcf33c2a618cbe41ee43ae6e9f2e48368cd9f9db2896f10167d8d762679f639"
+dependencies = [
+ "nix",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
 [[package]]
 name = "http"
 version = "0.1.0"
+dependencies = [
+ "ctrlc",
+ "quinn",
+]
+
+[[package]]
+name = "js-sys"
+version = "0.3.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.144"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "mio"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
+dependencies = [
+ "libc",
+ "log",
+ "wasi",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "nix"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "libc",
+ "static_assertions",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quinn"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "445cbfe2382fa023c4f2f3c7e1c95c03dcc1df2bf23cebcb2b13e1402c4394d1"
+dependencies = [
+ "bytes",
+ "pin-project-lite",
+ "quinn-proto",
+ "quinn-udp",
+ "rustc-hash",
+ "rustls",
+ "thiserror",
+ "tokio",
+ "tracing",
+ "webpki",
+]
+
+[[package]]
+name = "quinn-proto"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67c10f662eee9c94ddd7135043e544f3c82fa839a1e7b865911331961b53186c"
+dependencies = [
+ "bytes",
+ "rand",
+ "ring",
+ "rustc-hash",
+ "rustls",
+ "rustls-native-certs",
+ "slab",
+ "thiserror",
+ "tinyvec",
+ "tracing",
+ "webpki",
+]
+
+[[package]]
+name = "quinn-udp"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "641538578b21f5e5c8ea733b736895576d0fe329bb883b937db6f4d163dbaaf4"
+dependencies = [
+ "libc",
+ "quinn-proto",
+ "socket2",
+ "tracing",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "ring"
+version = "0.16.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
+dependencies = [
+ "cc",
+ "libc",
+ "once_cell",
+ "spin",
+ "untrusted",
+ "web-sys",
+ "winapi",
+]
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "rustls"
+version = "0.20.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
+dependencies = [
+ "ring",
+ "sct",
+ "webpki",
+]
+
+[[package]]
+name = "rustls-native-certs"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50"
+dependencies = [
+ "openssl-probe",
+ "rustls-pemfile",
+ "schannel",
+ "security-framework",
+]
+
+[[package]]
+name = "rustls-pemfile"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
+dependencies = [
+ "base64",
+]
+
+[[package]]
+name = "schannel"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3"
+dependencies = [
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "sct"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "security-framework"
+version = "2.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254"
+dependencies = [
+ "bitflags",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
 
 [[package]]
 name = "site"
@@ -12,3 +360,398 @@ version = "0.1.0"
 dependencies = [
  "http",
 ]
+
+[[package]]
+name = "slab"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "socket2"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "spin"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "tokio"
+version = "1.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f"
+dependencies = [
+ "autocfg",
+ "libc",
+ "mio",
+ "pin-project-lite",
+ "socket2",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "tracing"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
+dependencies = [
+ "cfg-if",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
+
+[[package]]
+name = "untrusted"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
+
+[[package]]
+name = "web-sys"
+version = "0.3.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "webpki"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.0",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.0",
+ "windows_aarch64_msvc 0.48.0",
+ "windows_i686_gnu 0.48.0",
+ "windows_i686_msvc 0.48.0",
+ "windows_x86_64_gnu 0.48.0",
+ "windows_x86_64_gnullvm 0.48.0",
+ "windows_x86_64_msvc 0.48.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
diff --git a/site/QLC-LS.jpg b/site/QLC-LS.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..07eb7f85ac26c70344d552f56a81c44a0bf1b3db
GIT binary patch
literal 51549
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
B#&7@t

literal 0
HcmV?d00001

diff --git a/site/hello.css b/site/hello.css
new file mode 100644
index 0000000..aba0df0
--- /dev/null
+++ b/site/hello.css
@@ -0,0 +1,4 @@
+body {
+  background-color: #212121;
+  color: #ffffff;
+}
diff --git a/site/hello.html b/site/hello.html
index ff4f652..52ef689 100644
--- a/site/hello.html
+++ b/site/hello.html
@@ -3,6 +3,7 @@
   <head>
     <meta charset="utf-8" />
     <title>Hello!</title>
+    <link rel="stylesheet" href="/hello.css" />
   </head>
   <body>
     <h1>Hello!</h1>
diff --git a/site/src/main.rs b/site/src/main.rs
index 435d748..55ea439 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -1,3 +1,3 @@
 fn main() {
-    http::build("192.168.179.2:8000").launch();
+    http::build("127.0.0.1:8000").mount("/", vec![]).launch();
 }
-- 
GitLab


From 9b9f4971c4cb25eed58396835db5840f4e222a68 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Tue, 9 May 2023 22:05:30 +0200
Subject: [PATCH 04/65] Add MIME support for the handler update routeing module

---
 core/http/Cargo.lock         |   7 +++++
 core/http/Cargo.toml         |   1 +
 core/http/src/handlers.rs    |  59 ++++++++++++++++++++++++++++-------
 core/http/src/routing.rs     |   5 ++-
 site/Cargo.lock              |   7 +++++
 site/{QLC-LS.jpg => img.jpg} | Bin
 6 files changed, 65 insertions(+), 14 deletions(-)
 rename site/{QLC-LS.jpg => img.jpg} (100%)

diff --git a/core/http/Cargo.lock b/core/http/Cargo.lock
index 755ed5e..6cd2bca 100644
--- a/core/http/Cargo.lock
+++ b/core/http/Cargo.lock
@@ -86,6 +86,7 @@ name = "http"
 version = "0.1.0"
 dependencies = [
  "ctrlc",
+ "mime",
  "quinn",
 ]
 
@@ -113,6 +114,12 @@ dependencies = [
  "cfg-if",
 ]
 
+[[package]]
+name = "mime"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
 [[package]]
 name = "mio"
 version = "0.8.6"
diff --git a/core/http/Cargo.toml b/core/http/Cargo.toml
index 34a4506..a5b887f 100644
--- a/core/http/Cargo.toml
+++ b/core/http/Cargo.toml
@@ -8,3 +8,4 @@ edition = "2021"
 [dependencies]
 quinn = "0.9.3"
 ctrlc = "3.2.5"
+mime = "0.3.17"
diff --git a/core/http/src/handlers.rs b/core/http/src/handlers.rs
index 944f60a..194eca3 100644
--- a/core/http/src/handlers.rs
+++ b/core/http/src/handlers.rs
@@ -2,8 +2,11 @@ use std::{
     fs,
     io::{BufRead, BufReader, Write},
     net::TcpStream,
+    path::PathBuf,
 };
 
+use mime::Mime;
+
 pub fn handle_connection(mut stream: TcpStream) {
     let buf_reader = BufReader::new(&mut stream);
     let http_request: Vec<_> = buf_reader
@@ -12,23 +15,57 @@ pub fn handle_connection(mut stream: TcpStream) {
         .take_while(|line| !line.is_empty())
         .collect();
 
-    let path_elements = http_request[0]
+    let path = parse_request(&http_request[0]);
+
+    let status_line;
+    let mime_type;
+    let contents = if let Ok(file) = fs::read(&path) {
+        status_line = "HTTP/1.1 200 OK";
+        mime_type = find_mimetype(&path.to_str().unwrap().to_string());
+        file
+    } else {
+        status_line = "HTTP/1.1 404 NOT FOUND";
+        mime_type = find_mimetype(&"html".to_string());
+        fs::read("404.html").unwrap()
+    };
+
+    println!("{mime_type}");
+
+    let response = format!(
+        "{}\r\nContent-Length: {}\r\nContent-Type: {}\r\n\r\n",
+        status_line,
+        contents.len(),
+        mime_type
+    );
+
+    stream.write_all(response.as_bytes()).unwrap();
+    stream.write(&contents).unwrap();
+}
+
+fn parse_request(request: &str) -> PathBuf {
+    let path_elements = request
         .split(" ")
         .nth(1)
         .unwrap()
         .split("/")
         .filter(|&val| val != ".." && val != "")
         .collect::<Vec<&str>>();
-    let mut path = String::from("./");
-    path.push_str(&path_elements.join("/"));
-    println!("{:?}", path_elements);
-    println!("{:?}", path);
-
-    let status_line = "HTTP/1.1 200 OK";
-    let contents = fs::read_to_string(path).unwrap_or(fs::read_to_string("404.html").unwrap());
-    let length = contents.len();
+    PathBuf::from(format!("./{}", path_elements.join("/")))
+}
 
-    let response = format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}");
+fn find_mimetype(filename: &String) -> Mime {
+    let parts: Vec<&str> = filename.split('.').collect();
 
-    stream.write_all(response.as_bytes()).unwrap();
+    let res = match parts.last() {
+        Some(v) => match *v {
+            "png" => mime::IMAGE_PNG,
+            "jpg" => mime::IMAGE_JPEG,
+            "json" => mime::APPLICATION_JSON,
+            "html" => mime::TEXT_HTML,
+            "css" => mime::TEXT_CSS,
+            &_ => mime::TEXT_PLAIN,
+        },
+        None => mime::TEXT_PLAIN,
+    };
+    return res;
 }
diff --git a/core/http/src/routing.rs b/core/http/src/routing.rs
index aee6f8a..2c5f74e 100644
--- a/core/http/src/routing.rs
+++ b/core/http/src/routing.rs
@@ -13,20 +13,19 @@ pub struct Route {
     // handler: fn(Request) -> Outcome,
     uri: &'static str,
     rank: isize,
-    format: Format,
+    format: Option<Format>,
 }
 
 impl Route {
     pub fn from(routeinfo: RoutInfo) -> Self {
         let rank = routeinfo.rank.unwrap_or(0);
-        let format = routeinfo.format.unwrap_or(Format::Plain);
         Route {
             name: routeinfo.name,
             method: routeinfo.method,
             // handler: routeinfo.handler,
             uri: routeinfo.path,
             rank,
-            format,
+            format: routeinfo.format,
         }
     }
 }
diff --git a/site/Cargo.lock b/site/Cargo.lock
index 498f9ed..7578765 100644
--- a/site/Cargo.lock
+++ b/site/Cargo.lock
@@ -86,6 +86,7 @@ name = "http"
 version = "0.1.0"
 dependencies = [
  "ctrlc",
+ "mime",
  "quinn",
 ]
 
@@ -113,6 +114,12 @@ dependencies = [
  "cfg-if",
 ]
 
+[[package]]
+name = "mime"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
 [[package]]
 name = "mio"
 version = "0.8.6"
diff --git a/site/QLC-LS.jpg b/site/img.jpg
similarity index 100%
rename from site/QLC-LS.jpg
rename to site/img.jpg
-- 
GitLab


From 299909a8fa22da06c2289d8619e234dad56d242d Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sat, 13 May 2023 20:07:44 +0200
Subject: [PATCH 05/65] Add routing with outcome functionality, improving
 fileserver improve division of code into different modules

---
 core/http/src/handlers.rs               |  71 -----------------
 core/http/src/handlers/file_handlers.rs |  65 +++++++++++++++
 core/http/src/handlers/handlers.rs      | 100 ++++++++++++++++++++++++
 core/http/src/handlers/mod.rs           |   2 +
 core/http/src/routing.rs                |  60 --------------
 core/http/src/routing/methods.rs        |  49 ++++++++++++
 core/http/src/routing/mod.rs            |   2 +
 core/http/src/routing/routes.rs         |  93 ++++++++++++++++++++++
 core/http/src/setup.rs                  |  47 ++++++-----
 site/hello.html                         |  12 ---
 site/static/hello.html                  |   7 ++
 11 files changed, 340 insertions(+), 168 deletions(-)
 delete mode 100644 core/http/src/handlers.rs
 create mode 100644 core/http/src/handlers/file_handlers.rs
 create mode 100644 core/http/src/handlers/handlers.rs
 create mode 100644 core/http/src/handlers/mod.rs
 delete mode 100644 core/http/src/routing.rs
 create mode 100644 core/http/src/routing/methods.rs
 create mode 100644 core/http/src/routing/mod.rs
 create mode 100644 core/http/src/routing/routes.rs
 delete mode 100644 site/hello.html
 create mode 100644 site/static/hello.html

diff --git a/core/http/src/handlers.rs b/core/http/src/handlers.rs
deleted file mode 100644
index 194eca3..0000000
--- a/core/http/src/handlers.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-use std::{
-    fs,
-    io::{BufRead, BufReader, Write},
-    net::TcpStream,
-    path::PathBuf,
-};
-
-use mime::Mime;
-
-pub fn handle_connection(mut stream: TcpStream) {
-    let buf_reader = BufReader::new(&mut stream);
-    let http_request: Vec<_> = buf_reader
-        .lines()
-        .map(|result| result.unwrap())
-        .take_while(|line| !line.is_empty())
-        .collect();
-
-    let path = parse_request(&http_request[0]);
-
-    let status_line;
-    let mime_type;
-    let contents = if let Ok(file) = fs::read(&path) {
-        status_line = "HTTP/1.1 200 OK";
-        mime_type = find_mimetype(&path.to_str().unwrap().to_string());
-        file
-    } else {
-        status_line = "HTTP/1.1 404 NOT FOUND";
-        mime_type = find_mimetype(&"html".to_string());
-        fs::read("404.html").unwrap()
-    };
-
-    println!("{mime_type}");
-
-    let response = format!(
-        "{}\r\nContent-Length: {}\r\nContent-Type: {}\r\n\r\n",
-        status_line,
-        contents.len(),
-        mime_type
-    );
-
-    stream.write_all(response.as_bytes()).unwrap();
-    stream.write(&contents).unwrap();
-}
-
-fn parse_request(request: &str) -> PathBuf {
-    let path_elements = request
-        .split(" ")
-        .nth(1)
-        .unwrap()
-        .split("/")
-        .filter(|&val| val != ".." && val != "")
-        .collect::<Vec<&str>>();
-    PathBuf::from(format!("./{}", path_elements.join("/")))
-}
-
-fn find_mimetype(filename: &String) -> Mime {
-    let parts: Vec<&str> = filename.split('.').collect();
-
-    let res = match parts.last() {
-        Some(v) => match *v {
-            "png" => mime::IMAGE_PNG,
-            "jpg" => mime::IMAGE_JPEG,
-            "json" => mime::APPLICATION_JSON,
-            "html" => mime::TEXT_HTML,
-            "css" => mime::TEXT_CSS,
-            &_ => mime::TEXT_PLAIN,
-        },
-        None => mime::TEXT_PLAIN,
-    };
-    return res;
-}
diff --git a/core/http/src/handlers/file_handlers.rs b/core/http/src/handlers/file_handlers.rs
new file mode 100644
index 0000000..708a046
--- /dev/null
+++ b/core/http/src/handlers/file_handlers.rs
@@ -0,0 +1,65 @@
+use std::{fs, path::PathBuf};
+
+use mime::Mime;
+
+use crate::routing::routes::{ResponseBody, Status};
+
+#[derive(Debug)]
+pub struct NamedFile {
+    pub content_len: usize,
+    pub content_type: Mime,
+    pub content: Vec<u8>,
+}
+
+impl ResponseBody for NamedFile {
+    fn get_data(&self) -> Vec<u8> {
+        self.content.clone()
+    }
+}
+
+impl NamedFile {
+    pub fn open(path: PathBuf) -> Result<NamedFile, Status> {
+        let path = proove_path(path);
+        let data = fs::read(&path);
+        let data = match data {
+            Ok(dat) => {
+                println!("{:?}", dat);
+                dat
+            }
+            Err(_) => {
+                return Err(Status { code: 404 });
+            }
+        };
+        println!("{:?}", data);
+        Ok(NamedFile {
+            content_len: data.len(),
+            content_type: find_mimetype(path.to_str().unwrap()),
+            content: data,
+        })
+    }
+}
+
+fn proove_path(path: PathBuf) -> PathBuf {
+    PathBuf::from(
+        path.to_str()
+            .unwrap()
+            .split("/")
+            .filter(|&val| val != ".." && val != "")
+            .collect::<Vec<&str>>()
+            .join("/"),
+    )
+}
+
+pub fn find_mimetype(filename: &str) -> Mime {
+    match filename.split('.').last() {
+        Some(v) => match v {
+            "png" => mime::IMAGE_PNG,
+            "jpg" => mime::IMAGE_JPEG,
+            "json" => mime::APPLICATION_JSON,
+            "html" => mime::TEXT_HTML,
+            "css" => mime::TEXT_CSS,
+            &_ => mime::TEXT_PLAIN,
+        },
+        None => mime::TEXT_PLAIN,
+    }
+}
diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
new file mode 100644
index 0000000..33a6dbd
--- /dev/null
+++ b/core/http/src/handlers/handlers.rs
@@ -0,0 +1,100 @@
+use std::{
+    fs,
+    io::{BufRead, BufReader, Write},
+    net::TcpStream,
+    path::PathBuf,
+};
+
+use crate::routing::methods::Method;
+use crate::routing::routes::{Data, Outcome, Request, Response, Status};
+
+use super::file_handlers::NamedFile;
+
+pub fn handle_connection(mut stream: TcpStream, _mountpoint: &str) {
+    let buf_reader = BufReader::new(&mut stream);
+    let http_request: Vec<String> = buf_reader
+        .lines()
+        .map(|result| result.unwrap())
+        .take_while(|line| !line.is_empty())
+        .collect();
+    let request_status_line = http_request.get(0);
+    if request_status_line == None {
+        return;
+    }
+    let request_status_line = request_status_line.unwrap();
+    let request = Request {
+        uri: &request_status_line.split(" ").nth(1).unwrap(),
+        headers: http_request.clone(),
+        method: Method::Get,
+    };
+
+    let data = Data {
+        buffer: vec![],
+        is_complete: true,
+    };
+
+    let handled_response = match handler(request, data) {
+        Outcome::Success(success) => (
+            format!("HTTP/1.1 {} OK\r\n", success.status.unwrap().code)
+                + &success.headers.join("\r\n")
+                + "\r\n\r\n",
+            success.body.get_data(),
+        ),
+        Outcome::Failure(error) => {
+            let content = fs::read("./404.html").unwrap();
+            (
+                format!(
+                    "HTTP/1.1 {} NOT FOUND\r\nContent-Length: {}\r\nContent-Type: text/html\r\n\r\n",
+                    error.code,
+                    content.len()
+                ),
+                content,
+            )
+        }
+        Outcome::Forward(_) => (
+            format!("HTTP/1.1 {} NOT FOUND", 404),
+            fs::read("./404.html").unwrap(),
+        ),
+    };
+    println!("{:?}", handled_response);
+
+    stream.write_all(handled_response.0.as_bytes()).unwrap();
+    stream.write(&handled_response.1).unwrap();
+}
+
+fn parse_request<'a>(request: &'a str, mountpoint: &'a str) -> Result<PathBuf, &'a str> {
+    let uri = request.split(" ").nth(1).unwrap();
+    if !uri.starts_with(mountpoint) {
+        return Err("Request isn't on mountpoint");
+    }
+    let path_elements = uri
+        .split_once(mountpoint)
+        .map(|(_, rest)| rest)
+        .unwrap()
+        .split("/")
+        .filter(|&val| val != ".." && val != "")
+        .collect::<Vec<&str>>();
+    Ok(PathBuf::from(format!("./{}", path_elements.join("/"))))
+}
+
+fn handler(request: Request, _data: Data) -> Outcome<Response, Status, Data> {
+    let response = fileserver(request.uri);
+    println!("{:?}", response);
+    let response = match response {
+        Ok(dat) => Response {
+            headers: vec![
+                format!("Content-Length: {}", dat.content_len),
+                format!("Content-Type: {}", dat.content_type),
+            ],
+            status: Some(Status { code: 200 }),
+            body: Box::new(dat),
+        },
+        Err(_) => return Outcome::Failure(Status { code: 404 }),
+    };
+    Outcome::Success(response)
+}
+
+fn fileserver(path: &str) -> Result<NamedFile, Status> {
+    println!("fileserver started");
+    NamedFile::open(PathBuf::from("static/".to_string() + path))
+}
diff --git a/core/http/src/handlers/mod.rs b/core/http/src/handlers/mod.rs
new file mode 100644
index 0000000..826c4f4
--- /dev/null
+++ b/core/http/src/handlers/mod.rs
@@ -0,0 +1,2 @@
+pub mod file_handlers;
+pub mod handlers;
diff --git a/core/http/src/routing.rs b/core/http/src/routing.rs
deleted file mode 100644
index 2c5f74e..0000000
--- a/core/http/src/routing.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-pub struct RoutInfo {
-    name: Option<&'static str>,
-    method: Method,
-    path: &'static str,
-    // handler: fn(Request) -> Outcome,
-    format: Option<Format>,
-    rank: Option<isize>,
-}
-
-pub struct Route {
-    name: Option<&'static str>,
-    method: Method,
-    // handler: fn(Request) -> Outcome,
-    uri: &'static str,
-    rank: isize,
-    format: Option<Format>,
-}
-
-impl Route {
-    pub fn from(routeinfo: RoutInfo) -> Self {
-        let rank = routeinfo.rank.unwrap_or(0);
-        Route {
-            name: routeinfo.name,
-            method: routeinfo.method,
-            // handler: routeinfo.handler,
-            uri: routeinfo.path,
-            rank,
-            format: routeinfo.format,
-        }
-    }
-}
-
-struct Request<'a> {
-    uri: &'a str,
-    headers: Vec<&'a str>,
-}
-
-enum Outcome<S, E, F> {
-    Success(S),
-    Failure(E),
-    Forward(F),
-}
-
-enum Method {
-    Get,
-    Head,
-    Post,
-    Put,
-    Delete,
-    Connect,
-    Options,
-    Trace,
-    Patch,
-}
-
-enum Format {
-    Json,
-    Plain,
-    Html,
-}
diff --git a/core/http/src/routing/methods.rs b/core/http/src/routing/methods.rs
new file mode 100644
index 0000000..328e697
--- /dev/null
+++ b/core/http/src/routing/methods.rs
@@ -0,0 +1,49 @@
+use std::{fmt::Display, str::FromStr};
+
+#[derive(PartialEq, Eq)]
+pub enum Method {
+    Get,
+    Head,
+    Post,
+    Put,
+    Delete,
+    Connect,
+    Options,
+    Trace,
+    Patch,
+}
+
+impl Display for Method {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            Self::Get => write!(f, "GET"),
+            Self::Head => write!(f, "HEAD"),
+            Self::Post => write!(f, "POST"),
+            Self::Put => write!(f, "PUT"),
+            Self::Delete => write!(f, "DELETE"),
+            Self::Connect => write!(f, "CONNECT"),
+            Self::Options => write!(f, "OPTIONS"),
+            Self::Trace => write!(f, "TRACE"),
+            Self::Patch => write!(f, "PATCH"),
+        }
+    }
+}
+
+impl FromStr for Method {
+    type Err = &'static str;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "GET" => Ok(Self::Get),
+            "HEAD" => Ok(Self::Head),
+            "POST" => Ok(Self::Post),
+            "PUT" => Ok(Self::Put),
+            "DELETE" => Ok(Self::Delete),
+            "CONNECT" => Ok(Self::Connect),
+            "OPTIONS" => Ok(Self::Options),
+            "TRACE" => Ok(Self::Trace),
+            "PATCH" => Ok(Self::Patch),
+            _ => Err("Not a Method"),
+        }
+    }
+}
diff --git a/core/http/src/routing/mod.rs b/core/http/src/routing/mod.rs
new file mode 100644
index 0000000..f1e52f9
--- /dev/null
+++ b/core/http/src/routing/mod.rs
@@ -0,0 +1,2 @@
+pub mod methods;
+pub mod routes;
diff --git a/core/http/src/routing/routes.rs b/core/http/src/routing/routes.rs
new file mode 100644
index 0000000..05ecf74
--- /dev/null
+++ b/core/http/src/routing/routes.rs
@@ -0,0 +1,93 @@
+use std::net::SocketAddr;
+
+use super::methods::Method;
+
+pub trait ResponseBody {
+    fn get_data(&self) -> Vec<u8>;
+}
+
+pub struct RoutInfo {
+    name: Option<&'static str>,
+    method: Method,
+    path: &'static str,
+    handler: fn(Request, Data) -> Outcome<Response, Status, Data>,
+    format: Option<MediaType>,
+    rank: Option<isize>,
+}
+
+pub struct Route<'a> {
+    name: Option<&'static str>,
+    method: Method,
+    uri: Uri<'a>,
+    handler: fn(Request, Data) -> Outcome<Response, Status, Data>,
+    rank: isize,
+    format: Option<MediaType>,
+}
+
+impl Route<'_> {
+    pub fn from(routeinfo: RoutInfo) -> Self {
+        let rank = routeinfo.rank.unwrap_or(0);
+        Route {
+            name: routeinfo.name,
+            method: routeinfo.method,
+            uri: routeinfo.path,
+            handler: routeinfo.handler,
+            rank,
+            format: routeinfo.format,
+        }
+    }
+}
+
+pub struct Request<'a> {
+    pub uri: Uri<'a>,
+    pub headers: HeaderMap,
+    pub method: Method,
+    // pub connection: ConnectionMeta,
+}
+
+struct ConnectionMeta {
+    remote: Option<SocketAddr>,
+    // certificates
+}
+
+type HeaderMap = Vec<String>;
+type Uri<'a> = &'a str;
+
+pub enum Outcome<S, E, F> {
+    Success(S),
+    Failure(E),
+    Forward(F),
+}
+
+enum MediaType {
+    Json,
+    Plain,
+    Html,
+}
+
+#[derive(Debug)]
+pub struct Status {
+    pub code: u16,
+}
+
+pub struct Body {
+    pub size: Option<usize>,
+    pub body: Vec<u8>,
+}
+
+impl ResponseBody for Body {
+    fn get_data(&self) -> Vec<u8> {
+        self.body.clone()
+    }
+}
+
+pub struct Response {
+    pub headers: HeaderMap,
+    pub status: Option<Status>,
+    pub body: Box<dyn ResponseBody>,
+}
+
+pub struct Data {
+    pub buffer: Vec<u8>,
+    pub is_complete: bool,
+}
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index b69bc0f..d3b106c 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -7,33 +7,27 @@ use std::{
     thread::available_parallelism,
 };
 
-use crate::{handlers::handle_connection, routing::Route, threading::ThreadPool};
+use crate::{handlers::handlers::handle_connection, routing::routes::Route, threading::ThreadPool};
 
-pub struct PreMountConfig {
-    address: TcpListener,
-    workers: usize,
-    threadpool: ThreadPool,
-}
-impl PreMountConfig {
-    pub fn mount(self, mountpoint: &str, routes: Vec<Route>) -> Config {
-        Config {
-            mountpoint,
-            address: self.address,
-            workers: self.workers,
-            threadpool: self.threadpool,
-            routes,
-        }
-    }
-}
 pub struct Config<'a> {
-    mountpoint: &'a str,
+    mountpoints: Option<Vec<&'static str>>,
     address: TcpListener,
-    workers: usize,
     threadpool: ThreadPool,
-    routes: Vec<Route>,
+    routes: Option<Vec<Route<'a>>>,
 }
 
-impl Config<'_> {
+impl<'a> Config<'a> {
+    pub fn mount(self, mountpoint: &'static str, routes: Vec<Route<'static>>) -> Config<'a> {
+        if self.mountpoints == None {
+            return Config {
+                mountpoints: Some(vec![mountpoint]),
+                routes: Some(routes),
+                ..self
+            };
+        } else {
+            return self;
+        }
+    }
     pub fn launch(self) {
         let running = Arc::new(AtomicBool::new(true));
 
@@ -54,11 +48,13 @@ impl Config<'_> {
                 break;
             }
             let stream = stream.unwrap();
-            self.threadpool.execute(|| handle_connection(stream))
+            let mountpoint = self.mountpoints.clone().unwrap();
+            self.threadpool
+                .execute(move || handle_connection(stream, &mountpoint[0].to_string()))
         }
     }
 }
-pub fn build(ip: &str) -> PreMountConfig {
+pub fn build(ip: &str) -> Config {
     let listener = TcpListener::bind(ip).unwrap();
     let ip = ip.splitn(2, ":").collect::<Vec<&str>>();
     if ip.len() != 2 {
@@ -77,9 +73,10 @@ pub fn build(ip: &str) -> PreMountConfig {
 Server has launched from {ip}:{port}.
 "
     );
-    PreMountConfig {
+    Config {
+        mountpoints: None,
+        routes: None,
         address: listener,
-        workers,
         threadpool,
     }
 }
diff --git a/site/hello.html b/site/hello.html
deleted file mode 100644
index 52ef689..0000000
--- a/site/hello.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta charset="utf-8" />
-    <title>Hello!</title>
-    <link rel="stylesheet" href="/hello.css" />
-  </head>
-  <body>
-    <h1>Hello!</h1>
-    <p>Hi from Rust</p>
-  </body>
-</html>
diff --git a/site/static/hello.html b/site/static/hello.html
new file mode 100644
index 0000000..1afeefd
--- /dev/null
+++ b/site/static/hello.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8" />
+    <title>JE</title>
+  </head>
+</html>
-- 
GitLab


From d611125a9b6f640701a17607ccc7dcd78859fe6f Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sat, 13 May 2023 20:23:45 +0200
Subject: [PATCH 06/65] Remove unnecessary println!s of file bytes

---
 core/http/src/handlers/file_handlers.rs | 6 +-----
 core/http/src/handlers/handlers.rs      | 3 ---
 2 files changed, 1 insertion(+), 8 deletions(-)

diff --git a/core/http/src/handlers/file_handlers.rs b/core/http/src/handlers/file_handlers.rs
index 708a046..879da03 100644
--- a/core/http/src/handlers/file_handlers.rs
+++ b/core/http/src/handlers/file_handlers.rs
@@ -22,15 +22,11 @@ impl NamedFile {
         let path = proove_path(path);
         let data = fs::read(&path);
         let data = match data {
-            Ok(dat) => {
-                println!("{:?}", dat);
-                dat
-            }
+            Ok(dat) => dat,
             Err(_) => {
                 return Err(Status { code: 404 });
             }
         };
-        println!("{:?}", data);
         Ok(NamedFile {
             content_len: data.len(),
             content_type: find_mimetype(path.to_str().unwrap()),
diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
index 33a6dbd..4f9073e 100644
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -56,7 +56,6 @@ pub fn handle_connection(mut stream: TcpStream, _mountpoint: &str) {
             fs::read("./404.html").unwrap(),
         ),
     };
-    println!("{:?}", handled_response);
 
     stream.write_all(handled_response.0.as_bytes()).unwrap();
     stream.write(&handled_response.1).unwrap();
@@ -79,7 +78,6 @@ fn parse_request<'a>(request: &'a str, mountpoint: &'a str) -> Result<PathBuf, &
 
 fn handler(request: Request, _data: Data) -> Outcome<Response, Status, Data> {
     let response = fileserver(request.uri);
-    println!("{:?}", response);
     let response = match response {
         Ok(dat) => Response {
             headers: vec![
@@ -95,6 +93,5 @@ fn handler(request: Request, _data: Data) -> Outcome<Response, Status, Data> {
 }
 
 fn fileserver(path: &str) -> Result<NamedFile, Status> {
-    println!("fileserver started");
     NamedFile::open(PathBuf::from("static/".to_string() + path))
 }
-- 
GitLab


From a6ffcabd22044eb87ce6f2c28ce7405967ab696a Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sun, 14 May 2023 13:25:15 +0200
Subject: [PATCH 07/65] Add addable routes

---
 core/http/src/handlers/handlers.rs | 112 ++++++++++++++---------------
 core/http/src/lib.rs               |   4 +-
 core/http/src/routing/methods.rs   |   2 +-
 core/http/src/routing/routes.rs    |  42 ++++++++---
 core/http/src/setup.rs             |  42 ++++++-----
 site/404.html                      |   6 +-
 site/src/main.rs                   |  43 ++++++++++-
 7 files changed, 163 insertions(+), 88 deletions(-)
 mode change 100644 => 100755 core/http/src/handlers/handlers.rs

diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
old mode 100644
new mode 100755
index 4f9073e..c3e06cf
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -1,16 +1,15 @@
 use std::{
-    fs,
     io::{BufRead, BufReader, Write},
     net::TcpStream,
     path::PathBuf,
 };
 
-use crate::routing::methods::Method;
 use crate::routing::routes::{Data, Outcome, Request, Response, Status};
+use crate::setup::MountPoint;
 
 use super::file_handlers::NamedFile;
 
-pub fn handle_connection(mut stream: TcpStream, _mountpoint: &str) {
+pub fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint>) {
     let buf_reader = BufReader::new(&mut stream);
     let http_request: Vec<String> = buf_reader
         .lines()
@@ -25,7 +24,12 @@ pub fn handle_connection(mut stream: TcpStream, _mountpoint: &str) {
     let request = Request {
         uri: &request_status_line.split(" ").nth(1).unwrap(),
         headers: http_request.clone(),
-        method: Method::Get,
+        method: request_status_line
+            .split(" ")
+            .next()
+            .unwrap()
+            .parse()
+            .unwrap(),
     };
 
     let data = Data {
@@ -33,65 +37,57 @@ pub fn handle_connection(mut stream: TcpStream, _mountpoint: &str) {
         is_complete: true,
     };
 
-    let handled_response = match handler(request, data) {
-        Outcome::Success(success) => (
-            format!("HTTP/1.1 {} OK\r\n", success.status.unwrap().code)
-                + &success.headers.join("\r\n")
-                + "\r\n\r\n",
-            success.body.get_data(),
-        ),
-        Outcome::Failure(error) => {
-            let content = fs::read("./404.html").unwrap();
-            (
-                format!(
-                    "HTTP/1.1 {} NOT FOUND\r\nContent-Length: {}\r\nContent-Type: text/html\r\n\r\n",
-                    error.code,
-                    content.len()
-                ),
-                content,
-            )
+    let mut handled_response: Option<Outcome<Response, Status, Data>> = None;
+    for mountpoint in mountpoints {
+        if !request.uri.starts_with(mountpoint.mountpoint) {
+            println!("MOUNTPOINT COMPARISON {}", request.uri);
+            continue;
+        }
+        let mounted_request_uri = request.uri.strip_prefix(mountpoint.mountpoint).unwrap();
+        for route in mountpoint.routes {
+            if route.method != request.method {
+                println!("METHOD COMPARE {}", request.method);
+                continue;
+            }
+            if !route.compare_uri(mounted_request_uri) {
+                println!("URI COMPARISON {} {}", mounted_request_uri, route.uri);
+                continue;
+            }
+            handled_response = Some((route.handler)(
+                Request {
+                    uri: mounted_request_uri,
+                    ..request.clone()
+                },
+                data.clone(),
+            ));
         }
-        Outcome::Forward(_) => (
-            format!("HTTP/1.1 {} NOT FOUND", 404),
-            fs::read("./404.html").unwrap(),
-        ),
-    };
-
-    stream.write_all(handled_response.0.as_bytes()).unwrap();
-    stream.write(&handled_response.1).unwrap();
-}
-
-fn parse_request<'a>(request: &'a str, mountpoint: &'a str) -> Result<PathBuf, &'a str> {
-    let uri = request.split(" ").nth(1).unwrap();
-    if !uri.starts_with(mountpoint) {
-        return Err("Request isn't on mountpoint");
     }
-    let path_elements = uri
-        .split_once(mountpoint)
-        .map(|(_, rest)| rest)
-        .unwrap()
-        .split("/")
-        .filter(|&val| val != ".." && val != "")
-        .collect::<Vec<&str>>();
-    Ok(PathBuf::from(format!("./{}", path_elements.join("/"))))
-}
 
-fn handler(request: Request, _data: Data) -> Outcome<Response, Status, Data> {
-    let response = fileserver(request.uri);
-    let response = match response {
-        Ok(dat) => Response {
-            headers: vec![
-                format!("Content-Length: {}", dat.content_len),
-                format!("Content-Type: {}", dat.content_type),
-            ],
-            status: Some(Status { code: 200 }),
-            body: Box::new(dat),
+    let response = match handled_response {
+        Some(val) => match val {
+            Outcome::Success(success) => (
+                format!("HTTP/1.1 {} OK\r\n", success.status.unwrap().code)
+                    + &success.headers.join("\r\n")
+                    + "\r\n\r\n",
+                success.body.get_data(),
+            ),
+            Outcome::Failure(error) => handler_404(error),
+            Outcome::Forward(_) => handler_404(Status { code: 404 }),
         },
-        Err(_) => return Outcome::Failure(Status { code: 404 }),
+        None => handler_404(Status { code: 404 }),
     };
-    Outcome::Success(response)
+
+    stream.write_all(response.0.as_bytes()).unwrap();
+    stream.write(&response.1).unwrap();
 }
 
-fn fileserver(path: &str) -> Result<NamedFile, Status> {
-    NamedFile::open(PathBuf::from("static/".to_string() + path))
+fn handler_404(status: Status) -> (String, Vec<u8>) {
+    let page_404 = NamedFile::open(PathBuf::from("404.html")).unwrap();
+    (
+        format!(
+            "HTTP/1.1 {} NOT FOUND\r\nContent-Length: {}\r\nContent-Type: {}\r\n\r\n",
+            status.code, page_404.content_len, page_404.content_type
+        ),
+        page_404.content,
+    )
 }
diff --git a/core/http/src/lib.rs b/core/http/src/lib.rs
index 0b86db5..bf072c9 100644
--- a/core/http/src/lib.rs
+++ b/core/http/src/lib.rs
@@ -1,5 +1,5 @@
-mod handlers;
-mod routing;
+pub mod handlers;
+pub mod routing;
 mod setup;
 mod threading;
 
diff --git a/core/http/src/routing/methods.rs b/core/http/src/routing/methods.rs
index 328e697..998cfa5 100644
--- a/core/http/src/routing/methods.rs
+++ b/core/http/src/routing/methods.rs
@@ -1,6 +1,6 @@
 use std::{fmt::Display, str::FromStr};
 
-#[derive(PartialEq, Eq)]
+#[derive(PartialEq, Eq, Clone, Debug, Copy)]
 pub enum Method {
     Get,
     Head,
diff --git a/core/http/src/routing/routes.rs b/core/http/src/routing/routes.rs
index 05ecf74..6da1218 100644
--- a/core/http/src/routing/routes.rs
+++ b/core/http/src/routing/routes.rs
@@ -15,13 +15,14 @@ pub struct RoutInfo {
     rank: Option<isize>,
 }
 
+#[derive(Clone, Copy)]
 pub struct Route<'a> {
-    name: Option<&'static str>,
-    method: Method,
-    uri: Uri<'a>,
-    handler: fn(Request, Data) -> Outcome<Response, Status, Data>,
-    rank: isize,
-    format: Option<MediaType>,
+    pub name: Option<&'static str>,
+    pub method: Method,
+    pub uri: Uri<'a>,
+    pub handler: fn(Request, Data) -> Outcome<Response, Status, Data>,
+    pub rank: isize,
+    pub format: Option<MediaType>,
 }
 
 impl Route<'_> {
@@ -36,8 +37,29 @@ impl Route<'_> {
             format: routeinfo.format,
         }
     }
+    pub fn compare_uri(self, uri: Uri) -> bool {
+        let mut iter_comp_str = uri.split("/");
+        for true_str in self.uri.split("/") {
+            let comp_str = if let Some(str) = iter_comp_str.next() {
+                str
+            } else {
+                return false;
+            };
+            if true_str.starts_with("<") && true_str.ends_with("..>") {
+                return true;
+            }
+            if true_str.starts_with("<") && true_str.ends_with(">") {
+                continue;
+            }
+            if true_str != comp_str {
+                return false;
+            }
+        }
+        return true;
+    }
 }
 
+#[derive(Clone)]
 pub struct Request<'a> {
     pub uri: Uri<'a>,
     pub headers: HeaderMap,
@@ -51,15 +73,17 @@ struct ConnectionMeta {
 }
 
 type HeaderMap = Vec<String>;
-type Uri<'a> = &'a str;
+pub type Uri<'a> = &'a str;
 
+#[derive(Debug)]
 pub enum Outcome<S, E, F> {
     Success(S),
     Failure(E),
     Forward(F),
 }
 
-enum MediaType {
+#[derive(Clone, Debug, Copy)]
+pub enum MediaType {
     Json,
     Plain,
     Html,
@@ -70,6 +94,7 @@ pub struct Status {
     pub code: u16,
 }
 
+#[derive(Debug)]
 pub struct Body {
     pub size: Option<usize>,
     pub body: Vec<u8>,
@@ -87,6 +112,7 @@ pub struct Response {
     pub body: Box<dyn ResponseBody>,
 }
 
+#[derive(Debug, Clone)]
 pub struct Data {
     pub buffer: Vec<u8>,
     pub is_complete: bool,
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index d3b106c..35c8a06 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -7,26 +7,36 @@ use std::{
     thread::available_parallelism,
 };
 
-use crate::{handlers::handlers::handle_connection, routing::routes::Route, threading::ThreadPool};
+use crate::{
+    handlers::handlers::handle_connection,
+    routing::routes::{Route, Uri},
+    threading::ThreadPool,
+};
+
+#[derive(Clone)]
+pub struct MountPoint<'a> {
+    pub mountpoint: Uri<'a>,
+    pub routes: Vec<Route<'a>>,
+}
 
-pub struct Config<'a> {
-    mountpoints: Option<Vec<&'static str>>,
+pub struct Config {
+    mountpoints: Option<Vec<MountPoint<'static>>>,
     address: TcpListener,
     threadpool: ThreadPool,
-    routes: Option<Vec<Route<'a>>>,
 }
 
-impl<'a> Config<'a> {
-    pub fn mount(self, mountpoint: &'static str, routes: Vec<Route<'static>>) -> Config<'a> {
-        if self.mountpoints == None {
-            return Config {
-                mountpoints: Some(vec![mountpoint]),
-                routes: Some(routes),
-                ..self
-            };
+impl<'a> Config {
+    pub fn mount(mut self, mountpoint: Uri<'static>, routes: Vec<Route<'static>>) -> Config {
+        let mut temp_mountpoints = None;
+        std::mem::swap(&mut self.mountpoints, &mut temp_mountpoints);
+
+        if let Some(mut mountpoints) = temp_mountpoints {
+            mountpoints.push(MountPoint { mountpoint, routes });
+            self.mountpoints = Some(mountpoints);
         } else {
-            return self;
+            self.mountpoints = Some(vec![MountPoint { mountpoint, routes }]);
         }
+        self
     }
     pub fn launch(self) {
         let running = Arc::new(AtomicBool::new(true));
@@ -42,15 +52,14 @@ impl<'a> Config<'a> {
             running_for_handler.store(false, atomic::Ordering::SeqCst);
         })
         .expect("Error setting Ctrl-C handler");
-
         for stream in self.address.incoming() {
             if !running.load(atomic::Ordering::SeqCst) {
                 break;
             }
             let stream = stream.unwrap();
-            let mountpoint = self.mountpoints.clone().unwrap();
+            let mountpoints = self.mountpoints.clone().unwrap();
             self.threadpool
-                .execute(move || handle_connection(stream, &mountpoint[0].to_string()))
+                .execute(move || handle_connection(stream, mountpoints));
         }
     }
 }
@@ -75,7 +84,6 @@ Server has launched from {ip}:{port}.
     );
     Config {
         mountpoints: None,
-        routes: None,
         address: listener,
         threadpool,
     }
diff --git a/site/404.html b/site/404.html
index 3a6ceb5..550831f 100644
--- a/site/404.html
+++ b/site/404.html
@@ -3,10 +3,14 @@
   <head>
     <meta charset="utf-8" />
     <title>404</title>
-    <link rel="stylesheet" href="/hello.css" />
   </head>
   <body>
     <h1>404</h1>
     <p>Hi from Rust</p>
+    <form action="/" method="POST">
+      <label for="message">Enter your message:</label>
+      <input type="text" id="message" name="message" />
+      <button type="submit">Send</button>
+    </form>
   </body>
 </html>
diff --git a/site/src/main.rs b/site/src/main.rs
index 55ea439..8974db9 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -1,3 +1,44 @@
+use std::path::PathBuf;
+
+use http::{
+    handlers::file_handlers::NamedFile,
+    routing::routes::{Data, Outcome, Request, Response, Route, Status},
+};
+
+fn handler(request: Request, _data: Data) -> Outcome<Response, Status, Data> {
+    println!("called");
+    let response = fileserver(request.uri.strip_prefix("static/").unwrap());
+    let response = match response {
+        Ok(dat) => Response {
+            headers: vec![
+                format!("Content-Length: {}", dat.content_len),
+                format!("Content-Type: {}", dat.content_type),
+            ],
+            status: Some(Status { code: 200 }),
+            body: Box::new(dat),
+        },
+        Err(_) => return Outcome::Failure(Status { code: 404 }),
+    };
+    println!("{:?}", response.headers);
+    Outcome::Success(response)
+}
+
+fn fileserver(path: &str) -> Result<NamedFile, Status> {
+    let file = NamedFile::open(PathBuf::from("static/".to_string() + path));
+    return file;
+}
+
 fn main() {
-    http::build("127.0.0.1:8000").mount("/", vec![]).launch();
+    let fileserver = Route {
+        format: None,
+        handler,
+        name: Some("file_server"),
+        uri: "static/<path..>",
+        method: http::routing::methods::Method::Get,
+        rank: 0,
+    };
+
+    http::build("127.0.0.1:8000")
+        .mount("/", vec![fileserver])
+        .launch();
 }
-- 
GitLab


From 19c473eaac70e0ceefd0cd3eeab71db8bb2e22f1 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Mon, 15 May 2023 21:11:33 +0200
Subject: [PATCH 08/65] Refactoring a lot of stuff

---
 core/http/src/handlers/handlers.rs            |  26 ++++---
 core/http/src/handlers/mod.rs                 |   1 -
 .../{handlers => handling}/file_handlers.rs   |  10 ++-
 .../http/src/{routing => handling}/methods.rs |   0
 core/http/src/handling/mod.rs                 |   5 ++
 core/http/src/handling/request.rs             |  24 ++++++
 core/http/src/handling/response.rs            |  70 ++++++++++++++++++
 core/http/src/{routing => handling}/routes.rs |  62 ++--------------
 core/http/src/lib.rs                          |   2 +-
 core/http/src/routing/mod.rs                  |   2 -
 core/http/src/setup.rs                        |   2 +-
 site/404.html                                 |   3 +
 site/src/main.rs                              |  20 ++---
 site/static/hello.css                         |   4 +
 site/static/hello.html                        |   7 +-
 site/static/img.jpg                           | Bin 0 -> 51549 bytes
 tree.txt                                      |  44 +++++++++++
 17 files changed, 198 insertions(+), 84 deletions(-)
 rename core/http/src/{handlers => handling}/file_handlers.rs (87%)
 rename core/http/src/{routing => handling}/methods.rs (100%)
 create mode 100644 core/http/src/handling/mod.rs
 create mode 100644 core/http/src/handling/request.rs
 create mode 100644 core/http/src/handling/response.rs
 rename core/http/src/{routing => handling}/routes.rs (63%)
 delete mode 100644 core/http/src/routing/mod.rs
 create mode 100644 site/static/hello.css
 create mode 100644 site/static/img.jpg
 create mode 100644 tree.txt

diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
index c3e06cf..2045ee5 100755
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -4,11 +4,14 @@ use std::{
     path::PathBuf,
 };
 
-use crate::routing::routes::{Data, Outcome, Request, Response, Status};
+use crate::handling::{
+    file_handlers::NamedFile,
+    request::Request,
+    response::{Outcome, Response, ResponseBody, Status},
+    routes::Data,
+};
 use crate::setup::MountPoint;
 
-use super::file_handlers::NamedFile;
-
 pub fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint>) {
     let buf_reader = BufReader::new(&mut stream);
     let http_request: Vec<String> = buf_reader
@@ -40,17 +43,14 @@ pub fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint>) {
     let mut handled_response: Option<Outcome<Response, Status, Data>> = None;
     for mountpoint in mountpoints {
         if !request.uri.starts_with(mountpoint.mountpoint) {
-            println!("MOUNTPOINT COMPARISON {}", request.uri);
             continue;
         }
         let mounted_request_uri = request.uri.strip_prefix(mountpoint.mountpoint).unwrap();
         for route in mountpoint.routes {
             if route.method != request.method {
-                println!("METHOD COMPARE {}", request.method);
                 continue;
             }
             if !route.compare_uri(mounted_request_uri) {
-                println!("URI COMPARISON {} {}", mounted_request_uri, route.uri);
                 continue;
             }
             handled_response = Some((route.handler)(
@@ -71,23 +71,25 @@ pub fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint>) {
                     + "\r\n\r\n",
                 success.body.get_data(),
             ),
-            Outcome::Failure(error) => handler_404(error),
-            Outcome::Forward(_) => handler_404(Status { code: 404 }),
+            Outcome::Failure(error) => failure_handler(error),
+            Outcome::Forward(_) => failure_handler(Status { code: 404 }),
         },
-        None => handler_404(Status { code: 404 }),
+        None => failure_handler(Status { code: 404 }),
     };
 
     stream.write_all(response.0.as_bytes()).unwrap();
     stream.write(&response.1).unwrap();
 }
 
-fn handler_404(status: Status) -> (String, Vec<u8>) {
+fn failure_handler(status: Status) -> (String, Vec<u8>) {
     let page_404 = NamedFile::open(PathBuf::from("404.html")).unwrap();
     (
         format!(
             "HTTP/1.1 {} NOT FOUND\r\nContent-Length: {}\r\nContent-Type: {}\r\n\r\n",
-            status.code, page_404.content_len, page_404.content_type
+            status.code,
+            page_404.get_len(),
+            page_404.get_mime()
         ),
-        page_404.content,
+        page_404.get_data(),
     )
 }
diff --git a/core/http/src/handlers/mod.rs b/core/http/src/handlers/mod.rs
index 826c4f4..c3d4495 100644
--- a/core/http/src/handlers/mod.rs
+++ b/core/http/src/handlers/mod.rs
@@ -1,2 +1 @@
-pub mod file_handlers;
 pub mod handlers;
diff --git a/core/http/src/handlers/file_handlers.rs b/core/http/src/handling/file_handlers.rs
similarity index 87%
rename from core/http/src/handlers/file_handlers.rs
rename to core/http/src/handling/file_handlers.rs
index 879da03..fdfd3d0 100644
--- a/core/http/src/handlers/file_handlers.rs
+++ b/core/http/src/handling/file_handlers.rs
@@ -2,7 +2,7 @@ use std::{fs, path::PathBuf};
 
 use mime::Mime;
 
-use crate::routing::routes::{ResponseBody, Status};
+use crate::handling::response::{ResponseBody, Status};
 
 #[derive(Debug)]
 pub struct NamedFile {
@@ -15,6 +15,14 @@ impl ResponseBody for NamedFile {
     fn get_data(&self) -> Vec<u8> {
         self.content.clone()
     }
+
+    fn get_mime(&self) -> Mime {
+        self.content_type.clone()
+    }
+
+    fn get_len(&self) -> usize {
+        self.content_len
+    }
 }
 
 impl NamedFile {
diff --git a/core/http/src/routing/methods.rs b/core/http/src/handling/methods.rs
similarity index 100%
rename from core/http/src/routing/methods.rs
rename to core/http/src/handling/methods.rs
diff --git a/core/http/src/handling/mod.rs b/core/http/src/handling/mod.rs
new file mode 100644
index 0000000..20cf31e
--- /dev/null
+++ b/core/http/src/handling/mod.rs
@@ -0,0 +1,5 @@
+pub mod file_handlers;
+pub mod methods;
+pub mod request;
+pub mod response;
+pub mod routes;
diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
new file mode 100644
index 0000000..d37ebb5
--- /dev/null
+++ b/core/http/src/handling/request.rs
@@ -0,0 +1,24 @@
+use std::net::SocketAddr;
+
+use super::{methods::Method, routes::Uri};
+
+type HeaderMap = Vec<String>;
+#[derive(Clone)]
+pub struct Request<'a> {
+    pub uri: Uri<'a>,
+    pub headers: HeaderMap,
+    pub method: Method,
+    // pub connection: ConnectionMeta,
+}
+
+struct ConnectionMeta {
+    remote: Option<SocketAddr>,
+    // certificates
+}
+
+#[derive(Clone, Debug, Copy)]
+pub enum MediaType {
+    Json,
+    Plain,
+    Html,
+}
diff --git a/core/http/src/handling/response.rs b/core/http/src/handling/response.rs
new file mode 100644
index 0000000..9ca6f4b
--- /dev/null
+++ b/core/http/src/handling/response.rs
@@ -0,0 +1,70 @@
+use mime::Mime;
+
+use super::routes::Body;
+
+type HeaderMap = Vec<String>;
+
+#[derive(Debug)]
+pub enum Outcome<S, E, F> {
+    Success(S),
+    Failure(E),
+    Forward(F),
+}
+
+pub trait ResponseBody {
+    fn get_data(&self) -> Vec<u8>;
+    fn get_mime(&self) -> Mime;
+    fn get_len(&self) -> usize;
+}
+
+impl ResponseBody for Body {
+    fn get_data(&self) -> Vec<u8> {
+        self.body.clone()
+    }
+    fn get_mime(&self) -> Mime {
+        mime::TEXT_PLAIN
+    }
+
+    fn get_len(&self) -> usize {
+        self.get_data().len()
+    }
+}
+
+impl ResponseBody for &str {
+    fn get_data(&self) -> Vec<u8> {
+        self.as_bytes().to_vec()
+    }
+
+    fn get_mime(&self) -> Mime {
+        mime::TEXT_PLAIN
+    }
+
+    fn get_len(&self) -> usize {
+        self.len()
+    }
+}
+
+impl ResponseBody for String {
+    fn get_data(&self) -> Vec<u8> {
+        self.as_bytes().to_vec()
+    }
+
+    fn get_mime(&self) -> Mime {
+        mime::TEXT_PLAIN
+    }
+
+    fn get_len(&self) -> usize {
+        self.len()
+    }
+}
+
+pub struct Response {
+    pub headers: HeaderMap,
+    pub status: Option<Status>,
+    pub body: Box<dyn ResponseBody>,
+}
+
+#[derive(Debug)]
+pub struct Status {
+    pub code: u16,
+}
diff --git a/core/http/src/routing/routes.rs b/core/http/src/handling/routes.rs
similarity index 63%
rename from core/http/src/routing/routes.rs
rename to core/http/src/handling/routes.rs
index 6da1218..fd3512d 100644
--- a/core/http/src/routing/routes.rs
+++ b/core/http/src/handling/routes.rs
@@ -1,10 +1,8 @@
-use std::net::SocketAddr;
-
-use super::methods::Method;
-
-pub trait ResponseBody {
-    fn get_data(&self) -> Vec<u8>;
-}
+use super::{
+    methods::Method,
+    request::{MediaType, Request},
+    response::{Outcome, Response, Status},
+};
 
 pub struct RoutInfo {
     name: Option<&'static str>,
@@ -55,63 +53,17 @@ impl Route<'_> {
                 return false;
             }
         }
-        return true;
+        true
     }
 }
 
-#[derive(Clone)]
-pub struct Request<'a> {
-    pub uri: Uri<'a>,
-    pub headers: HeaderMap,
-    pub method: Method,
-    // pub connection: ConnectionMeta,
-}
-
-struct ConnectionMeta {
-    remote: Option<SocketAddr>,
-    // certificates
-}
-
-type HeaderMap = Vec<String>;
 pub type Uri<'a> = &'a str;
 
-#[derive(Debug)]
-pub enum Outcome<S, E, F> {
-    Success(S),
-    Failure(E),
-    Forward(F),
-}
-
-#[derive(Clone, Debug, Copy)]
-pub enum MediaType {
-    Json,
-    Plain,
-    Html,
-}
-
-#[derive(Debug)]
-pub struct Status {
-    pub code: u16,
-}
-
-#[derive(Debug)]
+#[derive(Debug, Clone)]
 pub struct Body {
-    pub size: Option<usize>,
     pub body: Vec<u8>,
 }
 
-impl ResponseBody for Body {
-    fn get_data(&self) -> Vec<u8> {
-        self.body.clone()
-    }
-}
-
-pub struct Response {
-    pub headers: HeaderMap,
-    pub status: Option<Status>,
-    pub body: Box<dyn ResponseBody>,
-}
-
 #[derive(Debug, Clone)]
 pub struct Data {
     pub buffer: Vec<u8>,
diff --git a/core/http/src/lib.rs b/core/http/src/lib.rs
index bf072c9..7a1379c 100644
--- a/core/http/src/lib.rs
+++ b/core/http/src/lib.rs
@@ -1,5 +1,5 @@
 pub mod handlers;
-pub mod routing;
+pub mod handling;
 mod setup;
 mod threading;
 
diff --git a/core/http/src/routing/mod.rs b/core/http/src/routing/mod.rs
deleted file mode 100644
index f1e52f9..0000000
--- a/core/http/src/routing/mod.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-pub mod methods;
-pub mod routes;
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index 35c8a06..e2ba232 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -9,7 +9,7 @@ use std::{
 
 use crate::{
     handlers::handlers::handle_connection,
-    routing::routes::{Route, Uri},
+    handling::routes::{Route, Uri},
     threading::ThreadPool,
 };
 
diff --git a/site/404.html b/site/404.html
index 550831f..d4c09f4 100644
--- a/site/404.html
+++ b/site/404.html
@@ -11,6 +11,9 @@
       <label for="message">Enter your message:</label>
       <input type="text" id="message" name="message" />
       <button type="submit">Send</button>
+      <label for="message">Enter your message:</label>
+      <input type="text" id="asdf" name="message" />
+      <button type="submit">Send</button>
     </form>
   </body>
 </html>
diff --git a/site/src/main.rs b/site/src/main.rs
index 8974db9..da51a33 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -1,31 +1,31 @@
 use std::path::PathBuf;
 
-use http::{
-    handlers::file_handlers::NamedFile,
-    routing::routes::{Data, Outcome, Request, Response, Route, Status},
+use http::handling::{
+    file_handlers::NamedFile,
+    methods::Method,
+    request::Request,
+    response::{Outcome, Response, ResponseBody, Status},
+    routes::{Data, Route},
 };
 
 fn handler(request: Request, _data: Data) -> Outcome<Response, Status, Data> {
-    println!("called");
     let response = fileserver(request.uri.strip_prefix("static/").unwrap());
     let response = match response {
         Ok(dat) => Response {
             headers: vec![
-                format!("Content-Length: {}", dat.content_len),
-                format!("Content-Type: {}", dat.content_type),
+                format!("Content-Length: {}", dat.get_len()),
+                format!("Content-Type: {}", dat.get_mime()),
             ],
             status: Some(Status { code: 200 }),
             body: Box::new(dat),
         },
         Err(_) => return Outcome::Failure(Status { code: 404 }),
     };
-    println!("{:?}", response.headers);
     Outcome::Success(response)
 }
 
 fn fileserver(path: &str) -> Result<NamedFile, Status> {
-    let file = NamedFile::open(PathBuf::from("static/".to_string() + path));
-    return file;
+    NamedFile::open(PathBuf::from("static/".to_string() + path))
 }
 
 fn main() {
@@ -34,7 +34,7 @@ fn main() {
         handler,
         name: Some("file_server"),
         uri: "static/<path..>",
-        method: http::routing::methods::Method::Get,
+        method: Method::Get,
         rank: 0,
     };
 
diff --git a/site/static/hello.css b/site/static/hello.css
new file mode 100644
index 0000000..aba0df0
--- /dev/null
+++ b/site/static/hello.css
@@ -0,0 +1,4 @@
+body {
+  background-color: #212121;
+  color: #ffffff;
+}
diff --git a/site/static/hello.html b/site/static/hello.html
index 1afeefd..ff042af 100644
--- a/site/static/hello.html
+++ b/site/static/hello.html
@@ -2,6 +2,11 @@
 <html>
   <head>
     <meta charset="UTF-8" />
-    <title>JE</title>
+    <title>Hello</title>
+    <link rel="stylesheet" href="/static/hello.css" />
   </head>
+  <body>
+    <h1>Managed</h1>
+    <img src="/static/img.jpg" alt="" />
+  </body>
 </html>
diff --git a/site/static/img.jpg b/site/static/img.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..07eb7f85ac26c70344d552f56a81c44a0bf1b3db
GIT binary patch
literal 51549
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
B#&7@t

literal 0
HcmV?d00001

diff --git a/tree.txt b/tree.txt
new file mode 100644
index 0000000..05d432b
--- /dev/null
+++ b/tree.txt
@@ -0,0 +1,44 @@
+.
+├── core
+│   ├── codegen
+│   │   ├── Cargo.lock
+│   │   ├── Cargo.toml
+│   │   ├── src
+│   │   │   └── lib.rs
+│   ├── html
+│   │   ├── Cargo.lock
+│   │   ├── Cargo.toml
+│   │   └── src
+│   │       └── lib.rs
+│   └── http
+│       ├── Cargo.lock
+│       ├── Cargo.toml
+│       └── src
+│           ├── handlers
+│           │   ├── file_handlers.rs
+│           │   ├── handlers.rs
+│           │   └── mod.rs
+│           ├── lib.rs
+│           ├── routing
+│           │   ├── methods.rs
+│           │   ├── mod.rs
+│           │   └── routes.rs
+│           ├── setup.rs
+│           ├── threading.rs
+│           └── utils
+│               └── mod.rs
+├── README.md
+├── site
+│   ├── 404.html
+│   ├── Cargo.lock
+│   ├── Cargo.toml
+│   ├── hello.css
+│   ├── img.jpg
+│   ├── src
+│   │   └── main.rs
+│   ├── static
+│   │   └── hello.html
+│   └── target
+│       └── CACHEDIR.TAG
+└── tree.txt
+
-- 
GitLab


From 3eca9706cc21fb46fccfbaeaacef9bf83cf4da5f Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Thu, 18 May 2023 18:53:05 +0200
Subject: [PATCH 09/65] Adding route and mountpoint listing

---
 core/http/src/setup.rs | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index e2ba232..4bacada 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -27,6 +27,24 @@ pub struct Config {
 
 impl<'a> Config {
     pub fn mount(mut self, mountpoint: Uri<'static>, routes: Vec<Route<'static>>) -> Config {
+        let mut mount_message = format!("  >> \x1b[35m{}\x1b[0m\n", mountpoint);
+        for (index, route) in routes.iter().enumerate() {
+            let indent_sign;
+            match index {
+                i if i == routes.len() - 1 => indent_sign = "└─",
+                _ => indent_sign = "├─",
+            };
+
+            mount_message += &format!(
+            "     \x1b[35m{indent_sign}\x1b[0m \x1b[36m(\x1b[0m{}\x1b[36m)\x1b[0m \x1b[32m{}\x1b[0m \x1b[34;4m{}\x1b[24m{}\x1b[0m\n",
+                route.name.unwrap_or(""),
+                route.method,
+                mountpoint,
+                route.uri
+            )
+        }
+
+        println!("{mount_message}");
         let mut temp_mountpoints = None;
         std::mem::swap(&mut self.mountpoints, &mut temp_mountpoints);
 
@@ -78,9 +96,7 @@ pub fn build(ip: &str) -> Config {
   >> \x1b[34mIp\x1b[0m: {ip}
   >> \x1b[34mPort\x1b[0m: {port}
   >> \x1b[34mWorkers\x1b[0m: {workers}
-\n
-Server has launched from {ip}:{port}.
-"
+\x1b[35m🛪 Mountpoints\x1b[0m"
     );
     Config {
         mountpoints: None,
-- 
GitLab


From e40abea488d4a597f9567206b1aea542acd54b40 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Fri, 19 May 2023 13:59:18 +0200
Subject: [PATCH 10/65] Reading in body of requests with body

---
 core/http/src/handlers/handlers.rs | 55 +++++++++++++++++++++++++-----
 core/http/src/handling/request.rs  |  9 +++++
 2 files changed, 55 insertions(+), 9 deletions(-)

diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
index 2045ee5..c0e77e3 100755
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -1,5 +1,5 @@
 use std::{
-    io::{BufRead, BufReader, Write},
+    io::{BufRead, BufReader, Read, Write},
     net::TcpStream,
     path::PathBuf,
 };
@@ -13,12 +13,20 @@ use crate::handling::{
 use crate::setup::MountPoint;
 
 pub fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint>) {
-    let buf_reader = BufReader::new(&mut stream);
-    let http_request: Vec<String> = buf_reader
-        .lines()
-        .map(|result| result.unwrap())
-        .take_while(|line| !line.is_empty())
-        .collect();
+    let mut buf_reader = BufReader::new(&mut stream);
+    let mut http_request: Vec<String> = vec![];
+
+    loop {
+        let mut buffer = String::new();
+        let _ = buf_reader.read_line(&mut buffer).unwrap();
+        if buffer == "\r\n" {
+            break;
+        }
+        http_request.push(buffer);
+    }
+
+    println!("{:#?}", http_request);
+
     let request_status_line = http_request.get(0);
     if request_status_line == None {
         return;
@@ -35,10 +43,39 @@ pub fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint>) {
             .unwrap(),
     };
 
-    let data = Data {
+    let mut data = Data {
+        is_complete: false,
         buffer: vec![],
-        is_complete: true,
     };
+    if request.can_have_body() {
+        let length = if let Some(len) = request
+            .headers
+            .iter()
+            .filter(|header| header.contains("Content-Length: "))
+            .clone()
+            .map(|header| {
+                let header = header.strip_prefix("Content-Length: ").unwrap();
+                header.trim().parse::<usize>()
+            })
+            .next()
+        {
+            if let Ok(size) = len {
+                size
+            } else {
+                0
+            }
+        } else {
+            0
+        };
+        let mut buffer: Vec<u8> = vec![0; length];
+        let read_len = buf_reader.read(&mut buffer).unwrap();
+        if read_len != length {
+            eprintln!("User inputted invalid BUFLEN");
+            return;
+        }
+        data.is_complete = true;
+        data.buffer = buffer;
+    }
 
     let mut handled_response: Option<Outcome<Response, Status, Data>> = None;
     for mountpoint in mountpoints {
diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index d37ebb5..ba1cf37 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -22,3 +22,12 @@ pub enum MediaType {
     Plain,
     Html,
 }
+
+impl Request<'_> {
+    pub fn can_have_body(&self) -> bool {
+        match self.method {
+            Method::Post | Method::Put | Method::Patch | Method::Delete => true,
+            _ => false,
+        }
+    }
+}
-- 
GitLab


From 8d669447dffb1e635e6e256036a0c3f19103bdc6 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Fri, 19 May 2023 14:55:14 +0200
Subject: [PATCH 11/65] Implement Display for HTTP Status Codes

---
 core/http/src/handlers/handlers.rs | 16 ++++-
 core/http/src/handling/response.rs | 97 ++++++++++++++++++++++++++++++
 site/411.html                      |  9 +++
 3 files changed, 121 insertions(+), 1 deletion(-)
 create mode 100644 site/411.html

diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
index c0e77e3..b34416b 100755
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -70,7 +70,9 @@ pub fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint>) {
         let mut buffer: Vec<u8> = vec![0; length];
         let read_len = buf_reader.read(&mut buffer).unwrap();
         if read_len != length {
-            eprintln!("User inputted invalid BUFLEN");
+            let respone = len_not_defined(Status { code: 411 });
+            stream.write_all(respone.0.as_bytes()).unwrap();
+            stream.write(&respone.1).unwrap();
             return;
         }
         data.is_complete = true;
@@ -130,3 +132,15 @@ fn failure_handler(status: Status) -> (String, Vec<u8>) {
         page_404.get_data(),
     )
 }
+
+fn len_not_defined(status: Status) -> (String, Vec<u8>) {
+    let page_411 = NamedFile::open(PathBuf::from("411.html")).unwrap();
+    (
+        format!(
+            "HTTP/1.1 {status}\r\nContent-Length: {}\r\nContent-Type: {}\r\n\r\n",
+            page_411.get_len(),
+            page_411.get_mime()
+        ),
+        page_411.get_data(),
+    )
+}
diff --git a/core/http/src/handling/response.rs b/core/http/src/handling/response.rs
index 9ca6f4b..603ca55 100644
--- a/core/http/src/handling/response.rs
+++ b/core/http/src/handling/response.rs
@@ -1,3 +1,5 @@
+use std::fmt::Display;
+
 use mime::Mime;
 
 use super::routes::Body;
@@ -68,3 +70,98 @@ pub struct Response {
 pub struct Status {
     pub code: u16,
 }
+
+impl Display for Status {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self.code {
+            // INFORMATIONAL RESPONSE
+            100 => write!(f, "{} Continue", self.code),
+            101 => write!(f, "{} Switching Protocols", self.code),
+
+            // WebDAV
+            102 => write!(f, "{} Processing", self.code),
+
+            // Experimental
+            103 => write!(f, "{} Early Hints", self.code),
+
+            // SUCCESSFUL RESPONSE
+            200 => write!(f, "{} OK", self.code),
+            201 => write!(f, "{} Created", self.code),
+            203 => write!(f, "{} Non-Authorative Information", self.code),
+            204 => write!(f, "{} No Content", self.code),
+            205 => write!(f, "{} Reset Content", self.code),
+            206 => write!(f, "{} Partial Content", self.code),
+
+            // WebDAV
+            207 => write!(f, "{} Mutli-Status", self.code),
+            208 => write!(f, "{} Already Reported", self.code),
+
+            // HTTP Delta Encoding
+            226 => write!(f, "{} IM Used", self.code),
+
+            // REDIRECTION MESSAGES
+            300 => write!(f, "{} Multiple Choices", self.code),
+            301 => write!(f, "{} Moved Permanently", self.code),
+            302 => write!(f, "{} Found", self.code),
+            303 => write!(f, "{} See Other", self.code),
+            304 => write!(f, "{} Not Modified", self.code),
+            307 => write!(f, "{} Temporary Redirect", self.code),
+            308 => write!(f, "{} Permanent Redirect", self.code),
+
+            // Unused / Deprecated
+            305 => write!(f, "{} Use Proxy", self.code),
+            306 => write!(f, "{} unused", self.code),
+
+            // CLIENT ERROR
+            400 => write!(f, "{} Bad Request", self.code),
+            401 => write!(f, "{} Unauthorized", self.code),
+            403 => write!(f, "{} Forbidden", self.code),
+            404 => write!(f, "{} Not Found", self.code),
+            405 => write!(f, "{} Method Not Allowed", self.code),
+            406 => write!(f, "{} Not Acceptable", self.code),
+            407 => write!(f, "{} Proxy Athentication Required", self.code),
+            408 => write!(f, "{} Request Timout", self.code),
+            409 => write!(f, "{} Conflict", self.code),
+            410 => write!(f, "{} Gone", self.code),
+            411 => write!(f, "{} Length Required", self.code),
+            412 => write!(f, "{} Precondition Failed", self.code),
+            413 => write!(f, "{} Payload Too Large", self.code),
+            414 => write!(f, "{} URI Too Long", self.code),
+            415 => write!(f, "{} Unsupported Media Type", self.code),
+            416 => write!(f, "{} Range Not Satisfiable", self.code),
+            417 => write!(f, "{} Expectation Failed", self.code),
+            418 => write!(f, "{} I'm a Teapot", self.code),
+            421 => write!(f, "{} Misdirected Request", self.code),
+            422 => write!(f, "{} Unprocessable Content", self.code),
+            426 => write!(f, "{} Upgrade Required", self.code),
+            428 => write!(f, "{} Precondition Required", self.code),
+            429 => write!(f, "{} Too Many Requests", self.code),
+            431 => write!(f, "{} Request Header Fields Too Large", self.code),
+
+            451 => write!(f, "{} Unavailable For Legal Reasons", self.code),
+
+            // WebDAV
+            423 => write!(f, "{} Locked", self.code),
+            424 => write!(f, "{} Failed Dependency", self.code),
+
+            // Experimental / Not in use
+            402 => write!(f, "{} Payment Required", self.code),
+            425 => write!(f, "{} Too Early", self.code),
+
+            // SERVER ERROR RESPONSES
+            500 => write!(f, "{} Internal Server Error", self.code),
+            501 => write!(f, "{} Not Implmenented", self.code),
+            502 => write!(f, "{} Bad Getaway", self.code),
+            503 => write!(f, "{} Service Unavailable", self.code),
+            504 => write!(f, "{} Getaway Timeout", self.code),
+            505 => write!(f, "{} HTTP Version Not Supported", self.code),
+            506 => write!(f, "{} Variant Also Negotiates", self.code),
+            507 => write!(f, "{} Insufficient Storage", self.code),
+            508 => write!(f, "{} Loop Detected", self.code),
+            510 => write!(f, "{} Not Extendend", self.code),
+            511 => write!(f, "{} Network Authentication Required", self.code),
+
+            _ => write!(f, "500 "),
+        }
+    }
+}
diff --git a/site/411.html b/site/411.html
new file mode 100644
index 0000000..802df86
--- /dev/null
+++ b/site/411.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <title>411</title>
+  </head>
+  <h1>411</h1>
+</html>
-- 
GitLab


From 874798002e4bfa00ab56a361b458ee2cd46522b1 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Fri, 19 May 2023 22:40:58 +0200
Subject: [PATCH 12/65] Change Status to be an enum

---
 core/http/src/handlers/handlers.rs      |  12 +-
 core/http/src/handling/file_handlers.rs |   2 +-
 core/http/src/handling/response.rs      | 229 ++++++++++++++----------
 site/src/main.rs                        |   4 +-
 4 files changed, 146 insertions(+), 101 deletions(-)

diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
index b34416b..9477569 100755
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -70,7 +70,7 @@ pub fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint>) {
         let mut buffer: Vec<u8> = vec![0; length];
         let read_len = buf_reader.read(&mut buffer).unwrap();
         if read_len != length {
-            let respone = len_not_defined(Status { code: 411 });
+            let respone = len_not_defined(Status::LengthRequired);
             stream.write_all(respone.0.as_bytes()).unwrap();
             stream.write(&respone.1).unwrap();
             return;
@@ -105,15 +105,15 @@ pub fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint>) {
     let response = match handled_response {
         Some(val) => match val {
             Outcome::Success(success) => (
-                format!("HTTP/1.1 {} OK\r\n", success.status.unwrap().code)
+                format!("HTTP/1.1 {}\r\n", success.status.unwrap())
                     + &success.headers.join("\r\n")
                     + "\r\n\r\n",
                 success.body.get_data(),
             ),
             Outcome::Failure(error) => failure_handler(error),
-            Outcome::Forward(_) => failure_handler(Status { code: 404 }),
+            Outcome::Forward(_) => failure_handler(Status::NotFound),
         },
-        None => failure_handler(Status { code: 404 }),
+        None => failure_handler(Status::NotFound),
     };
 
     stream.write_all(response.0.as_bytes()).unwrap();
@@ -124,8 +124,8 @@ fn failure_handler(status: Status) -> (String, Vec<u8>) {
     let page_404 = NamedFile::open(PathBuf::from("404.html")).unwrap();
     (
         format!(
-            "HTTP/1.1 {} NOT FOUND\r\nContent-Length: {}\r\nContent-Type: {}\r\n\r\n",
-            status.code,
+            "HTTP/1.1 {}\r\nContent-Length: {}\r\nContent-Type: {}\r\n\r\n",
+            status,
             page_404.get_len(),
             page_404.get_mime()
         ),
diff --git a/core/http/src/handling/file_handlers.rs b/core/http/src/handling/file_handlers.rs
index fdfd3d0..c2945ae 100644
--- a/core/http/src/handling/file_handlers.rs
+++ b/core/http/src/handling/file_handlers.rs
@@ -32,7 +32,7 @@ impl NamedFile {
         let data = match data {
             Ok(dat) => dat,
             Err(_) => {
-                return Err(Status { code: 404 });
+                return Err(Status::NotFound);
             }
         };
         Ok(NamedFile {
diff --git a/core/http/src/handling/response.rs b/core/http/src/handling/response.rs
index 603ca55..8968852 100644
--- a/core/http/src/handling/response.rs
+++ b/core/http/src/handling/response.rs
@@ -1,4 +1,4 @@
-use std::fmt::Display;
+use std::{fmt::Display, fs::write};
 
 use mime::Mime;
 
@@ -67,101 +67,146 @@ pub struct Response {
 }
 
 #[derive(Debug)]
-pub struct Status {
-    pub code: u16,
+pub enum Status {
+    Continue,
+    SwitchingProtocols,
+    WebDavProcessing,
+    ExperimentalEarlyHints,
+    Ok,
+    Created,
+    Accepted,
+    NonAuthorativeIfnormation,
+    NoContent,
+    ResetContent,
+    PartialContent,
+    WebDavMultiStatus,
+    WebDavAlreadyReported,
+    HttpDataEncodingImUsed,
+    MultipleChoices,
+    MovedPermanently,
+    Found,
+    SeeOther,
+    NotModfiied,
+    DeprecatedUseProxy,
+    UnusedUnused,
+    TemporaryRedirect,
+    PermanentRedirect,
+    BadRequest,
+    Unauthorized,
+    ExperimentalPaymentRequired,
+    Forbidden,
+    NotFound,
+    MethodNotAllowed,
+    NotAcceptable,
+    ProxyAuthenticationRequired,
+    RequestTimeout,
+    Conflict,
+    Gone,
+    LengthRequired,
+    PreconditionFailed,
+    PayloadTooLarge,
+    UriTooLong,
+    UnsupportedMediaType,
+    RangeNotSatisfiable,
+    ExpectationFailed,
+    ImATeapot,
+    MisdirectedRequest,
+    WebDavUnprocessableContent,
+    WebDavLocked,
+    WebDavFailedDependency,
+    ExperimenalTooEarly,
+    UpgradeRequred,
+    PreconditionRequired,
+    TooManyRequests,
+    RequestHeaderFieldsTooLarge,
+    UnavailableForLegalReasons,
+    InternalServerError,
+    NotImplemented,
+    BadGetaway,
+    ServiceUnavailable,
+    GetawayTimeout,
+    HttpVersionNotSupported,
+    VariantAlsoNegotiates,
+    WebDavInsufficientStorage,
+    WebDavLoopDetected,
+    NotExtended,
+    NetworkAuthenticationRequired,
 }
 
 impl Display for Status {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        match self.code {
-            // INFORMATIONAL RESPONSE
-            100 => write!(f, "{} Continue", self.code),
-            101 => write!(f, "{} Switching Protocols", self.code),
-
-            // WebDAV
-            102 => write!(f, "{} Processing", self.code),
-
-            // Experimental
-            103 => write!(f, "{} Early Hints", self.code),
-
-            // SUCCESSFUL RESPONSE
-            200 => write!(f, "{} OK", self.code),
-            201 => write!(f, "{} Created", self.code),
-            203 => write!(f, "{} Non-Authorative Information", self.code),
-            204 => write!(f, "{} No Content", self.code),
-            205 => write!(f, "{} Reset Content", self.code),
-            206 => write!(f, "{} Partial Content", self.code),
-
-            // WebDAV
-            207 => write!(f, "{} Mutli-Status", self.code),
-            208 => write!(f, "{} Already Reported", self.code),
-
-            // HTTP Delta Encoding
-            226 => write!(f, "{} IM Used", self.code),
-
-            // REDIRECTION MESSAGES
-            300 => write!(f, "{} Multiple Choices", self.code),
-            301 => write!(f, "{} Moved Permanently", self.code),
-            302 => write!(f, "{} Found", self.code),
-            303 => write!(f, "{} See Other", self.code),
-            304 => write!(f, "{} Not Modified", self.code),
-            307 => write!(f, "{} Temporary Redirect", self.code),
-            308 => write!(f, "{} Permanent Redirect", self.code),
-
-            // Unused / Deprecated
-            305 => write!(f, "{} Use Proxy", self.code),
-            306 => write!(f, "{} unused", self.code),
-
-            // CLIENT ERROR
-            400 => write!(f, "{} Bad Request", self.code),
-            401 => write!(f, "{} Unauthorized", self.code),
-            403 => write!(f, "{} Forbidden", self.code),
-            404 => write!(f, "{} Not Found", self.code),
-            405 => write!(f, "{} Method Not Allowed", self.code),
-            406 => write!(f, "{} Not Acceptable", self.code),
-            407 => write!(f, "{} Proxy Athentication Required", self.code),
-            408 => write!(f, "{} Request Timout", self.code),
-            409 => write!(f, "{} Conflict", self.code),
-            410 => write!(f, "{} Gone", self.code),
-            411 => write!(f, "{} Length Required", self.code),
-            412 => write!(f, "{} Precondition Failed", self.code),
-            413 => write!(f, "{} Payload Too Large", self.code),
-            414 => write!(f, "{} URI Too Long", self.code),
-            415 => write!(f, "{} Unsupported Media Type", self.code),
-            416 => write!(f, "{} Range Not Satisfiable", self.code),
-            417 => write!(f, "{} Expectation Failed", self.code),
-            418 => write!(f, "{} I'm a Teapot", self.code),
-            421 => write!(f, "{} Misdirected Request", self.code),
-            422 => write!(f, "{} Unprocessable Content", self.code),
-            426 => write!(f, "{} Upgrade Required", self.code),
-            428 => write!(f, "{} Precondition Required", self.code),
-            429 => write!(f, "{} Too Many Requests", self.code),
-            431 => write!(f, "{} Request Header Fields Too Large", self.code),
-
-            451 => write!(f, "{} Unavailable For Legal Reasons", self.code),
-
-            // WebDAV
-            423 => write!(f, "{} Locked", self.code),
-            424 => write!(f, "{} Failed Dependency", self.code),
-
-            // Experimental / Not in use
-            402 => write!(f, "{} Payment Required", self.code),
-            425 => write!(f, "{} Too Early", self.code),
-
-            // SERVER ERROR RESPONSES
-            500 => write!(f, "{} Internal Server Error", self.code),
-            501 => write!(f, "{} Not Implmenented", self.code),
-            502 => write!(f, "{} Bad Getaway", self.code),
-            503 => write!(f, "{} Service Unavailable", self.code),
-            504 => write!(f, "{} Getaway Timeout", self.code),
-            505 => write!(f, "{} HTTP Version Not Supported", self.code),
-            506 => write!(f, "{} Variant Also Negotiates", self.code),
-            507 => write!(f, "{} Insufficient Storage", self.code),
-            508 => write!(f, "{} Loop Detected", self.code),
-            510 => write!(f, "{} Not Extendend", self.code),
-            511 => write!(f, "{} Network Authentication Required", self.code),
-
-            _ => write!(f, "500 "),
+        match self {
+            Status::Continue => write!(f, "100 Continue"),
+            Status::SwitchingProtocols => write!(f, "101 Switching Protocols"),
+            Status::WebDavProcessing => write!(f, "102 Processing"),
+            Status::ExperimentalEarlyHints => write!(f, "103 Early Hints"),
+            Status::Ok => write!(f, "200 OK"),
+            Status::Created => write!(f, "201 Created"),
+            Status::Accepted => write!(f, "202 Accepted"),
+            Status::NonAuthorativeIfnormation => write!(f, "203 Non-Authorative Information"),
+            Status::NoContent => write!(f, "204 No Content"),
+            Status::ResetContent => write!(f, "205 Reset Content"),
+            Status::PartialContent => write!(f, "206 Partial Content"),
+            Status::WebDavMultiStatus => write!(f, "207 Mutli-Status"),
+            Status::WebDavAlreadyReported => write!(f, "208 Already Reported"),
+            Status::HttpDataEncodingImUsed => write!(f, "226 IM Used"),
+            Status::MultipleChoices => write!(f, "300 Multiple Choices"),
+            Status::MovedPermanently => write!(f, "301 Moved Permanently"),
+            Status::Found => write!(f, "302 Found"),
+            Status::SeeOther => write!(f, "303 See Other"),
+            Status::NotModfiied => write!(f, "304 Not Modified"),
+            Status::TemporaryRedirect => write!(f, "307 Temporary Redirect"),
+            Status::PermanentRedirect => write!(f, "308 Permanent Redirect"),
+            Status::DeprecatedUseProxy => write!(f, "305 Use Proxy"),
+            Status::UnusedUnused => write!(f, "306 unused"),
+            Status::BadRequest => write!(f, "400 Bad Request"),
+            Status::Unauthorized => write!(f, "401 Unauthorized"),
+            Status::ExperimentalPaymentRequired => write!(f, "402 Payment Required"),
+            Status::Forbidden => write!(f, "403 Forbidden"),
+            Status::NotFound => write!(f, "404 Not Found"),
+            Status::MethodNotAllowed => write!(f, "405 Method Not Allowed"),
+            Status::NotAcceptable => write!(f, "406 Not Acceptable"),
+            Status::ProxyAuthenticationRequired => {
+                write!(f, "407 Proxy Athentication Required")
+            }
+            Status::RequestTimeout => write!(f, "408 Request Timout"),
+            Status::Conflict => write!(f, "409 Conflict"),
+            Status::Gone => write!(f, "410 Gone"),
+            Status::LengthRequired => write!(f, "411 Length Required"),
+            Status::PreconditionFailed => write!(f, "412 Precondition Failed"),
+            Status::PayloadTooLarge => write!(f, "413 Payload Too Large"),
+            Status::UriTooLong => write!(f, "414 URI Too Long"),
+            Status::UnsupportedMediaType => write!(f, "415 Unsupported Media Type"),
+            Status::RangeNotSatisfiable => write!(f, "416 Range Not Satisfiable"),
+            Status::ExpectationFailed => write!(f, "417 Expectation Failed"),
+            Status::ImATeapot => write!(f, "418 I'm a Teapot"),
+            Status::MisdirectedRequest => write!(f, "421 Misdirected Request"),
+            Status::WebDavUnprocessableContent => write!(f, "422 Unprocessable Content"),
+            Status::WebDavLocked => write!(f, "423 Locked"),
+            Status::WebDavFailedDependency => write!(f, "424 Failed Dependency"),
+            Status::ExperimenalTooEarly => write!(f, "425 Too Early"),
+            Status::UpgradeRequred => write!(f, "426 Upgrade Required"),
+            Status::PreconditionRequired => write!(f, "428 Precondition Required"),
+            Status::TooManyRequests => write!(f, "429 Too Many Requests"),
+            Status::RequestHeaderFieldsTooLarge => {
+                write!(f, "431 Request Header Fields Too Large")
+            }
+            Status::UnavailableForLegalReasons => {
+                write!(f, "451 Unavailable For Legal Reasons")
+            }
+            Status::InternalServerError => write!(f, "500 Internal Server Error"),
+            Status::NotImplemented => write!(f, "501 Not Implmenented"),
+            Status::BadGetaway => write!(f, "502 Bad Getaway"),
+            Status::ServiceUnavailable => write!(f, "503 Service Unavailable"),
+            Status::GetawayTimeout => write!(f, "504 Getaway Timeout"),
+            Status::HttpVersionNotSupported => write!(f, "505 HTTP Version Not Supported"),
+            Status::VariantAlsoNegotiates => write!(f, "506 Variant Also Negotiates"),
+            Status::WebDavInsufficientStorage => write!(f, "507 Insufficient Storage"),
+            Status::WebDavLoopDetected => write!(f, "508 Loop Detected"),
+            Status::NotExtended => write!(f, "510 Not Extendend"),
+            Status::NetworkAuthenticationRequired => {
+                write!(f, "511 Network Authentication Required")
+            }
         }
     }
 }
diff --git a/site/src/main.rs b/site/src/main.rs
index da51a33..0d90d26 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -16,10 +16,10 @@ fn handler(request: Request, _data: Data) -> Outcome<Response, Status, Data> {
                 format!("Content-Length: {}", dat.get_len()),
                 format!("Content-Type: {}", dat.get_mime()),
             ],
-            status: Some(Status { code: 200 }),
+            status: Some(Status::Ok),
             body: Box::new(dat),
         },
-        Err(_) => return Outcome::Failure(Status { code: 404 }),
+        Err(_) => return Outcome::Failure(Status::NotFound),
     };
     Outcome::Success(response)
 }
-- 
GitLab


From 0c607be9fbb3538df5f52109cedb9ba30ef380fd Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Mon, 22 May 2023 22:47:26 +0200
Subject: [PATCH 13/65] add a post handler

---
 core/http/src/handling/routes.rs |  6 ++++++
 site/src/main.rs                 | 35 +++++++++++++++++++++++++++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/core/http/src/handling/routes.rs b/core/http/src/handling/routes.rs
index fd3512d..3d8b405 100644
--- a/core/http/src/handling/routes.rs
+++ b/core/http/src/handling/routes.rs
@@ -69,3 +69,9 @@ pub struct Data {
     pub buffer: Vec<u8>,
     pub is_complete: bool,
 }
+
+impl Data {
+    pub fn is_empty(&self) -> bool {
+        self.buffer.len() == 0
+    }
+}
diff --git a/site/src/main.rs b/site/src/main.rs
index 0d90d26..dd6cf06 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -28,6 +28,30 @@ fn fileserver(path: &str) -> Result<NamedFile, Status> {
     NamedFile::open(PathBuf::from("static/".to_string() + path))
 }
 
+fn post_hi_handler(_request: Request, data: Data) -> Outcome<Response, Status, Data> {
+    if data.is_empty() {
+        return Outcome::Forward(data);
+    }
+    let data = if let Ok(str) = String::from_utf8(data.buffer) {
+        str
+    } else {
+        return Outcome::Failure(Status::BadRequest);
+    };
+    let dat = post_hi(data);
+    Outcome::Success(Response {
+        headers: vec![
+            format!("Content-Length: {}", dat.len()),
+            format!("Content-Type: text/plain"),
+        ],
+        status: Some(Status::Ok),
+        body: Box::new(dat),
+    })
+}
+
+fn post_hi(msg: String) -> String {
+    msg
+}
+
 fn main() {
     let fileserver = Route {
         format: None,
@@ -38,7 +62,16 @@ fn main() {
         rank: 0,
     };
 
+    let post_test = Route {
+        format: None,
+        handler: post_hi_handler,
+        name: Some("post_test"),
+        uri: "post",
+        method: Method::Post,
+        rank: 0,
+    };
+
     http::build("127.0.0.1:8000")
-        .mount("/", vec![fileserver])
+        .mount("/", vec![fileserver, post_test])
         .launch();
 }
-- 
GitLab


From db039567ecbc1a5582eb5537c8fd0791731b8c49 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sat, 27 May 2023 16:34:18 +0200
Subject: [PATCH 14/65] add runtime crate for async/await

---
 core/runtime/.gitignore |  1 +
 core/runtime/Cargo.lock |  7 +++++++
 core/runtime/Cargo.toml |  8 ++++++++
 core/runtime/src/lib.rs | 14 ++++++++++++++
 site/static/table.html  |  0
 5 files changed, 30 insertions(+)
 create mode 100644 core/runtime/.gitignore
 create mode 100644 core/runtime/Cargo.lock
 create mode 100644 core/runtime/Cargo.toml
 create mode 100644 core/runtime/src/lib.rs
 create mode 100644 site/static/table.html

diff --git a/core/runtime/.gitignore b/core/runtime/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/core/runtime/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/core/runtime/Cargo.lock b/core/runtime/Cargo.lock
new file mode 100644
index 0000000..0728315
--- /dev/null
+++ b/core/runtime/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "runtime"
+version = "0.1.0"
diff --git a/core/runtime/Cargo.toml b/core/runtime/Cargo.toml
new file mode 100644
index 0000000..65e9c1d
--- /dev/null
+++ b/core/runtime/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "runtime"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/core/runtime/src/lib.rs b/core/runtime/src/lib.rs
new file mode 100644
index 0000000..7d12d9a
--- /dev/null
+++ b/core/runtime/src/lib.rs
@@ -0,0 +1,14 @@
+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);
+    }
+}
diff --git a/site/static/table.html b/site/static/table.html
new file mode 100644
index 0000000..e69de29
-- 
GitLab


From ab9873adfa7a120e0892a1c9d1a25279713c9191 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sun, 28 May 2023 17:17:52 +0200
Subject: [PATCH 15/65] Add Tokio async runtime

---
 core/http/Cargo.lock               | 482 ++++-----------------------
 core/http/Cargo.toml               |   3 +-
 core/http/src/handlers/handlers.rs |  46 +--
 core/http/src/handling/response.rs |   4 +-
 core/http/src/lib.rs               |   1 -
 core/http/src/setup.rs             |  48 +--
 core/http/src/threading.rs         |  85 -----
 core/runtime/.gitignore            |   1 -
 core/runtime/Cargo.lock            |   7 -
 core/runtime/Cargo.toml            |   8 -
 core/runtime/src/lib.rs            |  14 -
 site/Cargo.lock                    | 505 ++++-------------------------
 site/Cargo.toml                    |   1 +
 site/src/main.rs                   |   9 +-
 14 files changed, 172 insertions(+), 1042 deletions(-)
 delete mode 100644 core/http/src/threading.rs
 delete mode 100644 core/runtime/.gitignore
 delete mode 100644 core/runtime/Cargo.lock
 delete mode 100644 core/runtime/Cargo.toml
 delete mode 100644 core/runtime/src/lib.rs

diff --git a/core/http/Cargo.lock b/core/http/Cargo.lock
index 6cd2bca..fd71f4c 100644
--- a/core/http/Cargo.lock
+++ b/core/http/Cargo.lock
@@ -8,36 +8,18 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
-[[package]]
-name = "base64"
-version = "0.21.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
-
 [[package]]
 name = "bitflags"
 version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
-[[package]]
-name = "bumpalo"
-version = "3.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8"
-
 [[package]]
 name = "bytes"
 version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
 
-[[package]]
-name = "cc"
-version = "1.0.79"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
-
 [[package]]
 name = "cfg-if"
 version = "1.0.0"
@@ -45,58 +27,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
-name = "core-foundation"
-version = "0.9.3"
+name = "hermit-abi"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
 dependencies = [
- "core-foundation-sys",
  "libc",
 ]
 
-[[package]]
-name = "core-foundation-sys"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
-
-[[package]]
-name = "ctrlc"
-version = "3.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbcf33c2a618cbe41ee43ae6e9f2e48368cd9f9db2896f10167d8d762679f639"
-dependencies = [
- "nix",
- "windows-sys 0.45.0",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.2.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi",
-]
-
 [[package]]
 name = "http"
 version = "0.1.0"
 dependencies = [
- "ctrlc",
  "mime",
- "quinn",
-]
-
-[[package]]
-name = "js-sys"
-version = "0.3.61"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
-dependencies = [
- "wasm-bindgen",
+ "tokio",
 ]
 
 [[package]]
@@ -105,6 +49,16 @@ version = "0.2.144"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
 
+[[package]]
+name = "lock_api"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
 [[package]]
 name = "log"
 version = "0.4.17"
@@ -133,28 +87,37 @@ dependencies = [
 ]
 
 [[package]]
-name = "nix"
-version = "0.26.2"
+name = "num_cpus"
+version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
 dependencies = [
- "bitflags",
- "cfg-if",
+ "hermit-abi",
  "libc",
- "static_assertions",
 ]
 
 [[package]]
-name = "once_cell"
-version = "1.17.1"
+name = "parking_lot"
+version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
 
 [[package]]
-name = "openssl-probe"
-version = "0.1.5"
+name = "parking_lot_core"
+version = "0.9.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-sys 0.45.0",
+]
 
 [[package]]
 name = "pin-project-lite"
@@ -162,12 +125,6 @@ version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
 
-[[package]]
-name = "ppv-lite86"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
-
 [[package]]
 name = "proc-macro2"
 version = "1.0.56"
@@ -177,56 +134,6 @@ dependencies = [
  "unicode-ident",
 ]
 
-[[package]]
-name = "quinn"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445cbfe2382fa023c4f2f3c7e1c95c03dcc1df2bf23cebcb2b13e1402c4394d1"
-dependencies = [
- "bytes",
- "pin-project-lite",
- "quinn-proto",
- "quinn-udp",
- "rustc-hash",
- "rustls",
- "thiserror",
- "tokio",
- "tracing",
- "webpki",
-]
-
-[[package]]
-name = "quinn-proto"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67c10f662eee9c94ddd7135043e544f3c82fa839a1e7b865911331961b53186c"
-dependencies = [
- "bytes",
- "rand",
- "ring",
- "rustc-hash",
- "rustls",
- "rustls-native-certs",
- "slab",
- "thiserror",
- "tinyvec",
- "tracing",
- "webpki",
-]
-
-[[package]]
-name = "quinn-udp"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "641538578b21f5e5c8ea733b736895576d0fe329bb883b937db6f4d163dbaaf4"
-dependencies = [
- "libc",
- "quinn-proto",
- "socket2",
- "tracing",
- "windows-sys 0.42.0",
-]
-
 [[package]]
 name = "quote"
 version = "1.0.27"
@@ -237,138 +144,34 @@ dependencies = [
 ]
 
 [[package]]
-name = "rand"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
-dependencies = [
- "libc",
- "rand_chacha",
- "rand_core",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "ring"
-version = "0.16.20"
+name = "redox_syscall"
+version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
 dependencies = [
- "cc",
- "libc",
- "once_cell",
- "spin",
- "untrusted",
- "web-sys",
- "winapi",
+ "bitflags",
 ]
 
 [[package]]
-name = "rustc-hash"
+name = "scopeguard"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
-
-[[package]]
-name = "rustls"
-version = "0.20.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
-dependencies = [
- "ring",
- "sct",
- "webpki",
-]
-
-[[package]]
-name = "rustls-native-certs"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50"
-dependencies = [
- "openssl-probe",
- "rustls-pemfile",
- "schannel",
- "security-framework",
-]
-
-[[package]]
-name = "rustls-pemfile"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
-dependencies = [
- "base64",
-]
-
-[[package]]
-name = "schannel"
-version = "0.1.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3"
-dependencies = [
- "windows-sys 0.42.0",
-]
-
-[[package]]
-name = "sct"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
-dependencies = [
- "ring",
- "untrusted",
-]
-
-[[package]]
-name = "security-framework"
-version = "2.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254"
-dependencies = [
- "bitflags",
- "core-foundation",
- "core-foundation-sys",
- "libc",
- "security-framework-sys",
-]
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
 [[package]]
-name = "security-framework-sys"
-version = "2.8.0"
+name = "signal-hook-registry"
+version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
+checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
 dependencies = [
- "core-foundation-sys",
  "libc",
 ]
 
 [[package]]
-name = "slab"
-version = "0.4.8"
+name = "smallvec"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
-dependencies = [
- "autocfg",
-]
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
 
 [[package]]
 name = "socket2"
@@ -380,29 +183,6 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "spin"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
-
-[[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
-[[package]]
-name = "syn"
-version = "1.0.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
 [[package]]
 name = "syn"
 version = "2.0.15"
@@ -414,85 +194,34 @@ dependencies = [
  "unicode-ident",
 ]
 
-[[package]]
-name = "thiserror"
-version = "1.0.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "1.0.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.15",
-]
-
-[[package]]
-name = "tinyvec"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
-dependencies = [
- "tinyvec_macros",
-]
-
-[[package]]
-name = "tinyvec_macros"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
-
 [[package]]
 name = "tokio"
-version = "1.28.0"
+version = "1.28.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f"
+checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2"
 dependencies = [
  "autocfg",
+ "bytes",
  "libc",
  "mio",
+ "num_cpus",
+ "parking_lot",
  "pin-project-lite",
+ "signal-hook-registry",
  "socket2",
+ "tokio-macros",
  "windows-sys 0.48.0",
 ]
 
 [[package]]
-name = "tracing"
-version = "0.1.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
-dependencies = [
- "cfg-if",
- "pin-project-lite",
- "tracing-attributes",
- "tracing-core",
-]
-
-[[package]]
-name = "tracing-attributes"
-version = "0.1.24"
+name = "tokio-macros"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
+checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.15",
-]
-
-[[package]]
-name = "tracing-core"
-version = "0.1.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
-dependencies = [
- "once_cell",
+ "syn",
 ]
 
 [[package]]
@@ -501,92 +230,12 @@ version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
 
-[[package]]
-name = "untrusted"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
-
 [[package]]
 name = "wasi"
 version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.84"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
-dependencies = [
- "cfg-if",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.84"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
-dependencies = [
- "bumpalo",
- "log",
- "once_cell",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.84"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.84"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.84"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
-
-[[package]]
-name = "web-sys"
-version = "0.3.61"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "webpki"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
-dependencies = [
- "ring",
- "untrusted",
-]
-
 [[package]]
 name = "winapi"
 version = "0.3.9"
@@ -609,21 +258,6 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
-[[package]]
-name = "windows-sys"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
-dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
-]
-
 [[package]]
 name = "windows-sys"
 version = "0.45.0"
diff --git a/core/http/Cargo.toml b/core/http/Cargo.toml
index a5b887f..4bc7eaf 100644
--- a/core/http/Cargo.toml
+++ b/core/http/Cargo.toml
@@ -6,6 +6,5 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-quinn = "0.9.3"
-ctrlc = "3.2.5"
 mime = "0.3.17"
+tokio = { version = "1.28.2", features = ["full"] }
diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
index 9477569..0cf7d48 100755
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -1,8 +1,6 @@
-use std::{
-    io::{BufRead, BufReader, Read, Write},
-    net::TcpStream,
-    path::PathBuf,
-};
+use std::path::PathBuf;
+
+use tokio::{io::{AsyncReadExt, BufReader, AsyncBufReadExt, AsyncWriteExt}, net::TcpStream};
 
 use crate::handling::{
     file_handlers::NamedFile,
@@ -12,13 +10,12 @@ use crate::handling::{
 };
 use crate::setup::MountPoint;
 
-pub fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint>) {
+pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint<'_>>) {
     let mut buf_reader = BufReader::new(&mut stream);
-    let mut http_request: Vec<String> = vec![];
-
+    let mut http_request: Vec<String> = Vec::with_capacity(100);
     loop {
         let mut buffer = String::new();
-        let _ = buf_reader.read_line(&mut buffer).unwrap();
+        let _ = buf_reader.read_line(&mut buffer).await.unwrap();
         if buffer == "\r\n" {
             break;
         }
@@ -67,12 +64,12 @@ pub fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint>) {
         } else {
             0
         };
-        let mut buffer: Vec<u8> = vec![0; length];
-        let read_len = buf_reader.read(&mut buffer).unwrap();
-        if read_len != length {
-            let respone = len_not_defined(Status::LengthRequired);
-            stream.write_all(respone.0.as_bytes()).unwrap();
-            stream.write(&respone.1).unwrap();
+        let mut buffer: Vec<u8> = vec![];
+        buf_reader.read_buf(&mut buffer).await.unwrap();
+        if buffer.len() != length {
+            let respone = len_not_defined(Status::LengthRequired).await;
+            stream.write_all(respone.0.as_bytes()).await.unwrap();
+            stream.write(&respone.1).await.unwrap();
             return;
         }
         data.is_complete = true;
@@ -99,6 +96,11 @@ pub fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint>) {
                 },
                 data.clone(),
             ));
+
+            if let Some(Outcome::Forward(_)) = handled_response {
+                continue;
+            }
+            break;
         }
     }
 
@@ -110,17 +112,17 @@ pub fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint>) {
                     + "\r\n\r\n",
                 success.body.get_data(),
             ),
-            Outcome::Failure(error) => failure_handler(error),
-            Outcome::Forward(_) => failure_handler(Status::NotFound),
+            Outcome::Failure(error) => failure_handler(error).await,
+            Outcome::Forward(_) => failure_handler(Status::NotFound).await,
         },
-        None => failure_handler(Status::NotFound),
+        None => failure_handler(Status::NotFound).await,
     };
 
-    stream.write_all(response.0.as_bytes()).unwrap();
-    stream.write(&response.1).unwrap();
+    stream.write_all(response.0.as_bytes()).await.unwrap();
+    stream.write(&response.1).await.unwrap();
 }
 
-fn failure_handler(status: Status) -> (String, Vec<u8>) {
+async fn failure_handler(status: Status) -> (String, Vec<u8>) {
     let page_404 = NamedFile::open(PathBuf::from("404.html")).unwrap();
     (
         format!(
@@ -133,7 +135,7 @@ fn failure_handler(status: Status) -> (String, Vec<u8>) {
     )
 }
 
-fn len_not_defined(status: Status) -> (String, Vec<u8>) {
+async fn len_not_defined(status: Status) -> (String, Vec<u8>) {
     let page_411 = NamedFile::open(PathBuf::from("411.html")).unwrap();
     (
         format!(
diff --git a/core/http/src/handling/response.rs b/core/http/src/handling/response.rs
index 8968852..446c8af 100644
--- a/core/http/src/handling/response.rs
+++ b/core/http/src/handling/response.rs
@@ -1,4 +1,4 @@
-use std::{fmt::Display, fs::write};
+use std::fmt::Display;
 
 use mime::Mime;
 
@@ -13,7 +13,7 @@ pub enum Outcome<S, E, F> {
     Forward(F),
 }
 
-pub trait ResponseBody {
+pub trait ResponseBody: Send {
     fn get_data(&self) -> Vec<u8>;
     fn get_mime(&self) -> Mime;
     fn get_len(&self) -> usize;
diff --git a/core/http/src/lib.rs b/core/http/src/lib.rs
index 7a1379c..a51c899 100644
--- a/core/http/src/lib.rs
+++ b/core/http/src/lib.rs
@@ -1,7 +1,6 @@
 pub mod handlers;
 pub mod handling;
 mod setup;
-mod threading;
 
 mod utils;
 
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index 4bacada..a38b154 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -1,16 +1,12 @@
 use std::{
-    net::TcpListener,
-    sync::{
-        atomic::{self, AtomicBool},
-        Arc,
-    },
-    thread::available_parallelism,
+    thread::available_parallelism, process::exit,
 };
 
+use tokio::{net::TcpListener, signal::unix::{SignalKind, signal}};
+
 use crate::{
     handlers::handlers::handle_connection,
     handling::routes::{Route, Uri},
-    threading::ThreadPool,
 };
 
 #[derive(Clone)]
@@ -22,7 +18,6 @@ pub struct MountPoint<'a> {
 pub struct Config {
     mountpoints: Option<Vec<MountPoint<'static>>>,
     address: TcpListener,
-    threadpool: ThreadPool,
 }
 
 impl<'a> Config {
@@ -56,33 +51,24 @@ impl<'a> Config {
         }
         self
     }
-    pub fn launch(self) {
-        let running = Arc::new(AtomicBool::new(true));
-
-        // Clone a reference to `running` to pass to the signal handler closure
-        let running_for_handler = running.clone();
-
+    pub async fn launch(self) {
         // Set up a signal handler for SIGINT
-        ctrlc::set_handler(move || {
-            // When the user sends a SIGINT signal (e.g. by pressing CTRL+C),
-            // set the `running` flag to false to initiate a graceful shutdown
-            println!("SIGNIT received, shutting down gracefully");
-            running_for_handler.store(false, atomic::Ordering::SeqCst);
-        })
-        .expect("Error setting Ctrl-C handler");
-        for stream in self.address.incoming() {
-            if !running.load(atomic::Ordering::SeqCst) {
-                break;
-            }
-            let stream = stream.unwrap();
+        tokio::spawn(async {
+            let mut sigint = signal(SignalKind::interrupt()).unwrap();
+            sigint.recv().await;
+            println!("Shutting down...");
+            exit(0)
+        });
+
+        loop {
+            let (socket, _) = self.address.accept().await.unwrap();
             let mountpoints = self.mountpoints.clone().unwrap();
-            self.threadpool
-                .execute(move || handle_connection(stream, mountpoints));
+            tokio::spawn(async move { handle_connection(socket, mountpoints).await; });
         }
     }
 }
-pub fn build(ip: &str) -> Config {
-    let listener = TcpListener::bind(ip).unwrap();
+pub async fn build(ip: &str) -> Config {
+    let listener = TcpListener::bind(ip).await.unwrap();
     let ip = ip.splitn(2, ":").collect::<Vec<&str>>();
     if ip.len() != 2 {
         panic!("Invalid IP Address");
@@ -90,7 +76,6 @@ pub fn build(ip: &str) -> Config {
     let port = ip[1];
     let ip = ip[0];
     let workers = available_parallelism().unwrap().get();
-    let threadpool = ThreadPool::new(workers);
     println!(
         "\x1b[34mâš™ Configuration\x1b[0m
   >> \x1b[34mIp\x1b[0m: {ip}
@@ -101,6 +86,5 @@ pub fn build(ip: &str) -> Config {
     Config {
         mountpoints: None,
         address: listener,
-        threadpool,
     }
 }
diff --git a/core/http/src/threading.rs b/core/http/src/threading.rs
deleted file mode 100644
index e743853..0000000
--- a/core/http/src/threading.rs
+++ /dev/null
@@ -1,85 +0,0 @@
-use std::{
-    sync::{mpsc, Arc, Mutex},
-    thread,
-};
-
-pub struct ThreadPool {
-    workers: Vec<Worker>,
-    sender: Option<mpsc::Sender<Job>>,
-}
-
-type Job = Box<dyn FnOnce() + Send + 'static>;
-
-impl ThreadPool {
-    /// Create a new ThreadPool.
-    ///
-    /// The size is the number of threads in the pool.
-    ///
-    /// # Panics
-    ///
-    /// The `new` function will panic if the size is zero.
-    pub fn new(size: usize) -> ThreadPool {
-        assert!(size > 0);
-
-        let (sender, receiver) = mpsc::channel();
-
-        let receiver = Arc::new(Mutex::new(receiver));
-
-        let mut workers = Vec::with_capacity(size);
-
-        for id in 0..size {
-            workers.push(Worker::new(id, Arc::clone(&receiver)));
-        }
-        ThreadPool {
-            workers,
-            sender: Some(sender),
-        }
-    }
-
-    pub fn execute<F>(&self, f: F)
-    where
-        F: FnOnce() + Send + 'static,
-    {
-        let job = Box::new(f);
-
-        self.sender.as_ref().unwrap().send(job).unwrap();
-    }
-}
-
-impl Drop for ThreadPool {
-    fn drop(&mut self) {
-        drop(self.sender.take());
-
-        for worker in &mut self.workers {
-            if let Some(thread) = worker.thread.take() {
-                thread.join().unwrap();
-            }
-        }
-    }
-}
-struct Worker {
-    id: usize,
-    thread: Option<thread::JoinHandle<()>>,
-}
-
-impl Worker {
-    fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
-        let thread = thread::spawn(move || loop {
-            let message = receiver.lock().unwrap().recv();
-
-            match message {
-                Ok(job) => {
-                    job();
-                }
-                Err(_) => {
-                    break;
-                }
-            }
-        });
-
-        Worker {
-            id,
-            thread: Some(thread),
-        }
-    }
-}
diff --git a/core/runtime/.gitignore b/core/runtime/.gitignore
deleted file mode 100644
index ea8c4bf..0000000
--- a/core/runtime/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target
diff --git a/core/runtime/Cargo.lock b/core/runtime/Cargo.lock
deleted file mode 100644
index 0728315..0000000
--- a/core/runtime/Cargo.lock
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "runtime"
-version = "0.1.0"
diff --git a/core/runtime/Cargo.toml b/core/runtime/Cargo.toml
deleted file mode 100644
index 65e9c1d..0000000
--- a/core/runtime/Cargo.toml
+++ /dev/null
@@ -1,8 +0,0 @@
-[package]
-name = "runtime"
-version = "0.1.0"
-edition = "2021"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
diff --git a/core/runtime/src/lib.rs b/core/runtime/src/lib.rs
deleted file mode 100644
index 7d12d9a..0000000
--- a/core/runtime/src/lib.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-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);
-    }
-}
diff --git a/site/Cargo.lock b/site/Cargo.lock
index 7578765..c714959 100644
--- a/site/Cargo.lock
+++ b/site/Cargo.lock
@@ -8,36 +8,18 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
-[[package]]
-name = "base64"
-version = "0.21.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
-
 [[package]]
 name = "bitflags"
 version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
-[[package]]
-name = "bumpalo"
-version = "3.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8"
-
 [[package]]
 name = "bytes"
 version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
 
-[[package]]
-name = "cc"
-version = "1.0.79"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
-
 [[package]]
 name = "cfg-if"
 version = "1.0.0"
@@ -45,58 +27,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
-name = "core-foundation"
-version = "0.9.3"
+name = "hermit-abi"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
 dependencies = [
- "core-foundation-sys",
  "libc",
 ]
 
-[[package]]
-name = "core-foundation-sys"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
-
-[[package]]
-name = "ctrlc"
-version = "3.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbcf33c2a618cbe41ee43ae6e9f2e48368cd9f9db2896f10167d8d762679f639"
-dependencies = [
- "nix",
- "windows-sys 0.45.0",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.2.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi",
-]
-
 [[package]]
 name = "http"
 version = "0.1.0"
 dependencies = [
- "ctrlc",
  "mime",
- "quinn",
-]
-
-[[package]]
-name = "js-sys"
-version = "0.3.61"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
-dependencies = [
- "wasm-bindgen",
+ "tokio",
 ]
 
 [[package]]
@@ -106,12 +50,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
 
 [[package]]
-name = "log"
-version = "0.4.17"
+name = "lock_api"
+version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
 dependencies = [
- "cfg-if",
+ "autocfg",
+ "scopeguard",
 ]
 
 [[package]]
@@ -122,39 +67,47 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
 
 [[package]]
 name = "mio"
-version = "0.8.6"
+version = "0.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
+checksum = "eebffdb73fe72e917997fad08bdbf31ac50b0fa91cec93e69a0662e4264d454c"
 dependencies = [
  "libc",
- "log",
  "wasi",
- "windows-sys 0.45.0",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
-name = "nix"
-version = "0.26.2"
+name = "num_cpus"
+version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
 dependencies = [
- "bitflags",
- "cfg-if",
+ "hermit-abi",
  "libc",
- "static_assertions",
 ]
 
 [[package]]
-name = "once_cell"
-version = "1.17.1"
+name = "parking_lot"
+version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
 
 [[package]]
-name = "openssl-probe"
-version = "0.1.5"
+name = "parking_lot_core"
+version = "0.9.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-sys 0.45.0",
+]
 
 [[package]]
 name = "pin-project-lite"
@@ -162,202 +115,45 @@ version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
 
-[[package]]
-name = "ppv-lite86"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
-
 [[package]]
 name = "proc-macro2"
-version = "1.0.56"
+version = "1.0.59"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
+checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
 dependencies = [
  "unicode-ident",
 ]
 
-[[package]]
-name = "quinn"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445cbfe2382fa023c4f2f3c7e1c95c03dcc1df2bf23cebcb2b13e1402c4394d1"
-dependencies = [
- "bytes",
- "pin-project-lite",
- "quinn-proto",
- "quinn-udp",
- "rustc-hash",
- "rustls",
- "thiserror",
- "tokio",
- "tracing",
- "webpki",
-]
-
-[[package]]
-name = "quinn-proto"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67c10f662eee9c94ddd7135043e544f3c82fa839a1e7b865911331961b53186c"
-dependencies = [
- "bytes",
- "rand",
- "ring",
- "rustc-hash",
- "rustls",
- "rustls-native-certs",
- "slab",
- "thiserror",
- "tinyvec",
- "tracing",
- "webpki",
-]
-
-[[package]]
-name = "quinn-udp"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "641538578b21f5e5c8ea733b736895576d0fe329bb883b937db6f4d163dbaaf4"
-dependencies = [
- "libc",
- "quinn-proto",
- "socket2",
- "tracing",
- "windows-sys 0.42.0",
-]
-
 [[package]]
 name = "quote"
-version = "1.0.27"
+version = "1.0.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
+checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
 dependencies = [
  "proc-macro2",
 ]
 
 [[package]]
-name = "rand"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
-dependencies = [
- "libc",
- "rand_chacha",
- "rand_core",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "ring"
-version = "0.16.20"
+name = "redox_syscall"
+version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
 dependencies = [
- "cc",
- "libc",
- "once_cell",
- "spin",
- "untrusted",
- "web-sys",
- "winapi",
+ "bitflags",
 ]
 
 [[package]]
-name = "rustc-hash"
+name = "scopeguard"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
-
-[[package]]
-name = "rustls"
-version = "0.20.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
-dependencies = [
- "ring",
- "sct",
- "webpki",
-]
-
-[[package]]
-name = "rustls-native-certs"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50"
-dependencies = [
- "openssl-probe",
- "rustls-pemfile",
- "schannel",
- "security-framework",
-]
-
-[[package]]
-name = "rustls-pemfile"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
-dependencies = [
- "base64",
-]
-
-[[package]]
-name = "schannel"
-version = "0.1.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3"
-dependencies = [
- "windows-sys 0.42.0",
-]
-
-[[package]]
-name = "sct"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
-dependencies = [
- "ring",
- "untrusted",
-]
-
-[[package]]
-name = "security-framework"
-version = "2.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254"
-dependencies = [
- "bitflags",
- "core-foundation",
- "core-foundation-sys",
- "libc",
- "security-framework-sys",
-]
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
 [[package]]
-name = "security-framework-sys"
-version = "2.8.0"
+name = "signal-hook-registry"
+version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
+checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
 dependencies = [
- "core-foundation-sys",
  "libc",
 ]
 
@@ -366,16 +162,14 @@ name = "site"
 version = "0.1.0"
 dependencies = [
  "http",
+ "tokio",
 ]
 
 [[package]]
-name = "slab"
-version = "0.4.8"
+name = "smallvec"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
-dependencies = [
- "autocfg",
-]
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
 
 [[package]]
 name = "socket2"
@@ -387,132 +181,52 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "spin"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
-
-[[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
-[[package]]
-name = "syn"
-version = "1.0.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
 [[package]]
 name = "syn"
-version = "2.0.15"
+version = "2.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
 dependencies = [
  "proc-macro2",
  "quote",
  "unicode-ident",
 ]
 
-[[package]]
-name = "thiserror"
-version = "1.0.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "1.0.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.15",
-]
-
-[[package]]
-name = "tinyvec"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
-dependencies = [
- "tinyvec_macros",
-]
-
-[[package]]
-name = "tinyvec_macros"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
-
 [[package]]
 name = "tokio"
-version = "1.28.0"
+version = "1.28.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f"
+checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2"
 dependencies = [
  "autocfg",
+ "bytes",
  "libc",
  "mio",
+ "num_cpus",
+ "parking_lot",
  "pin-project-lite",
+ "signal-hook-registry",
  "socket2",
+ "tokio-macros",
  "windows-sys 0.48.0",
 ]
 
 [[package]]
-name = "tracing"
-version = "0.1.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
-dependencies = [
- "cfg-if",
- "pin-project-lite",
- "tracing-attributes",
- "tracing-core",
-]
-
-[[package]]
-name = "tracing-attributes"
-version = "0.1.24"
+name = "tokio-macros"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
+checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.15",
-]
-
-[[package]]
-name = "tracing-core"
-version = "0.1.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
-dependencies = [
- "once_cell",
+ "syn",
 ]
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
-
-[[package]]
-name = "untrusted"
-version = "0.7.1"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
+checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
 
 [[package]]
 name = "wasi"
@@ -520,80 +234,6 @@ version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.84"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
-dependencies = [
- "cfg-if",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.84"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
-dependencies = [
- "bumpalo",
- "log",
- "once_cell",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.84"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.84"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.84"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
-
-[[package]]
-name = "web-sys"
-version = "0.3.61"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "webpki"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
-dependencies = [
- "ring",
- "untrusted",
-]
-
 [[package]]
 name = "winapi"
 version = "0.3.9"
@@ -616,21 +256,6 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
-[[package]]
-name = "windows-sys"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
-dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
-]
-
 [[package]]
 name = "windows-sys"
 version = "0.45.0"
diff --git a/site/Cargo.toml b/site/Cargo.toml
index d4e9a4a..55ff9b1 100644
--- a/site/Cargo.toml
+++ b/site/Cargo.toml
@@ -7,3 +7,4 @@ edition = "2021"
 
 [dependencies]
 http = { path = "../core/http" }
+tokio = { version = "1.28.2", features = ["full"] }
diff --git a/site/src/main.rs b/site/src/main.rs
index dd6cf06..fc87c26 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -8,7 +8,7 @@ use http::handling::{
     routes::{Data, Route},
 };
 
-fn handler(request: Request, _data: Data) -> Outcome<Response, Status, Data> {
+fn handler(request: Request<'_>, _data: Data) -> Outcome<Response, Status, Data> {
     let response = fileserver(request.uri.strip_prefix("static/").unwrap());
     let response = match response {
         Ok(dat) => Response {
@@ -52,7 +52,8 @@ fn post_hi(msg: String) -> String {
     msg
 }
 
-fn main() {
+#[tokio::main]
+async fn main() {
     let fileserver = Route {
         format: None,
         handler,
@@ -71,7 +72,7 @@ fn main() {
         rank: 0,
     };
 
-    http::build("127.0.0.1:8000")
+    http::build("127.0.0.1:8000").await
         .mount("/", vec![fileserver, post_test])
-        .launch();
+        .launch().await;
 }
-- 
GitLab


From a9ee87ffa056fb2e4cbcfe59add05d6dedc091cc Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sun, 28 May 2023 17:30:38 +0200
Subject: [PATCH 16/65] Add instant graceful shutdown with SIGNIT

---
 core/http/src/setup.rs | 27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index a38b154..dfdb496 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -2,7 +2,7 @@ use std::{
     thread::available_parallelism, process::exit,
 };
 
-use tokio::{net::TcpListener, signal::unix::{SignalKind, signal}};
+use tokio::{net::TcpListener, signal::unix::{SignalKind, signal}, runtime, select};
 
 use crate::{
     handlers::handlers::handle_connection,
@@ -52,18 +52,21 @@ impl<'a> Config {
         self
     }
     pub async fn launch(self) {
-        // Set up a signal handler for SIGINT
-        tokio::spawn(async {
-            let mut sigint = signal(SignalKind::interrupt()).unwrap();
-            sigint.recv().await;
-            println!("Shutting down...");
-            exit(0)
-        });
-
+        let mut sigint = signal(SignalKind::interrupt()).unwrap();
         loop {
-            let (socket, _) = self.address.accept().await.unwrap();
-            let mountpoints = self.mountpoints.clone().unwrap();
-            tokio::spawn(async move { handle_connection(socket, mountpoints).await; });
+            select! {
+                _ = sigint.recv() => {
+                    println!("Shutting down...");
+                    break;
+                }
+
+                income = self.address.accept() => {
+                    let income = income.unwrap();
+                    let (socket, _) = income;
+                    let mountpoints = self.mountpoints.clone().unwrap();
+                    tokio::spawn(async move { handle_connection(socket, mountpoints).await; });
+                }
+            }
         }
     }
 }
-- 
GitLab


From 677eb8a01a8f0cdc047872dadb9c1c7233328b88 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sun, 28 May 2023 18:04:45 +0200
Subject: [PATCH 17/65] Add Ranking

---
 core/http/src/handling/methods.rs |  2 +-
 core/http/src/handling/request.rs | 12 ++++++------
 core/http/src/setup.rs            |  9 ++++-----
 site/src/main.rs                  | 22 ++++++++++++++++++++--
 site/static/hi                    |  1 +
 5 files changed, 32 insertions(+), 14 deletions(-)
 create mode 100644 site/static/hi

diff --git a/core/http/src/handling/methods.rs b/core/http/src/handling/methods.rs
index 998cfa5..5ca6211 100644
--- a/core/http/src/handling/methods.rs
+++ b/core/http/src/handling/methods.rs
@@ -1,6 +1,6 @@
 use std::{fmt::Display, str::FromStr};
 
-#[derive(PartialEq, Eq, Clone, Debug, Copy)]
+#[derive(PartialEq, Eq, Clone, Debug, Copy, PartialOrd, Ord)]
 pub enum Method {
     Get,
     Head,
diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index ba1cf37..adfb6b8 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -1,4 +1,4 @@
-use std::net::SocketAddr;
+// use std::net::SocketAddr;
 
 use super::{methods::Method, routes::Uri};
 
@@ -11,12 +11,12 @@ pub struct Request<'a> {
     // pub connection: ConnectionMeta,
 }
 
-struct ConnectionMeta {
-    remote: Option<SocketAddr>,
-    // certificates
-}
+// struct ConnectionMeta {
+//     remote: Option<SocketAddr>,
+//     // certificates
+// }
 
-#[derive(Clone, Debug, Copy)]
+#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord)]
 pub enum MediaType {
     Json,
     Plain,
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index dfdb496..a50e7d1 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -1,8 +1,6 @@
-use std::{
-    thread::available_parallelism, process::exit,
-};
+use std::thread::available_parallelism;
 
-use tokio::{net::TcpListener, signal::unix::{SignalKind, signal}, runtime, select};
+use tokio::{net::TcpListener, signal::unix::{SignalKind, signal}, select};
 
 use crate::{
     handlers::handlers::handle_connection,
@@ -21,7 +19,8 @@ pub struct Config {
 }
 
 impl<'a> Config {
-    pub fn mount(mut self, mountpoint: Uri<'static>, routes: Vec<Route<'static>>) -> Config {
+    pub fn mount(mut self, mountpoint: Uri<'static>, mut routes: Vec<Route<'static>>) -> Config {
+        routes.sort_by(|a, b| a.rank.cmp(&b.rank));
         let mut mount_message = format!("  >> \x1b[35m{}\x1b[0m\n", mountpoint);
         for (index, route) in routes.iter().enumerate() {
             let indent_sign;
diff --git a/site/src/main.rs b/site/src/main.rs
index fc87c26..e58195a 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -8,6 +8,15 @@ use http::handling::{
     routes::{Data, Route},
 };
 
+fn handle_static_hi(request: Request<'_>, data: Data) -> Outcome<Response, Status, Data> {
+    // Outcome::Success(Response { headers: vec![
+    //     format!("Content-Length: 4"), 
+    //     format!("Content-Type: text/plain")
+    // ], status: Some(Status::Ok), body: Box::new("jkl;") })
+    Outcome::Forward(data)
+}
+
+
 fn handler(request: Request<'_>, _data: Data) -> Outcome<Response, Status, Data> {
     let response = fileserver(request.uri.strip_prefix("static/").unwrap());
     let response = match response {
@@ -60,7 +69,7 @@ async fn main() {
         name: Some("file_server"),
         uri: "static/<path..>",
         method: Method::Get,
-        rank: 0,
+        rank: 1,
     };
 
     let post_test = Route {
@@ -72,7 +81,16 @@ async fn main() {
         rank: 0,
     };
 
+    let static_hi = Route {
+        format: None, 
+        handler: handle_static_hi,
+        name: Some("Handle_Static_hi"),
+        uri: "static/hi",
+        method: Method::Get,
+        rank: 0
+    };
+
     http::build("127.0.0.1:8000").await
-        .mount("/", vec![fileserver, post_test])
+        .mount("/", vec![fileserver, post_test, static_hi])
         .launch().await;
 }
diff --git a/site/static/hi b/site/static/hi
new file mode 100644
index 0000000..8bd6648
--- /dev/null
+++ b/site/static/hi
@@ -0,0 +1 @@
+asdf
-- 
GitLab


From 844c43899839161d91c3ff71a505b6f2a30b22c9 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sun, 28 May 2023 20:03:15 +0200
Subject: [PATCH 18/65] Add Get request form data function

---
 core/http/src/handling/request.rs | 76 ++++++++++++++++++++++++++++++-
 core/http/src/handling/routes.rs  |  4 +-
 site/src/main.rs                  | 28 +++++++++---
 3 files changed, 99 insertions(+), 9 deletions(-)

diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index adfb6b8..b3615f1 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -1,6 +1,11 @@
 // use std::net::SocketAddr;
 
-use super::{methods::Method, routes::Uri};
+use std::{collections::HashMap, error::Error, fmt::Display};
+
+use super::{
+    methods::Method,
+    routes::{Data, Uri},
+};
 
 type HeaderMap = Vec<String>;
 #[derive(Clone)]
@@ -23,6 +28,34 @@ pub enum MediaType {
     Html,
 }
 
+#[derive(Debug)]
+pub enum ParseErrors {
+    NoData,
+    BadData,
+}
+
+#[derive(Debug)]
+pub struct ParseFormError {
+    pub error: ParseErrors,
+}
+
+impl Display for ParseFormError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", self.error)
+    }
+}
+
+impl Display for ParseErrors {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            ParseErrors::NoData => write!(f, "No Data at key"),
+            ParseErrors::BadData => write!(f, "Bad Data at key"),
+        }
+    }
+}
+
+impl Error for ParseFormError {}
+
 impl Request<'_> {
     pub fn can_have_body(&self) -> bool {
         match self.method {
@@ -30,4 +63,45 @@ impl Request<'_> {
             _ => false,
         }
     }
+    pub fn get_form_keys(&self, keys: Vec<&str>) -> Result<HashMap<&str, &str>, ParseFormError> {
+        let data = self.uri.split_once("?");
+        if data == None {
+            return Err(ParseFormError {
+                error: ParseErrors::NoData,
+            });
+        }
+        let data = data
+            .unwrap()
+            .1
+            .split("&")
+            .map(|kvp| kvp.split_once("="))
+            .collect::<Vec<Option<(&str, &str)>>>();
+
+        let mut values: HashMap<&str, &str> = HashMap::new();
+        for kvp in data {
+            if kvp == None {
+                continue;
+            }
+            let kvp = kvp.unwrap();
+            values.insert(kvp.0, kvp.1);
+        }
+        let mut response = HashMap::new();
+        for key in keys {
+            let entry = values.get_key_value(key);
+            if entry == None {
+                return Err(ParseFormError {
+                    error: ParseErrors::NoData,
+                });
+            }
+            response.insert(*entry.unwrap().0, *entry.unwrap().1);
+        }
+        Ok(response)
+    }
+    pub fn get_form_keys_with_data(
+        &self,
+        _keys: Vec<&str>,
+        _data_buffer: Data,
+    ) -> Result<HashMap<&str, &str>, ParseFormError> {
+        todo!()
+    }
 }
diff --git a/core/http/src/handling/routes.rs b/core/http/src/handling/routes.rs
index 3d8b405..795e760 100644
--- a/core/http/src/handling/routes.rs
+++ b/core/http/src/handling/routes.rs
@@ -43,7 +43,9 @@ impl Route<'_> {
             } else {
                 return false;
             };
-            if true_str.starts_with("<") && true_str.ends_with("..>") {
+            if (true_str.starts_with("<") && true_str.ends_with("..>"))
+                || (comp_str.starts_with(true_str) && comp_str.contains("?"))
+            {
                 return true;
             }
             if true_str.starts_with("<") && true_str.ends_with(">") {
diff --git a/site/src/main.rs b/site/src/main.rs
index e58195a..22897e2 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -1,4 +1,4 @@
-use std::path::PathBuf;
+use std::{path::PathBuf, collections::HashMap};
 
 use http::handling::{
     file_handlers::NamedFile,
@@ -8,12 +8,26 @@ use http::handling::{
     routes::{Data, Route},
 };
 
-fn handle_static_hi(request: Request<'_>, data: Data) -> Outcome<Response, Status, Data> {
-    // Outcome::Success(Response { headers: vec![
-    //     format!("Content-Length: 4"), 
-    //     format!("Content-Type: text/plain")
-    // ], status: Some(Status::Ok), body: Box::new("jkl;") })
-    Outcome::Forward(data)
+fn hashmap_to_string(map: &HashMap<&str, &str>) -> String {
+    let mut result = String::new();
+    for (key, value) in map {
+        result.push_str(key);
+        result.push('=');
+        result.push_str(value);
+        result.push(';');
+    }
+    result.pop(); // Remove the trailing semicolon if desired
+    result
+}
+
+
+fn handle_static_hi(request: Request<'_>, _data: Data) -> Outcome<Response, Status, Data> {
+    let response = hashmap_to_string(&request.get_form_keys(vec!["asdf", "jkj"]).unwrap());
+    Outcome::Success(Response { headers: vec![
+        format!("Content-Length: {}", response.len()), 
+        format!("Content-Type: text/plain")
+    ], status: Some(Status::Ok), body: Box::new(response) })
+    // Outcome::Forward(data)
 }
 
 
-- 
GitLab


From 2b30adc7e03eb236007e8a481bc1a6248d005478 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Mon, 29 May 2023 14:19:46 +0200
Subject: [PATCH 19/65] Cleaning up the codebase removing `unwraps()` and
 replacing them with propper error handling remove unnecessary `clone()` calls

---
 core/http/src/handlers/handlers.rs | 77 ++++++++++++++++++++----------
 core/http/src/handling/request.rs  | 24 +++++-----
 core/http/src/handling/routes.rs   |  2 +-
 core/http/src/setup.rs             | 28 ++++++++---
 site/src/main.rs                   | 27 ++++++-----
 5 files changed, 103 insertions(+), 55 deletions(-)

diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
index 0cf7d48..d9ba8df 100755
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -15,29 +15,45 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
     let mut http_request: Vec<String> = Vec::with_capacity(100);
     loop {
         let mut buffer = String::new();
-        let _ = buf_reader.read_line(&mut buffer).await.unwrap();
+        if let Err(_) = buf_reader.read_line(&mut buffer).await {
+            eprintln!("\x1b[31mAborting due to invalid UTF-8 in request header\x1b[0m");
+            return;
+        }
         if buffer == "\r\n" {
             break;
         }
         http_request.push(buffer);
     }
 
-    println!("{:#?}", http_request);
+    // println!("{:#?}", http_request);
 
-    let request_status_line = http_request.get(0);
-    if request_status_line == None {
+    let request_status_line = if let Some(status_line) = http_request.get(0).cloned() {
+        status_line
+    } else {
+        eprintln!("\x1b[31mAborting due to missing headers\x1b[0m");
         return;
-    }
-    let request_status_line = request_status_line.unwrap();
+    };
     let request = Request {
-        uri: &request_status_line.split(" ").nth(1).unwrap(),
-        headers: http_request.clone(),
-        method: request_status_line
+        uri: if let Some(uri) = &request_status_line.split(" ").nth(1) {
+            *uri
+        } else {
+            eprintln!("\x1b[31mAborting due to invalid status line\x1b[0m");
+            return;
+        },
+        headers: http_request,
+        method: if let Some(method) = request_status_line
             .split(" ")
-            .next()
-            .unwrap()
-            .parse()
-            .unwrap(),
+            .next() {
+            if let Ok(ok) = method.parse() {
+                ok
+            } else {
+                eprintln!("\x1b[31mAborting due to invalid request method\x1b[0m");
+                return;
+            }
+        } else {
+            eprintln!("\x1b[31mAborting due to invalid status line\x1b[0m");
+            return;
+        }
     };
 
     let mut data = Data {
@@ -48,8 +64,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
         let length = if let Some(len) = request
             .headers
             .iter()
-            .filter(|header| header.contains("Content-Length: "))
-            .clone()
+            .filter(|header| header.starts_with("Content-Length: "))
             .map(|header| {
                 let header = header.strip_prefix("Content-Length: ").unwrap();
                 header.trim().parse::<usize>()
@@ -64,12 +79,17 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
         } else {
             0
         };
+
         let mut buffer: Vec<u8> = vec![];
         buf_reader.read_buf(&mut buffer).await.unwrap();
         if buffer.len() != length {
-            let respone = len_not_defined(Status::LengthRequired).await;
-            stream.write_all(respone.0.as_bytes()).await.unwrap();
-            stream.write(&respone.1).await.unwrap();
+            let respone = len_not_defined(Status::LengthRequired);
+            let mut response = respone.0.as_bytes().to_vec();
+            response.extend_from_slice(&respone.1);
+            if let Err(e) = stream.write_all(&response).await {
+                eprintln!("\x1b[31mError {e} occured when trying to write answer to TCP-Stream for Client, aborting\x1b[0m");
+                return;
+            }
             return;
         }
         data.is_complete = true;
@@ -107,22 +127,27 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
     let response = match handled_response {
         Some(val) => match val {
             Outcome::Success(success) => (
-                format!("HTTP/1.1 {}\r\n", success.status.unwrap())
+                format!("HTTP/1.1 {}\r\n", success.status.unwrap_or(Status::Ok))
                     + &success.headers.join("\r\n")
                     + "\r\n\r\n",
                 success.body.get_data(),
             ),
-            Outcome::Failure(error) => failure_handler(error).await,
-            Outcome::Forward(_) => failure_handler(Status::NotFound).await,
+            Outcome::Failure(error) => failure_handler(error),
+            Outcome::Forward(_) => failure_handler(Status::NotFound),
         },
-        None => failure_handler(Status::NotFound).await,
+        None => failure_handler(Status::NotFound),
     };
 
-    stream.write_all(response.0.as_bytes()).await.unwrap();
-    stream.write(&response.1).await.unwrap();
+    let mut resp = response.0.as_bytes().to_vec();
+    resp.extend_from_slice(&response.1);
+    if let Err(e) = stream.write_all(&resp).await {
+        eprintln!("\x1b[31mError {e} occured when trying to write answer to TCP-Stream for Client, aborting\x1b[0m");
+        return;
+    }
+    return;
 }
 
-async fn failure_handler(status: Status) -> (String, Vec<u8>) {
+fn failure_handler(status: Status) -> (String, Vec<u8>) {
     let page_404 = NamedFile::open(PathBuf::from("404.html")).unwrap();
     (
         format!(
@@ -135,7 +160,7 @@ async fn failure_handler(status: Status) -> (String, Vec<u8>) {
     )
 }
 
-async fn len_not_defined(status: Status) -> (String, Vec<u8>) {
+fn len_not_defined(status: Status) -> (String, Vec<u8>) {
     let page_411 = NamedFile::open(PathBuf::from("411.html")).unwrap();
     (
         format!(
diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index b3615f1..7fa10b4 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -64,14 +64,14 @@ impl Request<'_> {
         }
     }
     pub fn get_form_keys(&self, keys: Vec<&str>) -> Result<HashMap<&str, &str>, ParseFormError> {
-        let data = self.uri.split_once("?");
-        if data == None {
+        let data = if let Some(val) = self.uri.split_once("?") {
+            val
+        } else {
             return Err(ParseFormError {
                 error: ParseErrors::NoData,
             });
-        }
+        };
         let data = data
-            .unwrap()
             .1
             .split("&")
             .map(|kvp| kvp.split_once("="))
@@ -79,21 +79,23 @@ impl Request<'_> {
 
         let mut values: HashMap<&str, &str> = HashMap::new();
         for kvp in data {
-            if kvp == None {
+            let kvp = if let Some(kvp) = kvp {
+                kvp
+            } else {
                 continue;
-            }
-            let kvp = kvp.unwrap();
+            };
             values.insert(kvp.0, kvp.1);
         }
         let mut response = HashMap::new();
         for key in keys {
-            let entry = values.get_key_value(key);
-            if entry == None {
+            let entry = if let Some(val) = values.get_key_value(key) {
+                val
+            } else {
                 return Err(ParseFormError {
                     error: ParseErrors::NoData,
                 });
-            }
-            response.insert(*entry.unwrap().0, *entry.unwrap().1);
+            };
+            response.insert(*entry.0, *entry.1);
         }
         Ok(response)
     }
diff --git a/core/http/src/handling/routes.rs b/core/http/src/handling/routes.rs
index 795e760..9ded1ce 100644
--- a/core/http/src/handling/routes.rs
+++ b/core/http/src/handling/routes.rs
@@ -35,7 +35,7 @@ impl Route<'_> {
             format: routeinfo.format,
         }
     }
-    pub fn compare_uri(self, uri: Uri) -> bool {
+    pub fn compare_uri(&self, uri: Uri) -> bool {
         let mut iter_comp_str = uri.split("/");
         for true_str in self.uri.split("/") {
             let comp_str = if let Some(str) = iter_comp_str.next() {
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index a50e7d1..9f57e76 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -19,7 +19,22 @@ pub struct Config {
 }
 
 impl<'a> Config {
-    pub fn mount(mut self, mountpoint: Uri<'static>, mut routes: Vec<Route<'static>>) -> Config {
+    fn check_mountpoint_taken(&self, to_insert: Uri) -> bool {
+        if let Some(to_check) = &self.mountpoints {
+            let len = to_check.len();
+            for i in 0..len {
+                if to_check[i].mountpoint == to_insert {
+                    return true; // Found a duplicate &str
+                }
+            }
+        };
+        false
+    }
+    pub fn mount(mut self, mountpoint: Uri<'static>, mut routes: Vec<Route<'static>>) -> Self {
+        if self.check_mountpoint_taken(mountpoint) {
+            eprintln!("\x1b[31mTrying to reassign a mountpoint, mountpoint `{mountpoint}` already taken.\x1b[0m");
+            return self;
+        }
         routes.sort_by(|a, b| a.rank.cmp(&b.rank));
         let mut mount_message = format!("  >> \x1b[35m{}\x1b[0m\n", mountpoint);
         for (index, route) in routes.iter().enumerate() {
@@ -58,10 +73,7 @@ impl<'a> Config {
                     println!("Shutting down...");
                     break;
                 }
-
-                income = self.address.accept() => {
-                    let income = income.unwrap();
-                    let (socket, _) = income;
+                Ok((socket, _)) = self.address.accept() => {
                     let mountpoints = self.mountpoints.clone().unwrap();
                     tokio::spawn(async move { handle_connection(socket, mountpoints).await; });
                 }
@@ -70,7 +82,11 @@ impl<'a> Config {
     }
 }
 pub async fn build(ip: &str) -> Config {
-    let listener = TcpListener::bind(ip).await.unwrap();
+    let listener = if let Ok(listener) = TcpListener::bind(ip).await {
+        listener
+    } else {
+        panic!("\x1b[31mCould't bind Listener to address\x1b[0m");
+    };
     let ip = ip.splitn(2, ":").collect::<Vec<&str>>();
     if ip.len() != 2 {
         panic!("Invalid IP Address");
diff --git a/site/src/main.rs b/site/src/main.rs
index 22897e2..48d109d 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -1,4 +1,4 @@
-use std::{path::PathBuf, collections::HashMap};
+use std::{collections::HashMap, path::PathBuf};
 
 use http::handling::{
     file_handlers::NamedFile,
@@ -20,17 +20,19 @@ fn hashmap_to_string(map: &HashMap<&str, &str>) -> String {
     result
 }
 
-
 fn handle_static_hi(request: Request<'_>, _data: Data) -> Outcome<Response, Status, Data> {
     let response = hashmap_to_string(&request.get_form_keys(vec!["asdf", "jkj"]).unwrap());
-    Outcome::Success(Response { headers: vec![
-        format!("Content-Length: {}", response.len()), 
-        format!("Content-Type: text/plain")
-    ], status: Some(Status::Ok), body: Box::new(response) })
+    Outcome::Success(Response {
+        headers: vec![
+            format!("Content-Length: {}", response.len()),
+            format!("Content-Type: text/plain"),
+        ],
+        status: Some(Status::Ok),
+        body: Box::new(response),
+    })
     // Outcome::Forward(data)
 }
 
-
 fn handler(request: Request<'_>, _data: Data) -> Outcome<Response, Status, Data> {
     let response = fileserver(request.uri.strip_prefix("static/").unwrap());
     let response = match response {
@@ -96,15 +98,18 @@ async fn main() {
     };
 
     let static_hi = Route {
-        format: None, 
+        format: None,
         handler: handle_static_hi,
         name: Some("Handle_Static_hi"),
         uri: "static/hi",
         method: Method::Get,
-        rank: 0
+        rank: 0,
     };
 
-    http::build("127.0.0.1:8000").await
+    http::build("127.0.0.1:8000")
+        .await
         .mount("/", vec![fileserver, post_test, static_hi])
-        .launch().await;
+        .mount("/post/", vec![post_test])
+        .launch()
+        .await;
 }
-- 
GitLab


From 21a170df00884fcb1d93f7352757149829bc89c2 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Mon, 29 May 2023 17:11:18 +0200
Subject: [PATCH 20/65] Add HEAD Method support

---
 core/http/src/handlers/handlers.rs | 11 ++++++++---
 site/src/main.rs                   |  9 +++++++--
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
index d9ba8df..f81441c 100755
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -6,7 +6,7 @@ use crate::handling::{
     file_handlers::NamedFile,
     request::Request,
     response::{Outcome, Response, ResponseBody, Status},
-    routes::Data,
+    routes::Data, methods::Method,
 };
 use crate::setup::MountPoint;
 
@@ -103,7 +103,8 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
         }
         let mounted_request_uri = request.uri.strip_prefix(mountpoint.mountpoint).unwrap();
         for route in mountpoint.routes {
-            if route.method != request.method {
+            if (route.method != request.method) && 
+            ((route.method != Method::Get) && (request.method == Method::Head)) {
                 continue;
             }
             if !route.compare_uri(mounted_request_uri) {
@@ -130,7 +131,11 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
                 format!("HTTP/1.1 {}\r\n", success.status.unwrap_or(Status::Ok))
                     + &success.headers.join("\r\n")
                     + "\r\n\r\n",
-                success.body.get_data(),
+                if request.method == Method::Head {
+                    vec![]
+                } else {
+                    success.body.get_data()
+                }
             ),
             Outcome::Failure(error) => failure_handler(error),
             Outcome::Forward(_) => failure_handler(Status::NotFound),
diff --git a/site/src/main.rs b/site/src/main.rs
index 48d109d..6e560d4 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -20,8 +20,13 @@ fn hashmap_to_string(map: &HashMap<&str, &str>) -> String {
     result
 }
 
-fn handle_static_hi(request: Request<'_>, _data: Data) -> Outcome<Response, Status, Data> {
-    let response = hashmap_to_string(&request.get_form_keys(vec!["asdf", "jkj"]).unwrap());
+fn handle_static_hi(request: Request<'_>, data: Data) -> Outcome<Response, Status, Data> {
+    let keys = if let Ok(keys) = request.get_form_keys(vec!["asdf", "jkl;"]) {
+        keys
+    } else {
+        return Outcome::Forward(data);
+    };
+    let response = hashmap_to_string(&keys);
     Outcome::Success(Response {
         headers: vec![
             format!("Content-Length: {}", response.len()),
-- 
GitLab


From 8c05e9c37c9eca247c21e680f3afb36cd100674b Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Mon, 29 May 2023 17:52:57 +0200
Subject: [PATCH 21/65] rename `get_form_keys` to `get_get_form_keys`

---
 core/http/src/handling/request.rs | 8 +++++++-
 site/src/main.rs                  | 2 +-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index 7fa10b4..f2d4e10 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -2,7 +2,10 @@
 
 use std::{collections::HashMap, error::Error, fmt::Display};
 
+use mime::Mime;
+
 use super::{
+    file_handlers::find_mimetype,
     methods::Method,
     routes::{Data, Uri},
 };
@@ -63,7 +66,10 @@ impl Request<'_> {
             _ => false,
         }
     }
-    pub fn get_form_keys(&self, keys: Vec<&str>) -> Result<HashMap<&str, &str>, ParseFormError> {
+    pub fn get_get_form_keys(
+        &self,
+        keys: Vec<&str>,
+    ) -> Result<HashMap<&str, &str>, ParseFormError> {
         let data = if let Some(val) = self.uri.split_once("?") {
             val
         } else {
diff --git a/site/src/main.rs b/site/src/main.rs
index 6e560d4..b8e4a50 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -21,7 +21,7 @@ fn hashmap_to_string(map: &HashMap<&str, &str>) -> String {
 }
 
 fn handle_static_hi(request: Request<'_>, data: Data) -> Outcome<Response, Status, Data> {
-    let keys = if let Ok(keys) = request.get_form_keys(vec!["asdf", "jkl;"]) {
+    let keys = if let Ok(keys) = request.get_get_form_keys(vec!["asdf", "jkl;"]) {
         keys
     } else {
         return Outcome::Forward(data);
-- 
GitLab


From d377be4bf6fbfc9d7495d2f6168b1bcebbdb3ce6 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Thu, 1 Jun 2023 21:38:32 +0200
Subject: [PATCH 22/65] Approach from request forms/data add a get request with
 form

---
 core/http/src/handling/request.rs | 4 +---
 site/404.html                     | 7 +++++++
 site/src/main.rs                  | 4 ++--
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index f2d4e10..efed546 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -2,10 +2,7 @@
 
 use std::{collections::HashMap, error::Error, fmt::Display};
 
-use mime::Mime;
-
 use super::{
-    file_handlers::find_mimetype,
     methods::Method,
     routes::{Data, Uri},
 };
@@ -66,6 +63,7 @@ impl Request<'_> {
             _ => false,
         }
     }
+    // pub fn get_post_form_key<T: FromRequest>(&self, data: Data) -> T {}
     pub fn get_get_form_keys(
         &self,
         keys: Vec<&str>,
diff --git a/site/404.html b/site/404.html
index d4c09f4..0a1a4ed 100644
--- a/site/404.html
+++ b/site/404.html
@@ -15,5 +15,12 @@
       <input type="text" id="asdf" name="message" />
       <button type="submit">Send</button>
     </form>
+    <form action="/static/hi" method="get">
+      <label for="jump">Enter asdf</label>
+      <input type="text" id="jump" name="asdf" />
+      <label for="jkl">Enter jkl;</label>
+      <input type="text" id="jkl" name="jkl" />
+      <button type="submit">Send</button>
+    </form>
   </body>
 </html>
diff --git a/site/src/main.rs b/site/src/main.rs
index b8e4a50..deb31d6 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -21,7 +21,7 @@ fn hashmap_to_string(map: &HashMap<&str, &str>) -> String {
 }
 
 fn handle_static_hi(request: Request<'_>, data: Data) -> Outcome<Response, Status, Data> {
-    let keys = if let Ok(keys) = request.get_get_form_keys(vec!["asdf", "jkl;"]) {
+    let keys = if let Ok(keys) = request.get_get_form_keys(vec!["asdf", "jkl"]) {
         keys
     } else {
         return Outcome::Forward(data);
@@ -111,7 +111,7 @@ async fn main() {
         rank: 0,
     };
 
-    http::build("127.0.0.1:8000")
+    http::build("192.168.178.32:8000")
         .await
         .mount("/", vec![fileserver, post_test, static_hi])
         .mount("/post/", vec![post_test])
-- 
GitLab


From 99f0bbdf127f2d77d1c08cabd2d1dd5d247d6908 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Fri, 2 Jun 2023 21:54:05 +0200
Subject: [PATCH 23/65] Introduced the MIME enum, not populated

---
 core/http/src/handling/request.rs | 11 ++++++-----
 core/http/src/utils/mime.rs       |  1 +
 core/http/src/utils/mod.rs        |  1 +
 3 files changed, 8 insertions(+), 5 deletions(-)
 create mode 100644 core/http/src/utils/mime.rs

diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index efed546..f90bacb 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -2,6 +2,11 @@
 
 use std::{collections::HashMap, error::Error, fmt::Display};
 
+trait FromPost {}
+
+impl FromPost for &str {}
+impl FromPost for Vec<u8> {}
+
 use super::{
     methods::Method,
     routes::{Data, Uri},
@@ -103,11 +108,7 @@ impl Request<'_> {
         }
         Ok(response)
     }
-    pub fn get_form_keys_with_data(
-        &self,
-        _keys: Vec<&str>,
-        _data_buffer: Data,
-    ) -> Result<HashMap<&str, &str>, ParseFormError> {
+    pub fn get_post_form_key(&self, key: &str, data: Data) {
         todo!()
     }
 }
diff --git a/core/http/src/utils/mime.rs b/core/http/src/utils/mime.rs
new file mode 100644
index 0000000..9d17bfb
--- /dev/null
+++ b/core/http/src/utils/mime.rs
@@ -0,0 +1 @@
+enum Mime {}
diff --git a/core/http/src/utils/mod.rs b/core/http/src/utils/mod.rs
index e69de29..909a531 100644
--- a/core/http/src/utils/mod.rs
+++ b/core/http/src/utils/mod.rs
@@ -0,0 +1 @@
+pub mod mime;
-- 
GitLab


From 2306b7b2eb7381021a2b277099879c0c11d86e25 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sat, 3 Jun 2023 20:18:05 +0200
Subject: [PATCH 24/65] add mime enum, remove mime::Mime dependency

---
 core/http/Cargo.lock                    |   84 +-
 core/http/Cargo.toml                    |    2 +-
 core/http/src/handling/file_handlers.rs |   23 +-
 core/http/src/handling/response.rs      |    8 +-
 core/http/src/utils/mime.rs             |    1 -
 core/http/src/utils/mime/map.rs         | 2022 +++++++++++
 core/http/src/utils/mime/mime_enum.rs   | 4095 +++++++++++++++++++++++
 core/http/src/utils/mime/mod.rs         |    2 +
 generatersenum.py                       |   73 +
 site/Cargo.lock                         |   84 +-
 small.csv                               |   20 +
 11 files changed, 6374 insertions(+), 40 deletions(-)
 delete mode 100644 core/http/src/utils/mime.rs
 create mode 100644 core/http/src/utils/mime/map.rs
 create mode 100644 core/http/src/utils/mime/mime_enum.rs
 create mode 100644 core/http/src/utils/mime/mod.rs
 create mode 100644 generatersenum.py
 create mode 100644 small.csv

diff --git a/core/http/Cargo.lock b/core/http/Cargo.lock
index fd71f4c..8496ac6 100644
--- a/core/http/Cargo.lock
+++ b/core/http/Cargo.lock
@@ -39,7 +39,7 @@ dependencies = [
 name = "http"
 version = "0.1.0"
 dependencies = [
- "mime",
+ "phf",
  "tokio",
 ]
 
@@ -68,12 +68,6 @@ dependencies = [
  "cfg-if",
 ]
 
-[[package]]
-name = "mime"
-version = "0.3.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
-
 [[package]]
 name = "mio"
 version = "0.8.6"
@@ -119,6 +113,48 @@ dependencies = [
  "windows-sys 0.45.0",
 ]
 
+[[package]]
+name = "phf"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c"
+dependencies = [
+ "phf_macros",
+ "phf_shared",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf"
+dependencies = [
+ "phf_shared",
+ "rand",
+]
+
+[[package]]
+name = "phf_macros"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92aacdc5f16768709a569e913f7451034034178b05bdc8acda226659a3dccc66"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676"
+dependencies = [
+ "siphasher",
+]
+
 [[package]]
 name = "pin-project-lite"
 version = "0.2.9"
@@ -143,6 +179,21 @@ dependencies = [
  "proc-macro2",
 ]
 
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+
 [[package]]
 name = "redox_syscall"
 version = "0.2.16"
@@ -167,6 +218,12 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "siphasher"
+version = "0.3.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
+
 [[package]]
 name = "smallvec"
 version = "1.10.0"
@@ -183,6 +240,17 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
 [[package]]
 name = "syn"
 version = "2.0.15"
@@ -221,7 +289,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 2.0.15",
 ]
 
 [[package]]
diff --git a/core/http/Cargo.toml b/core/http/Cargo.toml
index 4bc7eaf..45da492 100644
--- a/core/http/Cargo.toml
+++ b/core/http/Cargo.toml
@@ -6,5 +6,5 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-mime = "0.3.17"
 tokio = { version = "1.28.2", features = ["full"] }
+phf = { version = "0.11", features = ["macros"] }
diff --git a/core/http/src/handling/file_handlers.rs b/core/http/src/handling/file_handlers.rs
index c2945ae..9e34054 100644
--- a/core/http/src/handling/file_handlers.rs
+++ b/core/http/src/handling/file_handlers.rs
@@ -1,8 +1,9 @@
 use std::{fs, path::PathBuf};
 
-use mime::Mime;
-
-use crate::handling::response::{ResponseBody, Status};
+use crate::{
+    handling::response::{ResponseBody, Status},
+    utils::mime::mime_enum::Mime,
+};
 
 #[derive(Debug)]
 pub struct NamedFile {
@@ -37,7 +38,7 @@ impl NamedFile {
         };
         Ok(NamedFile {
             content_len: data.len(),
-            content_type: find_mimetype(path.to_str().unwrap()),
+            content_type: Mime::from_filename(path.to_str().unwrap()),
             content: data,
         })
     }
@@ -53,17 +54,3 @@ fn proove_path(path: PathBuf) -> PathBuf {
             .join("/"),
     )
 }
-
-pub fn find_mimetype(filename: &str) -> Mime {
-    match filename.split('.').last() {
-        Some(v) => match v {
-            "png" => mime::IMAGE_PNG,
-            "jpg" => mime::IMAGE_JPEG,
-            "json" => mime::APPLICATION_JSON,
-            "html" => mime::TEXT_HTML,
-            "css" => mime::TEXT_CSS,
-            &_ => mime::TEXT_PLAIN,
-        },
-        None => mime::TEXT_PLAIN,
-    }
-}
diff --git a/core/http/src/handling/response.rs b/core/http/src/handling/response.rs
index 446c8af..2f7fdcf 100644
--- a/core/http/src/handling/response.rs
+++ b/core/http/src/handling/response.rs
@@ -1,6 +1,6 @@
 use std::fmt::Display;
 
-use mime::Mime;
+use crate::utils::mime::mime_enum::Mime;
 
 use super::routes::Body;
 
@@ -24,7 +24,7 @@ impl ResponseBody for Body {
         self.body.clone()
     }
     fn get_mime(&self) -> Mime {
-        mime::TEXT_PLAIN
+        Mime::TextPlain
     }
 
     fn get_len(&self) -> usize {
@@ -38,7 +38,7 @@ impl ResponseBody for &str {
     }
 
     fn get_mime(&self) -> Mime {
-        mime::TEXT_PLAIN
+        Mime::TextPlain
     }
 
     fn get_len(&self) -> usize {
@@ -52,7 +52,7 @@ impl ResponseBody for String {
     }
 
     fn get_mime(&self) -> Mime {
-        mime::TEXT_PLAIN
+        Mime::TextPlain
     }
 
     fn get_len(&self) -> usize {
diff --git a/core/http/src/utils/mime.rs b/core/http/src/utils/mime.rs
deleted file mode 100644
index 9d17bfb..0000000
--- a/core/http/src/utils/mime.rs
+++ /dev/null
@@ -1 +0,0 @@
-enum Mime {}
diff --git a/core/http/src/utils/mime/map.rs b/core/http/src/utils/mime/map.rs
new file mode 100644
index 0000000..7117314
--- /dev/null
+++ b/core/http/src/utils/mime/map.rs
@@ -0,0 +1,2022 @@
+use super::mime_enum::Mime;
+
+pub static MIME_MAP: phf::Map<&'static str, Mime> = phf::phf_map! {
+    "application/1d-interleaved-parityfec" => Mime::Application1dInterleavedParityfec,
+    "application/3gpdash-qoe-report+xml" => Mime::Application3gpdashQoeReportXml,
+    "application/3gppHal+json" => Mime::Application3gpphalJson,
+    "application/3gppHalForms+json" => Mime::Application3gpphalformsJson,
+    "application/3gpp-ims+xml" => Mime::Application3gppImsXml,
+    "application/A2L" => Mime::ApplicationA2l,
+    "application/ace+cbor" => Mime::ApplicationAceCbor,
+    "application/ace+json" => Mime::ApplicationAceJson,
+    "application/activemessage" => Mime::ApplicationActivemessage,
+    "application/activity+json" => Mime::ApplicationActivityJson,
+    "application/aif+cbor" => Mime::ApplicationAifCbor,
+    "application/aif+json" => Mime::ApplicationAifJson,
+    "application/alto-cdni+json" => Mime::ApplicationAltoCdniJson,
+    "application/alto-cdnifilter+json" => Mime::ApplicationAltoCdnifilterJson,
+    "application/alto-costmap+json" => Mime::ApplicationAltoCostmapJson,
+    "application/alto-costmapfilter+json" => Mime::ApplicationAltoCostmapfilterJson,
+    "application/alto-directory+json" => Mime::ApplicationAltoDirectoryJson,
+    "application/alto-endpointprop+json" => Mime::ApplicationAltoEndpointpropJson,
+    "application/alto-endpointpropparams+json" => Mime::ApplicationAltoEndpointpropparamsJson,
+    "application/alto-endpointcost+json" => Mime::ApplicationAltoEndpointcostJson,
+    "application/alto-endpointcostparams+json" => Mime::ApplicationAltoEndpointcostparamsJson,
+    "application/alto-error+json" => Mime::ApplicationAltoErrorJson,
+    "application/alto-networkmapfilter+json" => Mime::ApplicationAltoNetworkmapfilterJson,
+    "application/alto-networkmap+json" => Mime::ApplicationAltoNetworkmapJson,
+    "application/alto-propmap+json" => Mime::ApplicationAltoPropmapJson,
+    "application/alto-propmapparams+json" => Mime::ApplicationAltoPropmapparamsJson,
+    "application/alto-updatestreamcontrol+json" => Mime::ApplicationAltoUpdatestreamcontrolJson,
+    "application/alto-updatestreamparams+json" => Mime::ApplicationAltoUpdatestreamparamsJson,
+    "application/AML" => Mime::ApplicationAml,
+    "application/andrew-inset" => Mime::ApplicationAndrewInset,
+    "application/applefile" => Mime::ApplicationApplefile,
+    "application/at+jwt" => Mime::ApplicationAtJwt,
+    "application/ATF" => Mime::ApplicationAtf,
+    "application/ATFX" => Mime::ApplicationAtfx,
+    "application/atom+xml" => Mime::ApplicationAtomXml,
+    "application/atomcat+xml" => Mime::ApplicationAtomcatXml,
+    "application/atomdeleted+xml" => Mime::ApplicationAtomdeletedXml,
+    "application/atomicmail" => Mime::ApplicationAtomicmail,
+    "application/atomsvc+xml" => Mime::ApplicationAtomsvcXml,
+    "application/atsc-dwd+xml" => Mime::ApplicationAtscDwdXml,
+    "application/atsc-dynamic-event-message" => Mime::ApplicationAtscDynamicEventMessage,
+    "application/atsc-held+xml" => Mime::ApplicationAtscHeldXml,
+    "application/atsc-rdt+json" => Mime::ApplicationAtscRdtJson,
+    "application/atsc-rsat+xml" => Mime::ApplicationAtscRsatXml,
+    "application/ATXML" => Mime::ApplicationAtxml,
+    "application/auth-policy+xml" => Mime::ApplicationAuthPolicyXml,
+    "application/automationml-aml+xml" => Mime::ApplicationAutomationmlAmlXml,
+    "application/automationml-amlx+zip" => Mime::ApplicationAutomationmlAmlxZip,
+    "application/bacnet-xdd+zip" => Mime::ApplicationBacnetXddZip,
+    "application/batch-SMTP" => Mime::ApplicationBatchSmtp,
+    "application/beep+xml" => Mime::ApplicationBeepXml,
+    "application/calendar+json" => Mime::ApplicationCalendarJson,
+    "application/calendar+xml" => Mime::ApplicationCalendarXml,
+    "application/call-completion" => Mime::ApplicationCallCompletion,
+    "application/CALS-1840" => Mime::ApplicationCals1840,
+    "application/captive+json" => Mime::ApplicationCaptiveJson,
+    "application/cbor" => Mime::ApplicationCbor,
+    "application/cbor-seq" => Mime::ApplicationCborSeq,
+    "application/cccex" => Mime::ApplicationCccex,
+    "application/ccmp+xml" => Mime::ApplicationCcmpXml,
+    "application/ccxml+xml" => Mime::ApplicationCcxmlXml,
+    "application/cda+xml" => Mime::ApplicationCdaXml,
+    "application/CDFX+XML" => Mime::ApplicationCdfxXml,
+    "application/cdmi-capability" => Mime::ApplicationCdmiCapability,
+    "application/cdmi-container" => Mime::ApplicationCdmiContainer,
+    "application/cdmi-domain" => Mime::ApplicationCdmiDomain,
+    "application/cdmi-object" => Mime::ApplicationCdmiObject,
+    "application/cdmi-queue" => Mime::ApplicationCdmiQueue,
+    "application/cdni" => Mime::ApplicationCdni,
+    "application/CEA" => Mime::ApplicationCea,
+    "application/cea-2018+xml" => Mime::ApplicationCea2018Xml,
+    "application/cellml+xml" => Mime::ApplicationCellmlXml,
+    "application/cfw" => Mime::ApplicationCfw,
+    "application/city+json" => Mime::ApplicationCityJson,
+    "application/clr" => Mime::ApplicationClr,
+    "application/clue_info+xml" => Mime::ApplicationClueInfoXml,
+    "application/clue+xml" => Mime::ApplicationClueXml,
+    "application/cms" => Mime::ApplicationCms,
+    "application/cnrp+xml" => Mime::ApplicationCnrpXml,
+    "application/coap-group+json" => Mime::ApplicationCoapGroupJson,
+    "application/coap-payload" => Mime::ApplicationCoapPayload,
+    "application/commonground" => Mime::ApplicationCommonground,
+    "application/concise-problem-details+cbor" => Mime::ApplicationConciseProblemDetailsCbor,
+    "application/conference-info+xml" => Mime::ApplicationConferenceInfoXml,
+    "application/cpl+xml" => Mime::ApplicationCplXml,
+    "application/cose" => Mime::ApplicationCose,
+    "application/cose-key" => Mime::ApplicationCoseKey,
+    "application/cose-key-set" => Mime::ApplicationCoseKeySet,
+    "application/cose-x509" => Mime::ApplicationCoseX509,
+    "application/csrattrs" => Mime::ApplicationCsrattrs,
+    "application/csta+xml" => Mime::ApplicationCstaXml,
+    "application/CSTAdata+xml" => Mime::ApplicationCstadataXml,
+    "application/csvm+json" => Mime::ApplicationCsvmJson,
+    "application/cwl" => Mime::ApplicationCwl,
+    "application/cwl+json" => Mime::ApplicationCwlJson,
+    "application/cwt" => Mime::ApplicationCwt,
+    "application/cybercash" => Mime::ApplicationCybercash,
+    "application/dash+xml" => Mime::ApplicationDashXml,
+    "application/dash-patch+xml" => Mime::ApplicationDashPatchXml,
+    "application/dashdelta" => Mime::ApplicationDashdelta,
+    "application/davmount+xml" => Mime::ApplicationDavmountXml,
+    "application/dca-rft" => Mime::ApplicationDcaRft,
+    "application/DCD" => Mime::ApplicationDcd,
+    "application/dec-dx" => Mime::ApplicationDecDx,
+    "application/dialog-info+xml" => Mime::ApplicationDialogInfoXml,
+    "application/dicom" => Mime::ApplicationDicom,
+    "application/dicom+json" => Mime::ApplicationDicomJson,
+    "application/dicom+xml" => Mime::ApplicationDicomXml,
+    "application/DII" => Mime::ApplicationDii,
+    "application/DIT" => Mime::ApplicationDit,
+    "application/dns" => Mime::ApplicationDns,
+    "application/dns+json" => Mime::ApplicationDnsJson,
+    "application/dns-message" => Mime::ApplicationDnsMessage,
+    "application/dots+cbor" => Mime::ApplicationDotsCbor,
+    "application/dpop+jwt" => Mime::ApplicationDpopJwt,
+    "application/dskpp+xml" => Mime::ApplicationDskppXml,
+    "application/dssc+der" => Mime::ApplicationDsscDer,
+    "application/dssc+xml" => Mime::ApplicationDsscXml,
+    "application/dvcs" => Mime::ApplicationDvcs,
+    "application/EDI-consent" => Mime::ApplicationEdiConsent,
+    "application/EDIFACT" => Mime::ApplicationEdifact,
+    "application/EDI-X12" => Mime::ApplicationEdiX12,
+    "application/efi" => Mime::ApplicationEfi,
+    "application/elm+json" => Mime::ApplicationElmJson,
+    "application/elm+xml" => Mime::ApplicationElmXml,
+    "application/EmergencyCallData.cap+xml" => Mime::ApplicationEmergencycalldataCapXml,
+    "application/EmergencyCallData.Comment+xml" => Mime::ApplicationEmergencycalldataCommentXml,
+    "application/EmergencyCallData.Control+xml" => Mime::ApplicationEmergencycalldataControlXml,
+    "application/EmergencyCallData.DeviceInfo+xml" => Mime::ApplicationEmergencycalldataDeviceinfoXml,
+    "application/EmergencyCallData.eCall.MSD" => Mime::ApplicationEmergencycalldataEcallMsd,
+    "application/EmergencyCallData.LegacyESN+json" => Mime::ApplicationEmergencycalldataLegacyesnJson,
+    "application/EmergencyCallData.ProviderInfo+xml" => Mime::ApplicationEmergencycalldataProviderinfoXml,
+    "application/EmergencyCallData.ServiceInfo+xml" => Mime::ApplicationEmergencycalldataServiceinfoXml,
+    "application/EmergencyCallData.SubscriberInfo+xml" => Mime::ApplicationEmergencycalldataSubscriberinfoXml,
+    "application/EmergencyCallData.VEDS+xml" => Mime::ApplicationEmergencycalldataVedsXml,
+    "application/emma+xml" => Mime::ApplicationEmmaXml,
+    "application/emotionml+xml" => Mime::ApplicationEmotionmlXml,
+    "application/encaprtp" => Mime::ApplicationEncaprtp,
+    "application/epp+xml" => Mime::ApplicationEppXml,
+    "application/epub+zip" => Mime::ApplicationEpubZip,
+    "application/eshop" => Mime::ApplicationEshop,
+    "application/example" => Mime::ApplicationExample,
+    "application/exi" => Mime::ApplicationExi,
+    "application/expect-ct-report+json" => Mime::ApplicationExpectCtReportJson,
+    "application/express" => Mime::ApplicationExpress,
+    "application/fastinfoset" => Mime::ApplicationFastinfoset,
+    "application/fastsoap" => Mime::ApplicationFastsoap,
+    "application/fdf" => Mime::ApplicationFdf,
+    "application/fdt+xml" => Mime::ApplicationFdtXml,
+    "application/fhir+json" => Mime::ApplicationFhirJson,
+    "application/fhir+xml" => Mime::ApplicationFhirXml,
+    "application/fits" => Mime::ApplicationFits,
+    "application/flexfec" => Mime::ApplicationFlexfec,
+    "application/font-tdpfr" => Mime::ApplicationFontTdpfr,
+    "application/framework-attributes+xml" => Mime::ApplicationFrameworkAttributesXml,
+    "application/geo+json" => Mime::ApplicationGeoJson,
+    "application/geo+json-seq" => Mime::ApplicationGeoJsonSeq,
+    "application/geopackage+sqlite3" => Mime::ApplicationGeopackageSqlite3,
+    "application/geoxacml+xml" => Mime::ApplicationGeoxacmlXml,
+    "application/gltf-buffer" => Mime::ApplicationGltfBuffer,
+    "application/gml+xml" => Mime::ApplicationGmlXml,
+    "application/gzip" => Mime::ApplicationGzip,
+    "application/H224" => Mime::ApplicationH224,
+    "application/held+xml" => Mime::ApplicationHeldXml,
+    "application/hl7v2+xml" => Mime::ApplicationHl7v2Xml,
+    "application/http" => Mime::ApplicationHttp,
+    "application/hyperstudio" => Mime::ApplicationHyperstudio,
+    "application/ibe-key-request+xml" => Mime::ApplicationIbeKeyRequestXml,
+    "application/ibe-pkg-reply+xml" => Mime::ApplicationIbePkgReplyXml,
+    "application/ibe-pp-data" => Mime::ApplicationIbePpData,
+    "application/iges" => Mime::ApplicationIges,
+    "application/im-iscomposing+xml" => Mime::ApplicationImIscomposingXml,
+    "application/index" => Mime::ApplicationIndex,
+    "application/index.cmd" => Mime::ApplicationIndexCmd,
+    "application/index.obj" => Mime::ApplicationIndexObj,
+    "application/index.response" => Mime::ApplicationIndexResponse,
+    "application/index.vnd" => Mime::ApplicationIndexVnd,
+    "application/inkml+xml" => Mime::ApplicationInkmlXml,
+    "application/IOTP" => Mime::ApplicationIotp,
+    "application/ipfix" => Mime::ApplicationIpfix,
+    "application/ipp" => Mime::ApplicationIpp,
+    "application/ISUP" => Mime::ApplicationIsup,
+    "application/its+xml" => Mime::ApplicationItsXml,
+    "application/java-archive" => Mime::ApplicationJavaArchive,
+    "application/jf2feed+json" => Mime::ApplicationJf2feedJson,
+    "application/jose" => Mime::ApplicationJose,
+    "application/jose+json" => Mime::ApplicationJoseJson,
+    "application/jrd+json" => Mime::ApplicationJrdJson,
+    "application/jscalendar+json" => Mime::ApplicationJscalendarJson,
+    "application/json" => Mime::ApplicationJson,
+    "application/json-patch+json" => Mime::ApplicationJsonPatchJson,
+    "application/json-seq" => Mime::ApplicationJsonSeq,
+    "application/jwk+json" => Mime::ApplicationJwkJson,
+    "application/jwk-set+json" => Mime::ApplicationJwkSetJson,
+    "application/jwt" => Mime::ApplicationJwt,
+    "application/kpml-request+xml" => Mime::ApplicationKpmlRequestXml,
+    "application/kpml-response+xml" => Mime::ApplicationKpmlResponseXml,
+    "application/ld+json" => Mime::ApplicationLdJson,
+    "application/lgr+xml" => Mime::ApplicationLgrXml,
+    "application/link-format" => Mime::ApplicationLinkFormat,
+    "application/linkset" => Mime::ApplicationLinkset,
+    "application/linkset+json" => Mime::ApplicationLinksetJson,
+    "application/load-control+xml" => Mime::ApplicationLoadControlXml,
+    "application/logout+jwt" => Mime::ApplicationLogoutJwt,
+    "application/lost+xml" => Mime::ApplicationLostXml,
+    "application/lostsync+xml" => Mime::ApplicationLostsyncXml,
+    "application/lpf+zip" => Mime::ApplicationLpfZip,
+    "application/LXF" => Mime::ApplicationLxf,
+    "application/mac-binhex40" => Mime::ApplicationMacBinhex40,
+    "application/macwriteii" => Mime::ApplicationMacwriteii,
+    "application/mads+xml" => Mime::ApplicationMadsXml,
+    "application/manifest+json" => Mime::ApplicationManifestJson,
+    "application/marc" => Mime::ApplicationMarc,
+    "application/marcxml+xml" => Mime::ApplicationMarcxmlXml,
+    "application/mathematica" => Mime::ApplicationMathematica,
+    "application/mathml+xml" => Mime::ApplicationMathmlXml,
+    "application/mathml-content+xml" => Mime::ApplicationMathmlContentXml,
+    "application/mathml-presentation+xml" => Mime::ApplicationMathmlPresentationXml,
+    "application/mbms-associated-procedure-description+xml" => Mime::ApplicationMbmsAssociatedProcedureDescriptionXml,
+    "application/mbms-deregister+xml" => Mime::ApplicationMbmsDeregisterXml,
+    "application/mbms-envelope+xml" => Mime::ApplicationMbmsEnvelopeXml,
+    "application/mbms-msk-response+xml" => Mime::ApplicationMbmsMskResponseXml,
+    "application/mbms-msk+xml" => Mime::ApplicationMbmsMskXml,
+    "application/mbms-protection-description+xml" => Mime::ApplicationMbmsProtectionDescriptionXml,
+    "application/mbms-reception-report+xml" => Mime::ApplicationMbmsReceptionReportXml,
+    "application/mbms-register-response+xml" => Mime::ApplicationMbmsRegisterResponseXml,
+    "application/mbms-register+xml" => Mime::ApplicationMbmsRegisterXml,
+    "application/mbms-schedule+xml" => Mime::ApplicationMbmsScheduleXml,
+    "application/mbms-user-service-description+xml" => Mime::ApplicationMbmsUserServiceDescriptionXml,
+    "application/mbox" => Mime::ApplicationMbox,
+    "application/media_control+xml" => Mime::ApplicationMediaControlXml,
+    "application/media-policy-dataset+xml" => Mime::ApplicationMediaPolicyDatasetXml,
+    "application/mediaservercontrol+xml" => Mime::ApplicationMediaservercontrolXml,
+    "application/merge-patch+json" => Mime::ApplicationMergePatchJson,
+    "application/metalink4+xml" => Mime::ApplicationMetalink4Xml,
+    "application/mets+xml" => Mime::ApplicationMetsXml,
+    "application/MF4" => Mime::ApplicationMf4,
+    "application/mikey" => Mime::ApplicationMikey,
+    "application/mipc" => Mime::ApplicationMipc,
+    "application/missing-blocks+cbor-seq" => Mime::ApplicationMissingBlocksCborSeq,
+    "application/mmt-aei+xml" => Mime::ApplicationMmtAeiXml,
+    "application/mmt-usd+xml" => Mime::ApplicationMmtUsdXml,
+    "application/mods+xml" => Mime::ApplicationModsXml,
+    "application/moss-keys" => Mime::ApplicationMossKeys,
+    "application/moss-signature" => Mime::ApplicationMossSignature,
+    "application/mosskey-data" => Mime::ApplicationMosskeyData,
+    "application/mosskey-request" => Mime::ApplicationMosskeyRequest,
+    "application/mp21" => Mime::ApplicationMp21,
+    "application/mp4" => Mime::ApplicationMp4,
+    "application/mpeg4-generic" => Mime::ApplicationMpeg4Generic,
+    "application/mpeg4-iod" => Mime::ApplicationMpeg4Iod,
+    "application/mpeg4-iod-xmt" => Mime::ApplicationMpeg4IodXmt,
+    "application/mrb-consumer+xml" => Mime::ApplicationMrbConsumerXml,
+    "application/mrb-publish+xml" => Mime::ApplicationMrbPublishXml,
+    "application/msc-ivr+xml" => Mime::ApplicationMscIvrXml,
+    "application/msc-mixer+xml" => Mime::ApplicationMscMixerXml,
+    "application/msword" => Mime::ApplicationMsword,
+    "application/mud+json" => Mime::ApplicationMudJson,
+    "application/multipart-core" => Mime::ApplicationMultipartCore,
+    "application/mxf" => Mime::ApplicationMxf,
+    "application/n-quads" => Mime::ApplicationNQuads,
+    "application/n-triples" => Mime::ApplicationNTriples,
+    "application/nasdata" => Mime::ApplicationNasdata,
+    "application/news-checkgroups" => Mime::ApplicationNewsCheckgroups,
+    "application/news-groupinfo" => Mime::ApplicationNewsGroupinfo,
+    "application/news-transmission" => Mime::ApplicationNewsTransmission,
+    "application/nlsml+xml" => Mime::ApplicationNlsmlXml,
+    "application/node" => Mime::ApplicationNode,
+    "application/nss" => Mime::ApplicationNss,
+    "application/oauth-authz-req+jwt" => Mime::ApplicationOauthAuthzReqJwt,
+    "application/oblivious-dns-message" => Mime::ApplicationObliviousDnsMessage,
+    "application/ocsp-request" => Mime::ApplicationOcspRequest,
+    "application/ocsp-response" => Mime::ApplicationOcspResponse,
+    "application/octet-stream" => Mime::ApplicationOctetStream,
+    "application/ODA" => Mime::ApplicationOda,
+    "application/odm+xml" => Mime::ApplicationOdmXml,
+    "application/ODX" => Mime::ApplicationOdx,
+    "application/oebps-package+xml" => Mime::ApplicationOebpsPackageXml,
+    "application/ogg" => Mime::ApplicationOgg,
+    "application/ohttp-keys" => Mime::ApplicationOhttpKeys,
+    "application/opc-nodeset+xml" => Mime::ApplicationOpcNodesetXml,
+    "application/oscore" => Mime::ApplicationOscore,
+    "application/oxps" => Mime::ApplicationOxps,
+    "application/p21" => Mime::ApplicationP21,
+    "application/p21+zip" => Mime::ApplicationP21Zip,
+    "application/p2p-overlay+xml" => Mime::ApplicationP2pOverlayXml,
+    "application/parityfec" => Mime::ApplicationParityfec,
+    "application/passport" => Mime::ApplicationPassport,
+    "application/patch-ops-error+xml" => Mime::ApplicationPatchOpsErrorXml,
+    "application/pdf" => Mime::ApplicationPdf,
+    "application/PDX" => Mime::ApplicationPdx,
+    "application/pem-certificate-chain" => Mime::ApplicationPemCertificateChain,
+    "application/pgp-encrypted" => Mime::ApplicationPgpEncrypted,
+    "application/pgp-keys" => Mime::ApplicationPgpKeys,
+    "application/pgp-signature" => Mime::ApplicationPgpSignature,
+    "application/pidf-diff+xml" => Mime::ApplicationPidfDiffXml,
+    "application/pidf+xml" => Mime::ApplicationPidfXml,
+    "application/pkcs10" => Mime::ApplicationPkcs10,
+    "application/pkcs7-mime" => Mime::ApplicationPkcs7Mime,
+    "application/pkcs7-signature" => Mime::ApplicationPkcs7Signature,
+    "application/pkcs8" => Mime::ApplicationPkcs8,
+    "application/pkcs8-encrypted" => Mime::ApplicationPkcs8Encrypted,
+    "application/pkcs12" => Mime::ApplicationPkcs12,
+    "application/pkix-attr-cert" => Mime::ApplicationPkixAttrCert,
+    "application/pkix-cert" => Mime::ApplicationPkixCert,
+    "application/pkix-crl" => Mime::ApplicationPkixCrl,
+    "application/pkix-pkipath" => Mime::ApplicationPkixPkipath,
+    "application/pkixcmp" => Mime::ApplicationPkixcmp,
+    "application/pls+xml" => Mime::ApplicationPlsXml,
+    "application/poc-settings+xml" => Mime::ApplicationPocSettingsXml,
+    "application/postscript" => Mime::ApplicationPostscript,
+    "application/ppsp-tracker+json" => Mime::ApplicationPpspTrackerJson,
+    "application/problem+json" => Mime::ApplicationProblemJson,
+    "application/problem+xml" => Mime::ApplicationProblemXml,
+    "application/provenance+xml" => Mime::ApplicationProvenanceXml,
+    "application/prs.alvestrand.titrax-sheet" => Mime::ApplicationPrsAlvestrandTitraxSheet,
+    "application/prs.cww" => Mime::ApplicationPrsCww,
+    "application/prs.cyn" => Mime::ApplicationPrsCyn,
+    "application/prs.hpub+zip" => Mime::ApplicationPrsHpubZip,
+    "application/prs.implied-document+xml" => Mime::ApplicationPrsImpliedDocumentXml,
+    "application/prs.implied-executable" => Mime::ApplicationPrsImpliedExecutable,
+    "application/prs.implied-structure" => Mime::ApplicationPrsImpliedStructure,
+    "application/prs.nprend" => Mime::ApplicationPrsNprend,
+    "application/prs.plucker" => Mime::ApplicationPrsPlucker,
+    "application/prs.rdf-xml-crypt" => Mime::ApplicationPrsRdfXmlCrypt,
+    "application/prs.xsf+xml" => Mime::ApplicationPrsXsfXml,
+    "application/pskc+xml" => Mime::ApplicationPskcXml,
+    "application/pvd+json" => Mime::ApplicationPvdJson,
+    "application/rdf+xml" => Mime::ApplicationRdfXml,
+    "application/route-apd+xml" => Mime::ApplicationRouteApdXml,
+    "application/route-s-tsid+xml" => Mime::ApplicationRouteSTsidXml,
+    "application/route-usd+xml" => Mime::ApplicationRouteUsdXml,
+    "application/QSIG" => Mime::ApplicationQsig,
+    "application/raptorfec" => Mime::ApplicationRaptorfec,
+    "application/rdap+json" => Mime::ApplicationRdapJson,
+    "application/reginfo+xml" => Mime::ApplicationReginfoXml,
+    "application/relax-ng-compact-syntax" => Mime::ApplicationRelaxNgCompactSyntax,
+    "application/reputon+json" => Mime::ApplicationReputonJson,
+    "application/resource-lists-diff+xml" => Mime::ApplicationResourceListsDiffXml,
+    "application/resource-lists+xml" => Mime::ApplicationResourceListsXml,
+    "application/rfc+xml" => Mime::ApplicationRfcXml,
+    "application/riscos" => Mime::ApplicationRiscos,
+    "application/rlmi+xml" => Mime::ApplicationRlmiXml,
+    "application/rls-services+xml" => Mime::ApplicationRlsServicesXml,
+    "application/rpki-checklist" => Mime::ApplicationRpkiChecklist,
+    "application/rpki-ghostbusters" => Mime::ApplicationRpkiGhostbusters,
+    "application/rpki-manifest" => Mime::ApplicationRpkiManifest,
+    "application/rpki-publication" => Mime::ApplicationRpkiPublication,
+    "application/rpki-roa" => Mime::ApplicationRpkiRoa,
+    "application/rpki-updown" => Mime::ApplicationRpkiUpdown,
+    "application/rtf" => Mime::ApplicationRtf,
+    "application/rtploopback" => Mime::ApplicationRtploopback,
+    "application/rtx" => Mime::ApplicationRtx,
+    "application/samlassertion+xml" => Mime::ApplicationSamlassertionXml,
+    "application/samlmetadata+xml" => Mime::ApplicationSamlmetadataXml,
+    "application/sarif-external-properties+json" => Mime::ApplicationSarifExternalPropertiesJson,
+    "application/sarif+json" => Mime::ApplicationSarifJson,
+    "application/sbe" => Mime::ApplicationSbe,
+    "application/sbml+xml" => Mime::ApplicationSbmlXml,
+    "application/scaip+xml" => Mime::ApplicationScaipXml,
+    "application/scim+json" => Mime::ApplicationScimJson,
+    "application/scvp-cv-request" => Mime::ApplicationScvpCvRequest,
+    "application/scvp-cv-response" => Mime::ApplicationScvpCvResponse,
+    "application/scvp-vp-request" => Mime::ApplicationScvpVpRequest,
+    "application/scvp-vp-response" => Mime::ApplicationScvpVpResponse,
+    "application/sdp" => Mime::ApplicationSdp,
+    "application/secevent+jwt" => Mime::ApplicationSeceventJwt,
+    "application/senml-etch+cbor" => Mime::ApplicationSenmlEtchCbor,
+    "application/senml-etch+json" => Mime::ApplicationSenmlEtchJson,
+    "application/senml-exi" => Mime::ApplicationSenmlExi,
+    "application/senml+cbor" => Mime::ApplicationSenmlCbor,
+    "application/senml+json" => Mime::ApplicationSenmlJson,
+    "application/senml+xml" => Mime::ApplicationSenmlXml,
+    "application/sensml-exi" => Mime::ApplicationSensmlExi,
+    "application/sensml+cbor" => Mime::ApplicationSensmlCbor,
+    "application/sensml+json" => Mime::ApplicationSensmlJson,
+    "application/sensml+xml" => Mime::ApplicationSensmlXml,
+    "application/sep-exi" => Mime::ApplicationSepExi,
+    "application/sep+xml" => Mime::ApplicationSepXml,
+    "application/session-info" => Mime::ApplicationSessionInfo,
+    "application/set-payment" => Mime::ApplicationSetPayment,
+    "application/set-payment-initiation" => Mime::ApplicationSetPaymentInitiation,
+    "application/set-registration" => Mime::ApplicationSetRegistration,
+    "application/set-registration-initiation" => Mime::ApplicationSetRegistrationInitiation,
+    "application/SGML" => Mime::ApplicationSgml,
+    "application/sgml-open-catalog" => Mime::ApplicationSgmlOpenCatalog,
+    "application/shf+xml" => Mime::ApplicationShfXml,
+    "application/sieve" => Mime::ApplicationSieve,
+    "application/simple-filter+xml" => Mime::ApplicationSimpleFilterXml,
+    "application/simple-message-summary" => Mime::ApplicationSimpleMessageSummary,
+    "application/simpleSymbolContainer" => Mime::ApplicationSimplesymbolcontainer,
+    "application/sipc" => Mime::ApplicationSipc,
+    "application/slate" => Mime::ApplicationSlate,
+    "application/smil+xml" => Mime::ApplicationSmilXml,
+    "application/smpte336m" => Mime::ApplicationSmpte336m,
+    "application/soap+fastinfoset" => Mime::ApplicationSoapFastinfoset,
+    "application/soap+xml" => Mime::ApplicationSoapXml,
+    "application/sparql-query" => Mime::ApplicationSparqlQuery,
+    "application/spdx+json" => Mime::ApplicationSpdxJson,
+    "application/sparql-results+xml" => Mime::ApplicationSparqlResultsXml,
+    "application/spirits-event+xml" => Mime::ApplicationSpiritsEventXml,
+    "application/sql" => Mime::ApplicationSql,
+    "application/srgs" => Mime::ApplicationSrgs,
+    "application/srgs+xml" => Mime::ApplicationSrgsXml,
+    "application/sru+xml" => Mime::ApplicationSruXml,
+    "application/ssml+xml" => Mime::ApplicationSsmlXml,
+    "application/stix+json" => Mime::ApplicationStixJson,
+    "application/swid+cbor" => Mime::ApplicationSwidCbor,
+    "application/swid+xml" => Mime::ApplicationSwidXml,
+    "application/tamp-apex-update" => Mime::ApplicationTampApexUpdate,
+    "application/tamp-apex-update-confirm" => Mime::ApplicationTampApexUpdateConfirm,
+    "application/tamp-community-update" => Mime::ApplicationTampCommunityUpdate,
+    "application/tamp-community-update-confirm" => Mime::ApplicationTampCommunityUpdateConfirm,
+    "application/tamp-error" => Mime::ApplicationTampError,
+    "application/tamp-sequence-adjust" => Mime::ApplicationTampSequenceAdjust,
+    "application/tamp-sequence-adjust-confirm" => Mime::ApplicationTampSequenceAdjustConfirm,
+    "application/tamp-status-query" => Mime::ApplicationTampStatusQuery,
+    "application/tamp-status-response" => Mime::ApplicationTampStatusResponse,
+    "application/tamp-update" => Mime::ApplicationTampUpdate,
+    "application/tamp-update-confirm" => Mime::ApplicationTampUpdateConfirm,
+    "application/taxii+json" => Mime::ApplicationTaxiiJson,
+    "application/td+json" => Mime::ApplicationTdJson,
+    "application/tei+xml" => Mime::ApplicationTeiXml,
+    "application/TETRA_ISI" => Mime::ApplicationTetraIsi,
+    "application/thraud+xml" => Mime::ApplicationThraudXml,
+    "application/timestamp-query" => Mime::ApplicationTimestampQuery,
+    "application/timestamp-reply" => Mime::ApplicationTimestampReply,
+    "application/timestamped-data" => Mime::ApplicationTimestampedData,
+    "application/tlsrpt+gzip" => Mime::ApplicationTlsrptGzip,
+    "application/tlsrpt+json" => Mime::ApplicationTlsrptJson,
+    "application/tm+json" => Mime::ApplicationTmJson,
+    "application/tnauthlist" => Mime::ApplicationTnauthlist,
+    "application/token-introspection+jwt" => Mime::ApplicationTokenIntrospectionJwt,
+    "application/trickle-ice-sdpfrag" => Mime::ApplicationTrickleIceSdpfrag,
+    "application/trig" => Mime::ApplicationTrig,
+    "application/ttml+xml" => Mime::ApplicationTtmlXml,
+    "application/tve-trigger" => Mime::ApplicationTveTrigger,
+    "application/tzif" => Mime::ApplicationTzif,
+    "application/tzif-leap" => Mime::ApplicationTzifLeap,
+    "application/ulpfec" => Mime::ApplicationUlpfec,
+    "application/urc-grpsheet+xml" => Mime::ApplicationUrcGrpsheetXml,
+    "application/urc-ressheet+xml" => Mime::ApplicationUrcRessheetXml,
+    "application/urc-targetdesc+xml" => Mime::ApplicationUrcTargetdescXml,
+    "application/urc-uisocketdesc+xml" => Mime::ApplicationUrcUisocketdescXml,
+    "application/vcard+json" => Mime::ApplicationVcardJson,
+    "application/vcard+xml" => Mime::ApplicationVcardXml,
+    "application/vemmi" => Mime::ApplicationVemmi,
+    "application/vnd.1000minds.decision-model+xml" => Mime::ApplicationVnd1000mindsDecisionModelXml,
+    "application/vnd.1ob" => Mime::ApplicationVnd1ob,
+    "application/vnd.3gpp.5gnas" => Mime::ApplicationVnd3gpp5gnas,
+    "application/vnd.3gpp.access-transfer-events+xml" => Mime::ApplicationVnd3gppAccessTransferEventsXml,
+    "application/vnd.3gpp.bsf+xml" => Mime::ApplicationVnd3gppBsfXml,
+    "application/vnd.3gpp.crs+xml" => Mime::ApplicationVnd3gppCrsXml,
+    "application/vnd.3gpp.current-location-discovery+xml" => Mime::ApplicationVnd3gppCurrentLocationDiscoveryXml,
+    "application/vnd.3gpp.GMOP+xml" => Mime::ApplicationVnd3gppGmopXml,
+    "application/vnd.3gpp.gtpc" => Mime::ApplicationVnd3gppGtpc,
+    "application/vnd.3gpp.interworking-data" => Mime::ApplicationVnd3gppInterworkingData,
+    "application/vnd.3gpp.lpp" => Mime::ApplicationVnd3gppLpp,
+    "application/vnd.3gpp.mc-signalling-ear" => Mime::ApplicationVnd3gppMcSignallingEar,
+    "application/vnd.3gpp.mcdata-affiliation-command+xml" => Mime::ApplicationVnd3gppMcdataAffiliationCommandXml,
+    "application/vnd.3gpp.mcdata-info+xml" => Mime::ApplicationVnd3gppMcdataInfoXml,
+    "application/vnd.3gpp.mcdata-msgstore-ctrl-request+xml" => Mime::ApplicationVnd3gppMcdataMsgstoreCtrlRequestXml,
+    "application/vnd.3gpp.mcdata-payload" => Mime::ApplicationVnd3gppMcdataPayload,
+    "application/vnd.3gpp.mcdata-regroup+xml" => Mime::ApplicationVnd3gppMcdataRegroupXml,
+    "application/vnd.3gpp.mcdata-service-config+xml" => Mime::ApplicationVnd3gppMcdataServiceConfigXml,
+    "application/vnd.3gpp.mcdata-signalling" => Mime::ApplicationVnd3gppMcdataSignalling,
+    "application/vnd.3gpp.mcdata-ue-config+xml" => Mime::ApplicationVnd3gppMcdataUeConfigXml,
+    "application/vnd.3gpp.mcdata-user-profile+xml" => Mime::ApplicationVnd3gppMcdataUserProfileXml,
+    "application/vnd.3gpp.mcptt-affiliation-command+xml" => Mime::ApplicationVnd3gppMcpttAffiliationCommandXml,
+    "application/vnd.3gpp.mcptt-floor-request+xml" => Mime::ApplicationVnd3gppMcpttFloorRequestXml,
+    "application/vnd.3gpp.mcptt-info+xml" => Mime::ApplicationVnd3gppMcpttInfoXml,
+    "application/vnd.3gpp.mcptt-location-info+xml" => Mime::ApplicationVnd3gppMcpttLocationInfoXml,
+    "application/vnd.3gpp.mcptt-mbms-usage-info+xml" => Mime::ApplicationVnd3gppMcpttMbmsUsageInfoXml,
+    "application/vnd.3gpp.mcptt-regroup+xml" => Mime::ApplicationVnd3gppMcpttRegroupXml,
+    "application/vnd.3gpp.mcptt-service-config+xml" => Mime::ApplicationVnd3gppMcpttServiceConfigXml,
+    "application/vnd.3gpp.mcptt-signed+xml" => Mime::ApplicationVnd3gppMcpttSignedXml,
+    "application/vnd.3gpp.mcptt-ue-config+xml" => Mime::ApplicationVnd3gppMcpttUeConfigXml,
+    "application/vnd.3gpp.mcptt-ue-init-config+xml" => Mime::ApplicationVnd3gppMcpttUeInitConfigXml,
+    "application/vnd.3gpp.mcptt-user-profile+xml" => Mime::ApplicationVnd3gppMcpttUserProfileXml,
+    "application/vnd.3gpp.mcvideo-affiliation-command+xml" => Mime::ApplicationVnd3gppMcvideoAffiliationCommandXml,
+    "application/vnd.3gpp.mcvideo-info+xml" => Mime::ApplicationVnd3gppMcvideoInfoXml,
+    "application/vnd.3gpp.mcvideo-location-info+xml" => Mime::ApplicationVnd3gppMcvideoLocationInfoXml,
+    "application/vnd.3gpp.mcvideo-mbms-usage-info+xml" => Mime::ApplicationVnd3gppMcvideoMbmsUsageInfoXml,
+    "application/vnd.3gpp.mcvideo-regroup+xml" => Mime::ApplicationVnd3gppMcvideoRegroupXml,
+    "application/vnd.3gpp.mcvideo-service-config+xml" => Mime::ApplicationVnd3gppMcvideoServiceConfigXml,
+    "application/vnd.3gpp.mcvideo-transmission-request+xml" => Mime::ApplicationVnd3gppMcvideoTransmissionRequestXml,
+    "application/vnd.3gpp.mcvideo-ue-config+xml" => Mime::ApplicationVnd3gppMcvideoUeConfigXml,
+    "application/vnd.3gpp.mcvideo-user-profile+xml" => Mime::ApplicationVnd3gppMcvideoUserProfileXml,
+    "application/vnd.3gpp.mid-call+xml" => Mime::ApplicationVnd3gppMidCallXml,
+    "application/vnd.3gpp.ngap" => Mime::ApplicationVnd3gppNgap,
+    "application/vnd.3gpp.pfcp" => Mime::ApplicationVnd3gppPfcp,
+    "application/vnd.3gpp.pic-bw-large" => Mime::ApplicationVnd3gppPicBwLarge,
+    "application/vnd.3gpp.pic-bw-small" => Mime::ApplicationVnd3gppPicBwSmall,
+    "application/vnd.3gpp.pic-bw-var" => Mime::ApplicationVnd3gppPicBwVar,
+    "application/vnd.3gpp-prose-pc3a+xml" => Mime::ApplicationVnd3gppProsePc3aXml,
+    "application/vnd.3gpp-prose-pc3ach+xml" => Mime::ApplicationVnd3gppProsePc3achXml,
+    "application/vnd.3gpp-prose-pc3ch+xml" => Mime::ApplicationVnd3gppProsePc3chXml,
+    "application/vnd.3gpp-prose-pc8+xml" => Mime::ApplicationVnd3gppProsePc8Xml,
+    "application/vnd.3gpp-prose+xml" => Mime::ApplicationVnd3gppProseXml,
+    "application/vnd.3gpp.s1ap" => Mime::ApplicationVnd3gppS1ap,
+    "application/vnd.3gpp.seal-group-doc+xml" => Mime::ApplicationVnd3gppSealGroupDocXml,
+    "application/vnd.3gpp.seal-info+xml" => Mime::ApplicationVnd3gppSealInfoXml,
+    "application/vnd.3gpp.seal-location-info+xml" => Mime::ApplicationVnd3gppSealLocationInfoXml,
+    "application/vnd.3gpp.seal-mbms-usage-info+xml" => Mime::ApplicationVnd3gppSealMbmsUsageInfoXml,
+    "application/vnd.3gpp.seal-network-QoS-management-info+xml" => Mime::ApplicationVnd3gppSealNetworkQosManagementInfoXml,
+    "application/vnd.3gpp.seal-ue-config-info+xml" => Mime::ApplicationVnd3gppSealUeConfigInfoXml,
+    "application/vnd.3gpp.seal-unicast-info+xml" => Mime::ApplicationVnd3gppSealUnicastInfoXml,
+    "application/vnd.3gpp.seal-user-profile-info+xml" => Mime::ApplicationVnd3gppSealUserProfileInfoXml,
+    "application/vnd.3gpp.sms" => Mime::ApplicationVnd3gppSms,
+    "application/vnd.3gpp.sms+xml" => Mime::ApplicationVnd3gppSmsXml,
+    "application/vnd.3gpp.srvcc-ext+xml" => Mime::ApplicationVnd3gppSrvccExtXml,
+    "application/vnd.3gpp.SRVCC-info+xml" => Mime::ApplicationVnd3gppSrvccInfoXml,
+    "application/vnd.3gpp.state-and-event-info+xml" => Mime::ApplicationVnd3gppStateAndEventInfoXml,
+    "application/vnd.3gpp.ussd+xml" => Mime::ApplicationVnd3gppUssdXml,
+    "application/vnd.3gpp.vae-info+xml" => Mime::ApplicationVnd3gppVaeInfoXml,
+    "application/vnd.3gpp-v2x-local-service-information" => Mime::ApplicationVnd3gppV2xLocalServiceInformation,
+    "application/vnd.3gpp2.bcmcsinfo+xml" => Mime::ApplicationVnd3gpp2BcmcsinfoXml,
+    "application/vnd.3gpp2.sms" => Mime::ApplicationVnd3gpp2Sms,
+    "application/vnd.3gpp2.tcap" => Mime::ApplicationVnd3gpp2Tcap,
+    "application/vnd.3gpp.v2x" => Mime::ApplicationVnd3gppV2x,
+    "application/vnd.3lightssoftware.imagescal" => Mime::ApplicationVnd3lightssoftwareImagescal,
+    "application/vnd.3M.Post-it-Notes" => Mime::ApplicationVnd3mPostItNotes,
+    "application/vnd.accpac.simply.aso" => Mime::ApplicationVndAccpacSimplyAso,
+    "application/vnd.accpac.simply.imp" => Mime::ApplicationVndAccpacSimplyImp,
+    "application/vnd.acm.addressxfer+json" => Mime::ApplicationVndAcmAddressxferJson,
+    "application/vnd.acucobol" => Mime::ApplicationVndAcucobol,
+    "application/vnd.acucorp" => Mime::ApplicationVndAcucorp,
+    "application/vnd.adobe.flash.movie" => Mime::ApplicationVndAdobeFlashMovie,
+    "application/vnd.adobe.formscentral.fcdt" => Mime::ApplicationVndAdobeFormscentralFcdt,
+    "application/vnd.adobe.fxp" => Mime::ApplicationVndAdobeFxp,
+    "application/vnd.adobe.partial-upload" => Mime::ApplicationVndAdobePartialUpload,
+    "application/vnd.adobe.xdp+xml" => Mime::ApplicationVndAdobeXdpXml,
+    "application/vnd.aether.imp" => Mime::ApplicationVndAetherImp,
+    "application/vnd.afpc.afplinedata" => Mime::ApplicationVndAfpcAfplinedata,
+    "application/vnd.afpc.afplinedata-pagedef" => Mime::ApplicationVndAfpcAfplinedataPagedef,
+    "application/vnd.afpc.cmoca-cmresource" => Mime::ApplicationVndAfpcCmocaCmresource,
+    "application/vnd.afpc.foca-charset" => Mime::ApplicationVndAfpcFocaCharset,
+    "application/vnd.afpc.foca-codedfont" => Mime::ApplicationVndAfpcFocaCodedfont,
+    "application/vnd.afpc.foca-codepage" => Mime::ApplicationVndAfpcFocaCodepage,
+    "application/vnd.afpc.modca" => Mime::ApplicationVndAfpcModca,
+    "application/vnd.afpc.modca-cmtable" => Mime::ApplicationVndAfpcModcaCmtable,
+    "application/vnd.afpc.modca-formdef" => Mime::ApplicationVndAfpcModcaFormdef,
+    "application/vnd.afpc.modca-mediummap" => Mime::ApplicationVndAfpcModcaMediummap,
+    "application/vnd.afpc.modca-objectcontainer" => Mime::ApplicationVndAfpcModcaObjectcontainer,
+    "application/vnd.afpc.modca-overlay" => Mime::ApplicationVndAfpcModcaOverlay,
+    "application/vnd.afpc.modca-pagesegment" => Mime::ApplicationVndAfpcModcaPagesegment,
+    "application/vnd.age" => Mime::ApplicationVndAge,
+    "application/vnd.ah-barcode" => Mime::ApplicationVndAhBarcode,
+    "application/vnd.ahead.space" => Mime::ApplicationVndAheadSpace,
+    "application/vnd.airzip.filesecure.azf" => Mime::ApplicationVndAirzipFilesecureAzf,
+    "application/vnd.airzip.filesecure.azs" => Mime::ApplicationVndAirzipFilesecureAzs,
+    "application/vnd.amadeus+json" => Mime::ApplicationVndAmadeusJson,
+    "application/vnd.amazon.mobi8-ebook" => Mime::ApplicationVndAmazonMobi8Ebook,
+    "application/vnd.americandynamics.acc" => Mime::ApplicationVndAmericandynamicsAcc,
+    "application/vnd.amiga.ami" => Mime::ApplicationVndAmigaAmi,
+    "application/vnd.amundsen.maze+xml" => Mime::ApplicationVndAmundsenMazeXml,
+    "application/vnd.android.ota" => Mime::ApplicationVndAndroidOta,
+    "application/vnd.anki" => Mime::ApplicationVndAnki,
+    "application/vnd.anser-web-certificate-issue-initiation" => Mime::ApplicationVndAnserWebCertificateIssueInitiation,
+    "application/vnd.antix.game-component" => Mime::ApplicationVndAntixGameComponent,
+    "application/vnd.apache.arrow.file" => Mime::ApplicationVndApacheArrowFile,
+    "application/vnd.apache.arrow.stream" => Mime::ApplicationVndApacheArrowStream,
+    "application/vnd.apache.thrift.binary" => Mime::ApplicationVndApacheThriftBinary,
+    "application/vnd.apache.thrift.compact" => Mime::ApplicationVndApacheThriftCompact,
+    "application/vnd.apache.thrift.json" => Mime::ApplicationVndApacheThriftJson,
+    "application/vnd.apexlang" => Mime::ApplicationVndApexlang,
+    "application/vnd.api+json" => Mime::ApplicationVndApiJson,
+    "application/vnd.aplextor.warrp+json" => Mime::ApplicationVndAplextorWarrpJson,
+    "application/vnd.apothekende.reservation+json" => Mime::ApplicationVndApothekendeReservationJson,
+    "application/vnd.apple.installer+xml" => Mime::ApplicationVndAppleInstallerXml,
+    "application/vnd.apple.keynote" => Mime::ApplicationVndAppleKeynote,
+    "application/vnd.apple.mpegurl" => Mime::ApplicationVndAppleMpegurl,
+    "application/vnd.apple.numbers" => Mime::ApplicationVndAppleNumbers,
+    "application/vnd.apple.pages" => Mime::ApplicationVndApplePages,
+    "application/vnd.aristanetworks.swi" => Mime::ApplicationVndAristanetworksSwi,
+    "application/vnd.artisan+json" => Mime::ApplicationVndArtisanJson,
+    "application/vnd.artsquare" => Mime::ApplicationVndArtsquare,
+    "application/vnd.astraea-software.iota" => Mime::ApplicationVndAstraeaSoftwareIota,
+    "application/vnd.audiograph" => Mime::ApplicationVndAudiograph,
+    "application/vnd.autopackage" => Mime::ApplicationVndAutopackage,
+    "application/vnd.avalon+json" => Mime::ApplicationVndAvalonJson,
+    "application/vnd.avistar+xml" => Mime::ApplicationVndAvistarXml,
+    "application/vnd.balsamiq.bmml+xml" => Mime::ApplicationVndBalsamiqBmmlXml,
+    "application/vnd.banana-accounting" => Mime::ApplicationVndBananaAccounting,
+    "application/vnd.bbf.usp.error" => Mime::ApplicationVndBbfUspError,
+    "application/vnd.bbf.usp.msg" => Mime::ApplicationVndBbfUspMsg,
+    "application/vnd.bbf.usp.msg+json" => Mime::ApplicationVndBbfUspMsgJson,
+    "application/vnd.balsamiq.bmpr" => Mime::ApplicationVndBalsamiqBmpr,
+    "application/vnd.bekitzur-stech+json" => Mime::ApplicationVndBekitzurStechJson,
+    "application/vnd.belightsoft.lhzd+zip" => Mime::ApplicationVndBelightsoftLhzdZip,
+    "application/vnd.belightsoft.lhzl+zip" => Mime::ApplicationVndBelightsoftLhzlZip,
+    "application/vnd.bint.med-content" => Mime::ApplicationVndBintMedContent,
+    "application/vnd.biopax.rdf+xml" => Mime::ApplicationVndBiopaxRdfXml,
+    "application/vnd.blink-idb-value-wrapper" => Mime::ApplicationVndBlinkIdbValueWrapper,
+    "application/vnd.blueice.multipass" => Mime::ApplicationVndBlueiceMultipass,
+    "application/vnd.bluetooth.ep.oob" => Mime::ApplicationVndBluetoothEpOob,
+    "application/vnd.bluetooth.le.oob" => Mime::ApplicationVndBluetoothLeOob,
+    "application/vnd.bmi" => Mime::ApplicationVndBmi,
+    "application/vnd.bpf" => Mime::ApplicationVndBpf,
+    "application/vnd.bpf3" => Mime::ApplicationVndBpf3,
+    "application/vnd.businessobjects" => Mime::ApplicationVndBusinessobjects,
+    "application/vnd.byu.uapi+json" => Mime::ApplicationVndByuUapiJson,
+    "application/vnd.cab-jscript" => Mime::ApplicationVndCabJscript,
+    "application/vnd.canon-cpdl" => Mime::ApplicationVndCanonCpdl,
+    "application/vnd.canon-lips" => Mime::ApplicationVndCanonLips,
+    "application/vnd.capasystems-pg+json" => Mime::ApplicationVndCapasystemsPgJson,
+    "application/vnd.cendio.thinlinc.clientconf" => Mime::ApplicationVndCendioThinlincClientconf,
+    "application/vnd.century-systems.tcp_stream" => Mime::ApplicationVndCenturySystemsTcpStream,
+    "application/vnd.chemdraw+xml" => Mime::ApplicationVndChemdrawXml,
+    "application/vnd.chess-pgn" => Mime::ApplicationVndChessPgn,
+    "application/vnd.chipnuts.karaoke-mmd" => Mime::ApplicationVndChipnutsKaraokeMmd,
+    "application/vnd.ciedi" => Mime::ApplicationVndCiedi,
+    "application/vnd.cinderella" => Mime::ApplicationVndCinderella,
+    "application/vnd.cirpack.isdn-ext" => Mime::ApplicationVndCirpackIsdnExt,
+    "application/vnd.citationstyles.style+xml" => Mime::ApplicationVndCitationstylesStyleXml,
+    "application/vnd.claymore" => Mime::ApplicationVndClaymore,
+    "application/vnd.cloanto.rp9" => Mime::ApplicationVndCloantoRp9,
+    "application/vnd.clonk.c4group" => Mime::ApplicationVndClonkC4group,
+    "application/vnd.cluetrust.cartomobile-config" => Mime::ApplicationVndCluetrustCartomobileConfig,
+    "application/vnd.cluetrust.cartomobile-config-pkg" => Mime::ApplicationVndCluetrustCartomobileConfigPkg,
+    "application/vnd.cncf.helm.chart.content.v1.tar+gzip" => Mime::ApplicationVndCncfHelmChartContentV1TarGzip,
+    "application/vnd.cncf.helm.chart.provenance.v1.prov" => Mime::ApplicationVndCncfHelmChartProvenanceV1Prov,
+    "application/vnd.cncf.helm.config.v1+json" => Mime::ApplicationVndCncfHelmConfigV1Json,
+    "application/vnd.coffeescript" => Mime::ApplicationVndCoffeescript,
+    "application/vnd.collabio.xodocuments.document" => Mime::ApplicationVndCollabioXodocumentsDocument,
+    "application/vnd.collabio.xodocuments.document-template" => Mime::ApplicationVndCollabioXodocumentsDocumentTemplate,
+    "application/vnd.collabio.xodocuments.presentation" => Mime::ApplicationVndCollabioXodocumentsPresentation,
+    "application/vnd.collabio.xodocuments.presentation-template" => Mime::ApplicationVndCollabioXodocumentsPresentationTemplate,
+    "application/vnd.collabio.xodocuments.spreadsheet" => Mime::ApplicationVndCollabioXodocumentsSpreadsheet,
+    "application/vnd.collabio.xodocuments.spreadsheet-template" => Mime::ApplicationVndCollabioXodocumentsSpreadsheetTemplate,
+    "application/vnd.collection.doc+json" => Mime::ApplicationVndCollectionDocJson,
+    "application/vnd.collection+json" => Mime::ApplicationVndCollectionJson,
+    "application/vnd.collection.next+json" => Mime::ApplicationVndCollectionNextJson,
+    "application/vnd.comicbook-rar" => Mime::ApplicationVndComicbookRar,
+    "application/vnd.comicbook+zip" => Mime::ApplicationVndComicbookZip,
+    "application/vnd.commerce-battelle" => Mime::ApplicationVndCommerceBattelle,
+    "application/vnd.commonspace" => Mime::ApplicationVndCommonspace,
+    "application/vnd.coreos.ignition+json" => Mime::ApplicationVndCoreosIgnitionJson,
+    "application/vnd.cosmocaller" => Mime::ApplicationVndCosmocaller,
+    "application/vnd.contact.cmsg" => Mime::ApplicationVndContactCmsg,
+    "application/vnd.crick.clicker" => Mime::ApplicationVndCrickClicker,
+    "application/vnd.crick.clicker.keyboard" => Mime::ApplicationVndCrickClickerKeyboard,
+    "application/vnd.crick.clicker.palette" => Mime::ApplicationVndCrickClickerPalette,
+    "application/vnd.crick.clicker.template" => Mime::ApplicationVndCrickClickerTemplate,
+    "application/vnd.crick.clicker.wordbank" => Mime::ApplicationVndCrickClickerWordbank,
+    "application/vnd.criticaltools.wbs+xml" => Mime::ApplicationVndCriticaltoolsWbsXml,
+    "application/vnd.cryptii.pipe+json" => Mime::ApplicationVndCryptiiPipeJson,
+    "application/vnd.crypto-shade-file" => Mime::ApplicationVndCryptoShadeFile,
+    "application/vnd.cryptomator.encrypted" => Mime::ApplicationVndCryptomatorEncrypted,
+    "application/vnd.cryptomator.vault" => Mime::ApplicationVndCryptomatorVault,
+    "application/vnd.ctc-posml" => Mime::ApplicationVndCtcPosml,
+    "application/vnd.ctct.ws+xml" => Mime::ApplicationVndCtctWsXml,
+    "application/vnd.cups-pdf" => Mime::ApplicationVndCupsPdf,
+    "application/vnd.cups-postscript" => Mime::ApplicationVndCupsPostscript,
+    "application/vnd.cups-ppd" => Mime::ApplicationVndCupsPpd,
+    "application/vnd.cups-raster" => Mime::ApplicationVndCupsRaster,
+    "application/vnd.cups-raw" => Mime::ApplicationVndCupsRaw,
+    "application/vnd.curl" => Mime::ApplicationVndCurl,
+    "application/vnd.cyan.dean.root+xml" => Mime::ApplicationVndCyanDeanRootXml,
+    "application/vnd.cybank" => Mime::ApplicationVndCybank,
+    "application/vnd.cyclonedx+json" => Mime::ApplicationVndCyclonedxJson,
+    "application/vnd.cyclonedx+xml" => Mime::ApplicationVndCyclonedxXml,
+    "application/vnd.d2l.coursepackage1p0+zip" => Mime::ApplicationVndD2lCoursepackage1p0Zip,
+    "application/vnd.d3m-dataset" => Mime::ApplicationVndD3mDataset,
+    "application/vnd.d3m-problem" => Mime::ApplicationVndD3mProblem,
+    "application/vnd.dart" => Mime::ApplicationVndDart,
+    "application/vnd.data-vision.rdz" => Mime::ApplicationVndDataVisionRdz,
+    "application/vnd.datalog" => Mime::ApplicationVndDatalog,
+    "application/vnd.datapackage+json" => Mime::ApplicationVndDatapackageJson,
+    "application/vnd.dataresource+json" => Mime::ApplicationVndDataresourceJson,
+    "application/vnd.dbf" => Mime::ApplicationVndDbf,
+    "application/vnd.debian.binary-package" => Mime::ApplicationVndDebianBinaryPackage,
+    "application/vnd.dece.data" => Mime::ApplicationVndDeceData,
+    "application/vnd.dece.ttml+xml" => Mime::ApplicationVndDeceTtmlXml,
+    "application/vnd.dece.unspecified" => Mime::ApplicationVndDeceUnspecified,
+    "application/vnd.dece.zip" => Mime::ApplicationVndDeceZip,
+    "application/vnd.denovo.fcselayout-link" => Mime::ApplicationVndDenovoFcselayoutLink,
+    "application/vnd.desmume.movie" => Mime::ApplicationVndDesmumeMovie,
+    "application/vnd.dir-bi.plate-dl-nosuffix" => Mime::ApplicationVndDirBiPlateDlNosuffix,
+    "application/vnd.dm.delegation+xml" => Mime::ApplicationVndDmDelegationXml,
+    "application/vnd.dna" => Mime::ApplicationVndDna,
+    "application/vnd.document+json" => Mime::ApplicationVndDocumentJson,
+    "application/vnd.dolby.mobile.1" => Mime::ApplicationVndDolbyMobile1,
+    "application/vnd.dolby.mobile.2" => Mime::ApplicationVndDolbyMobile2,
+    "application/vnd.doremir.scorecloud-binary-document" => Mime::ApplicationVndDoremirScorecloudBinaryDocument,
+    "application/vnd.dpgraph" => Mime::ApplicationVndDpgraph,
+    "application/vnd.dreamfactory" => Mime::ApplicationVndDreamfactory,
+    "application/vnd.drive+json" => Mime::ApplicationVndDriveJson,
+    "application/vnd.dtg.local" => Mime::ApplicationVndDtgLocal,
+    "application/vnd.dtg.local.flash" => Mime::ApplicationVndDtgLocalFlash,
+    "application/vnd.dtg.local.html" => Mime::ApplicationVndDtgLocalHtml,
+    "application/vnd.dvb.ait" => Mime::ApplicationVndDvbAit,
+    "application/vnd.dvb.dvbisl+xml" => Mime::ApplicationVndDvbDvbislXml,
+    "application/vnd.dvb.dvbj" => Mime::ApplicationVndDvbDvbj,
+    "application/vnd.dvb.esgcontainer" => Mime::ApplicationVndDvbEsgcontainer,
+    "application/vnd.dvb.ipdcdftnotifaccess" => Mime::ApplicationVndDvbIpdcdftnotifaccess,
+    "application/vnd.dvb.ipdcesgaccess" => Mime::ApplicationVndDvbIpdcesgaccess,
+    "application/vnd.dvb.ipdcesgaccess2" => Mime::ApplicationVndDvbIpdcesgaccess2,
+    "application/vnd.dvb.ipdcesgpdd" => Mime::ApplicationVndDvbIpdcesgpdd,
+    "application/vnd.dvb.ipdcroaming" => Mime::ApplicationVndDvbIpdcroaming,
+    "application/vnd.dvb.iptv.alfec-base" => Mime::ApplicationVndDvbIptvAlfecBase,
+    "application/vnd.dvb.iptv.alfec-enhancement" => Mime::ApplicationVndDvbIptvAlfecEnhancement,
+    "application/vnd.dvb.notif-aggregate-root+xml" => Mime::ApplicationVndDvbNotifAggregateRootXml,
+    "application/vnd.dvb.notif-container+xml" => Mime::ApplicationVndDvbNotifContainerXml,
+    "application/vnd.dvb.notif-generic+xml" => Mime::ApplicationVndDvbNotifGenericXml,
+    "application/vnd.dvb.notif-ia-msglist+xml" => Mime::ApplicationVndDvbNotifIaMsglistXml,
+    "application/vnd.dvb.notif-ia-registration-request+xml" => Mime::ApplicationVndDvbNotifIaRegistrationRequestXml,
+    "application/vnd.dvb.notif-ia-registration-response+xml" => Mime::ApplicationVndDvbNotifIaRegistrationResponseXml,
+    "application/vnd.dvb.notif-init+xml" => Mime::ApplicationVndDvbNotifInitXml,
+    "application/vnd.dvb.pfr" => Mime::ApplicationVndDvbPfr,
+    "application/vnd.dvb.service" => Mime::ApplicationVndDvbService,
+    "application/vnd.dxr" => Mime::ApplicationVndDxr,
+    "application/vnd.dynageo" => Mime::ApplicationVndDynageo,
+    "application/vnd.dzr" => Mime::ApplicationVndDzr,
+    "application/vnd.easykaraoke.cdgdownload" => Mime::ApplicationVndEasykaraokeCdgdownload,
+    "application/vnd.ecip.rlp" => Mime::ApplicationVndEcipRlp,
+    "application/vnd.ecdis-update" => Mime::ApplicationVndEcdisUpdate,
+    "application/vnd.eclipse.ditto+json" => Mime::ApplicationVndEclipseDittoJson,
+    "application/vnd.ecowin.chart" => Mime::ApplicationVndEcowinChart,
+    "application/vnd.ecowin.filerequest" => Mime::ApplicationVndEcowinFilerequest,
+    "application/vnd.ecowin.fileupdate" => Mime::ApplicationVndEcowinFileupdate,
+    "application/vnd.ecowin.series" => Mime::ApplicationVndEcowinSeries,
+    "application/vnd.ecowin.seriesrequest" => Mime::ApplicationVndEcowinSeriesrequest,
+    "application/vnd.ecowin.seriesupdate" => Mime::ApplicationVndEcowinSeriesupdate,
+    "application/vnd.efi.img" => Mime::ApplicationVndEfiImg,
+    "application/vnd.efi.iso" => Mime::ApplicationVndEfiIso,
+    "application/vnd.eln+zip" => Mime::ApplicationVndElnZip,
+    "application/vnd.emclient.accessrequest+xml" => Mime::ApplicationVndEmclientAccessrequestXml,
+    "application/vnd.enliven" => Mime::ApplicationVndEnliven,
+    "application/vnd.enphase.envoy" => Mime::ApplicationVndEnphaseEnvoy,
+    "application/vnd.eprints.data+xml" => Mime::ApplicationVndEprintsDataXml,
+    "application/vnd.epson.esf" => Mime::ApplicationVndEpsonEsf,
+    "application/vnd.epson.msf" => Mime::ApplicationVndEpsonMsf,
+    "application/vnd.epson.quickanime" => Mime::ApplicationVndEpsonQuickanime,
+    "application/vnd.epson.salt" => Mime::ApplicationVndEpsonSalt,
+    "application/vnd.epson.ssf" => Mime::ApplicationVndEpsonSsf,
+    "application/vnd.ericsson.quickcall" => Mime::ApplicationVndEricssonQuickcall,
+    "application/vnd.espass-espass+zip" => Mime::ApplicationVndEspassEspassZip,
+    "application/vnd.eszigno3+xml" => Mime::ApplicationVndEszigno3Xml,
+    "application/vnd.etsi.aoc+xml" => Mime::ApplicationVndEtsiAocXml,
+    "application/vnd.etsi.asic-s+zip" => Mime::ApplicationVndEtsiAsicSZip,
+    "application/vnd.etsi.asic-e+zip" => Mime::ApplicationVndEtsiAsicEZip,
+    "application/vnd.etsi.cug+xml" => Mime::ApplicationVndEtsiCugXml,
+    "application/vnd.etsi.iptvcommand+xml" => Mime::ApplicationVndEtsiIptvcommandXml,
+    "application/vnd.etsi.iptvdiscovery+xml" => Mime::ApplicationVndEtsiIptvdiscoveryXml,
+    "application/vnd.etsi.iptvprofile+xml" => Mime::ApplicationVndEtsiIptvprofileXml,
+    "application/vnd.etsi.iptvsad-bc+xml" => Mime::ApplicationVndEtsiIptvsadBcXml,
+    "application/vnd.etsi.iptvsad-cod+xml" => Mime::ApplicationVndEtsiIptvsadCodXml,
+    "application/vnd.etsi.iptvsad-npvr+xml" => Mime::ApplicationVndEtsiIptvsadNpvrXml,
+    "application/vnd.etsi.iptvservice+xml" => Mime::ApplicationVndEtsiIptvserviceXml,
+    "application/vnd.etsi.iptvsync+xml" => Mime::ApplicationVndEtsiIptvsyncXml,
+    "application/vnd.etsi.iptvueprofile+xml" => Mime::ApplicationVndEtsiIptvueprofileXml,
+    "application/vnd.etsi.mcid+xml" => Mime::ApplicationVndEtsiMcidXml,
+    "application/vnd.etsi.mheg5" => Mime::ApplicationVndEtsiMheg5,
+    "application/vnd.etsi.overload-control-policy-dataset+xml" => Mime::ApplicationVndEtsiOverloadControlPolicyDatasetXml,
+    "application/vnd.etsi.pstn+xml" => Mime::ApplicationVndEtsiPstnXml,
+    "application/vnd.etsi.sci+xml" => Mime::ApplicationVndEtsiSciXml,
+    "application/vnd.etsi.simservs+xml" => Mime::ApplicationVndEtsiSimservsXml,
+    "application/vnd.etsi.timestamp-token" => Mime::ApplicationVndEtsiTimestampToken,
+    "application/vnd.etsi.tsl+xml" => Mime::ApplicationVndEtsiTslXml,
+    "application/vnd.etsi.tsl.der" => Mime::ApplicationVndEtsiTslDer,
+    "application/vnd.eu.kasparian.car+json" => Mime::ApplicationVndEuKasparianCarJson,
+    "application/vnd.eudora.data" => Mime::ApplicationVndEudoraData,
+    "application/vnd.evolv.ecig.profile" => Mime::ApplicationVndEvolvEcigProfile,
+    "application/vnd.evolv.ecig.settings" => Mime::ApplicationVndEvolvEcigSettings,
+    "application/vnd.evolv.ecig.theme" => Mime::ApplicationVndEvolvEcigTheme,
+    "application/vnd.exstream-empower+zip" => Mime::ApplicationVndExstreamEmpowerZip,
+    "application/vnd.exstream-package" => Mime::ApplicationVndExstreamPackage,
+    "application/vnd.ezpix-album" => Mime::ApplicationVndEzpixAlbum,
+    "application/vnd.ezpix-package" => Mime::ApplicationVndEzpixPackage,
+    "application/vnd.f-secure.mobile" => Mime::ApplicationVndFSecureMobile,
+    "application/vnd.fastcopy-disk-image" => Mime::ApplicationVndFastcopyDiskImage,
+    "application/vnd.familysearch.gedcom+zip" => Mime::ApplicationVndFamilysearchGedcomZip,
+    "application/vnd.fdsn.mseed" => Mime::ApplicationVndFdsnMseed,
+    "application/vnd.fdsn.seed" => Mime::ApplicationVndFdsnSeed,
+    "application/vnd.ffsns" => Mime::ApplicationVndFfsns,
+    "application/vnd.ficlab.flb+zip" => Mime::ApplicationVndFiclabFlbZip,
+    "application/vnd.filmit.zfc" => Mime::ApplicationVndFilmitZfc,
+    "application/vnd.fints" => Mime::ApplicationVndFints,
+    "application/vnd.firemonkeys.cloudcell" => Mime::ApplicationVndFiremonkeysCloudcell,
+    "application/vnd.FloGraphIt" => Mime::ApplicationVndFlographit,
+    "application/vnd.fluxtime.clip" => Mime::ApplicationVndFluxtimeClip,
+    "application/vnd.font-fontforge-sfd" => Mime::ApplicationVndFontFontforgeSfd,
+    "application/vnd.framemaker" => Mime::ApplicationVndFramemaker,
+    "application/vnd.fsc.weblaunch" => Mime::ApplicationVndFscWeblaunch,
+    "application/vnd.fujifilm.fb.docuworks" => Mime::ApplicationVndFujifilmFbDocuworks,
+    "application/vnd.fujifilm.fb.docuworks.binder" => Mime::ApplicationVndFujifilmFbDocuworksBinder,
+    "application/vnd.fujifilm.fb.docuworks.container" => Mime::ApplicationVndFujifilmFbDocuworksContainer,
+    "application/vnd.fujifilm.fb.jfi+xml" => Mime::ApplicationVndFujifilmFbJfiXml,
+    "application/vnd.fujitsu.oasys" => Mime::ApplicationVndFujitsuOasys,
+    "application/vnd.fujitsu.oasys2" => Mime::ApplicationVndFujitsuOasys2,
+    "application/vnd.fujitsu.oasys3" => Mime::ApplicationVndFujitsuOasys3,
+    "application/vnd.fujitsu.oasysgp" => Mime::ApplicationVndFujitsuOasysgp,
+    "application/vnd.fujitsu.oasysprs" => Mime::ApplicationVndFujitsuOasysprs,
+    "application/vnd.fujixerox.ART4" => Mime::ApplicationVndFujixeroxArt4,
+    "application/vnd.fujixerox.ART-EX" => Mime::ApplicationVndFujixeroxArtEx,
+    "application/vnd.fujixerox.ddd" => Mime::ApplicationVndFujixeroxDdd,
+    "application/vnd.fujixerox.docuworks" => Mime::ApplicationVndFujixeroxDocuworks,
+    "application/vnd.fujixerox.docuworks.binder" => Mime::ApplicationVndFujixeroxDocuworksBinder,
+    "application/vnd.fujixerox.docuworks.container" => Mime::ApplicationVndFujixeroxDocuworksContainer,
+    "application/vnd.fujixerox.HBPL" => Mime::ApplicationVndFujixeroxHbpl,
+    "application/vnd.fut-misnet" => Mime::ApplicationVndFutMisnet,
+    "application/vnd.futoin+cbor" => Mime::ApplicationVndFutoinCbor,
+    "application/vnd.futoin+json" => Mime::ApplicationVndFutoinJson,
+    "application/vnd.fuzzysheet" => Mime::ApplicationVndFuzzysheet,
+    "application/vnd.genomatix.tuxedo" => Mime::ApplicationVndGenomatixTuxedo,
+    "application/vnd.genozip" => Mime::ApplicationVndGenozip,
+    "application/vnd.gentics.grd+json" => Mime::ApplicationVndGenticsGrdJson,
+    "application/vnd.gentoo.catmetadata+xml" => Mime::ApplicationVndGentooCatmetadataXml,
+    "application/vnd.gentoo.ebuild" => Mime::ApplicationVndGentooEbuild,
+    "application/vnd.gentoo.eclass" => Mime::ApplicationVndGentooEclass,
+    "application/vnd.gentoo.gpkg" => Mime::ApplicationVndGentooGpkg,
+    "application/vnd.gentoo.manifest" => Mime::ApplicationVndGentooManifest,
+    "application/vnd.gentoo.xpak" => Mime::ApplicationVndGentooXpak,
+    "application/vnd.gentoo.pkgmetadata+xml" => Mime::ApplicationVndGentooPkgmetadataXml,
+    "application/vnd.geogebra.file" => Mime::ApplicationVndGeogebraFile,
+    "application/vnd.geogebra.slides" => Mime::ApplicationVndGeogebraSlides,
+    "application/vnd.geogebra.tool" => Mime::ApplicationVndGeogebraTool,
+    "application/vnd.geometry-explorer" => Mime::ApplicationVndGeometryExplorer,
+    "application/vnd.geonext" => Mime::ApplicationVndGeonext,
+    "application/vnd.geoplan" => Mime::ApplicationVndGeoplan,
+    "application/vnd.geospace" => Mime::ApplicationVndGeospace,
+    "application/vnd.gerber" => Mime::ApplicationVndGerber,
+    "application/vnd.globalplatform.card-content-mgt" => Mime::ApplicationVndGlobalplatformCardContentMgt,
+    "application/vnd.globalplatform.card-content-mgt-response" => Mime::ApplicationVndGlobalplatformCardContentMgtResponse,
+    "application/vnd.gnu.taler.exchange+json" => Mime::ApplicationVndGnuTalerExchangeJson,
+    "application/vnd.gnu.taler.merchant+json" => Mime::ApplicationVndGnuTalerMerchantJson,
+    "application/vnd.google-earth.kml+xml" => Mime::ApplicationVndGoogleEarthKmlXml,
+    "application/vnd.google-earth.kmz" => Mime::ApplicationVndGoogleEarthKmz,
+    "application/vnd.gov.sk.e-form+xml" => Mime::ApplicationVndGovSkEFormXml,
+    "application/vnd.gov.sk.e-form+zip" => Mime::ApplicationVndGovSkEFormZip,
+    "application/vnd.gov.sk.xmldatacontainer+xml" => Mime::ApplicationVndGovSkXmldatacontainerXml,
+    "application/vnd.gpxsee.map+xml" => Mime::ApplicationVndGpxseeMapXml,
+    "application/vnd.grafeq" => Mime::ApplicationVndGrafeq,
+    "application/vnd.gridmp" => Mime::ApplicationVndGridmp,
+    "application/vnd.groove-account" => Mime::ApplicationVndGrooveAccount,
+    "application/vnd.groove-help" => Mime::ApplicationVndGrooveHelp,
+    "application/vnd.groove-identity-message" => Mime::ApplicationVndGrooveIdentityMessage,
+    "application/vnd.groove-injector" => Mime::ApplicationVndGrooveInjector,
+    "application/vnd.groove-tool-message" => Mime::ApplicationVndGrooveToolMessage,
+    "application/vnd.groove-tool-template" => Mime::ApplicationVndGrooveToolTemplate,
+    "application/vnd.groove-vcard" => Mime::ApplicationVndGrooveVcard,
+    "application/vnd.hal+json" => Mime::ApplicationVndHalJson,
+    "application/vnd.hal+xml" => Mime::ApplicationVndHalXml,
+    "application/vnd.HandHeld-Entertainment+xml" => Mime::ApplicationVndHandheldEntertainmentXml,
+    "application/vnd.hbci" => Mime::ApplicationVndHbci,
+    "application/vnd.hc+json" => Mime::ApplicationVndHcJson,
+    "application/vnd.hcl-bireports" => Mime::ApplicationVndHclBireports,
+    "application/vnd.hdt" => Mime::ApplicationVndHdt,
+    "application/vnd.heroku+json" => Mime::ApplicationVndHerokuJson,
+    "application/vnd.hhe.lesson-player" => Mime::ApplicationVndHheLessonPlayer,
+    "application/vnd.hp-HPGL" => Mime::ApplicationVndHpHpgl,
+    "application/vnd.hp-hpid" => Mime::ApplicationVndHpHpid,
+    "application/vnd.hp-hps" => Mime::ApplicationVndHpHps,
+    "application/vnd.hp-jlyt" => Mime::ApplicationVndHpJlyt,
+    "application/vnd.hp-PCL" => Mime::ApplicationVndHpPcl,
+    "application/vnd.hp-PCLXL" => Mime::ApplicationVndHpPclxl,
+    "application/vnd.hsl" => Mime::ApplicationVndHsl,
+    "application/vnd.httphone" => Mime::ApplicationVndHttphone,
+    "application/vnd.hydrostatix.sof-data" => Mime::ApplicationVndHydrostatixSofData,
+    "application/vnd.hyper-item+json" => Mime::ApplicationVndHyperItemJson,
+    "application/vnd.hyper+json" => Mime::ApplicationVndHyperJson,
+    "application/vnd.hyperdrive+json" => Mime::ApplicationVndHyperdriveJson,
+    "application/vnd.hzn-3d-crossword" => Mime::ApplicationVndHzn3dCrossword,
+    "application/vnd.ibm.electronic-media" => Mime::ApplicationVndIbmElectronicMedia,
+    "application/vnd.ibm.MiniPay" => Mime::ApplicationVndIbmMinipay,
+    "application/vnd.ibm.rights-management" => Mime::ApplicationVndIbmRightsManagement,
+    "application/vnd.ibm.secure-container" => Mime::ApplicationVndIbmSecureContainer,
+    "application/vnd.iccprofile" => Mime::ApplicationVndIccprofile,
+    "application/vnd.ieee.1905" => Mime::ApplicationVndIeee1905,
+    "application/vnd.igloader" => Mime::ApplicationVndIgloader,
+    "application/vnd.imagemeter.folder+zip" => Mime::ApplicationVndImagemeterFolderZip,
+    "application/vnd.imagemeter.image+zip" => Mime::ApplicationVndImagemeterImageZip,
+    "application/vnd.immervision-ivp" => Mime::ApplicationVndImmervisionIvp,
+    "application/vnd.immervision-ivu" => Mime::ApplicationVndImmervisionIvu,
+    "application/vnd.ims.imsccv1p1" => Mime::ApplicationVndImsImsccv1p1,
+    "application/vnd.ims.imsccv1p2" => Mime::ApplicationVndImsImsccv1p2,
+    "application/vnd.ims.imsccv1p3" => Mime::ApplicationVndImsImsccv1p3,
+    "application/vnd.ims.lis.v2.result+json" => Mime::ApplicationVndImsLisV2ResultJson,
+    "application/vnd.ims.lti.v2.toolconsumerprofile+json" => Mime::ApplicationVndImsLtiV2ToolconsumerprofileJson,
+    "application/vnd.ims.lti.v2.toolproxy.id+json" => Mime::ApplicationVndImsLtiV2ToolproxyIdJson,
+    "application/vnd.ims.lti.v2.toolproxy+json" => Mime::ApplicationVndImsLtiV2ToolproxyJson,
+    "application/vnd.ims.lti.v2.toolsettings+json" => Mime::ApplicationVndImsLtiV2ToolsettingsJson,
+    "application/vnd.ims.lti.v2.toolsettings.simple+json" => Mime::ApplicationVndImsLtiV2ToolsettingsSimpleJson,
+    "application/vnd.informedcontrol.rms+xml" => Mime::ApplicationVndInformedcontrolRmsXml,
+    "application/vnd.infotech.project" => Mime::ApplicationVndInfotechProject,
+    "application/vnd.infotech.project+xml" => Mime::ApplicationVndInfotechProjectXml,
+    "application/vnd.innopath.wamp.notification" => Mime::ApplicationVndInnopathWampNotification,
+    "application/vnd.insors.igm" => Mime::ApplicationVndInsorsIgm,
+    "application/vnd.intercon.formnet" => Mime::ApplicationVndInterconFormnet,
+    "application/vnd.intergeo" => Mime::ApplicationVndIntergeo,
+    "application/vnd.intertrust.digibox" => Mime::ApplicationVndIntertrustDigibox,
+    "application/vnd.intertrust.nncp" => Mime::ApplicationVndIntertrustNncp,
+    "application/vnd.intu.qbo" => Mime::ApplicationVndIntuQbo,
+    "application/vnd.intu.qfx" => Mime::ApplicationVndIntuQfx,
+    "application/vnd.ipfs.ipns-record" => Mime::ApplicationVndIpfsIpnsRecord,
+    "application/vnd.ipld.car" => Mime::ApplicationVndIpldCar,
+    "application/vnd.ipld.dag-cbor" => Mime::ApplicationVndIpldDagCbor,
+    "application/vnd.ipld.dag-json" => Mime::ApplicationVndIpldDagJson,
+    "application/vnd.ipld.raw" => Mime::ApplicationVndIpldRaw,
+    "application/vnd.iptc.g2.catalogitem+xml" => Mime::ApplicationVndIptcG2CatalogitemXml,
+    "application/vnd.iptc.g2.conceptitem+xml" => Mime::ApplicationVndIptcG2ConceptitemXml,
+    "application/vnd.iptc.g2.knowledgeitem+xml" => Mime::ApplicationVndIptcG2KnowledgeitemXml,
+    "application/vnd.iptc.g2.newsitem+xml" => Mime::ApplicationVndIptcG2NewsitemXml,
+    "application/vnd.iptc.g2.newsmessage+xml" => Mime::ApplicationVndIptcG2NewsmessageXml,
+    "application/vnd.iptc.g2.packageitem+xml" => Mime::ApplicationVndIptcG2PackageitemXml,
+    "application/vnd.iptc.g2.planningitem+xml" => Mime::ApplicationVndIptcG2PlanningitemXml,
+    "application/vnd.ipunplugged.rcprofile" => Mime::ApplicationVndIpunpluggedRcprofile,
+    "application/vnd.irepository.package+xml" => Mime::ApplicationVndIrepositoryPackageXml,
+    "application/vnd.is-xpr" => Mime::ApplicationVndIsXpr,
+    "application/vnd.isac.fcs" => Mime::ApplicationVndIsacFcs,
+    "application/vnd.jam" => Mime::ApplicationVndJam,
+    "application/vnd.iso11783-10+zip" => Mime::ApplicationVndIso1178310Zip,
+    "application/vnd.japannet-directory-service" => Mime::ApplicationVndJapannetDirectoryService,
+    "application/vnd.japannet-jpnstore-wakeup" => Mime::ApplicationVndJapannetJpnstoreWakeup,
+    "application/vnd.japannet-payment-wakeup" => Mime::ApplicationVndJapannetPaymentWakeup,
+    "application/vnd.japannet-registration" => Mime::ApplicationVndJapannetRegistration,
+    "application/vnd.japannet-registration-wakeup" => Mime::ApplicationVndJapannetRegistrationWakeup,
+    "application/vnd.japannet-setstore-wakeup" => Mime::ApplicationVndJapannetSetstoreWakeup,
+    "application/vnd.japannet-verification" => Mime::ApplicationVndJapannetVerification,
+    "application/vnd.japannet-verification-wakeup" => Mime::ApplicationVndJapannetVerificationWakeup,
+    "application/vnd.jcp.javame.midlet-rms" => Mime::ApplicationVndJcpJavameMidletRms,
+    "application/vnd.jisp" => Mime::ApplicationVndJisp,
+    "application/vnd.joost.joda-archive" => Mime::ApplicationVndJoostJodaArchive,
+    "application/vnd.jsk.isdn-ngn" => Mime::ApplicationVndJskIsdnNgn,
+    "application/vnd.kahootz" => Mime::ApplicationVndKahootz,
+    "application/vnd.kde.karbon" => Mime::ApplicationVndKdeKarbon,
+    "application/vnd.kde.kchart" => Mime::ApplicationVndKdeKchart,
+    "application/vnd.kde.kformula" => Mime::ApplicationVndKdeKformula,
+    "application/vnd.kde.kivio" => Mime::ApplicationVndKdeKivio,
+    "application/vnd.kde.kontour" => Mime::ApplicationVndKdeKontour,
+    "application/vnd.kde.kpresenter" => Mime::ApplicationVndKdeKpresenter,
+    "application/vnd.kde.kspread" => Mime::ApplicationVndKdeKspread,
+    "application/vnd.kde.kword" => Mime::ApplicationVndKdeKword,
+    "application/vnd.kenameaapp" => Mime::ApplicationVndKenameaapp,
+    "application/vnd.kidspiration" => Mime::ApplicationVndKidspiration,
+    "application/vnd.Kinar" => Mime::ApplicationVndKinar,
+    "application/vnd.koan" => Mime::ApplicationVndKoan,
+    "application/vnd.kodak-descriptor" => Mime::ApplicationVndKodakDescriptor,
+    "application/vnd.las" => Mime::ApplicationVndLas,
+    "application/vnd.las.las+json" => Mime::ApplicationVndLasLasJson,
+    "application/vnd.las.las+xml" => Mime::ApplicationVndLasLasXml,
+    "application/vnd.laszip" => Mime::ApplicationVndLaszip,
+    "application/vnd.leap+json" => Mime::ApplicationVndLeapJson,
+    "application/vnd.liberty-request+xml" => Mime::ApplicationVndLibertyRequestXml,
+    "application/vnd.llamagraphics.life-balance.desktop" => Mime::ApplicationVndLlamagraphicsLifeBalanceDesktop,
+    "application/vnd.llamagraphics.life-balance.exchange+xml" => Mime::ApplicationVndLlamagraphicsLifeBalanceExchangeXml,
+    "application/vnd.logipipe.circuit+zip" => Mime::ApplicationVndLogipipeCircuitZip,
+    "application/vnd.loom" => Mime::ApplicationVndLoom,
+    "application/vnd.lotus-1-2-3" => Mime::ApplicationVndLotus123,
+    "application/vnd.lotus-approach" => Mime::ApplicationVndLotusApproach,
+    "application/vnd.lotus-freelance" => Mime::ApplicationVndLotusFreelance,
+    "application/vnd.lotus-notes" => Mime::ApplicationVndLotusNotes,
+    "application/vnd.lotus-organizer" => Mime::ApplicationVndLotusOrganizer,
+    "application/vnd.lotus-screencam" => Mime::ApplicationVndLotusScreencam,
+    "application/vnd.lotus-wordpro" => Mime::ApplicationVndLotusWordpro,
+    "application/vnd.macports.portpkg" => Mime::ApplicationVndMacportsPortpkg,
+    "application/vnd.mapbox-vector-tile" => Mime::ApplicationVndMapboxVectorTile,
+    "application/vnd.marlin.drm.actiontoken+xml" => Mime::ApplicationVndMarlinDrmActiontokenXml,
+    "application/vnd.marlin.drm.conftoken+xml" => Mime::ApplicationVndMarlinDrmConftokenXml,
+    "application/vnd.marlin.drm.license+xml" => Mime::ApplicationVndMarlinDrmLicenseXml,
+    "application/vnd.marlin.drm.mdcf" => Mime::ApplicationVndMarlinDrmMdcf,
+    "application/vnd.mason+json" => Mime::ApplicationVndMasonJson,
+    "application/vnd.maxar.archive.3tz+zip" => Mime::ApplicationVndMaxarArchive3tzZip,
+    "application/vnd.maxmind.maxmind-db" => Mime::ApplicationVndMaxmindMaxmindDb,
+    "application/vnd.mcd" => Mime::ApplicationVndMcd,
+    "application/vnd.mdl" => Mime::ApplicationVndMdl,
+    "application/vnd.mdl-mbsdf" => Mime::ApplicationVndMdlMbsdf,
+    "application/vnd.medcalcdata" => Mime::ApplicationVndMedcalcdata,
+    "application/vnd.mediastation.cdkey" => Mime::ApplicationVndMediastationCdkey,
+    "application/vnd.medicalholodeck.recordxr" => Mime::ApplicationVndMedicalholodeckRecordxr,
+    "application/vnd.meridian-slingshot" => Mime::ApplicationVndMeridianSlingshot,
+    "application/vnd.MFER" => Mime::ApplicationVndMfer,
+    "application/vnd.mfmp" => Mime::ApplicationVndMfmp,
+    "application/vnd.micro+json" => Mime::ApplicationVndMicroJson,
+    "application/vnd.micrografx.flo" => Mime::ApplicationVndMicrografxFlo,
+    "application/vnd.micrografx.igx" => Mime::ApplicationVndMicrografxIgx,
+    "application/vnd.microsoft.portable-executable" => Mime::ApplicationVndMicrosoftPortableExecutable,
+    "application/vnd.microsoft.windows.thumbnail-cache" => Mime::ApplicationVndMicrosoftWindowsThumbnailCache,
+    "application/vnd.miele+json" => Mime::ApplicationVndMieleJson,
+    "application/vnd.mif" => Mime::ApplicationVndMif,
+    "application/vnd.minisoft-hp3000-save" => Mime::ApplicationVndMinisoftHp3000Save,
+    "application/vnd.mitsubishi.misty-guard.trustweb" => Mime::ApplicationVndMitsubishiMistyGuardTrustweb,
+    "application/vnd.Mobius.DAF" => Mime::ApplicationVndMobiusDaf,
+    "application/vnd.Mobius.DIS" => Mime::ApplicationVndMobiusDis,
+    "application/vnd.Mobius.MBK" => Mime::ApplicationVndMobiusMbk,
+    "application/vnd.Mobius.MQY" => Mime::ApplicationVndMobiusMqy,
+    "application/vnd.Mobius.MSL" => Mime::ApplicationVndMobiusMsl,
+    "application/vnd.Mobius.PLC" => Mime::ApplicationVndMobiusPlc,
+    "application/vnd.Mobius.TXF" => Mime::ApplicationVndMobiusTxf,
+    "application/vnd.modl" => Mime::ApplicationVndModl,
+    "application/vnd.mophun.application" => Mime::ApplicationVndMophunApplication,
+    "application/vnd.mophun.certificate" => Mime::ApplicationVndMophunCertificate,
+    "application/vnd.motorola.flexsuite" => Mime::ApplicationVndMotorolaFlexsuite,
+    "application/vnd.motorola.flexsuite.adsi" => Mime::ApplicationVndMotorolaFlexsuiteAdsi,
+    "application/vnd.motorola.flexsuite.fis" => Mime::ApplicationVndMotorolaFlexsuiteFis,
+    "application/vnd.motorola.flexsuite.gotap" => Mime::ApplicationVndMotorolaFlexsuiteGotap,
+    "application/vnd.motorola.flexsuite.kmr" => Mime::ApplicationVndMotorolaFlexsuiteKmr,
+    "application/vnd.motorola.flexsuite.ttc" => Mime::ApplicationVndMotorolaFlexsuiteTtc,
+    "application/vnd.motorola.flexsuite.wem" => Mime::ApplicationVndMotorolaFlexsuiteWem,
+    "application/vnd.motorola.iprm" => Mime::ApplicationVndMotorolaIprm,
+    "application/vnd.mozilla.xul+xml" => Mime::ApplicationVndMozillaXulXml,
+    "application/vnd.ms-artgalry" => Mime::ApplicationVndMsArtgalry,
+    "application/vnd.ms-asf" => Mime::ApplicationVndMsAsf,
+    "application/vnd.ms-cab-compressed" => Mime::ApplicationVndMsCabCompressed,
+    "application/vnd.ms-3mfdocument" => Mime::ApplicationVndMs3mfdocument,
+    "application/vnd.ms-excel" => Mime::ApplicationVndMsExcel,
+    "application/vnd.ms-excel.addin.macroEnabled.12" => Mime::ApplicationVndMsExcelAddinMacroenabled12,
+    "application/vnd.ms-excel.sheet.binary.macroEnabled.12" => Mime::ApplicationVndMsExcelSheetBinaryMacroenabled12,
+    "application/vnd.ms-excel.sheet.macroEnabled.12" => Mime::ApplicationVndMsExcelSheetMacroenabled12,
+    "application/vnd.ms-excel.template.macroEnabled.12" => Mime::ApplicationVndMsExcelTemplateMacroenabled12,
+    "application/vnd.ms-fontobject" => Mime::ApplicationVndMsFontobject,
+    "application/vnd.ms-htmlhelp" => Mime::ApplicationVndMsHtmlhelp,
+    "application/vnd.ms-ims" => Mime::ApplicationVndMsIms,
+    "application/vnd.ms-lrm" => Mime::ApplicationVndMsLrm,
+    "application/vnd.ms-office.activeX+xml" => Mime::ApplicationVndMsOfficeActivexXml,
+    "application/vnd.ms-officetheme" => Mime::ApplicationVndMsOfficetheme,
+    "application/vnd.ms-playready.initiator+xml" => Mime::ApplicationVndMsPlayreadyInitiatorXml,
+    "application/vnd.ms-powerpoint" => Mime::ApplicationVndMsPowerpoint,
+    "application/vnd.ms-powerpoint.addin.macroEnabled.12" => Mime::ApplicationVndMsPowerpointAddinMacroenabled12,
+    "application/vnd.ms-powerpoint.presentation.macroEnabled.12" => Mime::ApplicationVndMsPowerpointPresentationMacroenabled12,
+    "application/vnd.ms-powerpoint.slide.macroEnabled.12" => Mime::ApplicationVndMsPowerpointSlideMacroenabled12,
+    "application/vnd.ms-powerpoint.slideshow.macroEnabled.12" => Mime::ApplicationVndMsPowerpointSlideshowMacroenabled12,
+    "application/vnd.ms-powerpoint.template.macroEnabled.12" => Mime::ApplicationVndMsPowerpointTemplateMacroenabled12,
+    "application/vnd.ms-PrintDeviceCapabilities+xml" => Mime::ApplicationVndMsPrintdevicecapabilitiesXml,
+    "application/vnd.ms-PrintSchemaTicket+xml" => Mime::ApplicationVndMsPrintschematicketXml,
+    "application/vnd.ms-project" => Mime::ApplicationVndMsProject,
+    "application/vnd.ms-tnef" => Mime::ApplicationVndMsTnef,
+    "application/vnd.ms-windows.devicepairing" => Mime::ApplicationVndMsWindowsDevicepairing,
+    "application/vnd.ms-windows.nwprinting.oob" => Mime::ApplicationVndMsWindowsNwprintingOob,
+    "application/vnd.ms-windows.printerpairing" => Mime::ApplicationVndMsWindowsPrinterpairing,
+    "application/vnd.ms-windows.wsd.oob" => Mime::ApplicationVndMsWindowsWsdOob,
+    "application/vnd.ms-wmdrm.lic-chlg-req" => Mime::ApplicationVndMsWmdrmLicChlgReq,
+    "application/vnd.ms-wmdrm.lic-resp" => Mime::ApplicationVndMsWmdrmLicResp,
+    "application/vnd.ms-wmdrm.meter-chlg-req" => Mime::ApplicationVndMsWmdrmMeterChlgReq,
+    "application/vnd.ms-wmdrm.meter-resp" => Mime::ApplicationVndMsWmdrmMeterResp,
+    "application/vnd.ms-word.document.macroEnabled.12" => Mime::ApplicationVndMsWordDocumentMacroenabled12,
+    "application/vnd.ms-word.template.macroEnabled.12" => Mime::ApplicationVndMsWordTemplateMacroenabled12,
+    "application/vnd.ms-works" => Mime::ApplicationVndMsWorks,
+    "application/vnd.ms-wpl" => Mime::ApplicationVndMsWpl,
+    "application/vnd.ms-xpsdocument" => Mime::ApplicationVndMsXpsdocument,
+    "application/vnd.msa-disk-image" => Mime::ApplicationVndMsaDiskImage,
+    "application/vnd.mseq" => Mime::ApplicationVndMseq,
+    "application/vnd.msign" => Mime::ApplicationVndMsign,
+    "application/vnd.multiad.creator" => Mime::ApplicationVndMultiadCreator,
+    "application/vnd.multiad.creator.cif" => Mime::ApplicationVndMultiadCreatorCif,
+    "application/vnd.musician" => Mime::ApplicationVndMusician,
+    "application/vnd.music-niff" => Mime::ApplicationVndMusicNiff,
+    "application/vnd.muvee.style" => Mime::ApplicationVndMuveeStyle,
+    "application/vnd.mynfc" => Mime::ApplicationVndMynfc,
+    "application/vnd.nacamar.ybrid+json" => Mime::ApplicationVndNacamarYbridJson,
+    "application/vnd.ncd.control" => Mime::ApplicationVndNcdControl,
+    "application/vnd.ncd.reference" => Mime::ApplicationVndNcdReference,
+    "application/vnd.nearst.inv+json" => Mime::ApplicationVndNearstInvJson,
+    "application/vnd.nebumind.line" => Mime::ApplicationVndNebumindLine,
+    "application/vnd.nervana" => Mime::ApplicationVndNervana,
+    "application/vnd.netfpx" => Mime::ApplicationVndNetfpx,
+    "application/vnd.neurolanguage.nlu" => Mime::ApplicationVndNeurolanguageNlu,
+    "application/vnd.nimn" => Mime::ApplicationVndNimn,
+    "application/vnd.nintendo.snes.rom" => Mime::ApplicationVndNintendoSnesRom,
+    "application/vnd.nintendo.nitro.rom" => Mime::ApplicationVndNintendoNitroRom,
+    "application/vnd.nitf" => Mime::ApplicationVndNitf,
+    "application/vnd.noblenet-directory" => Mime::ApplicationVndNoblenetDirectory,
+    "application/vnd.noblenet-sealer" => Mime::ApplicationVndNoblenetSealer,
+    "application/vnd.noblenet-web" => Mime::ApplicationVndNoblenetWeb,
+    "application/vnd.nokia.catalogs" => Mime::ApplicationVndNokiaCatalogs,
+    "application/vnd.nokia.conml+wbxml" => Mime::ApplicationVndNokiaConmlWbxml,
+    "application/vnd.nokia.conml+xml" => Mime::ApplicationVndNokiaConmlXml,
+    "application/vnd.nokia.iptv.config+xml" => Mime::ApplicationVndNokiaIptvConfigXml,
+    "application/vnd.nokia.iSDS-radio-presets" => Mime::ApplicationVndNokiaIsdsRadioPresets,
+    "application/vnd.nokia.landmark+wbxml" => Mime::ApplicationVndNokiaLandmarkWbxml,
+    "application/vnd.nokia.landmark+xml" => Mime::ApplicationVndNokiaLandmarkXml,
+    "application/vnd.nokia.landmarkcollection+xml" => Mime::ApplicationVndNokiaLandmarkcollectionXml,
+    "application/vnd.nokia.ncd" => Mime::ApplicationVndNokiaNcd,
+    "application/vnd.nokia.n-gage.ac+xml" => Mime::ApplicationVndNokiaNGageAcXml,
+    "application/vnd.nokia.n-gage.data" => Mime::ApplicationVndNokiaNGageData,
+    "application/vnd.nokia.pcd+wbxml" => Mime::ApplicationVndNokiaPcdWbxml,
+    "application/vnd.nokia.pcd+xml" => Mime::ApplicationVndNokiaPcdXml,
+    "application/vnd.nokia.radio-preset" => Mime::ApplicationVndNokiaRadioPreset,
+    "application/vnd.nokia.radio-presets" => Mime::ApplicationVndNokiaRadioPresets,
+    "application/vnd.novadigm.EDM" => Mime::ApplicationVndNovadigmEdm,
+    "application/vnd.novadigm.EDX" => Mime::ApplicationVndNovadigmEdx,
+    "application/vnd.novadigm.EXT" => Mime::ApplicationVndNovadigmExt,
+    "application/vnd.ntt-local.content-share" => Mime::ApplicationVndNttLocalContentShare,
+    "application/vnd.ntt-local.file-transfer" => Mime::ApplicationVndNttLocalFileTransfer,
+    "application/vnd.ntt-local.ogw_remote-access" => Mime::ApplicationVndNttLocalOgwRemoteAccess,
+    "application/vnd.ntt-local.sip-ta_remote" => Mime::ApplicationVndNttLocalSipTaRemote,
+    "application/vnd.ntt-local.sip-ta_tcp_stream" => Mime::ApplicationVndNttLocalSipTaTcpStream,
+    "application/vnd.oasis.opendocument.base" => Mime::ApplicationVndOasisOpendocumentBase,
+    "application/vnd.oasis.opendocument.chart" => Mime::ApplicationVndOasisOpendocumentChart,
+    "application/vnd.oasis.opendocument.chart-template" => Mime::ApplicationVndOasisOpendocumentChartTemplate,
+    "application/vnd.oasis.opendocument.formula" => Mime::ApplicationVndOasisOpendocumentFormula,
+    "application/vnd.oasis.opendocument.formula-template" => Mime::ApplicationVndOasisOpendocumentFormulaTemplate,
+    "application/vnd.oasis.opendocument.graphics" => Mime::ApplicationVndOasisOpendocumentGraphics,
+    "application/vnd.oasis.opendocument.graphics-template" => Mime::ApplicationVndOasisOpendocumentGraphicsTemplate,
+    "application/vnd.oasis.opendocument.image" => Mime::ApplicationVndOasisOpendocumentImage,
+    "application/vnd.oasis.opendocument.image-template" => Mime::ApplicationVndOasisOpendocumentImageTemplate,
+    "application/vnd.oasis.opendocument.presentation" => Mime::ApplicationVndOasisOpendocumentPresentation,
+    "application/vnd.oasis.opendocument.presentation-template" => Mime::ApplicationVndOasisOpendocumentPresentationTemplate,
+    "application/vnd.oasis.opendocument.spreadsheet" => Mime::ApplicationVndOasisOpendocumentSpreadsheet,
+    "application/vnd.oasis.opendocument.spreadsheet-template" => Mime::ApplicationVndOasisOpendocumentSpreadsheetTemplate,
+    "application/vnd.oasis.opendocument.text" => Mime::ApplicationVndOasisOpendocumentText,
+    "application/vnd.oasis.opendocument.text-master" => Mime::ApplicationVndOasisOpendocumentTextMaster,
+    "application/vnd.oasis.opendocument.text-master-template" => Mime::ApplicationVndOasisOpendocumentTextMasterTemplate,
+    "application/vnd.oasis.opendocument.text-template" => Mime::ApplicationVndOasisOpendocumentTextTemplate,
+    "application/vnd.oasis.opendocument.text-web" => Mime::ApplicationVndOasisOpendocumentTextWeb,
+    "application/vnd.obn" => Mime::ApplicationVndObn,
+    "application/vnd.ocf+cbor" => Mime::ApplicationVndOcfCbor,
+    "application/vnd.oci.image.manifest.v1+json" => Mime::ApplicationVndOciImageManifestV1Json,
+    "application/vnd.oftn.l10n+json" => Mime::ApplicationVndOftnL10nJson,
+    "application/vnd.oipf.contentaccessdownload+xml" => Mime::ApplicationVndOipfContentaccessdownloadXml,
+    "application/vnd.oipf.contentaccessstreaming+xml" => Mime::ApplicationVndOipfContentaccessstreamingXml,
+    "application/vnd.oipf.cspg-hexbinary" => Mime::ApplicationVndOipfCspgHexbinary,
+    "application/vnd.oipf.dae.svg+xml" => Mime::ApplicationVndOipfDaeSvgXml,
+    "application/vnd.oipf.dae.xhtml+xml" => Mime::ApplicationVndOipfDaeXhtmlXml,
+    "application/vnd.oipf.mippvcontrolmessage+xml" => Mime::ApplicationVndOipfMippvcontrolmessageXml,
+    "application/vnd.oipf.pae.gem" => Mime::ApplicationVndOipfPaeGem,
+    "application/vnd.oipf.spdiscovery+xml" => Mime::ApplicationVndOipfSpdiscoveryXml,
+    "application/vnd.oipf.spdlist+xml" => Mime::ApplicationVndOipfSpdlistXml,
+    "application/vnd.oipf.ueprofile+xml" => Mime::ApplicationVndOipfUeprofileXml,
+    "application/vnd.oipf.userprofile+xml" => Mime::ApplicationVndOipfUserprofileXml,
+    "application/vnd.olpc-sugar" => Mime::ApplicationVndOlpcSugar,
+    "application/vnd.oma.bcast.associated-procedure-parameter+xml" => Mime::ApplicationVndOmaBcastAssociatedProcedureParameterXml,
+    "application/vnd.oma.bcast.drm-trigger+xml" => Mime::ApplicationVndOmaBcastDrmTriggerXml,
+    "application/vnd.oma.bcast.imd+xml" => Mime::ApplicationVndOmaBcastImdXml,
+    "application/vnd.oma.bcast.ltkm" => Mime::ApplicationVndOmaBcastLtkm,
+    "application/vnd.oma.bcast.notification+xml" => Mime::ApplicationVndOmaBcastNotificationXml,
+    "application/vnd.oma.bcast.provisioningtrigger" => Mime::ApplicationVndOmaBcastProvisioningtrigger,
+    "application/vnd.oma.bcast.sgboot" => Mime::ApplicationVndOmaBcastSgboot,
+    "application/vnd.oma.bcast.sgdd+xml" => Mime::ApplicationVndOmaBcastSgddXml,
+    "application/vnd.oma.bcast.sgdu" => Mime::ApplicationVndOmaBcastSgdu,
+    "application/vnd.oma.bcast.simple-symbol-container" => Mime::ApplicationVndOmaBcastSimpleSymbolContainer,
+    "application/vnd.oma.bcast.smartcard-trigger+xml" => Mime::ApplicationVndOmaBcastSmartcardTriggerXml,
+    "application/vnd.oma.bcast.sprov+xml" => Mime::ApplicationVndOmaBcastSprovXml,
+    "application/vnd.oma.bcast.stkm" => Mime::ApplicationVndOmaBcastStkm,
+    "application/vnd.oma.cab-address-book+xml" => Mime::ApplicationVndOmaCabAddressBookXml,
+    "application/vnd.oma.cab-feature-handler+xml" => Mime::ApplicationVndOmaCabFeatureHandlerXml,
+    "application/vnd.oma.cab-pcc+xml" => Mime::ApplicationVndOmaCabPccXml,
+    "application/vnd.oma.cab-subs-invite+xml" => Mime::ApplicationVndOmaCabSubsInviteXml,
+    "application/vnd.oma.cab-user-prefs+xml" => Mime::ApplicationVndOmaCabUserPrefsXml,
+    "application/vnd.oma.dcd" => Mime::ApplicationVndOmaDcd,
+    "application/vnd.oma.dcdc" => Mime::ApplicationVndOmaDcdc,
+    "application/vnd.oma.dd2+xml" => Mime::ApplicationVndOmaDd2Xml,
+    "application/vnd.oma.drm.risd+xml" => Mime::ApplicationVndOmaDrmRisdXml,
+    "application/vnd.oma.group-usage-list+xml" => Mime::ApplicationVndOmaGroupUsageListXml,
+    "application/vnd.oma.lwm2m+cbor" => Mime::ApplicationVndOmaLwm2mCbor,
+    "application/vnd.oma.lwm2m+json" => Mime::ApplicationVndOmaLwm2mJson,
+    "application/vnd.oma.lwm2m+tlv" => Mime::ApplicationVndOmaLwm2mTlv,
+    "application/vnd.oma.pal+xml" => Mime::ApplicationVndOmaPalXml,
+    "application/vnd.oma.poc.detailed-progress-report+xml" => Mime::ApplicationVndOmaPocDetailedProgressReportXml,
+    "application/vnd.oma.poc.final-report+xml" => Mime::ApplicationVndOmaPocFinalReportXml,
+    "application/vnd.oma.poc.groups+xml" => Mime::ApplicationVndOmaPocGroupsXml,
+    "application/vnd.oma.poc.invocation-descriptor+xml" => Mime::ApplicationVndOmaPocInvocationDescriptorXml,
+    "application/vnd.oma.poc.optimized-progress-report+xml" => Mime::ApplicationVndOmaPocOptimizedProgressReportXml,
+    "application/vnd.oma.push" => Mime::ApplicationVndOmaPush,
+    "application/vnd.oma.scidm.messages+xml" => Mime::ApplicationVndOmaScidmMessagesXml,
+    "application/vnd.oma.xcap-directory+xml" => Mime::ApplicationVndOmaXcapDirectoryXml,
+    "application/vnd.omads-email+xml" => Mime::ApplicationVndOmadsEmailXml,
+    "application/vnd.omads-file+xml" => Mime::ApplicationVndOmadsFileXml,
+    "application/vnd.omads-folder+xml" => Mime::ApplicationVndOmadsFolderXml,
+    "application/vnd.omaloc-supl-init" => Mime::ApplicationVndOmalocSuplInit,
+    "application/vnd.oma-scws-config" => Mime::ApplicationVndOmaScwsConfig,
+    "application/vnd.oma-scws-http-request" => Mime::ApplicationVndOmaScwsHttpRequest,
+    "application/vnd.oma-scws-http-response" => Mime::ApplicationVndOmaScwsHttpResponse,
+    "application/vnd.onepager" => Mime::ApplicationVndOnepager,
+    "application/vnd.onepagertamp" => Mime::ApplicationVndOnepagertamp,
+    "application/vnd.onepagertamx" => Mime::ApplicationVndOnepagertamx,
+    "application/vnd.onepagertat" => Mime::ApplicationVndOnepagertat,
+    "application/vnd.onepagertatp" => Mime::ApplicationVndOnepagertatp,
+    "application/vnd.onepagertatx" => Mime::ApplicationVndOnepagertatx,
+    "application/vnd.onvif.metadata" => Mime::ApplicationVndOnvifMetadata,
+    "application/vnd.openblox.game-binary" => Mime::ApplicationVndOpenbloxGameBinary,
+    "application/vnd.openblox.game+xml" => Mime::ApplicationVndOpenbloxGameXml,
+    "application/vnd.openeye.oeb" => Mime::ApplicationVndOpeneyeOeb,
+    "application/vnd.openstreetmap.data+xml" => Mime::ApplicationVndOpenstreetmapDataXml,
+    "application/vnd.opentimestamps.ots" => Mime::ApplicationVndOpentimestampsOts,
+    "application/vnd.openxmlformats-officedocument.custom-properties+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentCustomPropertiesXml,
+    "application/vnd.openxmlformats-officedocument.customXmlProperties+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentCustomxmlpropertiesXml,
+    "application/vnd.openxmlformats-officedocument.drawing+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentDrawingXml,
+    "application/vnd.openxmlformats-officedocument.drawingml.chart+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentDrawingmlChartXml,
+    "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentDrawingmlChartshapesXml,
+    "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentDrawingmlDiagramcolorsXml,
+    "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentDrawingmlDiagramdataXml,
+    "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentDrawingmlDiagramlayoutXml,
+    "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentDrawingmlDiagramstyleXml,
+    "application/vnd.openxmlformats-officedocument.extended-properties+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentExtendedPropertiesXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.commentAuthors+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlCommentauthorsXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.comments+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlCommentsXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.handoutMaster+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlHandoutmasterXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlNotesmasterXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlNotesslideXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.presentation" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlPresentation,
+    "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlPresentationMainXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.presProps+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlPrespropsXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.slide" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlide,
+    "application/vnd.openxmlformats-officedocument.presentationml.slide+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlideXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlidelayoutXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlidemasterXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.slideshow" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlideshow,
+    "application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlideshowMainXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.slideUpdateInfo+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlideupdateinfoXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlTablestylesXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.tags+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlTagsXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.template" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlTemplate,
+    "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlTemplateMainXml,
+    "application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlViewpropsXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlCalcchainXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlChartsheetXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlCommentsXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlConnectionsXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlDialogsheetXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlExternallinkXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlPivotcachedefinitionXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlPivotcacherecordsXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlPivottableXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlQuerytableXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlRevisionheadersXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlRevisionlogXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSharedstringsXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSheet,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSheetMainXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSheetmetadataXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlStylesXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlTableXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlTablesinglecellsXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.template" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlTemplate,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlTemplateMainXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlUsernamesXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.volatileDependencies+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlVolatiledependenciesXml,
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlWorksheetXml,
+    "application/vnd.openxmlformats-officedocument.theme+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentThemeXml,
+    "application/vnd.openxmlformats-officedocument.themeOverride+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentThemeoverrideXml,
+    "application/vnd.openxmlformats-officedocument.vmlDrawing" => Mime::ApplicationVndOpenxmlformatsOfficedocumentVmldrawing,
+    "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlCommentsXml,
+    "application/vnd.openxmlformats-officedocument.wordprocessingml.document" => Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlDocument,
+    "application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlDocumentGlossaryXml,
+    "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlDocumentMainXml,
+    "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlEndnotesXml,
+    "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlFonttableXml,
+    "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlFooterXml,
+    "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlFootnotesXml,
+    "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlNumberingXml,
+    "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlSettingsXml,
+    "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlStylesXml,
+    "application/vnd.openxmlformats-officedocument.wordprocessingml.template" => Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlTemplate,
+    "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlTemplateMainXml,
+    "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml" => Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlWebsettingsXml,
+    "application/vnd.openxmlformats-package.core-properties+xml" => Mime::ApplicationVndOpenxmlformatsPackageCorePropertiesXml,
+    "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml" => Mime::ApplicationVndOpenxmlformatsPackageDigitalSignatureXmlsignatureXml,
+    "application/vnd.openxmlformats-package.relationships+xml" => Mime::ApplicationVndOpenxmlformatsPackageRelationshipsXml,
+    "application/vnd.oracle.resource+json" => Mime::ApplicationVndOracleResourceJson,
+    "application/vnd.orange.indata" => Mime::ApplicationVndOrangeIndata,
+    "application/vnd.osa.netdeploy" => Mime::ApplicationVndOsaNetdeploy,
+    "application/vnd.osgeo.mapguide.package" => Mime::ApplicationVndOsgeoMapguidePackage,
+    "application/vnd.osgi.bundle" => Mime::ApplicationVndOsgiBundle,
+    "application/vnd.osgi.dp" => Mime::ApplicationVndOsgiDp,
+    "application/vnd.osgi.subsystem" => Mime::ApplicationVndOsgiSubsystem,
+    "application/vnd.otps.ct-kip+xml" => Mime::ApplicationVndOtpsCtKipXml,
+    "application/vnd.oxli.countgraph" => Mime::ApplicationVndOxliCountgraph,
+    "application/vnd.pagerduty+json" => Mime::ApplicationVndPagerdutyJson,
+    "application/vnd.palm" => Mime::ApplicationVndPalm,
+    "application/vnd.panoply" => Mime::ApplicationVndPanoply,
+    "application/vnd.paos.xml" => Mime::ApplicationVndPaosXml,
+    "application/vnd.patentdive" => Mime::ApplicationVndPatentdive,
+    "application/vnd.patientecommsdoc" => Mime::ApplicationVndPatientecommsdoc,
+    "application/vnd.pawaafile" => Mime::ApplicationVndPawaafile,
+    "application/vnd.pcos" => Mime::ApplicationVndPcos,
+    "application/vnd.pg.format" => Mime::ApplicationVndPgFormat,
+    "application/vnd.pg.osasli" => Mime::ApplicationVndPgOsasli,
+    "application/vnd.piaccess.application-licence" => Mime::ApplicationVndPiaccessApplicationLicence,
+    "application/vnd.picsel" => Mime::ApplicationVndPicsel,
+    "application/vnd.pmi.widget" => Mime::ApplicationVndPmiWidget,
+    "application/vnd.poc.group-advertisement+xml" => Mime::ApplicationVndPocGroupAdvertisementXml,
+    "application/vnd.pocketlearn" => Mime::ApplicationVndPocketlearn,
+    "application/vnd.powerbuilder6" => Mime::ApplicationVndPowerbuilder6,
+    "application/vnd.powerbuilder6-s" => Mime::ApplicationVndPowerbuilder6S,
+    "application/vnd.powerbuilder7" => Mime::ApplicationVndPowerbuilder7,
+    "application/vnd.powerbuilder75" => Mime::ApplicationVndPowerbuilder75,
+    "application/vnd.powerbuilder75-s" => Mime::ApplicationVndPowerbuilder75S,
+    "application/vnd.powerbuilder7-s" => Mime::ApplicationVndPowerbuilder7S,
+    "application/vnd.preminet" => Mime::ApplicationVndPreminet,
+    "application/vnd.previewsystems.box" => Mime::ApplicationVndPreviewsystemsBox,
+    "application/vnd.proteus.magazine" => Mime::ApplicationVndProteusMagazine,
+    "application/vnd.psfs" => Mime::ApplicationVndPsfs,
+    "application/vnd.pt.mundusmundi" => Mime::ApplicationVndPtMundusmundi,
+    "application/vnd.publishare-delta-tree" => Mime::ApplicationVndPublishareDeltaTree,
+    "application/vnd.pvi.ptid1" => Mime::ApplicationVndPviPtid1,
+    "application/vnd.pwg-multiplexed" => Mime::ApplicationVndPwgMultiplexed,
+    "application/vnd.pwg-xhtml-print+xml" => Mime::ApplicationVndPwgXhtmlPrintXml,
+    "application/vnd.qualcomm.brew-app-res" => Mime::ApplicationVndQualcommBrewAppRes,
+    "application/vnd.quarantainenet" => Mime::ApplicationVndQuarantainenet,
+    "application/vnd.Quark.QuarkXPress" => Mime::ApplicationVndQuarkQuarkxpress,
+    "application/vnd.quobject-quoxdocument" => Mime::ApplicationVndQuobjectQuoxdocument,
+    "application/vnd.radisys.moml+xml" => Mime::ApplicationVndRadisysMomlXml,
+    "application/vnd.radisys.msml-audit-conf+xml" => Mime::ApplicationVndRadisysMsmlAuditConfXml,
+    "application/vnd.radisys.msml-audit-conn+xml" => Mime::ApplicationVndRadisysMsmlAuditConnXml,
+    "application/vnd.radisys.msml-audit-dialog+xml" => Mime::ApplicationVndRadisysMsmlAuditDialogXml,
+    "application/vnd.radisys.msml-audit-stream+xml" => Mime::ApplicationVndRadisysMsmlAuditStreamXml,
+    "application/vnd.radisys.msml-audit+xml" => Mime::ApplicationVndRadisysMsmlAuditXml,
+    "application/vnd.radisys.msml-conf+xml" => Mime::ApplicationVndRadisysMsmlConfXml,
+    "application/vnd.radisys.msml-dialog-base+xml" => Mime::ApplicationVndRadisysMsmlDialogBaseXml,
+    "application/vnd.radisys.msml-dialog-fax-detect+xml" => Mime::ApplicationVndRadisysMsmlDialogFaxDetectXml,
+    "application/vnd.radisys.msml-dialog-fax-sendrecv+xml" => Mime::ApplicationVndRadisysMsmlDialogFaxSendrecvXml,
+    "application/vnd.radisys.msml-dialog-group+xml" => Mime::ApplicationVndRadisysMsmlDialogGroupXml,
+    "application/vnd.radisys.msml-dialog-speech+xml" => Mime::ApplicationVndRadisysMsmlDialogSpeechXml,
+    "application/vnd.radisys.msml-dialog-transform+xml" => Mime::ApplicationVndRadisysMsmlDialogTransformXml,
+    "application/vnd.radisys.msml-dialog+xml" => Mime::ApplicationVndRadisysMsmlDialogXml,
+    "application/vnd.radisys.msml+xml" => Mime::ApplicationVndRadisysMsmlXml,
+    "application/vnd.rainstor.data" => Mime::ApplicationVndRainstorData,
+    "application/vnd.rapid" => Mime::ApplicationVndRapid,
+    "application/vnd.rar" => Mime::ApplicationVndRar,
+    "application/vnd.realvnc.bed" => Mime::ApplicationVndRealvncBed,
+    "application/vnd.recordare.musicxml" => Mime::ApplicationVndRecordareMusicxml,
+    "application/vnd.recordare.musicxml+xml" => Mime::ApplicationVndRecordareMusicxmlXml,
+    "application/vnd.RenLearn.rlprint" => Mime::ApplicationVndRenlearnRlprint,
+    "application/vnd.resilient.logic" => Mime::ApplicationVndResilientLogic,
+    "application/vnd.restful+json" => Mime::ApplicationVndRestfulJson,
+    "application/vnd.rig.cryptonote" => Mime::ApplicationVndRigCryptonote,
+    "application/vnd.route66.link66+xml" => Mime::ApplicationVndRoute66Link66Xml,
+    "application/vnd.rs-274x" => Mime::ApplicationVndRs274x,
+    "application/vnd.ruckus.download" => Mime::ApplicationVndRuckusDownload,
+    "application/vnd.s3sms" => Mime::ApplicationVndS3sms,
+    "application/vnd.sailingtracker.track" => Mime::ApplicationVndSailingtrackerTrack,
+    "application/vnd.sar" => Mime::ApplicationVndSar,
+    "application/vnd.sbm.cid" => Mime::ApplicationVndSbmCid,
+    "application/vnd.sbm.mid2" => Mime::ApplicationVndSbmMid2,
+    "application/vnd.scribus" => Mime::ApplicationVndScribus,
+    "application/vnd.sealed.3df" => Mime::ApplicationVndSealed3df,
+    "application/vnd.sealed.csf" => Mime::ApplicationVndSealedCsf,
+    "application/vnd.sealed.doc" => Mime::ApplicationVndSealedDoc,
+    "application/vnd.sealed.eml" => Mime::ApplicationVndSealedEml,
+    "application/vnd.sealed.mht" => Mime::ApplicationVndSealedMht,
+    "application/vnd.sealed.net" => Mime::ApplicationVndSealedNet,
+    "application/vnd.sealed.ppt" => Mime::ApplicationVndSealedPpt,
+    "application/vnd.sealed.tiff" => Mime::ApplicationVndSealedTiff,
+    "application/vnd.sealed.xls" => Mime::ApplicationVndSealedXls,
+    "application/vnd.sealedmedia.softseal.html" => Mime::ApplicationVndSealedmediaSoftsealHtml,
+    "application/vnd.sealedmedia.softseal.pdf" => Mime::ApplicationVndSealedmediaSoftsealPdf,
+    "application/vnd.seemail" => Mime::ApplicationVndSeemail,
+    "application/vnd.seis+json" => Mime::ApplicationVndSeisJson,
+    "application/vnd.sema" => Mime::ApplicationVndSema,
+    "application/vnd.semd" => Mime::ApplicationVndSemd,
+    "application/vnd.semf" => Mime::ApplicationVndSemf,
+    "application/vnd.shade-save-file" => Mime::ApplicationVndShadeSaveFile,
+    "application/vnd.shana.informed.formdata" => Mime::ApplicationVndShanaInformedFormdata,
+    "application/vnd.shana.informed.formtemplate" => Mime::ApplicationVndShanaInformedFormtemplate,
+    "application/vnd.shana.informed.interchange" => Mime::ApplicationVndShanaInformedInterchange,
+    "application/vnd.shana.informed.package" => Mime::ApplicationVndShanaInformedPackage,
+    "application/vnd.shootproof+json" => Mime::ApplicationVndShootproofJson,
+    "application/vnd.shopkick+json" => Mime::ApplicationVndShopkickJson,
+    "application/vnd.shp" => Mime::ApplicationVndShp,
+    "application/vnd.shx" => Mime::ApplicationVndShx,
+    "application/vnd.sigrok.session" => Mime::ApplicationVndSigrokSession,
+    "application/vnd.SimTech-MindMapper" => Mime::ApplicationVndSimtechMindmapper,
+    "application/vnd.siren+json" => Mime::ApplicationVndSirenJson,
+    "application/vnd.smaf" => Mime::ApplicationVndSmaf,
+    "application/vnd.smart.notebook" => Mime::ApplicationVndSmartNotebook,
+    "application/vnd.smart.teacher" => Mime::ApplicationVndSmartTeacher,
+    "application/vnd.smintio.portals.archive" => Mime::ApplicationVndSmintioPortalsArchive,
+    "application/vnd.snesdev-page-table" => Mime::ApplicationVndSnesdevPageTable,
+    "application/vnd.software602.filler.form+xml" => Mime::ApplicationVndSoftware602FillerFormXml,
+    "application/vnd.software602.filler.form-xml-zip" => Mime::ApplicationVndSoftware602FillerFormXmlZip,
+    "application/vnd.solent.sdkm+xml" => Mime::ApplicationVndSolentSdkmXml,
+    "application/vnd.spotfire.dxp" => Mime::ApplicationVndSpotfireDxp,
+    "application/vnd.spotfire.sfs" => Mime::ApplicationVndSpotfireSfs,
+    "application/vnd.sqlite3" => Mime::ApplicationVndSqlite3,
+    "application/vnd.sss-cod" => Mime::ApplicationVndSssCod,
+    "application/vnd.sss-dtf" => Mime::ApplicationVndSssDtf,
+    "application/vnd.sss-ntf" => Mime::ApplicationVndSssNtf,
+    "application/vnd.stepmania.package" => Mime::ApplicationVndStepmaniaPackage,
+    "application/vnd.stepmania.stepchart" => Mime::ApplicationVndStepmaniaStepchart,
+    "application/vnd.street-stream" => Mime::ApplicationVndStreetStream,
+    "application/vnd.sun.wadl+xml" => Mime::ApplicationVndSunWadlXml,
+    "application/vnd.sus-calendar" => Mime::ApplicationVndSusCalendar,
+    "application/vnd.svd" => Mime::ApplicationVndSvd,
+    "application/vnd.swiftview-ics" => Mime::ApplicationVndSwiftviewIcs,
+    "application/vnd.sybyl.mol2" => Mime::ApplicationVndSybylMol2,
+    "application/vnd.sycle+xml" => Mime::ApplicationVndSycleXml,
+    "application/vnd.syft+json" => Mime::ApplicationVndSyftJson,
+    "application/vnd.syncml.dm.notification" => Mime::ApplicationVndSyncmlDmNotification,
+    "application/vnd.syncml.dmddf+xml" => Mime::ApplicationVndSyncmlDmddfXml,
+    "application/vnd.syncml.dmtnds+wbxml" => Mime::ApplicationVndSyncmlDmtndsWbxml,
+    "application/vnd.syncml.dmtnds+xml" => Mime::ApplicationVndSyncmlDmtndsXml,
+    "application/vnd.syncml.dmddf+wbxml" => Mime::ApplicationVndSyncmlDmddfWbxml,
+    "application/vnd.syncml.dm+wbxml" => Mime::ApplicationVndSyncmlDmWbxml,
+    "application/vnd.syncml.dm+xml" => Mime::ApplicationVndSyncmlDmXml,
+    "application/vnd.syncml.ds.notification" => Mime::ApplicationVndSyncmlDsNotification,
+    "application/vnd.syncml+xml" => Mime::ApplicationVndSyncmlXml,
+    "application/vnd.tableschema+json" => Mime::ApplicationVndTableschemaJson,
+    "application/vnd.tao.intent-module-archive" => Mime::ApplicationVndTaoIntentModuleArchive,
+    "application/vnd.tcpdump.pcap" => Mime::ApplicationVndTcpdumpPcap,
+    "application/vnd.think-cell.ppttc+json" => Mime::ApplicationVndThinkCellPpttcJson,
+    "application/vnd.tml" => Mime::ApplicationVndTml,
+    "application/vnd.tmd.mediaflex.api+xml" => Mime::ApplicationVndTmdMediaflexApiXml,
+    "application/vnd.tmobile-livetv" => Mime::ApplicationVndTmobileLivetv,
+    "application/vnd.tri.onesource" => Mime::ApplicationVndTriOnesource,
+    "application/vnd.trid.tpt" => Mime::ApplicationVndTridTpt,
+    "application/vnd.triscape.mxs" => Mime::ApplicationVndTriscapeMxs,
+    "application/vnd.trueapp" => Mime::ApplicationVndTrueapp,
+    "application/vnd.truedoc" => Mime::ApplicationVndTruedoc,
+    "application/vnd.ubisoft.webplayer" => Mime::ApplicationVndUbisoftWebplayer,
+    "application/vnd.ufdl" => Mime::ApplicationVndUfdl,
+    "application/vnd.uiq.theme" => Mime::ApplicationVndUiqTheme,
+    "application/vnd.umajin" => Mime::ApplicationVndUmajin,
+    "application/vnd.unity" => Mime::ApplicationVndUnity,
+    "application/vnd.uoml+xml" => Mime::ApplicationVndUomlXml,
+    "application/vnd.uplanet.alert" => Mime::ApplicationVndUplanetAlert,
+    "application/vnd.uplanet.alert-wbxml" => Mime::ApplicationVndUplanetAlertWbxml,
+    "application/vnd.uplanet.bearer-choice" => Mime::ApplicationVndUplanetBearerChoice,
+    "application/vnd.uplanet.bearer-choice-wbxml" => Mime::ApplicationVndUplanetBearerChoiceWbxml,
+    "application/vnd.uplanet.cacheop" => Mime::ApplicationVndUplanetCacheop,
+    "application/vnd.uplanet.cacheop-wbxml" => Mime::ApplicationVndUplanetCacheopWbxml,
+    "application/vnd.uplanet.channel" => Mime::ApplicationVndUplanetChannel,
+    "application/vnd.uplanet.channel-wbxml" => Mime::ApplicationVndUplanetChannelWbxml,
+    "application/vnd.uplanet.list" => Mime::ApplicationVndUplanetList,
+    "application/vnd.uplanet.listcmd" => Mime::ApplicationVndUplanetListcmd,
+    "application/vnd.uplanet.listcmd-wbxml" => Mime::ApplicationVndUplanetListcmdWbxml,
+    "application/vnd.uplanet.list-wbxml" => Mime::ApplicationVndUplanetListWbxml,
+    "application/vnd.uri-map" => Mime::ApplicationVndUriMap,
+    "application/vnd.uplanet.signal" => Mime::ApplicationVndUplanetSignal,
+    "application/vnd.valve.source.material" => Mime::ApplicationVndValveSourceMaterial,
+    "application/vnd.vcx" => Mime::ApplicationVndVcx,
+    "application/vnd.vd-study" => Mime::ApplicationVndVdStudy,
+    "application/vnd.vectorworks" => Mime::ApplicationVndVectorworks,
+    "application/vnd.vel+json" => Mime::ApplicationVndVelJson,
+    "application/vnd.verimatrix.vcas" => Mime::ApplicationVndVerimatrixVcas,
+    "application/vnd.veritone.aion+json" => Mime::ApplicationVndVeritoneAionJson,
+    "application/vnd.veryant.thin" => Mime::ApplicationVndVeryantThin,
+    "application/vnd.ves.encrypted" => Mime::ApplicationVndVesEncrypted,
+    "application/vnd.vidsoft.vidconference" => Mime::ApplicationVndVidsoftVidconference,
+    "application/vnd.visio" => Mime::ApplicationVndVisio,
+    "application/vnd.visionary" => Mime::ApplicationVndVisionary,
+    "application/vnd.vividence.scriptfile" => Mime::ApplicationVndVividenceScriptfile,
+    "application/vnd.vsf" => Mime::ApplicationVndVsf,
+    "application/vnd.wap.sic" => Mime::ApplicationVndWapSic,
+    "application/vnd.wap.slc" => Mime::ApplicationVndWapSlc,
+    "application/vnd.wap.wbxml" => Mime::ApplicationVndWapWbxml,
+    "application/vnd.wap.wmlc" => Mime::ApplicationVndWapWmlc,
+    "application/vnd.wap.wmlscriptc" => Mime::ApplicationVndWapWmlscriptc,
+    "application/vnd.wasmflow.wafl" => Mime::ApplicationVndWasmflowWafl,
+    "application/vnd.webturbo" => Mime::ApplicationVndWebturbo,
+    "application/vnd.wfa.dpp" => Mime::ApplicationVndWfaDpp,
+    "application/vnd.wfa.p2p" => Mime::ApplicationVndWfaP2p,
+    "application/vnd.wfa.wsc" => Mime::ApplicationVndWfaWsc,
+    "application/vnd.windows.devicepairing" => Mime::ApplicationVndWindowsDevicepairing,
+    "application/vnd.wmc" => Mime::ApplicationVndWmc,
+    "application/vnd.wmf.bootstrap" => Mime::ApplicationVndWmfBootstrap,
+    "application/vnd.wolfram.mathematica" => Mime::ApplicationVndWolframMathematica,
+    "application/vnd.wolfram.mathematica.package" => Mime::ApplicationVndWolframMathematicaPackage,
+    "application/vnd.wolfram.player" => Mime::ApplicationVndWolframPlayer,
+    "application/vnd.wordlift" => Mime::ApplicationVndWordlift,
+    "application/vnd.wordperfect" => Mime::ApplicationVndWordperfect,
+    "application/vnd.wqd" => Mime::ApplicationVndWqd,
+    "application/vnd.wrq-hp3000-labelled" => Mime::ApplicationVndWrqHp3000Labelled,
+    "application/vnd.wt.stf" => Mime::ApplicationVndWtStf,
+    "application/vnd.wv.csp+xml" => Mime::ApplicationVndWvCspXml,
+    "application/vnd.wv.csp+wbxml" => Mime::ApplicationVndWvCspWbxml,
+    "application/vnd.wv.ssp+xml" => Mime::ApplicationVndWvSspXml,
+    "application/vnd.xacml+json" => Mime::ApplicationVndXacmlJson,
+    "application/vnd.xara" => Mime::ApplicationVndXara,
+    "application/vnd.xfdl" => Mime::ApplicationVndXfdl,
+    "application/vnd.xfdl.webform" => Mime::ApplicationVndXfdlWebform,
+    "application/vnd.xmi+xml" => Mime::ApplicationVndXmiXml,
+    "application/vnd.xmpie.cpkg" => Mime::ApplicationVndXmpieCpkg,
+    "application/vnd.xmpie.dpkg" => Mime::ApplicationVndXmpieDpkg,
+    "application/vnd.xmpie.plan" => Mime::ApplicationVndXmpiePlan,
+    "application/vnd.xmpie.ppkg" => Mime::ApplicationVndXmpiePpkg,
+    "application/vnd.xmpie.xlim" => Mime::ApplicationVndXmpieXlim,
+    "application/vnd.yamaha.hv-dic" => Mime::ApplicationVndYamahaHvDic,
+    "application/vnd.yamaha.hv-script" => Mime::ApplicationVndYamahaHvScript,
+    "application/vnd.yamaha.hv-voice" => Mime::ApplicationVndYamahaHvVoice,
+    "application/vnd.yamaha.openscoreformat.osfpvg+xml" => Mime::ApplicationVndYamahaOpenscoreformatOsfpvgXml,
+    "application/vnd.yamaha.openscoreformat" => Mime::ApplicationVndYamahaOpenscoreformat,
+    "application/vnd.yamaha.remote-setup" => Mime::ApplicationVndYamahaRemoteSetup,
+    "application/vnd.yamaha.smaf-audio" => Mime::ApplicationVndYamahaSmafAudio,
+    "application/vnd.yamaha.smaf-phrase" => Mime::ApplicationVndYamahaSmafPhrase,
+    "application/vnd.yamaha.through-ngn" => Mime::ApplicationVndYamahaThroughNgn,
+    "application/vnd.yamaha.tunnel-udpencap" => Mime::ApplicationVndYamahaTunnelUdpencap,
+    "application/vnd.yaoweme" => Mime::ApplicationVndYaoweme,
+    "application/vnd.yellowriver-custom-menu" => Mime::ApplicationVndYellowriverCustomMenu,
+    "application/vnd.zul" => Mime::ApplicationVndZul,
+    "application/vnd.zzazz.deck+xml" => Mime::ApplicationVndZzazzDeckXml,
+    "application/voicexml+xml" => Mime::ApplicationVoicexmlXml,
+    "application/voucher-cms+json" => Mime::ApplicationVoucherCmsJson,
+    "application/vq-rtcpxr" => Mime::ApplicationVqRtcpxr,
+    "application/wasm" => Mime::ApplicationWasm,
+    "application/watcherinfo+xml" => Mime::ApplicationWatcherinfoXml,
+    "application/webpush-options+json" => Mime::ApplicationWebpushOptionsJson,
+    "application/whoispp-query" => Mime::ApplicationWhoisppQuery,
+    "application/whoispp-response" => Mime::ApplicationWhoisppResponse,
+    "application/widget" => Mime::ApplicationWidget,
+    "application/wita" => Mime::ApplicationWita,
+    "application/wordperfect5.1" => Mime::ApplicationWordperfect51,
+    "application/wsdl+xml" => Mime::ApplicationWsdlXml,
+    "application/wspolicy+xml" => Mime::ApplicationWspolicyXml,
+    "application/x-pki-message" => Mime::ApplicationXPkiMessage,
+    "application/x-www-form-urlencoded" => Mime::ApplicationXWwwFormUrlencoded,
+    "application/x-x509-ca-cert" => Mime::ApplicationXX509CaCert,
+    "application/x-x509-ca-ra-cert" => Mime::ApplicationXX509CaRaCert,
+    "application/x-x509-next-ca-cert" => Mime::ApplicationXX509NextCaCert,
+    "application/x400-bp" => Mime::ApplicationX400Bp,
+    "application/xacml+xml" => Mime::ApplicationXacmlXml,
+    "application/xcap-att+xml" => Mime::ApplicationXcapAttXml,
+    "application/xcap-caps+xml" => Mime::ApplicationXcapCapsXml,
+    "application/xcap-diff+xml" => Mime::ApplicationXcapDiffXml,
+    "application/xcap-el+xml" => Mime::ApplicationXcapElXml,
+    "application/xcap-error+xml" => Mime::ApplicationXcapErrorXml,
+    "application/xcap-ns+xml" => Mime::ApplicationXcapNsXml,
+    "application/xcon-conference-info-diff+xml" => Mime::ApplicationXconConferenceInfoDiffXml,
+    "application/xcon-conference-info+xml" => Mime::ApplicationXconConferenceInfoXml,
+    "application/xenc+xml" => Mime::ApplicationXencXml,
+    "application/xfdf" => Mime::ApplicationXfdf,
+    "application/xhtml+xml" => Mime::ApplicationXhtmlXml,
+    "application/xliff+xml" => Mime::ApplicationXliffXml,
+    "application/xml" => Mime::ApplicationXml,
+    "application/xml-dtd" => Mime::ApplicationXmlDtd,
+    "application/xml-external-parsed-entity" => Mime::ApplicationXmlExternalParsedEntity,
+    "application/xml-patch+xml" => Mime::ApplicationXmlPatchXml,
+    "application/xmpp+xml" => Mime::ApplicationXmppXml,
+    "application/xop+xml" => Mime::ApplicationXopXml,
+    "application/xslt+xml" => Mime::ApplicationXsltXml,
+    "application/xv+xml" => Mime::ApplicationXvXml,
+    "application/yang" => Mime::ApplicationYang,
+    "application/yang-data+cbor" => Mime::ApplicationYangDataCbor,
+    "application/yang-data+json" => Mime::ApplicationYangDataJson,
+    "application/yang-data+xml" => Mime::ApplicationYangDataXml,
+    "application/yang-patch+json" => Mime::ApplicationYangPatchJson,
+    "application/yang-patch+xml" => Mime::ApplicationYangPatchXml,
+    "application/yin+xml" => Mime::ApplicationYinXml,
+    "application/zip" => Mime::ApplicationZip,
+    "application/zlib" => Mime::ApplicationZlib,
+    "application/zstd" => Mime::ApplicationZstd,
+    "audio/1d-interleaved-parityfec" => Mime::Audio1dInterleavedParityfec,
+    "audio/32kadpcm" => Mime::Audio32kadpcm,
+    "audio/3gpp" => Mime::Audio3gpp,
+    "audio/3gpp2" => Mime::Audio3gpp2,
+    "audio/aac" => Mime::AudioAac,
+    "audio/ac3" => Mime::AudioAc3,
+    "audio/AMR" => Mime::AudioAmr,
+    "audio/AMR-WB" => Mime::AudioAmrWb,
+    "audio/amr-wb+" => Mime::AudioAmrWbPlus,
+    "audio/aptx" => Mime::AudioAptx,
+    "audio/asc" => Mime::AudioAsc,
+    "audio/ATRAC-ADVANCED-LOSSLESS" => Mime::AudioAtracAdvancedLossless,
+    "audio/ATRAC-X" => Mime::AudioAtracX,
+    "audio/ATRAC3" => Mime::AudioAtrac3,
+    "audio/basic" => Mime::AudioBasic,
+    "audio/BV16" => Mime::AudioBv16,
+    "audio/BV32" => Mime::AudioBv32,
+    "audio/clearmode" => Mime::AudioClearmode,
+    "audio/CN" => Mime::AudioCn,
+    "audio/DAT12" => Mime::AudioDat12,
+    "audio/dls" => Mime::AudioDls,
+    "audio/dsr-es201108" => Mime::AudioDsrEs201108,
+    "audio/dsr-es202050" => Mime::AudioDsrEs202050,
+    "audio/dsr-es202211" => Mime::AudioDsrEs202211,
+    "audio/dsr-es202212" => Mime::AudioDsrEs202212,
+    "audio/DV" => Mime::AudioDv,
+    "audio/DVI4" => Mime::AudioDvi4,
+    "audio/eac3" => Mime::AudioEac3,
+    "audio/encaprtp" => Mime::AudioEncaprtp,
+    "audio/EVRC" => Mime::AudioEvrc,
+    "audio/EVRC-QCP" => Mime::AudioEvrcQcp,
+    "audio/EVRC0" => Mime::AudioEvrc0,
+    "audio/EVRC1" => Mime::AudioEvrc1,
+    "audio/EVRCB" => Mime::AudioEvrcb,
+    "audio/EVRCB0" => Mime::AudioEvrcb0,
+    "audio/EVRCB1" => Mime::AudioEvrcb1,
+    "audio/EVRCNW" => Mime::AudioEvrcnw,
+    "audio/EVRCNW0" => Mime::AudioEvrcnw0,
+    "audio/EVRCNW1" => Mime::AudioEvrcnw1,
+    "audio/EVRCWB" => Mime::AudioEvrcwb,
+    "audio/EVRCWB0" => Mime::AudioEvrcwb0,
+    "audio/EVRCWB1" => Mime::AudioEvrcwb1,
+    "audio/EVS" => Mime::AudioEvs,
+    "audio/example" => Mime::AudioExample,
+    "audio/flexfec" => Mime::AudioFlexfec,
+    "audio/fwdred" => Mime::AudioFwdred,
+    "audio/G711-0" => Mime::AudioG7110,
+    "audio/G719" => Mime::AudioG719,
+    "audio/G7221" => Mime::AudioG7221,
+    "audio/G722" => Mime::AudioG722,
+    "audio/G723" => Mime::AudioG723,
+    "audio/G726-16" => Mime::AudioG72616,
+    "audio/G726-24" => Mime::AudioG72624,
+    "audio/G726-32" => Mime::AudioG72632,
+    "audio/G726-40" => Mime::AudioG72640,
+    "audio/G728" => Mime::AudioG728,
+    "audio/G729" => Mime::AudioG729,
+    "audio/G7291" => Mime::AudioG7291,
+    "audio/G729D" => Mime::AudioG729d,
+    "audio/G729E" => Mime::AudioG729e,
+    "audio/GSM" => Mime::AudioGsm,
+    "audio/GSM-EFR" => Mime::AudioGsmEfr,
+    "audio/GSM-HR-08" => Mime::AudioGsmHr08,
+    "audio/iLBC" => Mime::AudioIlbc,
+    "audio/ip-mr_v2.5" => Mime::AudioIpMrV25 ,
+    "audio/L8" => Mime::AudioL8,
+    "audio/L16" => Mime::AudioL16,
+    "audio/L20" => Mime::AudioL20,
+    "audio/L24" => Mime::AudioL24,
+    "audio/LPC" => Mime::AudioLpc,
+    "audio/MELP" => Mime::AudioMelp,
+    "audio/MELP600" => Mime::AudioMelp600,
+    "audio/MELP1200" => Mime::AudioMelp1200,
+    "audio/MELP2400" => Mime::AudioMelp2400,
+    "audio/mhas" => Mime::AudioMhas,
+    "audio/mobile-xmf" => Mime::AudioMobileXmf,
+    "audio/MPA" => Mime::AudioMpa,
+    "audio/mp4" => Mime::AudioMp4,
+    "audio/MP4A-LATM" => Mime::AudioMp4aLatm,
+    "audio/mpa-robust" => Mime::AudioMpaRobust,
+    "audio/mpeg" => Mime::AudioMpeg,
+    "audio/mpeg4-generic" => Mime::AudioMpeg4Generic,
+    "audio/ogg" => Mime::AudioOgg,
+    "audio/opus" => Mime::AudioOpus,
+    "audio/parityfec" => Mime::AudioParityfec,
+    "audio/PCMA" => Mime::AudioPcma,
+    "audio/PCMA-WB" => Mime::AudioPcmaWb,
+    "audio/PCMU" => Mime::AudioPcmu,
+    "audio/PCMU-WB" => Mime::AudioPcmuWb,
+    "audio/prs.sid" => Mime::AudioPrsSid,
+    "audio/QCELP" => Mime::AudioQcelp,
+    "audio/raptorfec" => Mime::AudioRaptorfec,
+    "audio/RED" => Mime::AudioRed,
+    "audio/rtp-enc-aescm128" => Mime::AudioRtpEncAescm128,
+    "audio/rtploopback" => Mime::AudioRtploopback,
+    "audio/rtp-midi" => Mime::AudioRtpMidi,
+    "audio/rtx" => Mime::AudioRtx,
+    "audio/scip" => Mime::AudioScip,
+    "audio/SMV" => Mime::AudioSmv,
+    "audio/SMV0" => Mime::AudioSmv0,
+    "audio/SMV-QCP" => Mime::AudioSmvQcp,
+    "audio/sofa" => Mime::AudioSofa,
+    "audio/sp-midi" => Mime::AudioSpMidi,
+    "audio/speex" => Mime::AudioSpeex,
+    "audio/t140c" => Mime::AudioT140c,
+    "audio/t38" => Mime::AudioT38,
+    "audio/telephone-event" => Mime::AudioTelephoneEvent,
+    "audio/tone" => Mime::AudioTone,
+    "audio/TETRA_ACELP" => Mime::AudioTetraAcelp,
+    "audio/TETRA_ACELP_BB" => Mime::AudioTetraAcelpBb ,
+    "audio/TSVCIS" => Mime::AudioTsvcis,
+    "audio/UEMCLIP" => Mime::AudioUemclip,
+    "audio/ulpfec" => Mime::AudioUlpfec,
+    "audio/usac" => Mime::AudioUsac,
+    "audio/VDVI" => Mime::AudioVdvi,
+    "audio/VMR-WB" => Mime::AudioVmrWb,
+    "audio/vnd.3gpp.iufp" => Mime::AudioVnd3gppIufp,
+    "audio/vnd.4SB" => Mime::AudioVnd4sb,
+    "audio/vnd.audiokoz" => Mime::AudioVndAudiokoz,
+    "audio/vnd.CELP" => Mime::AudioVndCelp,
+    "audio/vnd.cisco.nse" => Mime::AudioVndCiscoNse,
+    "audio/vnd.cmles.radio-events" => Mime::AudioVndCmlesRadioEvents,
+    "audio/vnd.cns.anp1" => Mime::AudioVndCnsAnp1,
+    "audio/vnd.cns.inf1" => Mime::AudioVndCnsInf1,
+    "audio/vnd.dece.audio" => Mime::AudioVndDeceAudio,
+    "audio/vnd.digital-winds" => Mime::AudioVndDigitalWinds,
+    "audio/vnd.dlna.adts" => Mime::AudioVndDlnaAdts,
+    "audio/vnd.dolby.heaac.1" => Mime::AudioVndDolbyHeaac1,
+    "audio/vnd.dolby.heaac.2" => Mime::AudioVndDolbyHeaac2,
+    "audio/vnd.dolby.mlp" => Mime::AudioVndDolbyMlp,
+    "audio/vnd.dolby.mps" => Mime::AudioVndDolbyMps,
+    "audio/vnd.dolby.pl2" => Mime::AudioVndDolbyPl2,
+    "audio/vnd.dolby.pl2x" => Mime::AudioVndDolbyPl2x,
+    "audio/vnd.dolby.pl2z" => Mime::AudioVndDolbyPl2z,
+    "audio/vnd.dolby.pulse.1" => Mime::AudioVndDolbyPulse1,
+    "audio/vnd.dra" => Mime::AudioVndDra,
+    "audio/vnd.dts" => Mime::AudioVndDts,
+    "audio/vnd.dts.hd" => Mime::AudioVndDtsHd,
+    "audio/vnd.dts.uhd" => Mime::AudioVndDtsUhd,
+    "audio/vnd.dvb.file" => Mime::AudioVndDvbFile,
+    "audio/vnd.everad.plj" => Mime::AudioVndEveradPlj,
+    "audio/vnd.hns.audio" => Mime::AudioVndHnsAudio,
+    "audio/vnd.lucent.voice" => Mime::AudioVndLucentVoice,
+    "audio/vnd.ms-playready.media.pya" => Mime::AudioVndMsPlayreadyMediaPya,
+    "audio/vnd.nokia.mobile-xmf" => Mime::AudioVndNokiaMobileXmf,
+    "audio/vnd.nortel.vbk" => Mime::AudioVndNortelVbk,
+    "audio/vnd.nuera.ecelp4800" => Mime::AudioVndNueraEcelp4800,
+    "audio/vnd.nuera.ecelp7470" => Mime::AudioVndNueraEcelp7470,
+    "audio/vnd.nuera.ecelp9600" => Mime::AudioVndNueraEcelp9600,
+    "audio/vnd.octel.sbc" => Mime::AudioVndOctelSbc,
+    "audio/vnd.presonus.multitrack" => Mime::AudioVndPresonusMultitrack,
+    "audio/vnd.rhetorex.32kadpcm" => Mime::AudioVndRhetorex32kadpcm,
+    "audio/vnd.rip" => Mime::AudioVndRip,
+    "audio/vnd.sealedmedia.softseal.mpeg" => Mime::AudioVndSealedmediaSoftsealMpeg,
+    "audio/vnd.vmx.cvsd" => Mime::AudioVndVmxCvsd,
+    "audio/vorbis" => Mime::AudioVorbis,
+    "audio/vorbis-config" => Mime::AudioVorbisConfig,
+    "font/collection" => Mime::FontCollection,
+    "font/otf" => Mime::FontOtf,
+    "font/sfnt" => Mime::FontSfnt,
+    "font/ttf" => Mime::FontTtf,
+    "font/woff" => Mime::FontWoff,
+    "font/woff2" => Mime::FontWoff2,
+    "image/aces" => Mime::ImageAces,
+    "image/apng" => Mime::ImageApng,
+    "image/avci" => Mime::ImageAvci,
+    "image/avcs" => Mime::ImageAvcs,
+    "image/avif" => Mime::ImageAvif,
+    "image/bmp" => Mime::ImageBmp,
+    "image/cgm" => Mime::ImageCgm,
+    "image/dicom-rle" => Mime::ImageDicomRle,
+    "image/dpx" => Mime::ImageDpx,
+    "image/emf" => Mime::ImageEmf,
+    "image/example" => Mime::ImageExample,
+    "image/fits" => Mime::ImageFits,
+    "image/g3fax" => Mime::ImageG3fax,
+    "image/heic" => Mime::ImageHeic,
+    "image/heic-sequence" => Mime::ImageHeicSequence,
+    "image/heif" => Mime::ImageHeif,
+    "image/heif-sequence" => Mime::ImageHeifSequence,
+    "image/hej2k" => Mime::ImageHej2k,
+    "image/hsj2" => Mime::ImageHsj2,
+    "image/jls" => Mime::ImageJls,
+    "image/jp2" => Mime::ImageJp2,
+    "image/jpeg" => Mime::ImageJpeg,
+    "image/jph" => Mime::ImageJph,
+    "image/jphc" => Mime::ImageJphc,
+    "image/jpm" => Mime::ImageJpm,
+    "image/jpx" => Mime::ImageJpx,
+    "image/jxr" => Mime::ImageJxr,
+    "image/jxrA" => Mime::ImageJxra,
+    "image/jxrS" => Mime::ImageJxrs,
+    "image/jxs" => Mime::ImageJxs,
+    "image/jxsc" => Mime::ImageJxsc,
+    "image/jxsi" => Mime::ImageJxsi,
+    "image/jxss" => Mime::ImageJxss,
+    "image/ktx" => Mime::ImageKtx,
+    "image/ktx2" => Mime::ImageKtx2,
+    "image/naplps" => Mime::ImageNaplps,
+    "image/png" => Mime::ImagePng,
+    "image/prs.btif" => Mime::ImagePrsBtif,
+    "image/prs.pti" => Mime::ImagePrsPti,
+    "image/pwg-raster" => Mime::ImagePwgRaster,
+    "image/svg+xml" => Mime::ImageSvgXml,
+    "image/t38" => Mime::ImageT38,
+    "image/tiff" => Mime::ImageTiff,
+    "image/tiff-fx" => Mime::ImageTiffFx,
+    "image/vnd.adobe.photoshop" => Mime::ImageVndAdobePhotoshop,
+    "image/vnd.airzip.accelerator.azv" => Mime::ImageVndAirzipAcceleratorAzv,
+    "image/vnd.cns.inf2" => Mime::ImageVndCnsInf2,
+    "image/vnd.dece.graphic" => Mime::ImageVndDeceGraphic,
+    "image/vnd.djvu" => Mime::ImageVndDjvu,
+    "image/vnd.dwg" => Mime::ImageVndDwg,
+    "image/vnd.dxf" => Mime::ImageVndDxf,
+    "image/vnd.dvb.subtitle" => Mime::ImageVndDvbSubtitle,
+    "image/vnd.fastbidsheet" => Mime::ImageVndFastbidsheet,
+    "image/vnd.fpx" => Mime::ImageVndFpx,
+    "image/vnd.fst" => Mime::ImageVndFst,
+    "image/vnd.fujixerox.edmics-mmr" => Mime::ImageVndFujixeroxEdmicsMmr,
+    "image/vnd.fujixerox.edmics-rlc" => Mime::ImageVndFujixeroxEdmicsRlc,
+    "image/vnd.globalgraphics.pgb" => Mime::ImageVndGlobalgraphicsPgb,
+    "image/vnd.microsoft.icon" => Mime::ImageVndMicrosoftIcon,
+    "image/vnd.mix" => Mime::ImageVndMix,
+    "image/vnd.ms-modi" => Mime::ImageVndMsModi,
+    "image/vnd.mozilla.apng" => Mime::ImageVndMozillaApng,
+    "image/vnd.net-fpx" => Mime::ImageVndNetFpx,
+    "image/vnd.pco.b16" => Mime::ImageVndPcoB16,
+    "image/vnd.radiance" => Mime::ImageVndRadiance,
+    "image/vnd.sealed.png" => Mime::ImageVndSealedPng,
+    "image/vnd.sealedmedia.softseal.gif" => Mime::ImageVndSealedmediaSoftsealGif,
+    "image/vnd.sealedmedia.softseal.jpg" => Mime::ImageVndSealedmediaSoftsealJpg,
+    "image/vnd.svf" => Mime::ImageVndSvf,
+    "image/vnd.tencent.tap" => Mime::ImageVndTencentTap,
+    "image/vnd.valve.source.texture" => Mime::ImageVndValveSourceTexture,
+    "image/vnd.wap.wbmp" => Mime::ImageVndWapWbmp,
+    "image/vnd.xiff" => Mime::ImageVndXiff,
+    "image/vnd.zbrush.pcx" => Mime::ImageVndZbrushPcx,
+    "image/webp" => Mime::ImageWebp,
+    "image/wmf" => Mime::ImageWmf,
+    "message/bhttp" => Mime::MessageBhttp,
+    "message/CPIM" => Mime::MessageCpim,
+    "message/delivery-status" => Mime::MessageDeliveryStatus,
+    "message/disposition-notification" => Mime::MessageDispositionNotification,
+    "message/example" => Mime::MessageExample,
+    "message/feedback-report" => Mime::MessageFeedbackReport,
+    "message/global" => Mime::MessageGlobal,
+    "message/global-delivery-status" => Mime::MessageGlobalDeliveryStatus,
+    "message/global-disposition-notification" => Mime::MessageGlobalDispositionNotification,
+    "message/global-headers" => Mime::MessageGlobalHeaders,
+    "message/http" => Mime::MessageHttp,
+    "message/imdn+xml" => Mime::MessageImdnXml,
+    "message/mls" => Mime::MessageMls,
+    "message/ohttp-req" => Mime::MessageOhttpReq,
+    "message/ohttp-res" => Mime::MessageOhttpRes,
+    "message/sip" => Mime::MessageSip,
+    "message/sipfrag" => Mime::MessageSipfrag,
+    "message/tracking-status" => Mime::MessageTrackingStatus,
+    "message/vnd.wfa.wsc" => Mime::MessageVndWfaWsc,
+    "model/3mf" => Mime::Model3mf,
+    "model/e57" => Mime::ModelE57,
+    "model/example" => Mime::ModelExample,
+    "model/gltf-binary" => Mime::ModelGltfBinary,
+    "model/gltf+json" => Mime::ModelGltfJson,
+    "model/JT" => Mime::ModelJt,
+    "model/iges" => Mime::ModelIges,
+    "model/mtl" => Mime::ModelMtl,
+    "model/obj" => Mime::ModelObj,
+    "model/prc" => Mime::ModelPrc,
+    "model/step" => Mime::ModelStep,
+    "model/step+xml" => Mime::ModelStepXml,
+    "model/step+zip" => Mime::ModelStepZip,
+    "model/step-xml+zip" => Mime::ModelStepXmlZip,
+    "model/stl" => Mime::ModelStl,
+    "model/u3d" => Mime::ModelU3d,
+    "model/vnd.bary" => Mime::ModelVndBary,
+    "model/vnd.cld" => Mime::ModelVndCld,
+    "model/vnd.collada+xml" => Mime::ModelVndColladaXml,
+    "model/vnd.dwf" => Mime::ModelVndDwf,
+    "model/vnd.flatland.3dml" => Mime::ModelVndFlatland3dml,
+    "model/vnd.gdl" => Mime::ModelVndGdl,
+    "model/vnd.gs-gdl" => Mime::ModelVndGsGdl,
+    "model/vnd.gtw" => Mime::ModelVndGtw,
+    "model/vnd.moml+xml" => Mime::ModelVndMomlXml,
+    "model/vnd.mts" => Mime::ModelVndMts,
+    "model/vnd.opengex" => Mime::ModelVndOpengex,
+    "model/vnd.parasolid.transmit.binary" => Mime::ModelVndParasolidTransmitBinary,
+    "model/vnd.parasolid.transmit.text" => Mime::ModelVndParasolidTransmitText,
+    "model/vnd.pytha.pyox" => Mime::ModelVndPythaPyox,
+    "model/vnd.rosette.annotated-data-model" => Mime::ModelVndRosetteAnnotatedDataModel,
+    "model/vnd.sap.vds" => Mime::ModelVndSapVds,
+    "model/vnd.usda" => Mime::ModelVndUsda,
+    "model/vnd.usdz+zip" => Mime::ModelVndUsdzZip,
+    "model/vnd.valve.source.compiled-map" => Mime::ModelVndValveSourceCompiledMap,
+    "model/vnd.vtu" => Mime::ModelVndVtu,
+    "model/x3d-vrml" => Mime::ModelX3dVrml,
+    "model/x3d+fastinfoset" => Mime::ModelX3dFastinfoset,
+    "model/x3d+xml" => Mime::ModelX3dXml,
+    "multipart/appledouble" => Mime::MultipartAppledouble,
+    "multipart/byteranges" => Mime::MultipartByteranges,
+    "multipart/encrypted" => Mime::MultipartEncrypted,
+    "multipart/example" => Mime::MultipartExample,
+    "multipart/form-data" => Mime::MultipartFormData,
+    "multipart/header-set" => Mime::MultipartHeaderSet,
+    "multipart/multilingual" => Mime::MultipartMultilingual,
+    "multipart/related" => Mime::MultipartRelated,
+    "multipart/report" => Mime::MultipartReport,
+    "multipart/signed" => Mime::MultipartSigned,
+    "multipart/vnd.bint.med-plus" => Mime::MultipartVndBintMedPlus,
+    "multipart/voice-message" => Mime::MultipartVoiceMessage,
+    "multipart/x-mixed-replace" => Mime::MultipartXMixedReplace,
+    "text/1d-interleaved-parityfec" => Mime::Text1dInterleavedParityfec,
+    "text/cache-manifest" => Mime::TextCacheManifest,
+    "text/calendar" => Mime::TextCalendar,
+    "text/cql" => Mime::TextCql,
+    "text/cql-expression" => Mime::TextCqlExpression,
+    "text/cql-identifier" => Mime::TextCqlIdentifier,
+    "text/css" => Mime::TextCss,
+    "text/csv" => Mime::TextCsv,
+    "text/csv-schema" => Mime::TextCsvSchema,
+    "text/dns" => Mime::TextDns,
+    "text/encaprtp" => Mime::TextEncaprtp,
+    "text/example" => Mime::TextExample,
+    "text/fhirpath" => Mime::TextFhirpath,
+    "text/flexfec" => Mime::TextFlexfec,
+    "text/fwdred" => Mime::TextFwdred,
+    "text/gff3" => Mime::TextGff3,
+    "text/grammar-ref-list" => Mime::TextGrammarRefList,
+    "text/hl7v2" => Mime::TextHl7v2,
+    "text/html" => Mime::TextHtml,
+    "text/javascript" => Mime::TextJavascript,
+    "text/jcr-cnd" => Mime::TextJcrCnd,
+    "text/markdown" => Mime::TextMarkdown,
+    "text/mizar" => Mime::TextMizar,
+    "text/n3" => Mime::TextN3,
+    "text/parameters" => Mime::TextParameters,
+    "text/parityfec" => Mime::TextParityfec,
+    "text/plain" => Mime::TextPlain,
+    "text/provenance-notation" => Mime::TextProvenanceNotation,
+    "text/prs.fallenstein.rst" => Mime::TextPrsFallensteinRst,
+    "text/prs.lines.tag" => Mime::TextPrsLinesTag,
+    "text/prs.prop.logic" => Mime::TextPrsPropLogic,
+    "text/raptorfec" => Mime::TextRaptorfec,
+    "text/RED" => Mime::TextRed,
+    "text/rfc822-headers" => Mime::TextRfc822Headers,
+    "text/rtf" => Mime::TextRtf,
+    "text/rtp-enc-aescm128" => Mime::TextRtpEncAescm128,
+    "text/rtploopback" => Mime::TextRtploopback,
+    "text/rtx" => Mime::TextRtx,
+    "text/SGML" => Mime::TextSgml,
+    "text/shaclc" => Mime::TextShaclc,
+    "text/shex" => Mime::TextShex,
+    "text/spdx" => Mime::TextSpdx,
+    "text/strings" => Mime::TextStrings,
+    "text/t140" => Mime::TextT140,
+    "text/tab-separated-values" => Mime::TextTabSeparatedValues,
+    "text/troff" => Mime::TextTroff,
+    "text/turtle" => Mime::TextTurtle,
+    "text/ulpfec" => Mime::TextUlpfec,
+    "text/uri-list" => Mime::TextUriList,
+    "text/vcard" => Mime::TextVcard,
+    "text/vnd.a" => Mime::TextVndA,
+    "text/vnd.abc" => Mime::TextVndAbc,
+    "text/vnd.ascii-art" => Mime::TextVndAsciiArt,
+    "text/vnd.curl" => Mime::TextVndCurl,
+    "text/vnd.debian.copyright" => Mime::TextVndDebianCopyright,
+    "text/vnd.DMClientScript" => Mime::TextVndDmclientscript,
+    "text/vnd.dvb.subtitle" => Mime::TextVndDvbSubtitle,
+    "text/vnd.esmertec.theme-descriptor" => Mime::TextVndEsmertecThemeDescriptor,
+    "text/vnd.exchangeable" => Mime::TextVndExchangeable,
+    "text/vnd.familysearch.gedcom" => Mime::TextVndFamilysearchGedcom,
+    "text/vnd.ficlab.flt" => Mime::TextVndFiclabFlt,
+    "text/vnd.fly" => Mime::TextVndFly,
+    "text/vnd.fmi.flexstor" => Mime::TextVndFmiFlexstor,
+    "text/vnd.gml" => Mime::TextVndGml,
+    "text/vnd.graphviz" => Mime::TextVndGraphviz,
+    "text/vnd.hans" => Mime::TextVndHans,
+    "text/vnd.hgl" => Mime::TextVndHgl,
+    "text/vnd.in3d.3dml" => Mime::TextVndIn3d3dml,
+    "text/vnd.in3d.spot" => Mime::TextVndIn3dSpot,
+    "text/vnd.IPTC.NewsML" => Mime::TextVndIptcNewsml,
+    "text/vnd.IPTC.NITF" => Mime::TextVndIptcNitf,
+    "text/vnd.latex-z" => Mime::TextVndLatexZ,
+    "text/vnd.motorola.reflex" => Mime::TextVndMotorolaReflex,
+    "text/vnd.ms-mediapackage" => Mime::TextVndMsMediapackage,
+    "text/vnd.net2phone.commcenter.command" => Mime::TextVndNet2phoneCommcenterCommand,
+    "text/vnd.radisys.msml-basic-layout" => Mime::TextVndRadisysMsmlBasicLayout,
+    "text/vnd.senx.warpscript" => Mime::TextVndSenxWarpscript,
+    "text/vnd.sun.j2me.app-descriptor" => Mime::TextVndSunJ2meAppDescriptor,
+    "text/vnd.sosi" => Mime::TextVndSosi,
+    "text/vnd.trolltech.linguist" => Mime::TextVndTrolltechLinguist,
+    "text/vnd.wap.si" => Mime::TextVndWapSi,
+    "text/vnd.wap.sl" => Mime::TextVndWapSl,
+    "text/vnd.wap.wml" => Mime::TextVndWapWml,
+    "text/vnd.wap.wmlscript" => Mime::TextVndWapWmlscript,
+    "text/vtt" => Mime::TextVtt,
+    "text/wgsl" => Mime::TextWgsl,
+    "text/xml" => Mime::TextXml,
+    "text/xml-external-parsed-entity" => Mime::TextXmlExternalParsedEntity,
+    "video/1d-interleaved-parityfec" => Mime::Video1dInterleavedParityfec,
+    "video/3gpp" => Mime::Video3gpp,
+    "video/3gpp2" => Mime::Video3gpp2,
+    "video/3gpp-tt" => Mime::Video3gppTt,
+    "video/AV1" => Mime::VideoAv1,
+    "video/BMPEG" => Mime::VideoBmpeg,
+    "video/BT656" => Mime::VideoBt656,
+    "video/CelB" => Mime::VideoCelb,
+    "video/DV" => Mime::VideoDv,
+    "video/encaprtp" => Mime::VideoEncaprtp,
+    "video/example" => Mime::VideoExample,
+    "video/FFV1" => Mime::VideoFfv1,
+    "video/flexfec" => Mime::VideoFlexfec,
+    "video/H261" => Mime::VideoH261,
+    "video/H263" => Mime::VideoH263,
+    "video/H263-1998" => Mime::VideoH2631998,
+    "video/H263-2000" => Mime::VideoH2632000,
+    "video/H264" => Mime::VideoH264,
+    "video/H264-RCDO" => Mime::VideoH264Rcdo,
+    "video/H264-SVC" => Mime::VideoH264Svc,
+    "video/H265" => Mime::VideoH265,
+    "video/H266" => Mime::VideoH266,
+    "video/iso.segment" => Mime::VideoIsoSegment,
+    "video/JPEG" => Mime::VideoJpeg,
+    "video/jpeg2000" => Mime::VideoJpeg2000,
+    "video/jxsv" => Mime::VideoJxsv,
+    "video/mj2" => Mime::VideoMj2,
+    "video/MP1S" => Mime::VideoMp1s,
+    "video/MP2P" => Mime::VideoMp2p,
+    "video/MP2T" => Mime::VideoMp2t,
+    "video/mp4" => Mime::VideoMp4,
+    "video/MP4V-ES" => Mime::VideoMp4vEs,
+    "video/MPV" => Mime::VideoMpv,
+    "video/mpeg4-generic" => Mime::VideoMpeg4Generic,
+    "video/nv" => Mime::VideoNv,
+    "video/ogg" => Mime::VideoOgg,
+    "video/parityfec" => Mime::VideoParityfec,
+    "video/pointer" => Mime::VideoPointer,
+    "video/quicktime" => Mime::VideoQuicktime,
+    "video/raptorfec" => Mime::VideoRaptorfec,
+    "video/raw" => Mime::VideoRaw,
+    "video/rtp-enc-aescm128" => Mime::VideoRtpEncAescm128,
+    "video/rtploopback" => Mime::VideoRtploopback,
+    "video/rtx" => Mime::VideoRtx,
+    "video/scip" => Mime::VideoScip,
+    "video/smpte291" => Mime::VideoSmpte291,
+    "video/SMPTE292M" => Mime::VideoSmpte292m,
+    "video/ulpfec" => Mime::VideoUlpfec,
+    "video/vc1" => Mime::VideoVc1,
+    "video/vc2" => Mime::VideoVc2,
+    "video/vnd.CCTV" => Mime::VideoVndCctv,
+    "video/vnd.dece.hd" => Mime::VideoVndDeceHd,
+    "video/vnd.dece.mobile" => Mime::VideoVndDeceMobile,
+    "video/vnd.dece.mp4" => Mime::VideoVndDeceMp4,
+    "video/vnd.dece.pd" => Mime::VideoVndDecePd,
+    "video/vnd.dece.sd" => Mime::VideoVndDeceSd,
+    "video/vnd.dece.video" => Mime::VideoVndDeceVideo,
+    "video/vnd.directv.mpeg" => Mime::VideoVndDirectvMpeg,
+    "video/vnd.directv.mpeg-tts" => Mime::VideoVndDirectvMpegTts,
+    "video/vnd.dlna.mpeg-tts" => Mime::VideoVndDlnaMpegTts,
+    "video/vnd.dvb.file" => Mime::VideoVndDvbFile,
+    "video/vnd.fvt" => Mime::VideoVndFvt,
+    "video/vnd.hns.video" => Mime::VideoVndHnsVideo,
+    "video/vnd.iptvforum.1dparityfec-1010" => Mime::VideoVndIptvforum1dparityfec1010,
+    "video/vnd.iptvforum.1dparityfec-2005" => Mime::VideoVndIptvforum1dparityfec2005,
+    "video/vnd.iptvforum.2dparityfec-1010" => Mime::VideoVndIptvforum2dparityfec1010,
+    "video/vnd.iptvforum.2dparityfec-2005" => Mime::VideoVndIptvforum2dparityfec2005,
+    "video/vnd.iptvforum.ttsavc" => Mime::VideoVndIptvforumTtsavc,
+    "video/vnd.iptvforum.ttsmpeg2" => Mime::VideoVndIptvforumTtsmpeg2,
+    "video/vnd.motorola.video" => Mime::VideoVndMotorolaVideo,
+    "video/vnd.motorola.videop" => Mime::VideoVndMotorolaVideop,
+    "video/vnd.mpegurl" => Mime::VideoVndMpegurl,
+    "video/vnd.ms-playready.media.pyv" => Mime::VideoVndMsPlayreadyMediaPyv,
+    "video/vnd.nokia.interleaved-multimedia" => Mime::VideoVndNokiaInterleavedMultimedia,
+    "video/vnd.nokia.mp4vr" => Mime::VideoVndNokiaMp4vr,
+    "video/vnd.nokia.videovoip" => Mime::VideoVndNokiaVideovoip,
+    "video/vnd.objectvideo" => Mime::VideoVndObjectvideo,
+    "video/vnd.radgamettools.bink" => Mime::VideoVndRadgamettoolsBink,
+    "video/vnd.radgamettools.smacker" => Mime::VideoVndRadgamettoolsSmacker,
+    "video/vnd.sealed.mpeg1" => Mime::VideoVndSealedMpeg1,
+    "video/vnd.sealed.mpeg4" => Mime::VideoVndSealedMpeg4,
+    "video/vnd.sealed.swf" => Mime::VideoVndSealedSwf,
+    "video/vnd.sealedmedia.softseal.mov" => Mime::VideoVndSealedmediaSoftsealMov,
+    "video/vnd.uvvu.mp4" => Mime::VideoVndUvvuMp4,
+    "video/vnd.youtube.yt" => Mime::VideoVndYoutubeYt,
+    "video/vnd.vivo" => Mime::VideoVndVivo,
+    "video/VP8" => Mime::VideoVp8,
+    "video/VP9" => Mime::VideoVp9,
+};
diff --git a/core/http/src/utils/mime/mime_enum.rs b/core/http/src/utils/mime/mime_enum.rs
new file mode 100644
index 0000000..fbf4415
--- /dev/null
+++ b/core/http/src/utils/mime/mime_enum.rs
@@ -0,0 +1,4095 @@
+use super::map::MIME_MAP;
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub enum Mime {
+    Application1dInterleavedParityfec,
+    Application3gpdashQoeReportXml,
+    Application3gpphalJson,
+    Application3gpphalformsJson,
+    Application3gppImsXml,
+    ApplicationA2l,
+    ApplicationAceCbor,
+    ApplicationAceJson,
+    ApplicationActivemessage,
+    ApplicationActivityJson,
+    ApplicationAifCbor,
+    ApplicationAifJson,
+    ApplicationAltoCdniJson,
+    ApplicationAltoCdnifilterJson,
+    ApplicationAltoCostmapJson,
+    ApplicationAltoCostmapfilterJson,
+    ApplicationAltoDirectoryJson,
+    ApplicationAltoEndpointpropJson,
+    ApplicationAltoEndpointpropparamsJson,
+    ApplicationAltoEndpointcostJson,
+    ApplicationAltoEndpointcostparamsJson,
+    ApplicationAltoErrorJson,
+    ApplicationAltoNetworkmapfilterJson,
+    ApplicationAltoNetworkmapJson,
+    ApplicationAltoPropmapJson,
+    ApplicationAltoPropmapparamsJson,
+    ApplicationAltoUpdatestreamcontrolJson,
+    ApplicationAltoUpdatestreamparamsJson,
+    ApplicationAml,
+    ApplicationAndrewInset,
+    ApplicationApplefile,
+    ApplicationAtJwt,
+    ApplicationAtf,
+    ApplicationAtfx,
+    ApplicationAtomXml,
+    ApplicationAtomcatXml,
+    ApplicationAtomdeletedXml,
+    ApplicationAtomicmail,
+    ApplicationAtomsvcXml,
+    ApplicationAtscDwdXml,
+    ApplicationAtscDynamicEventMessage,
+    ApplicationAtscHeldXml,
+    ApplicationAtscRdtJson,
+    ApplicationAtscRsatXml,
+    ApplicationAtxml,
+    ApplicationAuthPolicyXml,
+    ApplicationAutomationmlAmlXml,
+    ApplicationAutomationmlAmlxZip,
+    ApplicationBacnetXddZip,
+    ApplicationBatchSmtp,
+    ApplicationBeepXml,
+    ApplicationCalendarJson,
+    ApplicationCalendarXml,
+    ApplicationCallCompletion,
+    ApplicationCals1840,
+    ApplicationCaptiveJson,
+    ApplicationCbor,
+    ApplicationCborSeq,
+    ApplicationCccex,
+    ApplicationCcmpXml,
+    ApplicationCcxmlXml,
+    ApplicationCdaXml,
+    ApplicationCdfxXml,
+    ApplicationCdmiCapability,
+    ApplicationCdmiContainer,
+    ApplicationCdmiDomain,
+    ApplicationCdmiObject,
+    ApplicationCdmiQueue,
+    ApplicationCdni,
+    ApplicationCea,
+    ApplicationCea2018Xml,
+    ApplicationCellmlXml,
+    ApplicationCfw,
+    ApplicationCityJson,
+    ApplicationClr,
+    ApplicationClueInfoXml,
+    ApplicationClueXml,
+    ApplicationCms,
+    ApplicationCnrpXml,
+    ApplicationCoapGroupJson,
+    ApplicationCoapPayload,
+    ApplicationCommonground,
+    ApplicationConciseProblemDetailsCbor,
+    ApplicationConferenceInfoXml,
+    ApplicationCplXml,
+    ApplicationCose,
+    ApplicationCoseKey,
+    ApplicationCoseKeySet,
+    ApplicationCoseX509,
+    ApplicationCsrattrs,
+    ApplicationCstaXml,
+    ApplicationCstadataXml,
+    ApplicationCsvmJson,
+    ApplicationCwl,
+    ApplicationCwlJson,
+    ApplicationCwt,
+    ApplicationCybercash,
+    ApplicationDashXml,
+    ApplicationDashPatchXml,
+    ApplicationDashdelta,
+    ApplicationDavmountXml,
+    ApplicationDcaRft,
+    ApplicationDcd,
+    ApplicationDecDx,
+    ApplicationDialogInfoXml,
+    ApplicationDicom,
+    ApplicationDicomJson,
+    ApplicationDicomXml,
+    ApplicationDii,
+    ApplicationDit,
+    ApplicationDns,
+    ApplicationDnsJson,
+    ApplicationDnsMessage,
+    ApplicationDotsCbor,
+    ApplicationDpopJwt,
+    ApplicationDskppXml,
+    ApplicationDsscDer,
+    ApplicationDsscXml,
+    ApplicationDvcs,
+    ApplicationEdiConsent,
+    ApplicationEdifact,
+    ApplicationEdiX12,
+    ApplicationEfi,
+    ApplicationElmJson,
+    ApplicationElmXml,
+    ApplicationEmergencycalldataCapXml,
+    ApplicationEmergencycalldataCommentXml,
+    ApplicationEmergencycalldataControlXml,
+    ApplicationEmergencycalldataDeviceinfoXml,
+    ApplicationEmergencycalldataEcallMsd,
+    ApplicationEmergencycalldataLegacyesnJson,
+    ApplicationEmergencycalldataProviderinfoXml,
+    ApplicationEmergencycalldataServiceinfoXml,
+    ApplicationEmergencycalldataSubscriberinfoXml,
+    ApplicationEmergencycalldataVedsXml,
+    ApplicationEmmaXml,
+    ApplicationEmotionmlXml,
+    ApplicationEncaprtp,
+    ApplicationEppXml,
+    ApplicationEpubZip,
+    ApplicationEshop,
+    ApplicationExample,
+    ApplicationExi,
+    ApplicationExpectCtReportJson,
+    ApplicationExpress,
+    ApplicationFastinfoset,
+    ApplicationFastsoap,
+    ApplicationFdf,
+    ApplicationFdtXml,
+    ApplicationFhirJson,
+    ApplicationFhirXml,
+    ApplicationFits,
+    ApplicationFlexfec,
+    ApplicationFontTdpfr,
+    ApplicationFrameworkAttributesXml,
+    ApplicationGeoJson,
+    ApplicationGeoJsonSeq,
+    ApplicationGeopackageSqlite3,
+    ApplicationGeoxacmlXml,
+    ApplicationGltfBuffer,
+    ApplicationGmlXml,
+    ApplicationGzip,
+    ApplicationH224,
+    ApplicationHeldXml,
+    ApplicationHl7v2Xml,
+    ApplicationHttp,
+    ApplicationHyperstudio,
+    ApplicationIbeKeyRequestXml,
+    ApplicationIbePkgReplyXml,
+    ApplicationIbePpData,
+    ApplicationIges,
+    ApplicationImIscomposingXml,
+    ApplicationIndex,
+    ApplicationIndexCmd,
+    ApplicationIndexObj,
+    ApplicationIndexResponse,
+    ApplicationIndexVnd,
+    ApplicationInkmlXml,
+    ApplicationIotp,
+    ApplicationIpfix,
+    ApplicationIpp,
+    ApplicationIsup,
+    ApplicationItsXml,
+    ApplicationJavaArchive,
+    ApplicationJf2feedJson,
+    ApplicationJose,
+    ApplicationJoseJson,
+    ApplicationJrdJson,
+    ApplicationJscalendarJson,
+    ApplicationJson,
+    ApplicationJsonPatchJson,
+    ApplicationJsonSeq,
+    ApplicationJwkJson,
+    ApplicationJwkSetJson,
+    ApplicationJwt,
+    ApplicationKpmlRequestXml,
+    ApplicationKpmlResponseXml,
+    ApplicationLdJson,
+    ApplicationLgrXml,
+    ApplicationLinkFormat,
+    ApplicationLinkset,
+    ApplicationLinksetJson,
+    ApplicationLoadControlXml,
+    ApplicationLogoutJwt,
+    ApplicationLostXml,
+    ApplicationLostsyncXml,
+    ApplicationLpfZip,
+    ApplicationLxf,
+    ApplicationMacBinhex40,
+    ApplicationMacwriteii,
+    ApplicationMadsXml,
+    ApplicationManifestJson,
+    ApplicationMarc,
+    ApplicationMarcxmlXml,
+    ApplicationMathematica,
+    ApplicationMathmlXml,
+    ApplicationMathmlContentXml,
+    ApplicationMathmlPresentationXml,
+    ApplicationMbmsAssociatedProcedureDescriptionXml,
+    ApplicationMbmsDeregisterXml,
+    ApplicationMbmsEnvelopeXml,
+    ApplicationMbmsMskResponseXml,
+    ApplicationMbmsMskXml,
+    ApplicationMbmsProtectionDescriptionXml,
+    ApplicationMbmsReceptionReportXml,
+    ApplicationMbmsRegisterResponseXml,
+    ApplicationMbmsRegisterXml,
+    ApplicationMbmsScheduleXml,
+    ApplicationMbmsUserServiceDescriptionXml,
+    ApplicationMbox,
+    ApplicationMediaControlXml,
+    ApplicationMediaPolicyDatasetXml,
+    ApplicationMediaservercontrolXml,
+    ApplicationMergePatchJson,
+    ApplicationMetalink4Xml,
+    ApplicationMetsXml,
+    ApplicationMf4,
+    ApplicationMikey,
+    ApplicationMipc,
+    ApplicationMissingBlocksCborSeq,
+    ApplicationMmtAeiXml,
+    ApplicationMmtUsdXml,
+    ApplicationModsXml,
+    ApplicationMossKeys,
+    ApplicationMossSignature,
+    ApplicationMosskeyData,
+    ApplicationMosskeyRequest,
+    ApplicationMp21,
+    ApplicationMp4,
+    ApplicationMpeg4Generic,
+    ApplicationMpeg4Iod,
+    ApplicationMpeg4IodXmt,
+    ApplicationMrbConsumerXml,
+    ApplicationMrbPublishXml,
+    ApplicationMscIvrXml,
+    ApplicationMscMixerXml,
+    ApplicationMsword,
+    ApplicationMudJson,
+    ApplicationMultipartCore,
+    ApplicationMxf,
+    ApplicationNQuads,
+    ApplicationNTriples,
+    ApplicationNasdata,
+    ApplicationNewsCheckgroups,
+    ApplicationNewsGroupinfo,
+    ApplicationNewsTransmission,
+    ApplicationNlsmlXml,
+    ApplicationNode,
+    ApplicationNss,
+    ApplicationOauthAuthzReqJwt,
+    ApplicationObliviousDnsMessage,
+    ApplicationOcspRequest,
+    ApplicationOcspResponse,
+    ApplicationOctetStream,
+    ApplicationOda,
+    ApplicationOdmXml,
+    ApplicationOdx,
+    ApplicationOebpsPackageXml,
+    ApplicationOgg,
+    ApplicationOhttpKeys,
+    ApplicationOpcNodesetXml,
+    ApplicationOscore,
+    ApplicationOxps,
+    ApplicationP21,
+    ApplicationP21Zip,
+    ApplicationP2pOverlayXml,
+    ApplicationParityfec,
+    ApplicationPassport,
+    ApplicationPatchOpsErrorXml,
+    ApplicationPdf,
+    ApplicationPdx,
+    ApplicationPemCertificateChain,
+    ApplicationPgpEncrypted,
+    ApplicationPgpKeys,
+    ApplicationPgpSignature,
+    ApplicationPidfDiffXml,
+    ApplicationPidfXml,
+    ApplicationPkcs10,
+    ApplicationPkcs7Mime,
+    ApplicationPkcs7Signature,
+    ApplicationPkcs8,
+    ApplicationPkcs8Encrypted,
+    ApplicationPkcs12,
+    ApplicationPkixAttrCert,
+    ApplicationPkixCert,
+    ApplicationPkixCrl,
+    ApplicationPkixPkipath,
+    ApplicationPkixcmp,
+    ApplicationPlsXml,
+    ApplicationPocSettingsXml,
+    ApplicationPostscript,
+    ApplicationPpspTrackerJson,
+    ApplicationProblemJson,
+    ApplicationProblemXml,
+    ApplicationProvenanceXml,
+    ApplicationPrsAlvestrandTitraxSheet,
+    ApplicationPrsCww,
+    ApplicationPrsCyn,
+    ApplicationPrsHpubZip,
+    ApplicationPrsImpliedDocumentXml,
+    ApplicationPrsImpliedExecutable,
+    ApplicationPrsImpliedStructure,
+    ApplicationPrsNprend,
+    ApplicationPrsPlucker,
+    ApplicationPrsRdfXmlCrypt,
+    ApplicationPrsXsfXml,
+    ApplicationPskcXml,
+    ApplicationPvdJson,
+    ApplicationRdfXml,
+    ApplicationRouteApdXml,
+    ApplicationRouteSTsidXml,
+    ApplicationRouteUsdXml,
+    ApplicationQsig,
+    ApplicationRaptorfec,
+    ApplicationRdapJson,
+    ApplicationReginfoXml,
+    ApplicationRelaxNgCompactSyntax,
+    ApplicationReputonJson,
+    ApplicationResourceListsDiffXml,
+    ApplicationResourceListsXml,
+    ApplicationRfcXml,
+    ApplicationRiscos,
+    ApplicationRlmiXml,
+    ApplicationRlsServicesXml,
+    ApplicationRpkiChecklist,
+    ApplicationRpkiGhostbusters,
+    ApplicationRpkiManifest,
+    ApplicationRpkiPublication,
+    ApplicationRpkiRoa,
+    ApplicationRpkiUpdown,
+    ApplicationRtf,
+    ApplicationRtploopback,
+    ApplicationRtx,
+    ApplicationSamlassertionXml,
+    ApplicationSamlmetadataXml,
+    ApplicationSarifExternalPropertiesJson,
+    ApplicationSarifJson,
+    ApplicationSbe,
+    ApplicationSbmlXml,
+    ApplicationScaipXml,
+    ApplicationScimJson,
+    ApplicationScvpCvRequest,
+    ApplicationScvpCvResponse,
+    ApplicationScvpVpRequest,
+    ApplicationScvpVpResponse,
+    ApplicationSdp,
+    ApplicationSeceventJwt,
+    ApplicationSenmlEtchCbor,
+    ApplicationSenmlEtchJson,
+    ApplicationSenmlExi,
+    ApplicationSenmlCbor,
+    ApplicationSenmlJson,
+    ApplicationSenmlXml,
+    ApplicationSensmlExi,
+    ApplicationSensmlCbor,
+    ApplicationSensmlJson,
+    ApplicationSensmlXml,
+    ApplicationSepExi,
+    ApplicationSepXml,
+    ApplicationSessionInfo,
+    ApplicationSetPayment,
+    ApplicationSetPaymentInitiation,
+    ApplicationSetRegistration,
+    ApplicationSetRegistrationInitiation,
+    ApplicationSgml,
+    ApplicationSgmlOpenCatalog,
+    ApplicationShfXml,
+    ApplicationSieve,
+    ApplicationSimpleFilterXml,
+    ApplicationSimpleMessageSummary,
+    ApplicationSimplesymbolcontainer,
+    ApplicationSipc,
+    ApplicationSlate,
+    ApplicationSmilXml,
+    ApplicationSmpte336m,
+    ApplicationSoapFastinfoset,
+    ApplicationSoapXml,
+    ApplicationSparqlQuery,
+    ApplicationSpdxJson,
+    ApplicationSparqlResultsXml,
+    ApplicationSpiritsEventXml,
+    ApplicationSql,
+    ApplicationSrgs,
+    ApplicationSrgsXml,
+    ApplicationSruXml,
+    ApplicationSsmlXml,
+    ApplicationStixJson,
+    ApplicationSwidCbor,
+    ApplicationSwidXml,
+    ApplicationTampApexUpdate,
+    ApplicationTampApexUpdateConfirm,
+    ApplicationTampCommunityUpdate,
+    ApplicationTampCommunityUpdateConfirm,
+    ApplicationTampError,
+    ApplicationTampSequenceAdjust,
+    ApplicationTampSequenceAdjustConfirm,
+    ApplicationTampStatusQuery,
+    ApplicationTampStatusResponse,
+    ApplicationTampUpdate,
+    ApplicationTampUpdateConfirm,
+    ApplicationTaxiiJson,
+    ApplicationTdJson,
+    ApplicationTeiXml,
+    ApplicationTetraIsi,
+    ApplicationThraudXml,
+    ApplicationTimestampQuery,
+    ApplicationTimestampReply,
+    ApplicationTimestampedData,
+    ApplicationTlsrptGzip,
+    ApplicationTlsrptJson,
+    ApplicationTmJson,
+    ApplicationTnauthlist,
+    ApplicationTokenIntrospectionJwt,
+    ApplicationTrickleIceSdpfrag,
+    ApplicationTrig,
+    ApplicationTtmlXml,
+    ApplicationTveTrigger,
+    ApplicationTzif,
+    ApplicationTzifLeap,
+    ApplicationUlpfec,
+    ApplicationUrcGrpsheetXml,
+    ApplicationUrcRessheetXml,
+    ApplicationUrcTargetdescXml,
+    ApplicationUrcUisocketdescXml,
+    ApplicationVcardJson,
+    ApplicationVcardXml,
+    ApplicationVemmi,
+    ApplicationVnd1000mindsDecisionModelXml,
+    ApplicationVnd1ob,
+    ApplicationVnd3gpp5gnas,
+    ApplicationVnd3gppAccessTransferEventsXml,
+    ApplicationVnd3gppBsfXml,
+    ApplicationVnd3gppCrsXml,
+    ApplicationVnd3gppCurrentLocationDiscoveryXml,
+    ApplicationVnd3gppGmopXml,
+    ApplicationVnd3gppGtpc,
+    ApplicationVnd3gppInterworkingData,
+    ApplicationVnd3gppLpp,
+    ApplicationVnd3gppMcSignallingEar,
+    ApplicationVnd3gppMcdataAffiliationCommandXml,
+    ApplicationVnd3gppMcdataInfoXml,
+    ApplicationVnd3gppMcdataMsgstoreCtrlRequestXml,
+    ApplicationVnd3gppMcdataPayload,
+    ApplicationVnd3gppMcdataRegroupXml,
+    ApplicationVnd3gppMcdataServiceConfigXml,
+    ApplicationVnd3gppMcdataSignalling,
+    ApplicationVnd3gppMcdataUeConfigXml,
+    ApplicationVnd3gppMcdataUserProfileXml,
+    ApplicationVnd3gppMcpttAffiliationCommandXml,
+    ApplicationVnd3gppMcpttFloorRequestXml,
+    ApplicationVnd3gppMcpttInfoXml,
+    ApplicationVnd3gppMcpttLocationInfoXml,
+    ApplicationVnd3gppMcpttMbmsUsageInfoXml,
+    ApplicationVnd3gppMcpttRegroupXml,
+    ApplicationVnd3gppMcpttServiceConfigXml,
+    ApplicationVnd3gppMcpttSignedXml,
+    ApplicationVnd3gppMcpttUeConfigXml,
+    ApplicationVnd3gppMcpttUeInitConfigXml,
+    ApplicationVnd3gppMcpttUserProfileXml,
+    ApplicationVnd3gppMcvideoAffiliationCommandXml,
+    ApplicationVnd3gppMcvideoInfoXml,
+    ApplicationVnd3gppMcvideoLocationInfoXml,
+    ApplicationVnd3gppMcvideoMbmsUsageInfoXml,
+    ApplicationVnd3gppMcvideoRegroupXml,
+    ApplicationVnd3gppMcvideoServiceConfigXml,
+    ApplicationVnd3gppMcvideoTransmissionRequestXml,
+    ApplicationVnd3gppMcvideoUeConfigXml,
+    ApplicationVnd3gppMcvideoUserProfileXml,
+    ApplicationVnd3gppMidCallXml,
+    ApplicationVnd3gppNgap,
+    ApplicationVnd3gppPfcp,
+    ApplicationVnd3gppPicBwLarge,
+    ApplicationVnd3gppPicBwSmall,
+    ApplicationVnd3gppPicBwVar,
+    ApplicationVnd3gppProsePc3aXml,
+    ApplicationVnd3gppProsePc3achXml,
+    ApplicationVnd3gppProsePc3chXml,
+    ApplicationVnd3gppProsePc8Xml,
+    ApplicationVnd3gppProseXml,
+    ApplicationVnd3gppS1ap,
+    ApplicationVnd3gppSealGroupDocXml,
+    ApplicationVnd3gppSealInfoXml,
+    ApplicationVnd3gppSealLocationInfoXml,
+    ApplicationVnd3gppSealMbmsUsageInfoXml,
+    ApplicationVnd3gppSealNetworkQosManagementInfoXml,
+    ApplicationVnd3gppSealUeConfigInfoXml,
+    ApplicationVnd3gppSealUnicastInfoXml,
+    ApplicationVnd3gppSealUserProfileInfoXml,
+    ApplicationVnd3gppSms,
+    ApplicationVnd3gppSmsXml,
+    ApplicationVnd3gppSrvccExtXml,
+    ApplicationVnd3gppSrvccInfoXml,
+    ApplicationVnd3gppStateAndEventInfoXml,
+    ApplicationVnd3gppUssdXml,
+    ApplicationVnd3gppVaeInfoXml,
+    ApplicationVnd3gppV2xLocalServiceInformation,
+    ApplicationVnd3gpp2BcmcsinfoXml,
+    ApplicationVnd3gpp2Sms,
+    ApplicationVnd3gpp2Tcap,
+    ApplicationVnd3gppV2x,
+    ApplicationVnd3lightssoftwareImagescal,
+    ApplicationVnd3mPostItNotes,
+    ApplicationVndAccpacSimplyAso,
+    ApplicationVndAccpacSimplyImp,
+    ApplicationVndAcmAddressxferJson,
+    ApplicationVndAcucobol,
+    ApplicationVndAcucorp,
+    ApplicationVndAdobeFlashMovie,
+    ApplicationVndAdobeFormscentralFcdt,
+    ApplicationVndAdobeFxp,
+    ApplicationVndAdobePartialUpload,
+    ApplicationVndAdobeXdpXml,
+    ApplicationVndAetherImp,
+    ApplicationVndAfpcAfplinedata,
+    ApplicationVndAfpcAfplinedataPagedef,
+    ApplicationVndAfpcCmocaCmresource,
+    ApplicationVndAfpcFocaCharset,
+    ApplicationVndAfpcFocaCodedfont,
+    ApplicationVndAfpcFocaCodepage,
+    ApplicationVndAfpcModca,
+    ApplicationVndAfpcModcaCmtable,
+    ApplicationVndAfpcModcaFormdef,
+    ApplicationVndAfpcModcaMediummap,
+    ApplicationVndAfpcModcaObjectcontainer,
+    ApplicationVndAfpcModcaOverlay,
+    ApplicationVndAfpcModcaPagesegment,
+    ApplicationVndAge,
+    ApplicationVndAhBarcode,
+    ApplicationVndAheadSpace,
+    ApplicationVndAirzipFilesecureAzf,
+    ApplicationVndAirzipFilesecureAzs,
+    ApplicationVndAmadeusJson,
+    ApplicationVndAmazonMobi8Ebook,
+    ApplicationVndAmericandynamicsAcc,
+    ApplicationVndAmigaAmi,
+    ApplicationVndAmundsenMazeXml,
+    ApplicationVndAndroidOta,
+    ApplicationVndAnki,
+    ApplicationVndAnserWebCertificateIssueInitiation,
+    ApplicationVndAntixGameComponent,
+    ApplicationVndApacheArrowFile,
+    ApplicationVndApacheArrowStream,
+    ApplicationVndApacheThriftBinary,
+    ApplicationVndApacheThriftCompact,
+    ApplicationVndApacheThriftJson,
+    ApplicationVndApexlang,
+    ApplicationVndApiJson,
+    ApplicationVndAplextorWarrpJson,
+    ApplicationVndApothekendeReservationJson,
+    ApplicationVndAppleInstallerXml,
+    ApplicationVndAppleKeynote,
+    ApplicationVndAppleMpegurl,
+    ApplicationVndAppleNumbers,
+    ApplicationVndApplePages,
+    ApplicationVndAristanetworksSwi,
+    ApplicationVndArtisanJson,
+    ApplicationVndArtsquare,
+    ApplicationVndAstraeaSoftwareIota,
+    ApplicationVndAudiograph,
+    ApplicationVndAutopackage,
+    ApplicationVndAvalonJson,
+    ApplicationVndAvistarXml,
+    ApplicationVndBalsamiqBmmlXml,
+    ApplicationVndBananaAccounting,
+    ApplicationVndBbfUspError,
+    ApplicationVndBbfUspMsg,
+    ApplicationVndBbfUspMsgJson,
+    ApplicationVndBalsamiqBmpr,
+    ApplicationVndBekitzurStechJson,
+    ApplicationVndBelightsoftLhzdZip,
+    ApplicationVndBelightsoftLhzlZip,
+    ApplicationVndBintMedContent,
+    ApplicationVndBiopaxRdfXml,
+    ApplicationVndBlinkIdbValueWrapper,
+    ApplicationVndBlueiceMultipass,
+    ApplicationVndBluetoothEpOob,
+    ApplicationVndBluetoothLeOob,
+    ApplicationVndBmi,
+    ApplicationVndBpf,
+    ApplicationVndBpf3,
+    ApplicationVndBusinessobjects,
+    ApplicationVndByuUapiJson,
+    ApplicationVndCabJscript,
+    ApplicationVndCanonCpdl,
+    ApplicationVndCanonLips,
+    ApplicationVndCapasystemsPgJson,
+    ApplicationVndCendioThinlincClientconf,
+    ApplicationVndCenturySystemsTcpStream,
+    ApplicationVndChemdrawXml,
+    ApplicationVndChessPgn,
+    ApplicationVndChipnutsKaraokeMmd,
+    ApplicationVndCiedi,
+    ApplicationVndCinderella,
+    ApplicationVndCirpackIsdnExt,
+    ApplicationVndCitationstylesStyleXml,
+    ApplicationVndClaymore,
+    ApplicationVndCloantoRp9,
+    ApplicationVndClonkC4group,
+    ApplicationVndCluetrustCartomobileConfig,
+    ApplicationVndCluetrustCartomobileConfigPkg,
+    ApplicationVndCncfHelmChartContentV1TarGzip,
+    ApplicationVndCncfHelmChartProvenanceV1Prov,
+    ApplicationVndCncfHelmConfigV1Json,
+    ApplicationVndCoffeescript,
+    ApplicationVndCollabioXodocumentsDocument,
+    ApplicationVndCollabioXodocumentsDocumentTemplate,
+    ApplicationVndCollabioXodocumentsPresentation,
+    ApplicationVndCollabioXodocumentsPresentationTemplate,
+    ApplicationVndCollabioXodocumentsSpreadsheet,
+    ApplicationVndCollabioXodocumentsSpreadsheetTemplate,
+    ApplicationVndCollectionDocJson,
+    ApplicationVndCollectionJson,
+    ApplicationVndCollectionNextJson,
+    ApplicationVndComicbookRar,
+    ApplicationVndComicbookZip,
+    ApplicationVndCommerceBattelle,
+    ApplicationVndCommonspace,
+    ApplicationVndCoreosIgnitionJson,
+    ApplicationVndCosmocaller,
+    ApplicationVndContactCmsg,
+    ApplicationVndCrickClicker,
+    ApplicationVndCrickClickerKeyboard,
+    ApplicationVndCrickClickerPalette,
+    ApplicationVndCrickClickerTemplate,
+    ApplicationVndCrickClickerWordbank,
+    ApplicationVndCriticaltoolsWbsXml,
+    ApplicationVndCryptiiPipeJson,
+    ApplicationVndCryptoShadeFile,
+    ApplicationVndCryptomatorEncrypted,
+    ApplicationVndCryptomatorVault,
+    ApplicationVndCtcPosml,
+    ApplicationVndCtctWsXml,
+    ApplicationVndCupsPdf,
+    ApplicationVndCupsPostscript,
+    ApplicationVndCupsPpd,
+    ApplicationVndCupsRaster,
+    ApplicationVndCupsRaw,
+    ApplicationVndCurl,
+    ApplicationVndCyanDeanRootXml,
+    ApplicationVndCybank,
+    ApplicationVndCyclonedxJson,
+    ApplicationVndCyclonedxXml,
+    ApplicationVndD2lCoursepackage1p0Zip,
+    ApplicationVndD3mDataset,
+    ApplicationVndD3mProblem,
+    ApplicationVndDart,
+    ApplicationVndDataVisionRdz,
+    ApplicationVndDatalog,
+    ApplicationVndDatapackageJson,
+    ApplicationVndDataresourceJson,
+    ApplicationVndDbf,
+    ApplicationVndDebianBinaryPackage,
+    ApplicationVndDeceData,
+    ApplicationVndDeceTtmlXml,
+    ApplicationVndDeceUnspecified,
+    ApplicationVndDeceZip,
+    ApplicationVndDenovoFcselayoutLink,
+    ApplicationVndDesmumeMovie,
+    ApplicationVndDirBiPlateDlNosuffix,
+    ApplicationVndDmDelegationXml,
+    ApplicationVndDna,
+    ApplicationVndDocumentJson,
+    ApplicationVndDolbyMobile1,
+    ApplicationVndDolbyMobile2,
+    ApplicationVndDoremirScorecloudBinaryDocument,
+    ApplicationVndDpgraph,
+    ApplicationVndDreamfactory,
+    ApplicationVndDriveJson,
+    ApplicationVndDtgLocal,
+    ApplicationVndDtgLocalFlash,
+    ApplicationVndDtgLocalHtml,
+    ApplicationVndDvbAit,
+    ApplicationVndDvbDvbislXml,
+    ApplicationVndDvbDvbj,
+    ApplicationVndDvbEsgcontainer,
+    ApplicationVndDvbIpdcdftnotifaccess,
+    ApplicationVndDvbIpdcesgaccess,
+    ApplicationVndDvbIpdcesgaccess2,
+    ApplicationVndDvbIpdcesgpdd,
+    ApplicationVndDvbIpdcroaming,
+    ApplicationVndDvbIptvAlfecBase,
+    ApplicationVndDvbIptvAlfecEnhancement,
+    ApplicationVndDvbNotifAggregateRootXml,
+    ApplicationVndDvbNotifContainerXml,
+    ApplicationVndDvbNotifGenericXml,
+    ApplicationVndDvbNotifIaMsglistXml,
+    ApplicationVndDvbNotifIaRegistrationRequestXml,
+    ApplicationVndDvbNotifIaRegistrationResponseXml,
+    ApplicationVndDvbNotifInitXml,
+    ApplicationVndDvbPfr,
+    ApplicationVndDvbService,
+    ApplicationVndDxr,
+    ApplicationVndDynageo,
+    ApplicationVndDzr,
+    ApplicationVndEasykaraokeCdgdownload,
+    ApplicationVndEcipRlp,
+    ApplicationVndEcdisUpdate,
+    ApplicationVndEclipseDittoJson,
+    ApplicationVndEcowinChart,
+    ApplicationVndEcowinFilerequest,
+    ApplicationVndEcowinFileupdate,
+    ApplicationVndEcowinSeries,
+    ApplicationVndEcowinSeriesrequest,
+    ApplicationVndEcowinSeriesupdate,
+    ApplicationVndEfiImg,
+    ApplicationVndEfiIso,
+    ApplicationVndElnZip,
+    ApplicationVndEmclientAccessrequestXml,
+    ApplicationVndEnliven,
+    ApplicationVndEnphaseEnvoy,
+    ApplicationVndEprintsDataXml,
+    ApplicationVndEpsonEsf,
+    ApplicationVndEpsonMsf,
+    ApplicationVndEpsonQuickanime,
+    ApplicationVndEpsonSalt,
+    ApplicationVndEpsonSsf,
+    ApplicationVndEricssonQuickcall,
+    ApplicationVndEspassEspassZip,
+    ApplicationVndEszigno3Xml,
+    ApplicationVndEtsiAocXml,
+    ApplicationVndEtsiAsicSZip,
+    ApplicationVndEtsiAsicEZip,
+    ApplicationVndEtsiCugXml,
+    ApplicationVndEtsiIptvcommandXml,
+    ApplicationVndEtsiIptvdiscoveryXml,
+    ApplicationVndEtsiIptvprofileXml,
+    ApplicationVndEtsiIptvsadBcXml,
+    ApplicationVndEtsiIptvsadCodXml,
+    ApplicationVndEtsiIptvsadNpvrXml,
+    ApplicationVndEtsiIptvserviceXml,
+    ApplicationVndEtsiIptvsyncXml,
+    ApplicationVndEtsiIptvueprofileXml,
+    ApplicationVndEtsiMcidXml,
+    ApplicationVndEtsiMheg5,
+    ApplicationVndEtsiOverloadControlPolicyDatasetXml,
+    ApplicationVndEtsiPstnXml,
+    ApplicationVndEtsiSciXml,
+    ApplicationVndEtsiSimservsXml,
+    ApplicationVndEtsiTimestampToken,
+    ApplicationVndEtsiTslXml,
+    ApplicationVndEtsiTslDer,
+    ApplicationVndEuKasparianCarJson,
+    ApplicationVndEudoraData,
+    ApplicationVndEvolvEcigProfile,
+    ApplicationVndEvolvEcigSettings,
+    ApplicationVndEvolvEcigTheme,
+    ApplicationVndExstreamEmpowerZip,
+    ApplicationVndExstreamPackage,
+    ApplicationVndEzpixAlbum,
+    ApplicationVndEzpixPackage,
+    ApplicationVndFSecureMobile,
+    ApplicationVndFastcopyDiskImage,
+    ApplicationVndFamilysearchGedcomZip,
+    ApplicationVndFdsnMseed,
+    ApplicationVndFdsnSeed,
+    ApplicationVndFfsns,
+    ApplicationVndFiclabFlbZip,
+    ApplicationVndFilmitZfc,
+    ApplicationVndFints,
+    ApplicationVndFiremonkeysCloudcell,
+    ApplicationVndFlographit,
+    ApplicationVndFluxtimeClip,
+    ApplicationVndFontFontforgeSfd,
+    ApplicationVndFramemaker,
+    ApplicationVndFscWeblaunch,
+    ApplicationVndFujifilmFbDocuworks,
+    ApplicationVndFujifilmFbDocuworksBinder,
+    ApplicationVndFujifilmFbDocuworksContainer,
+    ApplicationVndFujifilmFbJfiXml,
+    ApplicationVndFujitsuOasys,
+    ApplicationVndFujitsuOasys2,
+    ApplicationVndFujitsuOasys3,
+    ApplicationVndFujitsuOasysgp,
+    ApplicationVndFujitsuOasysprs,
+    ApplicationVndFujixeroxArt4,
+    ApplicationVndFujixeroxArtEx,
+    ApplicationVndFujixeroxDdd,
+    ApplicationVndFujixeroxDocuworks,
+    ApplicationVndFujixeroxDocuworksBinder,
+    ApplicationVndFujixeroxDocuworksContainer,
+    ApplicationVndFujixeroxHbpl,
+    ApplicationVndFutMisnet,
+    ApplicationVndFutoinCbor,
+    ApplicationVndFutoinJson,
+    ApplicationVndFuzzysheet,
+    ApplicationVndGenomatixTuxedo,
+    ApplicationVndGenozip,
+    ApplicationVndGenticsGrdJson,
+    ApplicationVndGentooCatmetadataXml,
+    ApplicationVndGentooEbuild,
+    ApplicationVndGentooEclass,
+    ApplicationVndGentooGpkg,
+    ApplicationVndGentooManifest,
+    ApplicationVndGentooXpak,
+    ApplicationVndGentooPkgmetadataXml,
+    ApplicationVndGeogebraFile,
+    ApplicationVndGeogebraSlides,
+    ApplicationVndGeogebraTool,
+    ApplicationVndGeometryExplorer,
+    ApplicationVndGeonext,
+    ApplicationVndGeoplan,
+    ApplicationVndGeospace,
+    ApplicationVndGerber,
+    ApplicationVndGlobalplatformCardContentMgt,
+    ApplicationVndGlobalplatformCardContentMgtResponse,
+    ApplicationVndGnuTalerExchangeJson,
+    ApplicationVndGnuTalerMerchantJson,
+    ApplicationVndGoogleEarthKmlXml,
+    ApplicationVndGoogleEarthKmz,
+    ApplicationVndGovSkEFormXml,
+    ApplicationVndGovSkEFormZip,
+    ApplicationVndGovSkXmldatacontainerXml,
+    ApplicationVndGpxseeMapXml,
+    ApplicationVndGrafeq,
+    ApplicationVndGridmp,
+    ApplicationVndGrooveAccount,
+    ApplicationVndGrooveHelp,
+    ApplicationVndGrooveIdentityMessage,
+    ApplicationVndGrooveInjector,
+    ApplicationVndGrooveToolMessage,
+    ApplicationVndGrooveToolTemplate,
+    ApplicationVndGrooveVcard,
+    ApplicationVndHalJson,
+    ApplicationVndHalXml,
+    ApplicationVndHandheldEntertainmentXml,
+    ApplicationVndHbci,
+    ApplicationVndHcJson,
+    ApplicationVndHclBireports,
+    ApplicationVndHdt,
+    ApplicationVndHerokuJson,
+    ApplicationVndHheLessonPlayer,
+    ApplicationVndHpHpgl,
+    ApplicationVndHpHpid,
+    ApplicationVndHpHps,
+    ApplicationVndHpJlyt,
+    ApplicationVndHpPcl,
+    ApplicationVndHpPclxl,
+    ApplicationVndHsl,
+    ApplicationVndHttphone,
+    ApplicationVndHydrostatixSofData,
+    ApplicationVndHyperItemJson,
+    ApplicationVndHyperJson,
+    ApplicationVndHyperdriveJson,
+    ApplicationVndHzn3dCrossword,
+    ApplicationVndIbmElectronicMedia,
+    ApplicationVndIbmMinipay,
+    ApplicationVndIbmRightsManagement,
+    ApplicationVndIbmSecureContainer,
+    ApplicationVndIccprofile,
+    ApplicationVndIeee1905,
+    ApplicationVndIgloader,
+    ApplicationVndImagemeterFolderZip,
+    ApplicationVndImagemeterImageZip,
+    ApplicationVndImmervisionIvp,
+    ApplicationVndImmervisionIvu,
+    ApplicationVndImsImsccv1p1,
+    ApplicationVndImsImsccv1p2,
+    ApplicationVndImsImsccv1p3,
+    ApplicationVndImsLisV2ResultJson,
+    ApplicationVndImsLtiV2ToolconsumerprofileJson,
+    ApplicationVndImsLtiV2ToolproxyIdJson,
+    ApplicationVndImsLtiV2ToolproxyJson,
+    ApplicationVndImsLtiV2ToolsettingsJson,
+    ApplicationVndImsLtiV2ToolsettingsSimpleJson,
+    ApplicationVndInformedcontrolRmsXml,
+    ApplicationVndInfotechProject,
+    ApplicationVndInfotechProjectXml,
+    ApplicationVndInnopathWampNotification,
+    ApplicationVndInsorsIgm,
+    ApplicationVndInterconFormnet,
+    ApplicationVndIntergeo,
+    ApplicationVndIntertrustDigibox,
+    ApplicationVndIntertrustNncp,
+    ApplicationVndIntuQbo,
+    ApplicationVndIntuQfx,
+    ApplicationVndIpfsIpnsRecord,
+    ApplicationVndIpldCar,
+    ApplicationVndIpldDagCbor,
+    ApplicationVndIpldDagJson,
+    ApplicationVndIpldRaw,
+    ApplicationVndIptcG2CatalogitemXml,
+    ApplicationVndIptcG2ConceptitemXml,
+    ApplicationVndIptcG2KnowledgeitemXml,
+    ApplicationVndIptcG2NewsitemXml,
+    ApplicationVndIptcG2NewsmessageXml,
+    ApplicationVndIptcG2PackageitemXml,
+    ApplicationVndIptcG2PlanningitemXml,
+    ApplicationVndIpunpluggedRcprofile,
+    ApplicationVndIrepositoryPackageXml,
+    ApplicationVndIsXpr,
+    ApplicationVndIsacFcs,
+    ApplicationVndJam,
+    ApplicationVndIso1178310Zip,
+    ApplicationVndJapannetDirectoryService,
+    ApplicationVndJapannetJpnstoreWakeup,
+    ApplicationVndJapannetPaymentWakeup,
+    ApplicationVndJapannetRegistration,
+    ApplicationVndJapannetRegistrationWakeup,
+    ApplicationVndJapannetSetstoreWakeup,
+    ApplicationVndJapannetVerification,
+    ApplicationVndJapannetVerificationWakeup,
+    ApplicationVndJcpJavameMidletRms,
+    ApplicationVndJisp,
+    ApplicationVndJoostJodaArchive,
+    ApplicationVndJskIsdnNgn,
+    ApplicationVndKahootz,
+    ApplicationVndKdeKarbon,
+    ApplicationVndKdeKchart,
+    ApplicationVndKdeKformula,
+    ApplicationVndKdeKivio,
+    ApplicationVndKdeKontour,
+    ApplicationVndKdeKpresenter,
+    ApplicationVndKdeKspread,
+    ApplicationVndKdeKword,
+    ApplicationVndKenameaapp,
+    ApplicationVndKidspiration,
+    ApplicationVndKinar,
+    ApplicationVndKoan,
+    ApplicationVndKodakDescriptor,
+    ApplicationVndLas,
+    ApplicationVndLasLasJson,
+    ApplicationVndLasLasXml,
+    ApplicationVndLaszip,
+    ApplicationVndLeapJson,
+    ApplicationVndLibertyRequestXml,
+    ApplicationVndLlamagraphicsLifeBalanceDesktop,
+    ApplicationVndLlamagraphicsLifeBalanceExchangeXml,
+    ApplicationVndLogipipeCircuitZip,
+    ApplicationVndLoom,
+    ApplicationVndLotus123,
+    ApplicationVndLotusApproach,
+    ApplicationVndLotusFreelance,
+    ApplicationVndLotusNotes,
+    ApplicationVndLotusOrganizer,
+    ApplicationVndLotusScreencam,
+    ApplicationVndLotusWordpro,
+    ApplicationVndMacportsPortpkg,
+    ApplicationVndMapboxVectorTile,
+    ApplicationVndMarlinDrmActiontokenXml,
+    ApplicationVndMarlinDrmConftokenXml,
+    ApplicationVndMarlinDrmLicenseXml,
+    ApplicationVndMarlinDrmMdcf,
+    ApplicationVndMasonJson,
+    ApplicationVndMaxarArchive3tzZip,
+    ApplicationVndMaxmindMaxmindDb,
+    ApplicationVndMcd,
+    ApplicationVndMdl,
+    ApplicationVndMdlMbsdf,
+    ApplicationVndMedcalcdata,
+    ApplicationVndMediastationCdkey,
+    ApplicationVndMedicalholodeckRecordxr,
+    ApplicationVndMeridianSlingshot,
+    ApplicationVndMfer,
+    ApplicationVndMfmp,
+    ApplicationVndMicroJson,
+    ApplicationVndMicrografxFlo,
+    ApplicationVndMicrografxIgx,
+    ApplicationVndMicrosoftPortableExecutable,
+    ApplicationVndMicrosoftWindowsThumbnailCache,
+    ApplicationVndMieleJson,
+    ApplicationVndMif,
+    ApplicationVndMinisoftHp3000Save,
+    ApplicationVndMitsubishiMistyGuardTrustweb,
+    ApplicationVndMobiusDaf,
+    ApplicationVndMobiusDis,
+    ApplicationVndMobiusMbk,
+    ApplicationVndMobiusMqy,
+    ApplicationVndMobiusMsl,
+    ApplicationVndMobiusPlc,
+    ApplicationVndMobiusTxf,
+    ApplicationVndModl,
+    ApplicationVndMophunApplication,
+    ApplicationVndMophunCertificate,
+    ApplicationVndMotorolaFlexsuite,
+    ApplicationVndMotorolaFlexsuiteAdsi,
+    ApplicationVndMotorolaFlexsuiteFis,
+    ApplicationVndMotorolaFlexsuiteGotap,
+    ApplicationVndMotorolaFlexsuiteKmr,
+    ApplicationVndMotorolaFlexsuiteTtc,
+    ApplicationVndMotorolaFlexsuiteWem,
+    ApplicationVndMotorolaIprm,
+    ApplicationVndMozillaXulXml,
+    ApplicationVndMsArtgalry,
+    ApplicationVndMsAsf,
+    ApplicationVndMsCabCompressed,
+    ApplicationVndMs3mfdocument,
+    ApplicationVndMsExcel,
+    ApplicationVndMsExcelAddinMacroenabled12,
+    ApplicationVndMsExcelSheetBinaryMacroenabled12,
+    ApplicationVndMsExcelSheetMacroenabled12,
+    ApplicationVndMsExcelTemplateMacroenabled12,
+    ApplicationVndMsFontobject,
+    ApplicationVndMsHtmlhelp,
+    ApplicationVndMsIms,
+    ApplicationVndMsLrm,
+    ApplicationVndMsOfficeActivexXml,
+    ApplicationVndMsOfficetheme,
+    ApplicationVndMsPlayreadyInitiatorXml,
+    ApplicationVndMsPowerpoint,
+    ApplicationVndMsPowerpointAddinMacroenabled12,
+    ApplicationVndMsPowerpointPresentationMacroenabled12,
+    ApplicationVndMsPowerpointSlideMacroenabled12,
+    ApplicationVndMsPowerpointSlideshowMacroenabled12,
+    ApplicationVndMsPowerpointTemplateMacroenabled12,
+    ApplicationVndMsPrintdevicecapabilitiesXml,
+    ApplicationVndMsPrintschematicketXml,
+    ApplicationVndMsProject,
+    ApplicationVndMsTnef,
+    ApplicationVndMsWindowsDevicepairing,
+    ApplicationVndMsWindowsNwprintingOob,
+    ApplicationVndMsWindowsPrinterpairing,
+    ApplicationVndMsWindowsWsdOob,
+    ApplicationVndMsWmdrmLicChlgReq,
+    ApplicationVndMsWmdrmLicResp,
+    ApplicationVndMsWmdrmMeterChlgReq,
+    ApplicationVndMsWmdrmMeterResp,
+    ApplicationVndMsWordDocumentMacroenabled12,
+    ApplicationVndMsWordTemplateMacroenabled12,
+    ApplicationVndMsWorks,
+    ApplicationVndMsWpl,
+    ApplicationVndMsXpsdocument,
+    ApplicationVndMsaDiskImage,
+    ApplicationVndMseq,
+    ApplicationVndMsign,
+    ApplicationVndMultiadCreator,
+    ApplicationVndMultiadCreatorCif,
+    ApplicationVndMusician,
+    ApplicationVndMusicNiff,
+    ApplicationVndMuveeStyle,
+    ApplicationVndMynfc,
+    ApplicationVndNacamarYbridJson,
+    ApplicationVndNcdControl,
+    ApplicationVndNcdReference,
+    ApplicationVndNearstInvJson,
+    ApplicationVndNebumindLine,
+    ApplicationVndNervana,
+    ApplicationVndNetfpx,
+    ApplicationVndNeurolanguageNlu,
+    ApplicationVndNimn,
+    ApplicationVndNintendoSnesRom,
+    ApplicationVndNintendoNitroRom,
+    ApplicationVndNitf,
+    ApplicationVndNoblenetDirectory,
+    ApplicationVndNoblenetSealer,
+    ApplicationVndNoblenetWeb,
+    ApplicationVndNokiaCatalogs,
+    ApplicationVndNokiaConmlWbxml,
+    ApplicationVndNokiaConmlXml,
+    ApplicationVndNokiaIptvConfigXml,
+    ApplicationVndNokiaIsdsRadioPresets,
+    ApplicationVndNokiaLandmarkWbxml,
+    ApplicationVndNokiaLandmarkXml,
+    ApplicationVndNokiaLandmarkcollectionXml,
+    ApplicationVndNokiaNcd,
+    ApplicationVndNokiaNGageAcXml,
+    ApplicationVndNokiaNGageData,
+    ApplicationVndNokiaPcdWbxml,
+    ApplicationVndNokiaPcdXml,
+    ApplicationVndNokiaRadioPreset,
+    ApplicationVndNokiaRadioPresets,
+    ApplicationVndNovadigmEdm,
+    ApplicationVndNovadigmEdx,
+    ApplicationVndNovadigmExt,
+    ApplicationVndNttLocalContentShare,
+    ApplicationVndNttLocalFileTransfer,
+    ApplicationVndNttLocalOgwRemoteAccess,
+    ApplicationVndNttLocalSipTaRemote,
+    ApplicationVndNttLocalSipTaTcpStream,
+    ApplicationVndOasisOpendocumentBase,
+    ApplicationVndOasisOpendocumentChart,
+    ApplicationVndOasisOpendocumentChartTemplate,
+    ApplicationVndOasisOpendocumentFormula,
+    ApplicationVndOasisOpendocumentFormulaTemplate,
+    ApplicationVndOasisOpendocumentGraphics,
+    ApplicationVndOasisOpendocumentGraphicsTemplate,
+    ApplicationVndOasisOpendocumentImage,
+    ApplicationVndOasisOpendocumentImageTemplate,
+    ApplicationVndOasisOpendocumentPresentation,
+    ApplicationVndOasisOpendocumentPresentationTemplate,
+    ApplicationVndOasisOpendocumentSpreadsheet,
+    ApplicationVndOasisOpendocumentSpreadsheetTemplate,
+    ApplicationVndOasisOpendocumentText,
+    ApplicationVndOasisOpendocumentTextMaster,
+    ApplicationVndOasisOpendocumentTextMasterTemplate,
+    ApplicationVndOasisOpendocumentTextTemplate,
+    ApplicationVndOasisOpendocumentTextWeb,
+    ApplicationVndObn,
+    ApplicationVndOcfCbor,
+    ApplicationVndOciImageManifestV1Json,
+    ApplicationVndOftnL10nJson,
+    ApplicationVndOipfContentaccessdownloadXml,
+    ApplicationVndOipfContentaccessstreamingXml,
+    ApplicationVndOipfCspgHexbinary,
+    ApplicationVndOipfDaeSvgXml,
+    ApplicationVndOipfDaeXhtmlXml,
+    ApplicationVndOipfMippvcontrolmessageXml,
+    ApplicationVndOipfPaeGem,
+    ApplicationVndOipfSpdiscoveryXml,
+    ApplicationVndOipfSpdlistXml,
+    ApplicationVndOipfUeprofileXml,
+    ApplicationVndOipfUserprofileXml,
+    ApplicationVndOlpcSugar,
+    ApplicationVndOmaBcastAssociatedProcedureParameterXml,
+    ApplicationVndOmaBcastDrmTriggerXml,
+    ApplicationVndOmaBcastImdXml,
+    ApplicationVndOmaBcastLtkm,
+    ApplicationVndOmaBcastNotificationXml,
+    ApplicationVndOmaBcastProvisioningtrigger,
+    ApplicationVndOmaBcastSgboot,
+    ApplicationVndOmaBcastSgddXml,
+    ApplicationVndOmaBcastSgdu,
+    ApplicationVndOmaBcastSimpleSymbolContainer,
+    ApplicationVndOmaBcastSmartcardTriggerXml,
+    ApplicationVndOmaBcastSprovXml,
+    ApplicationVndOmaBcastStkm,
+    ApplicationVndOmaCabAddressBookXml,
+    ApplicationVndOmaCabFeatureHandlerXml,
+    ApplicationVndOmaCabPccXml,
+    ApplicationVndOmaCabSubsInviteXml,
+    ApplicationVndOmaCabUserPrefsXml,
+    ApplicationVndOmaDcd,
+    ApplicationVndOmaDcdc,
+    ApplicationVndOmaDd2Xml,
+    ApplicationVndOmaDrmRisdXml,
+    ApplicationVndOmaGroupUsageListXml,
+    ApplicationVndOmaLwm2mCbor,
+    ApplicationVndOmaLwm2mJson,
+    ApplicationVndOmaLwm2mTlv,
+    ApplicationVndOmaPalXml,
+    ApplicationVndOmaPocDetailedProgressReportXml,
+    ApplicationVndOmaPocFinalReportXml,
+    ApplicationVndOmaPocGroupsXml,
+    ApplicationVndOmaPocInvocationDescriptorXml,
+    ApplicationVndOmaPocOptimizedProgressReportXml,
+    ApplicationVndOmaPush,
+    ApplicationVndOmaScidmMessagesXml,
+    ApplicationVndOmaXcapDirectoryXml,
+    ApplicationVndOmadsEmailXml,
+    ApplicationVndOmadsFileXml,
+    ApplicationVndOmadsFolderXml,
+    ApplicationVndOmalocSuplInit,
+    ApplicationVndOmaScwsConfig,
+    ApplicationVndOmaScwsHttpRequest,
+    ApplicationVndOmaScwsHttpResponse,
+    ApplicationVndOnepager,
+    ApplicationVndOnepagertamp,
+    ApplicationVndOnepagertamx,
+    ApplicationVndOnepagertat,
+    ApplicationVndOnepagertatp,
+    ApplicationVndOnepagertatx,
+    ApplicationVndOnvifMetadata,
+    ApplicationVndOpenbloxGameBinary,
+    ApplicationVndOpenbloxGameXml,
+    ApplicationVndOpeneyeOeb,
+    ApplicationVndOpenstreetmapDataXml,
+    ApplicationVndOpentimestampsOts,
+    ApplicationVndOpenxmlformatsOfficedocumentCustomPropertiesXml,
+    ApplicationVndOpenxmlformatsOfficedocumentCustomxmlpropertiesXml,
+    ApplicationVndOpenxmlformatsOfficedocumentDrawingXml,
+    ApplicationVndOpenxmlformatsOfficedocumentDrawingmlChartXml,
+    ApplicationVndOpenxmlformatsOfficedocumentDrawingmlChartshapesXml,
+    ApplicationVndOpenxmlformatsOfficedocumentDrawingmlDiagramcolorsXml,
+    ApplicationVndOpenxmlformatsOfficedocumentDrawingmlDiagramdataXml,
+    ApplicationVndOpenxmlformatsOfficedocumentDrawingmlDiagramlayoutXml,
+    ApplicationVndOpenxmlformatsOfficedocumentDrawingmlDiagramstyleXml,
+    ApplicationVndOpenxmlformatsOfficedocumentExtendedPropertiesXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlCommentauthorsXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlCommentsXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlHandoutmasterXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlNotesmasterXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlNotesslideXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlPresentation,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlPresentationMainXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlPrespropsXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlide,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlideXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlidelayoutXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlidemasterXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlideshow,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlideshowMainXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlideupdateinfoXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlTablestylesXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlTagsXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlTemplate,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlTemplateMainXml,
+    ApplicationVndOpenxmlformatsOfficedocumentPresentationmlViewpropsXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlCalcchainXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlChartsheetXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlCommentsXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlConnectionsXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlDialogsheetXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlExternallinkXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlPivotcachedefinitionXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlPivotcacherecordsXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlPivottableXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlQuerytableXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlRevisionheadersXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlRevisionlogXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSharedstringsXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSheet,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSheetMainXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSheetmetadataXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlStylesXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlTableXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlTablesinglecellsXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlTemplate,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlTemplateMainXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlUsernamesXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlVolatiledependenciesXml,
+    ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlWorksheetXml,
+    ApplicationVndOpenxmlformatsOfficedocumentThemeXml,
+    ApplicationVndOpenxmlformatsOfficedocumentThemeoverrideXml,
+    ApplicationVndOpenxmlformatsOfficedocumentVmldrawing,
+    ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlCommentsXml,
+    ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlDocument,
+    ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlDocumentGlossaryXml,
+    ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlDocumentMainXml,
+    ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlEndnotesXml,
+    ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlFonttableXml,
+    ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlFooterXml,
+    ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlFootnotesXml,
+    ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlNumberingXml,
+    ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlSettingsXml,
+    ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlStylesXml,
+    ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlTemplate,
+    ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlTemplateMainXml,
+    ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlWebsettingsXml,
+    ApplicationVndOpenxmlformatsPackageCorePropertiesXml,
+    ApplicationVndOpenxmlformatsPackageDigitalSignatureXmlsignatureXml,
+    ApplicationVndOpenxmlformatsPackageRelationshipsXml,
+    ApplicationVndOracleResourceJson,
+    ApplicationVndOrangeIndata,
+    ApplicationVndOsaNetdeploy,
+    ApplicationVndOsgeoMapguidePackage,
+    ApplicationVndOsgiBundle,
+    ApplicationVndOsgiDp,
+    ApplicationVndOsgiSubsystem,
+    ApplicationVndOtpsCtKipXml,
+    ApplicationVndOxliCountgraph,
+    ApplicationVndPagerdutyJson,
+    ApplicationVndPalm,
+    ApplicationVndPanoply,
+    ApplicationVndPaosXml,
+    ApplicationVndPatentdive,
+    ApplicationVndPatientecommsdoc,
+    ApplicationVndPawaafile,
+    ApplicationVndPcos,
+    ApplicationVndPgFormat,
+    ApplicationVndPgOsasli,
+    ApplicationVndPiaccessApplicationLicence,
+    ApplicationVndPicsel,
+    ApplicationVndPmiWidget,
+    ApplicationVndPocGroupAdvertisementXml,
+    ApplicationVndPocketlearn,
+    ApplicationVndPowerbuilder6,
+    ApplicationVndPowerbuilder6S,
+    ApplicationVndPowerbuilder7,
+    ApplicationVndPowerbuilder75,
+    ApplicationVndPowerbuilder75S,
+    ApplicationVndPowerbuilder7S,
+    ApplicationVndPreminet,
+    ApplicationVndPreviewsystemsBox,
+    ApplicationVndProteusMagazine,
+    ApplicationVndPsfs,
+    ApplicationVndPtMundusmundi,
+    ApplicationVndPublishareDeltaTree,
+    ApplicationVndPviPtid1,
+    ApplicationVndPwgMultiplexed,
+    ApplicationVndPwgXhtmlPrintXml,
+    ApplicationVndQualcommBrewAppRes,
+    ApplicationVndQuarantainenet,
+    ApplicationVndQuarkQuarkxpress,
+    ApplicationVndQuobjectQuoxdocument,
+    ApplicationVndRadisysMomlXml,
+    ApplicationVndRadisysMsmlAuditConfXml,
+    ApplicationVndRadisysMsmlAuditConnXml,
+    ApplicationVndRadisysMsmlAuditDialogXml,
+    ApplicationVndRadisysMsmlAuditStreamXml,
+    ApplicationVndRadisysMsmlAuditXml,
+    ApplicationVndRadisysMsmlConfXml,
+    ApplicationVndRadisysMsmlDialogBaseXml,
+    ApplicationVndRadisysMsmlDialogFaxDetectXml,
+    ApplicationVndRadisysMsmlDialogFaxSendrecvXml,
+    ApplicationVndRadisysMsmlDialogGroupXml,
+    ApplicationVndRadisysMsmlDialogSpeechXml,
+    ApplicationVndRadisysMsmlDialogTransformXml,
+    ApplicationVndRadisysMsmlDialogXml,
+    ApplicationVndRadisysMsmlXml,
+    ApplicationVndRainstorData,
+    ApplicationVndRapid,
+    ApplicationVndRar,
+    ApplicationVndRealvncBed,
+    ApplicationVndRecordareMusicxml,
+    ApplicationVndRecordareMusicxmlXml,
+    ApplicationVndRenlearnRlprint,
+    ApplicationVndResilientLogic,
+    ApplicationVndRestfulJson,
+    ApplicationVndRigCryptonote,
+    ApplicationVndRoute66Link66Xml,
+    ApplicationVndRs274x,
+    ApplicationVndRuckusDownload,
+    ApplicationVndS3sms,
+    ApplicationVndSailingtrackerTrack,
+    ApplicationVndSar,
+    ApplicationVndSbmCid,
+    ApplicationVndSbmMid2,
+    ApplicationVndScribus,
+    ApplicationVndSealed3df,
+    ApplicationVndSealedCsf,
+    ApplicationVndSealedDoc,
+    ApplicationVndSealedEml,
+    ApplicationVndSealedMht,
+    ApplicationVndSealedNet,
+    ApplicationVndSealedPpt,
+    ApplicationVndSealedTiff,
+    ApplicationVndSealedXls,
+    ApplicationVndSealedmediaSoftsealHtml,
+    ApplicationVndSealedmediaSoftsealPdf,
+    ApplicationVndSeemail,
+    ApplicationVndSeisJson,
+    ApplicationVndSema,
+    ApplicationVndSemd,
+    ApplicationVndSemf,
+    ApplicationVndShadeSaveFile,
+    ApplicationVndShanaInformedFormdata,
+    ApplicationVndShanaInformedFormtemplate,
+    ApplicationVndShanaInformedInterchange,
+    ApplicationVndShanaInformedPackage,
+    ApplicationVndShootproofJson,
+    ApplicationVndShopkickJson,
+    ApplicationVndShp,
+    ApplicationVndShx,
+    ApplicationVndSigrokSession,
+    ApplicationVndSimtechMindmapper,
+    ApplicationVndSirenJson,
+    ApplicationVndSmaf,
+    ApplicationVndSmartNotebook,
+    ApplicationVndSmartTeacher,
+    ApplicationVndSmintioPortalsArchive,
+    ApplicationVndSnesdevPageTable,
+    ApplicationVndSoftware602FillerFormXml,
+    ApplicationVndSoftware602FillerFormXmlZip,
+    ApplicationVndSolentSdkmXml,
+    ApplicationVndSpotfireDxp,
+    ApplicationVndSpotfireSfs,
+    ApplicationVndSqlite3,
+    ApplicationVndSssCod,
+    ApplicationVndSssDtf,
+    ApplicationVndSssNtf,
+    ApplicationVndStepmaniaPackage,
+    ApplicationVndStepmaniaStepchart,
+    ApplicationVndStreetStream,
+    ApplicationVndSunWadlXml,
+    ApplicationVndSusCalendar,
+    ApplicationVndSvd,
+    ApplicationVndSwiftviewIcs,
+    ApplicationVndSybylMol2,
+    ApplicationVndSycleXml,
+    ApplicationVndSyftJson,
+    ApplicationVndSyncmlDmNotification,
+    ApplicationVndSyncmlDmddfXml,
+    ApplicationVndSyncmlDmtndsWbxml,
+    ApplicationVndSyncmlDmtndsXml,
+    ApplicationVndSyncmlDmddfWbxml,
+    ApplicationVndSyncmlDmWbxml,
+    ApplicationVndSyncmlDmXml,
+    ApplicationVndSyncmlDsNotification,
+    ApplicationVndSyncmlXml,
+    ApplicationVndTableschemaJson,
+    ApplicationVndTaoIntentModuleArchive,
+    ApplicationVndTcpdumpPcap,
+    ApplicationVndThinkCellPpttcJson,
+    ApplicationVndTml,
+    ApplicationVndTmdMediaflexApiXml,
+    ApplicationVndTmobileLivetv,
+    ApplicationVndTriOnesource,
+    ApplicationVndTridTpt,
+    ApplicationVndTriscapeMxs,
+    ApplicationVndTrueapp,
+    ApplicationVndTruedoc,
+    ApplicationVndUbisoftWebplayer,
+    ApplicationVndUfdl,
+    ApplicationVndUiqTheme,
+    ApplicationVndUmajin,
+    ApplicationVndUnity,
+    ApplicationVndUomlXml,
+    ApplicationVndUplanetAlert,
+    ApplicationVndUplanetAlertWbxml,
+    ApplicationVndUplanetBearerChoice,
+    ApplicationVndUplanetBearerChoiceWbxml,
+    ApplicationVndUplanetCacheop,
+    ApplicationVndUplanetCacheopWbxml,
+    ApplicationVndUplanetChannel,
+    ApplicationVndUplanetChannelWbxml,
+    ApplicationVndUplanetList,
+    ApplicationVndUplanetListcmd,
+    ApplicationVndUplanetListcmdWbxml,
+    ApplicationVndUplanetListWbxml,
+    ApplicationVndUriMap,
+    ApplicationVndUplanetSignal,
+    ApplicationVndValveSourceMaterial,
+    ApplicationVndVcx,
+    ApplicationVndVdStudy,
+    ApplicationVndVectorworks,
+    ApplicationVndVelJson,
+    ApplicationVndVerimatrixVcas,
+    ApplicationVndVeritoneAionJson,
+    ApplicationVndVeryantThin,
+    ApplicationVndVesEncrypted,
+    ApplicationVndVidsoftVidconference,
+    ApplicationVndVisio,
+    ApplicationVndVisionary,
+    ApplicationVndVividenceScriptfile,
+    ApplicationVndVsf,
+    ApplicationVndWapSic,
+    ApplicationVndWapSlc,
+    ApplicationVndWapWbxml,
+    ApplicationVndWapWmlc,
+    ApplicationVndWapWmlscriptc,
+    ApplicationVndWasmflowWafl,
+    ApplicationVndWebturbo,
+    ApplicationVndWfaDpp,
+    ApplicationVndWfaP2p,
+    ApplicationVndWfaWsc,
+    ApplicationVndWindowsDevicepairing,
+    ApplicationVndWmc,
+    ApplicationVndWmfBootstrap,
+    ApplicationVndWolframMathematica,
+    ApplicationVndWolframMathematicaPackage,
+    ApplicationVndWolframPlayer,
+    ApplicationVndWordlift,
+    ApplicationVndWordperfect,
+    ApplicationVndWqd,
+    ApplicationVndWrqHp3000Labelled,
+    ApplicationVndWtStf,
+    ApplicationVndWvCspXml,
+    ApplicationVndWvCspWbxml,
+    ApplicationVndWvSspXml,
+    ApplicationVndXacmlJson,
+    ApplicationVndXara,
+    ApplicationVndXfdl,
+    ApplicationVndXfdlWebform,
+    ApplicationVndXmiXml,
+    ApplicationVndXmpieCpkg,
+    ApplicationVndXmpieDpkg,
+    ApplicationVndXmpiePlan,
+    ApplicationVndXmpiePpkg,
+    ApplicationVndXmpieXlim,
+    ApplicationVndYamahaHvDic,
+    ApplicationVndYamahaHvScript,
+    ApplicationVndYamahaHvVoice,
+    ApplicationVndYamahaOpenscoreformatOsfpvgXml,
+    ApplicationVndYamahaOpenscoreformat,
+    ApplicationVndYamahaRemoteSetup,
+    ApplicationVndYamahaSmafAudio,
+    ApplicationVndYamahaSmafPhrase,
+    ApplicationVndYamahaThroughNgn,
+    ApplicationVndYamahaTunnelUdpencap,
+    ApplicationVndYaoweme,
+    ApplicationVndYellowriverCustomMenu,
+    ApplicationVndZul,
+    ApplicationVndZzazzDeckXml,
+    ApplicationVoicexmlXml,
+    ApplicationVoucherCmsJson,
+    ApplicationVqRtcpxr,
+    ApplicationWasm,
+    ApplicationWatcherinfoXml,
+    ApplicationWebpushOptionsJson,
+    ApplicationWhoisppQuery,
+    ApplicationWhoisppResponse,
+    ApplicationWidget,
+    ApplicationWita,
+    ApplicationWordperfect51,
+    ApplicationWsdlXml,
+    ApplicationWspolicyXml,
+    ApplicationXPkiMessage,
+    ApplicationXWwwFormUrlencoded,
+    ApplicationXX509CaCert,
+    ApplicationXX509CaRaCert,
+    ApplicationXX509NextCaCert,
+    ApplicationX400Bp,
+    ApplicationXacmlXml,
+    ApplicationXcapAttXml,
+    ApplicationXcapCapsXml,
+    ApplicationXcapDiffXml,
+    ApplicationXcapElXml,
+    ApplicationXcapErrorXml,
+    ApplicationXcapNsXml,
+    ApplicationXconConferenceInfoDiffXml,
+    ApplicationXconConferenceInfoXml,
+    ApplicationXencXml,
+    ApplicationXfdf,
+    ApplicationXhtmlXml,
+    ApplicationXliffXml,
+    ApplicationXml,
+    ApplicationXmlDtd,
+    ApplicationXmlExternalParsedEntity,
+    ApplicationXmlPatchXml,
+    ApplicationXmppXml,
+    ApplicationXopXml,
+    ApplicationXsltXml,
+    ApplicationXvXml,
+    ApplicationYang,
+    ApplicationYangDataCbor,
+    ApplicationYangDataJson,
+    ApplicationYangDataXml,
+    ApplicationYangPatchJson,
+    ApplicationYangPatchXml,
+    ApplicationYinXml,
+    ApplicationZip,
+    ApplicationZlib,
+    ApplicationZstd,
+    Audio1dInterleavedParityfec,
+    Audio32kadpcm,
+    Audio3gpp,
+    Audio3gpp2,
+    AudioAac,
+    AudioAc3,
+    AudioAmr,
+    AudioAmrWbPlus,
+    AudioAmrWb,
+    AudioAptx,
+    AudioAsc,
+    AudioAtracAdvancedLossless,
+    AudioAtracX,
+    AudioAtrac3,
+    AudioBasic,
+    AudioBv16,
+    AudioBv32,
+    AudioClearmode,
+    AudioCn,
+    AudioDat12,
+    AudioDls,
+    AudioDsrEs201108,
+    AudioDsrEs202050,
+    AudioDsrEs202211,
+    AudioDsrEs202212,
+    AudioDv,
+    AudioDvi4,
+    AudioEac3,
+    AudioEncaprtp,
+    AudioEvrc,
+    AudioEvrcQcp,
+    AudioEvrc0,
+    AudioEvrc1,
+    AudioEvrcb,
+    AudioEvrcb0,
+    AudioEvrcb1,
+    AudioEvrcnw,
+    AudioEvrcnw0,
+    AudioEvrcnw1,
+    AudioEvrcwb,
+    AudioEvrcwb0,
+    AudioEvrcwb1,
+    AudioEvs,
+    AudioExample,
+    AudioFlexfec,
+    AudioFwdred,
+    AudioG7110,
+    AudioG719,
+    AudioG7221,
+    AudioG722,
+    AudioG723,
+    AudioG72616,
+    AudioG72624,
+    AudioG72632,
+    AudioG72640,
+    AudioG728,
+    AudioG729,
+    AudioG7291,
+    AudioG729d,
+    AudioG729e,
+    AudioGsm,
+    AudioGsmEfr,
+    AudioGsmHr08,
+    AudioIlbc,
+    AudioIpMrV25,
+    AudioL8,
+    AudioL16,
+    AudioL20,
+    AudioL24,
+    AudioLpc,
+    AudioMelp,
+    AudioMelp600,
+    AudioMelp1200,
+    AudioMelp2400,
+    AudioMhas,
+    AudioMobileXmf,
+    AudioMpa,
+    AudioMp4,
+    AudioMp4aLatm,
+    AudioMpaRobust,
+    AudioMpeg,
+    AudioMpeg4Generic,
+    AudioOgg,
+    AudioOpus,
+    AudioParityfec,
+    AudioPcma,
+    AudioPcmaWb,
+    AudioPcmu,
+    AudioPcmuWb,
+    AudioPrsSid,
+    AudioQcelp,
+    AudioRaptorfec,
+    AudioRed,
+    AudioRtpEncAescm128,
+    AudioRtploopback,
+    AudioRtpMidi,
+    AudioRtx,
+    AudioScip,
+    AudioSmv,
+    AudioSmv0,
+    AudioSmvQcp,
+    AudioSofa,
+    AudioSpMidi,
+    AudioSpeex,
+    AudioT140c,
+    AudioT38,
+    AudioTelephoneEvent,
+    AudioTetraAcelp,
+    AudioTetraAcelpBb,
+    AudioTone,
+    AudioTsvcis,
+    AudioUemclip,
+    AudioUlpfec,
+    AudioUsac,
+    AudioVdvi,
+    AudioVmrWb,
+    AudioVnd3gppIufp,
+    AudioVnd4sb,
+    AudioVndAudiokoz,
+    AudioVndCelp,
+    AudioVndCiscoNse,
+    AudioVndCmlesRadioEvents,
+    AudioVndCnsAnp1,
+    AudioVndCnsInf1,
+    AudioVndDeceAudio,
+    AudioVndDigitalWinds,
+    AudioVndDlnaAdts,
+    AudioVndDolbyHeaac1,
+    AudioVndDolbyHeaac2,
+    AudioVndDolbyMlp,
+    AudioVndDolbyMps,
+    AudioVndDolbyPl2,
+    AudioVndDolbyPl2x,
+    AudioVndDolbyPl2z,
+    AudioVndDolbyPulse1,
+    AudioVndDra,
+    AudioVndDts,
+    AudioVndDtsHd,
+    AudioVndDtsUhd,
+    AudioVndDvbFile,
+    AudioVndEveradPlj,
+    AudioVndHnsAudio,
+    AudioVndLucentVoice,
+    AudioVndMsPlayreadyMediaPya,
+    AudioVndNokiaMobileXmf,
+    AudioVndNortelVbk,
+    AudioVndNueraEcelp4800,
+    AudioVndNueraEcelp7470,
+    AudioVndNueraEcelp9600,
+    AudioVndOctelSbc,
+    AudioVndPresonusMultitrack,
+    AudioVndRhetorex32kadpcm,
+    AudioVndRip,
+    AudioVndSealedmediaSoftsealMpeg,
+    AudioVndVmxCvsd,
+    AudioVorbis,
+    AudioVorbisConfig,
+    FontCollection,
+    FontOtf,
+    FontSfnt,
+    FontTtf,
+    FontWoff,
+    FontWoff2,
+    ImageAces,
+    ImageApng,
+    ImageAvci,
+    ImageAvcs,
+    ImageAvif,
+    ImageBmp,
+    ImageCgm,
+    ImageDicomRle,
+    ImageDpx,
+    ImageEmf,
+    ImageExample,
+    ImageFits,
+    ImageG3fax,
+    ImageHeic,
+    ImageHeicSequence,
+    ImageHeif,
+    ImageHeifSequence,
+    ImageHej2k,
+    ImageHsj2,
+    ImageJls,
+    ImageJp2,
+    ImageJpeg,
+    ImageJph,
+    ImageJphc,
+    ImageJpm,
+    ImageJpx,
+    ImageJxr,
+    ImageJxra,
+    ImageJxrs,
+    ImageJxs,
+    ImageJxsc,
+    ImageJxsi,
+    ImageJxss,
+    ImageKtx,
+    ImageKtx2,
+    ImageNaplps,
+    ImagePng,
+    ImagePrsBtif,
+    ImagePrsPti,
+    ImagePwgRaster,
+    ImageSvgXml,
+    ImageT38,
+    ImageTiff,
+    ImageTiffFx,
+    ImageVndAdobePhotoshop,
+    ImageVndAirzipAcceleratorAzv,
+    ImageVndCnsInf2,
+    ImageVndDeceGraphic,
+    ImageVndDjvu,
+    ImageVndDwg,
+    ImageVndDxf,
+    ImageVndDvbSubtitle,
+    ImageVndFastbidsheet,
+    ImageVndFpx,
+    ImageVndFst,
+    ImageVndFujixeroxEdmicsMmr,
+    ImageVndFujixeroxEdmicsRlc,
+    ImageVndGlobalgraphicsPgb,
+    ImageVndMicrosoftIcon,
+    ImageVndMix,
+    ImageVndMsModi,
+    ImageVndMozillaApng,
+    ImageVndNetFpx,
+    ImageVndPcoB16,
+    ImageVndRadiance,
+    ImageVndSealedPng,
+    ImageVndSealedmediaSoftsealGif,
+    ImageVndSealedmediaSoftsealJpg,
+    ImageVndSvf,
+    ImageVndTencentTap,
+    ImageVndValveSourceTexture,
+    ImageVndWapWbmp,
+    ImageVndXiff,
+    ImageVndZbrushPcx,
+    ImageWebp,
+    ImageWmf,
+    MessageBhttp,
+    MessageCpim,
+    MessageDeliveryStatus,
+    MessageDispositionNotification,
+    MessageExample,
+    MessageFeedbackReport,
+    MessageGlobal,
+    MessageGlobalDeliveryStatus,
+    MessageGlobalDispositionNotification,
+    MessageGlobalHeaders,
+    MessageHttp,
+    MessageImdnXml,
+    MessageMls,
+    MessageOhttpReq,
+    MessageOhttpRes,
+    MessageSip,
+    MessageSipfrag,
+    MessageTrackingStatus,
+    MessageVndWfaWsc,
+    Model3mf,
+    ModelE57,
+    ModelExample,
+    ModelGltfBinary,
+    ModelGltfJson,
+    ModelJt,
+    ModelIges,
+    ModelMtl,
+    ModelObj,
+    ModelPrc,
+    ModelStep,
+    ModelStepXml,
+    ModelStepZip,
+    ModelStepXmlZip,
+    ModelStl,
+    ModelU3d,
+    ModelVndBary,
+    ModelVndCld,
+    ModelVndColladaXml,
+    ModelVndDwf,
+    ModelVndFlatland3dml,
+    ModelVndGdl,
+    ModelVndGsGdl,
+    ModelVndGtw,
+    ModelVndMomlXml,
+    ModelVndMts,
+    ModelVndOpengex,
+    ModelVndParasolidTransmitBinary,
+    ModelVndParasolidTransmitText,
+    ModelVndPythaPyox,
+    ModelVndRosetteAnnotatedDataModel,
+    ModelVndSapVds,
+    ModelVndUsda,
+    ModelVndUsdzZip,
+    ModelVndValveSourceCompiledMap,
+    ModelVndVtu,
+    ModelX3dVrml,
+    ModelX3dFastinfoset,
+    ModelX3dXml,
+    MultipartAppledouble,
+    MultipartByteranges,
+    MultipartEncrypted,
+    MultipartExample,
+    MultipartFormData,
+    MultipartHeaderSet,
+    MultipartMultilingual,
+    MultipartRelated,
+    MultipartReport,
+    MultipartSigned,
+    MultipartVndBintMedPlus,
+    MultipartVoiceMessage,
+    MultipartXMixedReplace,
+    Text1dInterleavedParityfec,
+    TextCacheManifest,
+    TextCalendar,
+    TextCql,
+    TextCqlExpression,
+    TextCqlIdentifier,
+    TextCss,
+    TextCsv,
+    TextCsvSchema,
+    TextDns,
+    TextEncaprtp,
+    TextExample,
+    TextFhirpath,
+    TextFlexfec,
+    TextFwdred,
+    TextGff3,
+    TextGrammarRefList,
+    TextHl7v2,
+    TextHtml,
+    TextJavascript,
+    TextJcrCnd,
+    TextMarkdown,
+    TextMizar,
+    TextN3,
+    TextParameters,
+    TextParityfec,
+    TextPlain,
+    TextProvenanceNotation,
+    TextPrsFallensteinRst,
+    TextPrsLinesTag,
+    TextPrsPropLogic,
+    TextRaptorfec,
+    TextRed,
+    TextRfc822Headers,
+    TextRtf,
+    TextRtpEncAescm128,
+    TextRtploopback,
+    TextRtx,
+    TextSgml,
+    TextShaclc,
+    TextShex,
+    TextSpdx,
+    TextStrings,
+    TextT140,
+    TextTabSeparatedValues,
+    TextTroff,
+    TextTurtle,
+    TextUlpfec,
+    TextUriList,
+    TextVcard,
+    TextVndA,
+    TextVndAbc,
+    TextVndAsciiArt,
+    TextVndCurl,
+    TextVndDebianCopyright,
+    TextVndDmclientscript,
+    TextVndDvbSubtitle,
+    TextVndEsmertecThemeDescriptor,
+    TextVndExchangeable,
+    TextVndFamilysearchGedcom,
+    TextVndFiclabFlt,
+    TextVndFly,
+    TextVndFmiFlexstor,
+    TextVndGml,
+    TextVndGraphviz,
+    TextVndHans,
+    TextVndHgl,
+    TextVndIn3d3dml,
+    TextVndIn3dSpot,
+    TextVndIptcNewsml,
+    TextVndIptcNitf,
+    TextVndLatexZ,
+    TextVndMotorolaReflex,
+    TextVndMsMediapackage,
+    TextVndNet2phoneCommcenterCommand,
+    TextVndRadisysMsmlBasicLayout,
+    TextVndSenxWarpscript,
+    TextVndSunJ2meAppDescriptor,
+    TextVndSosi,
+    TextVndTrolltechLinguist,
+    TextVndWapSi,
+    TextVndWapSl,
+    TextVndWapWml,
+    TextVndWapWmlscript,
+    TextVtt,
+    TextWgsl,
+    TextXml,
+    TextXmlExternalParsedEntity,
+    Video1dInterleavedParityfec,
+    Video3gpp,
+    Video3gpp2,
+    Video3gppTt,
+    VideoAv1,
+    VideoBmpeg,
+    VideoBt656,
+    VideoCelb,
+    VideoDv,
+    VideoEncaprtp,
+    VideoExample,
+    VideoFfv1,
+    VideoFlexfec,
+    VideoH261,
+    VideoH263,
+    VideoH2631998,
+    VideoH2632000,
+    VideoH264,
+    VideoH264Rcdo,
+    VideoH264Svc,
+    VideoH265,
+    VideoH266,
+    VideoIsoSegment,
+    VideoJpeg,
+    VideoJpeg2000,
+    VideoJxsv,
+    VideoMj2,
+    VideoMp1s,
+    VideoMp2p,
+    VideoMp2t,
+    VideoMp4,
+    VideoMp4vEs,
+    VideoMpv,
+    VideoMpeg4Generic,
+    VideoNv,
+    VideoOgg,
+    VideoParityfec,
+    VideoPointer,
+    VideoQuicktime,
+    VideoRaptorfec,
+    VideoRaw,
+    VideoRtpEncAescm128,
+    VideoRtploopback,
+    VideoRtx,
+    VideoScip,
+    VideoSmpte291,
+    VideoSmpte292m,
+    VideoUlpfec,
+    VideoVc1,
+    VideoVc2,
+    VideoVndCctv,
+    VideoVndDeceHd,
+    VideoVndDeceMobile,
+    VideoVndDeceMp4,
+    VideoVndDecePd,
+    VideoVndDeceSd,
+    VideoVndDeceVideo,
+    VideoVndDirectvMpeg,
+    VideoVndDirectvMpegTts,
+    VideoVndDlnaMpegTts,
+    VideoVndDvbFile,
+    VideoVndFvt,
+    VideoVndHnsVideo,
+    VideoVndIptvforum1dparityfec1010,
+    VideoVndIptvforum1dparityfec2005,
+    VideoVndIptvforum2dparityfec1010,
+    VideoVndIptvforum2dparityfec2005,
+    VideoVndIptvforumTtsavc,
+    VideoVndIptvforumTtsmpeg2,
+    VideoVndMotorolaVideo,
+    VideoVndMotorolaVideop,
+    VideoVndMpegurl,
+    VideoVndMsPlayreadyMediaPyv,
+    VideoVndNokiaInterleavedMultimedia,
+    VideoVndNokiaMp4vr,
+    VideoVndNokiaVideovoip,
+    VideoVndObjectvideo,
+    VideoVndRadgamettoolsBink,
+    VideoVndRadgamettoolsSmacker,
+    VideoVndSealedMpeg1,
+    VideoVndSealedMpeg4,
+    VideoVndSealedSwf,
+    VideoVndSealedmediaSoftsealMov,
+    VideoVndUvvuMp4,
+    VideoVndYoutubeYt,
+    VideoVndVivo,
+    VideoVp8,
+    VideoVp9,
+}
+
+impl std::fmt::Display for Mime {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        match self {
+			Mime::Application1dInterleavedParityfec => write!(f, "application/1d-interleaved-parityfec"),
+			Mime::Application3gpdashQoeReportXml => write!(f, "application/3gpdash-qoe-report+xml"),
+			Mime::Application3gpphalJson => write!(f, "application/3gppHal+json"),
+			Mime::Application3gpphalformsJson => write!(f, "application/3gppHalForms+json"),
+			Mime::Application3gppImsXml => write!(f, "application/3gpp-ims+xml"),
+			Mime::ApplicationA2l => write!(f, "application/A2L"),
+			Mime::ApplicationAceCbor => write!(f, "application/ace+cbor"),
+			Mime::ApplicationAceJson => write!(f, "application/ace+json"),
+			Mime::ApplicationActivemessage => write!(f, "application/activemessage"),
+			Mime::ApplicationActivityJson => write!(f, "application/activity+json"),
+			Mime::ApplicationAifCbor => write!(f, "application/aif+cbor"),
+			Mime::ApplicationAifJson => write!(f, "application/aif+json"),
+			Mime::ApplicationAltoCdniJson => write!(f, "application/alto-cdni+json"),
+			Mime::ApplicationAltoCdnifilterJson => write!(f, "application/alto-cdnifilter+json"),
+			Mime::ApplicationAltoCostmapJson => write!(f, "application/alto-costmap+json"),
+			Mime::ApplicationAltoCostmapfilterJson => write!(f, "application/alto-costmapfilter+json"),
+			Mime::ApplicationAltoDirectoryJson => write!(f, "application/alto-directory+json"),
+			Mime::ApplicationAltoEndpointpropJson => write!(f, "application/alto-endpointprop+json"),
+			Mime::ApplicationAltoEndpointpropparamsJson => write!(f, "application/alto-endpointpropparams+json"),
+			Mime::ApplicationAltoEndpointcostJson => write!(f, "application/alto-endpointcost+json"),
+			Mime::ApplicationAltoEndpointcostparamsJson => write!(f, "application/alto-endpointcostparams+json"),
+			Mime::ApplicationAltoErrorJson => write!(f, "application/alto-error+json"),
+			Mime::ApplicationAltoNetworkmapfilterJson => write!(f, "application/alto-networkmapfilter+json"),
+			Mime::ApplicationAltoNetworkmapJson => write!(f, "application/alto-networkmap+json"),
+			Mime::ApplicationAltoPropmapJson => write!(f, "application/alto-propmap+json"),
+			Mime::ApplicationAltoPropmapparamsJson => write!(f, "application/alto-propmapparams+json"),
+			Mime::ApplicationAltoUpdatestreamcontrolJson => write!(f, "application/alto-updatestreamcontrol+json"),
+			Mime::ApplicationAltoUpdatestreamparamsJson => write!(f, "application/alto-updatestreamparams+json"),
+			Mime::ApplicationAml => write!(f, "application/AML"),
+			Mime::ApplicationAndrewInset => write!(f, "application/andrew-inset"),
+			Mime::ApplicationApplefile => write!(f, "application/applefile"),
+			Mime::ApplicationAtJwt => write!(f, "application/at+jwt"),
+			Mime::ApplicationAtf => write!(f, "application/ATF"),
+			Mime::ApplicationAtfx => write!(f, "application/ATFX"),
+			Mime::ApplicationAtomXml => write!(f, "application/atom+xml"),
+			Mime::ApplicationAtomcatXml => write!(f, "application/atomcat+xml"),
+			Mime::ApplicationAtomdeletedXml => write!(f, "application/atomdeleted+xml"),
+			Mime::ApplicationAtomicmail => write!(f, "application/atomicmail"),
+			Mime::ApplicationAtomsvcXml => write!(f, "application/atomsvc+xml"),
+			Mime::ApplicationAtscDwdXml => write!(f, "application/atsc-dwd+xml"),
+			Mime::ApplicationAtscDynamicEventMessage => write!(f, "application/atsc-dynamic-event-message"),
+			Mime::ApplicationAtscHeldXml => write!(f, "application/atsc-held+xml"),
+			Mime::ApplicationAtscRdtJson => write!(f, "application/atsc-rdt+json"),
+			Mime::ApplicationAtscRsatXml => write!(f, "application/atsc-rsat+xml"),
+			Mime::ApplicationAtxml => write!(f, "application/ATXML"),
+			Mime::ApplicationAuthPolicyXml => write!(f, "application/auth-policy+xml"),
+			Mime::ApplicationAutomationmlAmlXml => write!(f, "application/automationml-aml+xml"),
+			Mime::ApplicationAutomationmlAmlxZip => write!(f, "application/automationml-amlx+zip"),
+			Mime::ApplicationBacnetXddZip => write!(f, "application/bacnet-xdd+zip"),
+			Mime::ApplicationBatchSmtp => write!(f, "application/batch-SMTP"),
+			Mime::ApplicationBeepXml => write!(f, "application/beep+xml"),
+			Mime::ApplicationCalendarJson => write!(f, "application/calendar+json"),
+			Mime::ApplicationCalendarXml => write!(f, "application/calendar+xml"),
+			Mime::ApplicationCallCompletion => write!(f, "application/call-completion"),
+			Mime::ApplicationCals1840 => write!(f, "application/CALS-1840"),
+			Mime::ApplicationCaptiveJson => write!(f, "application/captive+json"),
+			Mime::ApplicationCbor => write!(f, "application/cbor"),
+			Mime::ApplicationCborSeq => write!(f, "application/cbor-seq"),
+			Mime::ApplicationCccex => write!(f, "application/cccex"),
+			Mime::ApplicationCcmpXml => write!(f, "application/ccmp+xml"),
+			Mime::ApplicationCcxmlXml => write!(f, "application/ccxml+xml"),
+			Mime::ApplicationCdaXml => write!(f, "application/cda+xml"),
+			Mime::ApplicationCdfxXml => write!(f, "application/CDFX+XML"),
+			Mime::ApplicationCdmiCapability => write!(f, "application/cdmi-capability"),
+			Mime::ApplicationCdmiContainer => write!(f, "application/cdmi-container"),
+			Mime::ApplicationCdmiDomain => write!(f, "application/cdmi-domain"),
+			Mime::ApplicationCdmiObject => write!(f, "application/cdmi-object"),
+			Mime::ApplicationCdmiQueue => write!(f, "application/cdmi-queue"),
+			Mime::ApplicationCdni => write!(f, "application/cdni"),
+			Mime::ApplicationCea => write!(f, "application/CEA"),
+			Mime::ApplicationCea2018Xml => write!(f, "application/cea-2018+xml"),
+			Mime::ApplicationCellmlXml => write!(f, "application/cellml+xml"),
+			Mime::ApplicationCfw => write!(f, "application/cfw"),
+			Mime::ApplicationCityJson => write!(f, "application/city+json"),
+			Mime::ApplicationClr => write!(f, "application/clr"),
+			Mime::ApplicationClueInfoXml => write!(f, "application/clue_info+xml"),
+			Mime::ApplicationClueXml => write!(f, "application/clue+xml"),
+			Mime::ApplicationCms => write!(f, "application/cms"),
+			Mime::ApplicationCnrpXml => write!(f, "application/cnrp+xml"),
+			Mime::ApplicationCoapGroupJson => write!(f, "application/coap-group+json"),
+			Mime::ApplicationCoapPayload => write!(f, "application/coap-payload"),
+			Mime::ApplicationCommonground => write!(f, "application/commonground"),
+			Mime::ApplicationConciseProblemDetailsCbor => write!(f, "application/concise-problem-details+cbor"),
+			Mime::ApplicationConferenceInfoXml => write!(f, "application/conference-info+xml"),
+			Mime::ApplicationCplXml => write!(f, "application/cpl+xml"),
+			Mime::ApplicationCose => write!(f, "application/cose"),
+			Mime::ApplicationCoseKey => write!(f, "application/cose-key"),
+			Mime::ApplicationCoseKeySet => write!(f, "application/cose-key-set"),
+			Mime::ApplicationCoseX509 => write!(f, "application/cose-x509"),
+			Mime::ApplicationCsrattrs => write!(f, "application/csrattrs"),
+			Mime::ApplicationCstaXml => write!(f, "application/csta+xml"),
+			Mime::ApplicationCstadataXml => write!(f, "application/CSTAdata+xml"),
+			Mime::ApplicationCsvmJson => write!(f, "application/csvm+json"),
+			Mime::ApplicationCwl => write!(f, "application/cwl"),
+			Mime::ApplicationCwlJson => write!(f, "application/cwl+json"),
+			Mime::ApplicationCwt => write!(f, "application/cwt"),
+			Mime::ApplicationCybercash => write!(f, "application/cybercash"),
+			Mime::ApplicationDashXml => write!(f, "application/dash+xml"),
+			Mime::ApplicationDashPatchXml => write!(f, "application/dash-patch+xml"),
+			Mime::ApplicationDashdelta => write!(f, "application/dashdelta"),
+			Mime::ApplicationDavmountXml => write!(f, "application/davmount+xml"),
+			Mime::ApplicationDcaRft => write!(f, "application/dca-rft"),
+			Mime::ApplicationDcd => write!(f, "application/DCD"),
+			Mime::ApplicationDecDx => write!(f, "application/dec-dx"),
+			Mime::ApplicationDialogInfoXml => write!(f, "application/dialog-info+xml"),
+			Mime::ApplicationDicom => write!(f, "application/dicom"),
+			Mime::ApplicationDicomJson => write!(f, "application/dicom+json"),
+			Mime::ApplicationDicomXml => write!(f, "application/dicom+xml"),
+			Mime::ApplicationDii => write!(f, "application/DII"),
+			Mime::ApplicationDit => write!(f, "application/DIT"),
+			Mime::ApplicationDns => write!(f, "application/dns"),
+			Mime::ApplicationDnsJson => write!(f, "application/dns+json"),
+			Mime::ApplicationDnsMessage => write!(f, "application/dns-message"),
+			Mime::ApplicationDotsCbor => write!(f, "application/dots+cbor"),
+			Mime::ApplicationDpopJwt => write!(f, "application/dpop+jwt"),
+			Mime::ApplicationDskppXml => write!(f, "application/dskpp+xml"),
+			Mime::ApplicationDsscDer => write!(f, "application/dssc+der"),
+			Mime::ApplicationDsscXml => write!(f, "application/dssc+xml"),
+			Mime::ApplicationDvcs => write!(f, "application/dvcs"),
+			Mime::ApplicationEdiConsent => write!(f, "application/EDI-consent"),
+			Mime::ApplicationEdifact => write!(f, "application/EDIFACT"),
+			Mime::ApplicationEdiX12 => write!(f, "application/EDI-X12"),
+			Mime::ApplicationEfi => write!(f, "application/efi"),
+			Mime::ApplicationElmJson => write!(f, "application/elm+json"),
+			Mime::ApplicationElmXml => write!(f, "application/elm+xml"),
+			Mime::ApplicationEmergencycalldataCapXml => write!(f, "application/EmergencyCallData.cap+xml"),
+			Mime::ApplicationEmergencycalldataCommentXml => write!(f, "application/EmergencyCallData.Comment+xml"),
+			Mime::ApplicationEmergencycalldataControlXml => write!(f, "application/EmergencyCallData.Control+xml"),
+			Mime::ApplicationEmergencycalldataDeviceinfoXml => write!(f, "application/EmergencyCallData.DeviceInfo+xml"),
+			Mime::ApplicationEmergencycalldataEcallMsd => write!(f, "application/EmergencyCallData.eCall.MSD"),
+			Mime::ApplicationEmergencycalldataLegacyesnJson => write!(f, "application/EmergencyCallData.LegacyESN+json"),
+			Mime::ApplicationEmergencycalldataProviderinfoXml => write!(f, "application/EmergencyCallData.ProviderInfo+xml"),
+			Mime::ApplicationEmergencycalldataServiceinfoXml => write!(f, "application/EmergencyCallData.ServiceInfo+xml"),
+			Mime::ApplicationEmergencycalldataSubscriberinfoXml => write!(f, "application/EmergencyCallData.SubscriberInfo+xml"),
+			Mime::ApplicationEmergencycalldataVedsXml => write!(f, "application/EmergencyCallData.VEDS+xml"),
+			Mime::ApplicationEmmaXml => write!(f, "application/emma+xml"),
+			Mime::ApplicationEmotionmlXml => write!(f, "application/emotionml+xml"),
+			Mime::ApplicationEncaprtp => write!(f, "application/encaprtp"),
+			Mime::ApplicationEppXml => write!(f, "application/epp+xml"),
+			Mime::ApplicationEpubZip => write!(f, "application/epub+zip"),
+			Mime::ApplicationEshop => write!(f, "application/eshop"),
+			Mime::ApplicationExample => write!(f, "application/example"),
+			Mime::ApplicationExi => write!(f, "application/exi"),
+			Mime::ApplicationExpectCtReportJson => write!(f, "application/expect-ct-report+json"),
+			Mime::ApplicationExpress => write!(f, "application/express"),
+			Mime::ApplicationFastinfoset => write!(f, "application/fastinfoset"),
+			Mime::ApplicationFastsoap => write!(f, "application/fastsoap"),
+			Mime::ApplicationFdf => write!(f, "application/fdf"),
+			Mime::ApplicationFdtXml => write!(f, "application/fdt+xml"),
+			Mime::ApplicationFhirJson => write!(f, "application/fhir+json"),
+			Mime::ApplicationFhirXml => write!(f, "application/fhir+xml"),
+			Mime::ApplicationFits => write!(f, "application/fits"),
+			Mime::ApplicationFlexfec => write!(f, "application/flexfec"),
+			Mime::ApplicationFontTdpfr => write!(f, "application/font-tdpfr"),
+			Mime::ApplicationFrameworkAttributesXml => write!(f, "application/framework-attributes+xml"),
+			Mime::ApplicationGeoJson => write!(f, "application/geo+json"),
+			Mime::ApplicationGeoJsonSeq => write!(f, "application/geo+json-seq"),
+			Mime::ApplicationGeopackageSqlite3 => write!(f, "application/geopackage+sqlite3"),
+			Mime::ApplicationGeoxacmlXml => write!(f, "application/geoxacml+xml"),
+			Mime::ApplicationGltfBuffer => write!(f, "application/gltf-buffer"),
+			Mime::ApplicationGmlXml => write!(f, "application/gml+xml"),
+			Mime::ApplicationGzip => write!(f, "application/gzip"),
+			Mime::ApplicationH224 => write!(f, "application/H224"),
+			Mime::ApplicationHeldXml => write!(f, "application/held+xml"),
+			Mime::ApplicationHl7v2Xml => write!(f, "application/hl7v2+xml"),
+			Mime::ApplicationHttp => write!(f, "application/http"),
+			Mime::ApplicationHyperstudio => write!(f, "application/hyperstudio"),
+			Mime::ApplicationIbeKeyRequestXml => write!(f, "application/ibe-key-request+xml"),
+			Mime::ApplicationIbePkgReplyXml => write!(f, "application/ibe-pkg-reply+xml"),
+			Mime::ApplicationIbePpData => write!(f, "application/ibe-pp-data"),
+			Mime::ApplicationIges => write!(f, "application/iges"),
+			Mime::ApplicationImIscomposingXml => write!(f, "application/im-iscomposing+xml"),
+			Mime::ApplicationIndex => write!(f, "application/index"),
+			Mime::ApplicationIndexCmd => write!(f, "application/index.cmd"),
+			Mime::ApplicationIndexObj => write!(f, "application/index.obj"),
+			Mime::ApplicationIndexResponse => write!(f, "application/index.response"),
+			Mime::ApplicationIndexVnd => write!(f, "application/index.vnd"),
+			Mime::ApplicationInkmlXml => write!(f, "application/inkml+xml"),
+			Mime::ApplicationIotp => write!(f, "application/IOTP"),
+			Mime::ApplicationIpfix => write!(f, "application/ipfix"),
+			Mime::ApplicationIpp => write!(f, "application/ipp"),
+			Mime::ApplicationIsup => write!(f, "application/ISUP"),
+			Mime::ApplicationItsXml => write!(f, "application/its+xml"),
+			Mime::ApplicationJavaArchive => write!(f, "application/java-archive"),
+			Mime::ApplicationJf2feedJson => write!(f, "application/jf2feed+json"),
+			Mime::ApplicationJose => write!(f, "application/jose"),
+			Mime::ApplicationJoseJson => write!(f, "application/jose+json"),
+			Mime::ApplicationJrdJson => write!(f, "application/jrd+json"),
+			Mime::ApplicationJscalendarJson => write!(f, "application/jscalendar+json"),
+			Mime::ApplicationJson => write!(f, "application/json"),
+			Mime::ApplicationJsonPatchJson => write!(f, "application/json-patch+json"),
+			Mime::ApplicationJsonSeq => write!(f, "application/json-seq"),
+			Mime::ApplicationJwkJson => write!(f, "application/jwk+json"),
+			Mime::ApplicationJwkSetJson => write!(f, "application/jwk-set+json"),
+			Mime::ApplicationJwt => write!(f, "application/jwt"),
+			Mime::ApplicationKpmlRequestXml => write!(f, "application/kpml-request+xml"),
+			Mime::ApplicationKpmlResponseXml => write!(f, "application/kpml-response+xml"),
+			Mime::ApplicationLdJson => write!(f, "application/ld+json"),
+			Mime::ApplicationLgrXml => write!(f, "application/lgr+xml"),
+			Mime::ApplicationLinkFormat => write!(f, "application/link-format"),
+			Mime::ApplicationLinkset => write!(f, "application/linkset"),
+			Mime::ApplicationLinksetJson => write!(f, "application/linkset+json"),
+			Mime::ApplicationLoadControlXml => write!(f, "application/load-control+xml"),
+			Mime::ApplicationLogoutJwt => write!(f, "application/logout+jwt"),
+			Mime::ApplicationLostXml => write!(f, "application/lost+xml"),
+			Mime::ApplicationLostsyncXml => write!(f, "application/lostsync+xml"),
+			Mime::ApplicationLpfZip => write!(f, "application/lpf+zip"),
+			Mime::ApplicationLxf => write!(f, "application/LXF"),
+			Mime::ApplicationMacBinhex40 => write!(f, "application/mac-binhex40"),
+			Mime::ApplicationMacwriteii => write!(f, "application/macwriteii"),
+			Mime::ApplicationMadsXml => write!(f, "application/mads+xml"),
+			Mime::ApplicationManifestJson => write!(f, "application/manifest+json"),
+			Mime::ApplicationMarc => write!(f, "application/marc"),
+			Mime::ApplicationMarcxmlXml => write!(f, "application/marcxml+xml"),
+			Mime::ApplicationMathematica => write!(f, "application/mathematica"),
+			Mime::ApplicationMathmlXml => write!(f, "application/mathml+xml"),
+			Mime::ApplicationMathmlContentXml => write!(f, "application/mathml-content+xml"),
+			Mime::ApplicationMathmlPresentationXml => write!(f, "application/mathml-presentation+xml"),
+			Mime::ApplicationMbmsAssociatedProcedureDescriptionXml => write!(f, "application/mbms-associated-procedure-description+xml"),
+			Mime::ApplicationMbmsDeregisterXml => write!(f, "application/mbms-deregister+xml"),
+			Mime::ApplicationMbmsEnvelopeXml => write!(f, "application/mbms-envelope+xml"),
+			Mime::ApplicationMbmsMskResponseXml => write!(f, "application/mbms-msk-response+xml"),
+			Mime::ApplicationMbmsMskXml => write!(f, "application/mbms-msk+xml"),
+			Mime::ApplicationMbmsProtectionDescriptionXml => write!(f, "application/mbms-protection-description+xml"),
+			Mime::ApplicationMbmsReceptionReportXml => write!(f, "application/mbms-reception-report+xml"),
+			Mime::ApplicationMbmsRegisterResponseXml => write!(f, "application/mbms-register-response+xml"),
+			Mime::ApplicationMbmsRegisterXml => write!(f, "application/mbms-register+xml"),
+			Mime::ApplicationMbmsScheduleXml => write!(f, "application/mbms-schedule+xml"),
+			Mime::ApplicationMbmsUserServiceDescriptionXml => write!(f, "application/mbms-user-service-description+xml"),
+			Mime::ApplicationMbox => write!(f, "application/mbox"),
+			Mime::ApplicationMediaControlXml => write!(f, "application/media_control+xml"),
+			Mime::ApplicationMediaPolicyDatasetXml => write!(f, "application/media-policy-dataset+xml"),
+			Mime::ApplicationMediaservercontrolXml => write!(f, "application/mediaservercontrol+xml"),
+			Mime::ApplicationMergePatchJson => write!(f, "application/merge-patch+json"),
+			Mime::ApplicationMetalink4Xml => write!(f, "application/metalink4+xml"),
+			Mime::ApplicationMetsXml => write!(f, "application/mets+xml"),
+			Mime::ApplicationMf4 => write!(f, "application/MF4"),
+			Mime::ApplicationMikey => write!(f, "application/mikey"),
+			Mime::ApplicationMipc => write!(f, "application/mipc"),
+			Mime::ApplicationMissingBlocksCborSeq => write!(f, "application/missing-blocks+cbor-seq"),
+			Mime::ApplicationMmtAeiXml => write!(f, "application/mmt-aei+xml"),
+			Mime::ApplicationMmtUsdXml => write!(f, "application/mmt-usd+xml"),
+			Mime::ApplicationModsXml => write!(f, "application/mods+xml"),
+			Mime::ApplicationMossKeys => write!(f, "application/moss-keys"),
+			Mime::ApplicationMossSignature => write!(f, "application/moss-signature"),
+			Mime::ApplicationMosskeyData => write!(f, "application/mosskey-data"),
+			Mime::ApplicationMosskeyRequest => write!(f, "application/mosskey-request"),
+			Mime::ApplicationMp21 => write!(f, "application/mp21"),
+			Mime::ApplicationMp4 => write!(f, "application/mp4"),
+			Mime::ApplicationMpeg4Generic => write!(f, "application/mpeg4-generic"),
+			Mime::ApplicationMpeg4Iod => write!(f, "application/mpeg4-iod"),
+			Mime::ApplicationMpeg4IodXmt => write!(f, "application/mpeg4-iod-xmt"),
+			Mime::ApplicationMrbConsumerXml => write!(f, "application/mrb-consumer+xml"),
+			Mime::ApplicationMrbPublishXml => write!(f, "application/mrb-publish+xml"),
+			Mime::ApplicationMscIvrXml => write!(f, "application/msc-ivr+xml"),
+			Mime::ApplicationMscMixerXml => write!(f, "application/msc-mixer+xml"),
+			Mime::ApplicationMsword => write!(f, "application/msword"),
+			Mime::ApplicationMudJson => write!(f, "application/mud+json"),
+			Mime::ApplicationMultipartCore => write!(f, "application/multipart-core"),
+			Mime::ApplicationMxf => write!(f, "application/mxf"),
+			Mime::ApplicationNQuads => write!(f, "application/n-quads"),
+			Mime::ApplicationNTriples => write!(f, "application/n-triples"),
+			Mime::ApplicationNasdata => write!(f, "application/nasdata"),
+			Mime::ApplicationNewsCheckgroups => write!(f, "application/news-checkgroups"),
+			Mime::ApplicationNewsGroupinfo => write!(f, "application/news-groupinfo"),
+			Mime::ApplicationNewsTransmission => write!(f, "application/news-transmission"),
+			Mime::ApplicationNlsmlXml => write!(f, "application/nlsml+xml"),
+			Mime::ApplicationNode => write!(f, "application/node"),
+			Mime::ApplicationNss => write!(f, "application/nss"),
+			Mime::ApplicationOauthAuthzReqJwt => write!(f, "application/oauth-authz-req+jwt"),
+			Mime::ApplicationObliviousDnsMessage => write!(f, "application/oblivious-dns-message"),
+			Mime::ApplicationOcspRequest => write!(f, "application/ocsp-request"),
+			Mime::ApplicationOcspResponse => write!(f, "application/ocsp-response"),
+			Mime::ApplicationOctetStream => write!(f, "application/octet-stream"),
+			Mime::ApplicationOda => write!(f, "application/ODA"),
+			Mime::ApplicationOdmXml => write!(f, "application/odm+xml"),
+			Mime::ApplicationOdx => write!(f, "application/ODX"),
+			Mime::ApplicationOebpsPackageXml => write!(f, "application/oebps-package+xml"),
+			Mime::ApplicationOgg => write!(f, "application/ogg"),
+			Mime::ApplicationOhttpKeys => write!(f, "application/ohttp-keys"),
+			Mime::ApplicationOpcNodesetXml => write!(f, "application/opc-nodeset+xml"),
+			Mime::ApplicationOscore => write!(f, "application/oscore"),
+			Mime::ApplicationOxps => write!(f, "application/oxps"),
+			Mime::ApplicationP21 => write!(f, "application/p21"),
+			Mime::ApplicationP21Zip => write!(f, "application/p21+zip"),
+			Mime::ApplicationP2pOverlayXml => write!(f, "application/p2p-overlay+xml"),
+			Mime::ApplicationParityfec => write!(f, "application/parityfec"),
+			Mime::ApplicationPassport => write!(f, "application/passport"),
+			Mime::ApplicationPatchOpsErrorXml => write!(f, "application/patch-ops-error+xml"),
+			Mime::ApplicationPdf => write!(f, "application/pdf"),
+			Mime::ApplicationPdx => write!(f, "application/PDX"),
+			Mime::ApplicationPemCertificateChain => write!(f, "application/pem-certificate-chain"),
+			Mime::ApplicationPgpEncrypted => write!(f, "application/pgp-encrypted"),
+			Mime::ApplicationPgpKeys => write!(f, "application/pgp-keys"),
+			Mime::ApplicationPgpSignature => write!(f, "application/pgp-signature"),
+			Mime::ApplicationPidfDiffXml => write!(f, "application/pidf-diff+xml"),
+			Mime::ApplicationPidfXml => write!(f, "application/pidf+xml"),
+			Mime::ApplicationPkcs10 => write!(f, "application/pkcs10"),
+			Mime::ApplicationPkcs7Mime => write!(f, "application/pkcs7-mime"),
+			Mime::ApplicationPkcs7Signature => write!(f, "application/pkcs7-signature"),
+			Mime::ApplicationPkcs8 => write!(f, "application/pkcs8"),
+			Mime::ApplicationPkcs8Encrypted => write!(f, "application/pkcs8-encrypted"),
+			Mime::ApplicationPkcs12 => write!(f, "application/pkcs12"),
+			Mime::ApplicationPkixAttrCert => write!(f, "application/pkix-attr-cert"),
+			Mime::ApplicationPkixCert => write!(f, "application/pkix-cert"),
+			Mime::ApplicationPkixCrl => write!(f, "application/pkix-crl"),
+			Mime::ApplicationPkixPkipath => write!(f, "application/pkix-pkipath"),
+			Mime::ApplicationPkixcmp => write!(f, "application/pkixcmp"),
+			Mime::ApplicationPlsXml => write!(f, "application/pls+xml"),
+			Mime::ApplicationPocSettingsXml => write!(f, "application/poc-settings+xml"),
+			Mime::ApplicationPostscript => write!(f, "application/postscript"),
+			Mime::ApplicationPpspTrackerJson => write!(f, "application/ppsp-tracker+json"),
+			Mime::ApplicationProblemJson => write!(f, "application/problem+json"),
+			Mime::ApplicationProblemXml => write!(f, "application/problem+xml"),
+			Mime::ApplicationProvenanceXml => write!(f, "application/provenance+xml"),
+			Mime::ApplicationPrsAlvestrandTitraxSheet => write!(f, "application/prs.alvestrand.titrax-sheet"),
+			Mime::ApplicationPrsCww => write!(f, "application/prs.cww"),
+			Mime::ApplicationPrsCyn => write!(f, "application/prs.cyn"),
+			Mime::ApplicationPrsHpubZip => write!(f, "application/prs.hpub+zip"),
+			Mime::ApplicationPrsImpliedDocumentXml => write!(f, "application/prs.implied-document+xml"),
+			Mime::ApplicationPrsImpliedExecutable => write!(f, "application/prs.implied-executable"),
+			Mime::ApplicationPrsImpliedStructure => write!(f, "application/prs.implied-structure"),
+			Mime::ApplicationPrsNprend => write!(f, "application/prs.nprend"),
+			Mime::ApplicationPrsPlucker => write!(f, "application/prs.plucker"),
+			Mime::ApplicationPrsRdfXmlCrypt => write!(f, "application/prs.rdf-xml-crypt"),
+			Mime::ApplicationPrsXsfXml => write!(f, "application/prs.xsf+xml"),
+			Mime::ApplicationPskcXml => write!(f, "application/pskc+xml"),
+			Mime::ApplicationPvdJson => write!(f, "application/pvd+json"),
+			Mime::ApplicationRdfXml => write!(f, "application/rdf+xml"),
+			Mime::ApplicationRouteApdXml => write!(f, "application/route-apd+xml"),
+			Mime::ApplicationRouteSTsidXml => write!(f, "application/route-s-tsid+xml"),
+			Mime::ApplicationRouteUsdXml => write!(f, "application/route-usd+xml"),
+			Mime::ApplicationQsig => write!(f, "application/QSIG"),
+			Mime::ApplicationRaptorfec => write!(f, "application/raptorfec"),
+			Mime::ApplicationRdapJson => write!(f, "application/rdap+json"),
+			Mime::ApplicationReginfoXml => write!(f, "application/reginfo+xml"),
+			Mime::ApplicationRelaxNgCompactSyntax => write!(f, "application/relax-ng-compact-syntax"),
+			Mime::ApplicationReputonJson => write!(f, "application/reputon+json"),
+			Mime::ApplicationResourceListsDiffXml => write!(f, "application/resource-lists-diff+xml"),
+			Mime::ApplicationResourceListsXml => write!(f, "application/resource-lists+xml"),
+			Mime::ApplicationRfcXml => write!(f, "application/rfc+xml"),
+			Mime::ApplicationRiscos => write!(f, "application/riscos"),
+			Mime::ApplicationRlmiXml => write!(f, "application/rlmi+xml"),
+			Mime::ApplicationRlsServicesXml => write!(f, "application/rls-services+xml"),
+			Mime::ApplicationRpkiChecklist => write!(f, "application/rpki-checklist"),
+			Mime::ApplicationRpkiGhostbusters => write!(f, "application/rpki-ghostbusters"),
+			Mime::ApplicationRpkiManifest => write!(f, "application/rpki-manifest"),
+			Mime::ApplicationRpkiPublication => write!(f, "application/rpki-publication"),
+			Mime::ApplicationRpkiRoa => write!(f, "application/rpki-roa"),
+			Mime::ApplicationRpkiUpdown => write!(f, "application/rpki-updown"),
+			Mime::ApplicationRtf => write!(f, "application/rtf"),
+			Mime::ApplicationRtploopback => write!(f, "application/rtploopback"),
+			Mime::ApplicationRtx => write!(f, "application/rtx"),
+			Mime::ApplicationSamlassertionXml => write!(f, "application/samlassertion+xml"),
+			Mime::ApplicationSamlmetadataXml => write!(f, "application/samlmetadata+xml"),
+			Mime::ApplicationSarifExternalPropertiesJson => write!(f, "application/sarif-external-properties+json"),
+			Mime::ApplicationSarifJson => write!(f, "application/sarif+json"),
+			Mime::ApplicationSbe => write!(f, "application/sbe"),
+			Mime::ApplicationSbmlXml => write!(f, "application/sbml+xml"),
+			Mime::ApplicationScaipXml => write!(f, "application/scaip+xml"),
+			Mime::ApplicationScimJson => write!(f, "application/scim+json"),
+			Mime::ApplicationScvpCvRequest => write!(f, "application/scvp-cv-request"),
+			Mime::ApplicationScvpCvResponse => write!(f, "application/scvp-cv-response"),
+			Mime::ApplicationScvpVpRequest => write!(f, "application/scvp-vp-request"),
+			Mime::ApplicationScvpVpResponse => write!(f, "application/scvp-vp-response"),
+			Mime::ApplicationSdp => write!(f, "application/sdp"),
+			Mime::ApplicationSeceventJwt => write!(f, "application/secevent+jwt"),
+			Mime::ApplicationSenmlEtchCbor => write!(f, "application/senml-etch+cbor"),
+			Mime::ApplicationSenmlEtchJson => write!(f, "application/senml-etch+json"),
+			Mime::ApplicationSenmlExi => write!(f, "application/senml-exi"),
+			Mime::ApplicationSenmlCbor => write!(f, "application/senml+cbor"),
+			Mime::ApplicationSenmlJson => write!(f, "application/senml+json"),
+			Mime::ApplicationSenmlXml => write!(f, "application/senml+xml"),
+			Mime::ApplicationSensmlExi => write!(f, "application/sensml-exi"),
+			Mime::ApplicationSensmlCbor => write!(f, "application/sensml+cbor"),
+			Mime::ApplicationSensmlJson => write!(f, "application/sensml+json"),
+			Mime::ApplicationSensmlXml => write!(f, "application/sensml+xml"),
+			Mime::ApplicationSepExi => write!(f, "application/sep-exi"),
+			Mime::ApplicationSepXml => write!(f, "application/sep+xml"),
+			Mime::ApplicationSessionInfo => write!(f, "application/session-info"),
+			Mime::ApplicationSetPayment => write!(f, "application/set-payment"),
+			Mime::ApplicationSetPaymentInitiation => write!(f, "application/set-payment-initiation"),
+			Mime::ApplicationSetRegistration => write!(f, "application/set-registration"),
+			Mime::ApplicationSetRegistrationInitiation => write!(f, "application/set-registration-initiation"),
+			Mime::ApplicationSgml => write!(f, "application/SGML"),
+			Mime::ApplicationSgmlOpenCatalog => write!(f, "application/sgml-open-catalog"),
+			Mime::ApplicationShfXml => write!(f, "application/shf+xml"),
+			Mime::ApplicationSieve => write!(f, "application/sieve"),
+			Mime::ApplicationSimpleFilterXml => write!(f, "application/simple-filter+xml"),
+			Mime::ApplicationSimpleMessageSummary => write!(f, "application/simple-message-summary"),
+			Mime::ApplicationSimplesymbolcontainer => write!(f, "application/simpleSymbolContainer"),
+			Mime::ApplicationSipc => write!(f, "application/sipc"),
+			Mime::ApplicationSlate => write!(f, "application/slate"),
+			Mime::ApplicationSmilXml => write!(f, "application/smil+xml"),
+			Mime::ApplicationSmpte336m => write!(f, "application/smpte336m"),
+			Mime::ApplicationSoapFastinfoset => write!(f, "application/soap+fastinfoset"),
+			Mime::ApplicationSoapXml => write!(f, "application/soap+xml"),
+			Mime::ApplicationSparqlQuery => write!(f, "application/sparql-query"),
+			Mime::ApplicationSpdxJson => write!(f, "application/spdx+json"),
+			Mime::ApplicationSparqlResultsXml => write!(f, "application/sparql-results+xml"),
+			Mime::ApplicationSpiritsEventXml => write!(f, "application/spirits-event+xml"),
+			Mime::ApplicationSql => write!(f, "application/sql"),
+			Mime::ApplicationSrgs => write!(f, "application/srgs"),
+			Mime::ApplicationSrgsXml => write!(f, "application/srgs+xml"),
+			Mime::ApplicationSruXml => write!(f, "application/sru+xml"),
+			Mime::ApplicationSsmlXml => write!(f, "application/ssml+xml"),
+			Mime::ApplicationStixJson => write!(f, "application/stix+json"),
+			Mime::ApplicationSwidCbor => write!(f, "application/swid+cbor"),
+			Mime::ApplicationSwidXml => write!(f, "application/swid+xml"),
+			Mime::ApplicationTampApexUpdate => write!(f, "application/tamp-apex-update"),
+			Mime::ApplicationTampApexUpdateConfirm => write!(f, "application/tamp-apex-update-confirm"),
+			Mime::ApplicationTampCommunityUpdate => write!(f, "application/tamp-community-update"),
+			Mime::ApplicationTampCommunityUpdateConfirm => write!(f, "application/tamp-community-update-confirm"),
+			Mime::ApplicationTampError => write!(f, "application/tamp-error"),
+			Mime::ApplicationTampSequenceAdjust => write!(f, "application/tamp-sequence-adjust"),
+			Mime::ApplicationTampSequenceAdjustConfirm => write!(f, "application/tamp-sequence-adjust-confirm"),
+			Mime::ApplicationTampStatusQuery => write!(f, "application/tamp-status-query"),
+			Mime::ApplicationTampStatusResponse => write!(f, "application/tamp-status-response"),
+			Mime::ApplicationTampUpdate => write!(f, "application/tamp-update"),
+			Mime::ApplicationTampUpdateConfirm => write!(f, "application/tamp-update-confirm"),
+			Mime::ApplicationTaxiiJson => write!(f, "application/taxii+json"),
+			Mime::ApplicationTdJson => write!(f, "application/td+json"),
+			Mime::ApplicationTeiXml => write!(f, "application/tei+xml"),
+			Mime::ApplicationTetraIsi => write!(f, "application/TETRA_ISI"),
+			Mime::ApplicationThraudXml => write!(f, "application/thraud+xml"),
+			Mime::ApplicationTimestampQuery => write!(f, "application/timestamp-query"),
+			Mime::ApplicationTimestampReply => write!(f, "application/timestamp-reply"),
+			Mime::ApplicationTimestampedData => write!(f, "application/timestamped-data"),
+			Mime::ApplicationTlsrptGzip => write!(f, "application/tlsrpt+gzip"),
+			Mime::ApplicationTlsrptJson => write!(f, "application/tlsrpt+json"),
+			Mime::ApplicationTmJson => write!(f, "application/tm+json"),
+			Mime::ApplicationTnauthlist => write!(f, "application/tnauthlist"),
+			Mime::ApplicationTokenIntrospectionJwt => write!(f, "application/token-introspection+jwt"),
+			Mime::ApplicationTrickleIceSdpfrag => write!(f, "application/trickle-ice-sdpfrag"),
+			Mime::ApplicationTrig => write!(f, "application/trig"),
+			Mime::ApplicationTtmlXml => write!(f, "application/ttml+xml"),
+			Mime::ApplicationTveTrigger => write!(f, "application/tve-trigger"),
+			Mime::ApplicationTzif => write!(f, "application/tzif"),
+			Mime::ApplicationTzifLeap => write!(f, "application/tzif-leap"),
+			Mime::ApplicationUlpfec => write!(f, "application/ulpfec"),
+			Mime::ApplicationUrcGrpsheetXml => write!(f, "application/urc-grpsheet+xml"),
+			Mime::ApplicationUrcRessheetXml => write!(f, "application/urc-ressheet+xml"),
+			Mime::ApplicationUrcTargetdescXml => write!(f, "application/urc-targetdesc+xml"),
+			Mime::ApplicationUrcUisocketdescXml => write!(f, "application/urc-uisocketdesc+xml"),
+			Mime::ApplicationVcardJson => write!(f, "application/vcard+json"),
+			Mime::ApplicationVcardXml => write!(f, "application/vcard+xml"),
+			Mime::ApplicationVemmi => write!(f, "application/vemmi"),
+			Mime::ApplicationVnd1000mindsDecisionModelXml => write!(f, "application/vnd.1000minds.decision-model+xml"),
+			Mime::ApplicationVnd1ob => write!(f, "application/vnd.1ob"),
+			Mime::ApplicationVnd3gpp5gnas => write!(f, "application/vnd.3gpp.5gnas"),
+			Mime::ApplicationVnd3gppAccessTransferEventsXml => write!(f, "application/vnd.3gpp.access-transfer-events+xml"),
+			Mime::ApplicationVnd3gppBsfXml => write!(f, "application/vnd.3gpp.bsf+xml"),
+			Mime::ApplicationVnd3gppCrsXml => write!(f, "application/vnd.3gpp.crs+xml"),
+			Mime::ApplicationVnd3gppCurrentLocationDiscoveryXml => write!(f, "application/vnd.3gpp.current-location-discovery+xml"),
+			Mime::ApplicationVnd3gppGmopXml => write!(f, "application/vnd.3gpp.GMOP+xml"),
+			Mime::ApplicationVnd3gppGtpc => write!(f, "application/vnd.3gpp.gtpc"),
+			Mime::ApplicationVnd3gppInterworkingData => write!(f, "application/vnd.3gpp.interworking-data"),
+			Mime::ApplicationVnd3gppLpp => write!(f, "application/vnd.3gpp.lpp"),
+			Mime::ApplicationVnd3gppMcSignallingEar => write!(f, "application/vnd.3gpp.mc-signalling-ear"),
+			Mime::ApplicationVnd3gppMcdataAffiliationCommandXml => write!(f, "application/vnd.3gpp.mcdata-affiliation-command+xml"),
+			Mime::ApplicationVnd3gppMcdataInfoXml => write!(f, "application/vnd.3gpp.mcdata-info+xml"),
+			Mime::ApplicationVnd3gppMcdataMsgstoreCtrlRequestXml => write!(f, "application/vnd.3gpp.mcdata-msgstore-ctrl-request+xml"),
+			Mime::ApplicationVnd3gppMcdataPayload => write!(f, "application/vnd.3gpp.mcdata-payload"),
+			Mime::ApplicationVnd3gppMcdataRegroupXml => write!(f, "application/vnd.3gpp.mcdata-regroup+xml"),
+			Mime::ApplicationVnd3gppMcdataServiceConfigXml => write!(f, "application/vnd.3gpp.mcdata-service-config+xml"),
+			Mime::ApplicationVnd3gppMcdataSignalling => write!(f, "application/vnd.3gpp.mcdata-signalling"),
+			Mime::ApplicationVnd3gppMcdataUeConfigXml => write!(f, "application/vnd.3gpp.mcdata-ue-config+xml"),
+			Mime::ApplicationVnd3gppMcdataUserProfileXml => write!(f, "application/vnd.3gpp.mcdata-user-profile+xml"),
+			Mime::ApplicationVnd3gppMcpttAffiliationCommandXml => write!(f, "application/vnd.3gpp.mcptt-affiliation-command+xml"),
+			Mime::ApplicationVnd3gppMcpttFloorRequestXml => write!(f, "application/vnd.3gpp.mcptt-floor-request+xml"),
+			Mime::ApplicationVnd3gppMcpttInfoXml => write!(f, "application/vnd.3gpp.mcptt-info+xml"),
+			Mime::ApplicationVnd3gppMcpttLocationInfoXml => write!(f, "application/vnd.3gpp.mcptt-location-info+xml"),
+			Mime::ApplicationVnd3gppMcpttMbmsUsageInfoXml => write!(f, "application/vnd.3gpp.mcptt-mbms-usage-info+xml"),
+			Mime::ApplicationVnd3gppMcpttRegroupXml => write!(f, "application/vnd.3gpp.mcptt-regroup+xml"),
+			Mime::ApplicationVnd3gppMcpttServiceConfigXml => write!(f, "application/vnd.3gpp.mcptt-service-config+xml"),
+			Mime::ApplicationVnd3gppMcpttSignedXml => write!(f, "application/vnd.3gpp.mcptt-signed+xml"),
+			Mime::ApplicationVnd3gppMcpttUeConfigXml => write!(f, "application/vnd.3gpp.mcptt-ue-config+xml"),
+			Mime::ApplicationVnd3gppMcpttUeInitConfigXml => write!(f, "application/vnd.3gpp.mcptt-ue-init-config+xml"),
+			Mime::ApplicationVnd3gppMcpttUserProfileXml => write!(f, "application/vnd.3gpp.mcptt-user-profile+xml"),
+			Mime::ApplicationVnd3gppMcvideoAffiliationCommandXml => write!(f, "application/vnd.3gpp.mcvideo-affiliation-command+xml"),
+			Mime::ApplicationVnd3gppMcvideoInfoXml => write!(f, "application/vnd.3gpp.mcvideo-info+xml"),
+			Mime::ApplicationVnd3gppMcvideoLocationInfoXml => write!(f, "application/vnd.3gpp.mcvideo-location-info+xml"),
+			Mime::ApplicationVnd3gppMcvideoMbmsUsageInfoXml => write!(f, "application/vnd.3gpp.mcvideo-mbms-usage-info+xml"),
+			Mime::ApplicationVnd3gppMcvideoRegroupXml => write!(f, "application/vnd.3gpp.mcvideo-regroup+xml"),
+			Mime::ApplicationVnd3gppMcvideoServiceConfigXml => write!(f, "application/vnd.3gpp.mcvideo-service-config+xml"),
+			Mime::ApplicationVnd3gppMcvideoTransmissionRequestXml => write!(f, "application/vnd.3gpp.mcvideo-transmission-request+xml"),
+			Mime::ApplicationVnd3gppMcvideoUeConfigXml => write!(f, "application/vnd.3gpp.mcvideo-ue-config+xml"),
+			Mime::ApplicationVnd3gppMcvideoUserProfileXml => write!(f, "application/vnd.3gpp.mcvideo-user-profile+xml"),
+			Mime::ApplicationVnd3gppMidCallXml => write!(f, "application/vnd.3gpp.mid-call+xml"),
+			Mime::ApplicationVnd3gppNgap => write!(f, "application/vnd.3gpp.ngap"),
+			Mime::ApplicationVnd3gppPfcp => write!(f, "application/vnd.3gpp.pfcp"),
+			Mime::ApplicationVnd3gppPicBwLarge => write!(f, "application/vnd.3gpp.pic-bw-large"),
+			Mime::ApplicationVnd3gppPicBwSmall => write!(f, "application/vnd.3gpp.pic-bw-small"),
+			Mime::ApplicationVnd3gppPicBwVar => write!(f, "application/vnd.3gpp.pic-bw-var"),
+			Mime::ApplicationVnd3gppProsePc3aXml => write!(f, "application/vnd.3gpp-prose-pc3a+xml"),
+			Mime::ApplicationVnd3gppProsePc3achXml => write!(f, "application/vnd.3gpp-prose-pc3ach+xml"),
+			Mime::ApplicationVnd3gppProsePc3chXml => write!(f, "application/vnd.3gpp-prose-pc3ch+xml"),
+			Mime::ApplicationVnd3gppProsePc8Xml => write!(f, "application/vnd.3gpp-prose-pc8+xml"),
+			Mime::ApplicationVnd3gppProseXml => write!(f, "application/vnd.3gpp-prose+xml"),
+			Mime::ApplicationVnd3gppS1ap => write!(f, "application/vnd.3gpp.s1ap"),
+			Mime::ApplicationVnd3gppSealGroupDocXml => write!(f, "application/vnd.3gpp.seal-group-doc+xml"),
+			Mime::ApplicationVnd3gppSealInfoXml => write!(f, "application/vnd.3gpp.seal-info+xml"),
+			Mime::ApplicationVnd3gppSealLocationInfoXml => write!(f, "application/vnd.3gpp.seal-location-info+xml"),
+			Mime::ApplicationVnd3gppSealMbmsUsageInfoXml => write!(f, "application/vnd.3gpp.seal-mbms-usage-info+xml"),
+			Mime::ApplicationVnd3gppSealNetworkQosManagementInfoXml => write!(f, "application/vnd.3gpp.seal-network-QoS-management-info+xml"),
+			Mime::ApplicationVnd3gppSealUeConfigInfoXml => write!(f, "application/vnd.3gpp.seal-ue-config-info+xml"),
+			Mime::ApplicationVnd3gppSealUnicastInfoXml => write!(f, "application/vnd.3gpp.seal-unicast-info+xml"),
+			Mime::ApplicationVnd3gppSealUserProfileInfoXml => write!(f, "application/vnd.3gpp.seal-user-profile-info+xml"),
+			Mime::ApplicationVnd3gppSms => write!(f, "application/vnd.3gpp.sms"),
+			Mime::ApplicationVnd3gppSmsXml => write!(f, "application/vnd.3gpp.sms+xml"),
+			Mime::ApplicationVnd3gppSrvccExtXml => write!(f, "application/vnd.3gpp.srvcc-ext+xml"),
+			Mime::ApplicationVnd3gppSrvccInfoXml => write!(f, "application/vnd.3gpp.SRVCC-info+xml"),
+			Mime::ApplicationVnd3gppStateAndEventInfoXml => write!(f, "application/vnd.3gpp.state-and-event-info+xml"),
+			Mime::ApplicationVnd3gppUssdXml => write!(f, "application/vnd.3gpp.ussd+xml"),
+			Mime::ApplicationVnd3gppVaeInfoXml => write!(f, "application/vnd.3gpp.vae-info+xml"),
+			Mime::ApplicationVnd3gppV2xLocalServiceInformation => write!(f, "application/vnd.3gpp-v2x-local-service-information"),
+			Mime::ApplicationVnd3gpp2BcmcsinfoXml => write!(f, "application/vnd.3gpp2.bcmcsinfo+xml"),
+			Mime::ApplicationVnd3gpp2Sms => write!(f, "application/vnd.3gpp2.sms"),
+			Mime::ApplicationVnd3gpp2Tcap => write!(f, "application/vnd.3gpp2.tcap"),
+			Mime::ApplicationVnd3gppV2x => write!(f, "application/vnd.3gpp.v2x"),
+			Mime::ApplicationVnd3lightssoftwareImagescal => write!(f, "application/vnd.3lightssoftware.imagescal"),
+			Mime::ApplicationVnd3mPostItNotes => write!(f, "application/vnd.3M.Post-it-Notes"),
+			Mime::ApplicationVndAccpacSimplyAso => write!(f, "application/vnd.accpac.simply.aso"),
+			Mime::ApplicationVndAccpacSimplyImp => write!(f, "application/vnd.accpac.simply.imp"),
+			Mime::ApplicationVndAcmAddressxferJson => write!(f, "application/vnd.acm.addressxfer+json"),
+			Mime::ApplicationVndAcucobol => write!(f, "application/vnd.acucobol"),
+			Mime::ApplicationVndAcucorp => write!(f, "application/vnd.acucorp"),
+			Mime::ApplicationVndAdobeFlashMovie => write!(f, "application/vnd.adobe.flash.movie"),
+			Mime::ApplicationVndAdobeFormscentralFcdt => write!(f, "application/vnd.adobe.formscentral.fcdt"),
+			Mime::ApplicationVndAdobeFxp => write!(f, "application/vnd.adobe.fxp"),
+			Mime::ApplicationVndAdobePartialUpload => write!(f, "application/vnd.adobe.partial-upload"),
+			Mime::ApplicationVndAdobeXdpXml => write!(f, "application/vnd.adobe.xdp+xml"),
+			Mime::ApplicationVndAetherImp => write!(f, "application/vnd.aether.imp"),
+			Mime::ApplicationVndAfpcAfplinedata => write!(f, "application/vnd.afpc.afplinedata"),
+			Mime::ApplicationVndAfpcAfplinedataPagedef => write!(f, "application/vnd.afpc.afplinedata-pagedef"),
+			Mime::ApplicationVndAfpcCmocaCmresource => write!(f, "application/vnd.afpc.cmoca-cmresource"),
+			Mime::ApplicationVndAfpcFocaCharset => write!(f, "application/vnd.afpc.foca-charset"),
+			Mime::ApplicationVndAfpcFocaCodedfont => write!(f, "application/vnd.afpc.foca-codedfont"),
+			Mime::ApplicationVndAfpcFocaCodepage => write!(f, "application/vnd.afpc.foca-codepage"),
+			Mime::ApplicationVndAfpcModca => write!(f, "application/vnd.afpc.modca"),
+			Mime::ApplicationVndAfpcModcaCmtable => write!(f, "application/vnd.afpc.modca-cmtable"),
+			Mime::ApplicationVndAfpcModcaFormdef => write!(f, "application/vnd.afpc.modca-formdef"),
+			Mime::ApplicationVndAfpcModcaMediummap => write!(f, "application/vnd.afpc.modca-mediummap"),
+			Mime::ApplicationVndAfpcModcaObjectcontainer => write!(f, "application/vnd.afpc.modca-objectcontainer"),
+			Mime::ApplicationVndAfpcModcaOverlay => write!(f, "application/vnd.afpc.modca-overlay"),
+			Mime::ApplicationVndAfpcModcaPagesegment => write!(f, "application/vnd.afpc.modca-pagesegment"),
+			Mime::ApplicationVndAge => write!(f, "application/vnd.age"),
+			Mime::ApplicationVndAhBarcode => write!(f, "application/vnd.ah-barcode"),
+			Mime::ApplicationVndAheadSpace => write!(f, "application/vnd.ahead.space"),
+			Mime::ApplicationVndAirzipFilesecureAzf => write!(f, "application/vnd.airzip.filesecure.azf"),
+			Mime::ApplicationVndAirzipFilesecureAzs => write!(f, "application/vnd.airzip.filesecure.azs"),
+			Mime::ApplicationVndAmadeusJson => write!(f, "application/vnd.amadeus+json"),
+			Mime::ApplicationVndAmazonMobi8Ebook => write!(f, "application/vnd.amazon.mobi8-ebook"),
+			Mime::ApplicationVndAmericandynamicsAcc => write!(f, "application/vnd.americandynamics.acc"),
+			Mime::ApplicationVndAmigaAmi => write!(f, "application/vnd.amiga.ami"),
+			Mime::ApplicationVndAmundsenMazeXml => write!(f, "application/vnd.amundsen.maze+xml"),
+			Mime::ApplicationVndAndroidOta => write!(f, "application/vnd.android.ota"),
+			Mime::ApplicationVndAnki => write!(f, "application/vnd.anki"),
+			Mime::ApplicationVndAnserWebCertificateIssueInitiation => write!(f, "application/vnd.anser-web-certificate-issue-initiation"),
+			Mime::ApplicationVndAntixGameComponent => write!(f, "application/vnd.antix.game-component"),
+			Mime::ApplicationVndApacheArrowFile => write!(f, "application/vnd.apache.arrow.file"),
+			Mime::ApplicationVndApacheArrowStream => write!(f, "application/vnd.apache.arrow.stream"),
+			Mime::ApplicationVndApacheThriftBinary => write!(f, "application/vnd.apache.thrift.binary"),
+			Mime::ApplicationVndApacheThriftCompact => write!(f, "application/vnd.apache.thrift.compact"),
+			Mime::ApplicationVndApacheThriftJson => write!(f, "application/vnd.apache.thrift.json"),
+			Mime::ApplicationVndApexlang => write!(f, "application/vnd.apexlang"),
+			Mime::ApplicationVndApiJson => write!(f, "application/vnd.api+json"),
+			Mime::ApplicationVndAplextorWarrpJson => write!(f, "application/vnd.aplextor.warrp+json"),
+			Mime::ApplicationVndApothekendeReservationJson => write!(f, "application/vnd.apothekende.reservation+json"),
+			Mime::ApplicationVndAppleInstallerXml => write!(f, "application/vnd.apple.installer+xml"),
+			Mime::ApplicationVndAppleKeynote => write!(f, "application/vnd.apple.keynote"),
+			Mime::ApplicationVndAppleMpegurl => write!(f, "application/vnd.apple.mpegurl"),
+			Mime::ApplicationVndAppleNumbers => write!(f, "application/vnd.apple.numbers"),
+			Mime::ApplicationVndApplePages => write!(f, "application/vnd.apple.pages"),
+			Mime::ApplicationVndAristanetworksSwi => write!(f, "application/vnd.aristanetworks.swi"),
+			Mime::ApplicationVndArtisanJson => write!(f, "application/vnd.artisan+json"),
+			Mime::ApplicationVndArtsquare => write!(f, "application/vnd.artsquare"),
+			Mime::ApplicationVndAstraeaSoftwareIota => write!(f, "application/vnd.astraea-software.iota"),
+			Mime::ApplicationVndAudiograph => write!(f, "application/vnd.audiograph"),
+			Mime::ApplicationVndAutopackage => write!(f, "application/vnd.autopackage"),
+			Mime::ApplicationVndAvalonJson => write!(f, "application/vnd.avalon+json"),
+			Mime::ApplicationVndAvistarXml => write!(f, "application/vnd.avistar+xml"),
+			Mime::ApplicationVndBalsamiqBmmlXml => write!(f, "application/vnd.balsamiq.bmml+xml"),
+			Mime::ApplicationVndBananaAccounting => write!(f, "application/vnd.banana-accounting"),
+			Mime::ApplicationVndBbfUspError => write!(f, "application/vnd.bbf.usp.error"),
+			Mime::ApplicationVndBbfUspMsg => write!(f, "application/vnd.bbf.usp.msg"),
+			Mime::ApplicationVndBbfUspMsgJson => write!(f, "application/vnd.bbf.usp.msg+json"),
+			Mime::ApplicationVndBalsamiqBmpr => write!(f, "application/vnd.balsamiq.bmpr"),
+			Mime::ApplicationVndBekitzurStechJson => write!(f, "application/vnd.bekitzur-stech+json"),
+			Mime::ApplicationVndBelightsoftLhzdZip => write!(f, "application/vnd.belightsoft.lhzd+zip"),
+			Mime::ApplicationVndBelightsoftLhzlZip => write!(f, "application/vnd.belightsoft.lhzl+zip"),
+			Mime::ApplicationVndBintMedContent => write!(f, "application/vnd.bint.med-content"),
+			Mime::ApplicationVndBiopaxRdfXml => write!(f, "application/vnd.biopax.rdf+xml"),
+			Mime::ApplicationVndBlinkIdbValueWrapper => write!(f, "application/vnd.blink-idb-value-wrapper"),
+			Mime::ApplicationVndBlueiceMultipass => write!(f, "application/vnd.blueice.multipass"),
+			Mime::ApplicationVndBluetoothEpOob => write!(f, "application/vnd.bluetooth.ep.oob"),
+			Mime::ApplicationVndBluetoothLeOob => write!(f, "application/vnd.bluetooth.le.oob"),
+			Mime::ApplicationVndBmi => write!(f, "application/vnd.bmi"),
+			Mime::ApplicationVndBpf => write!(f, "application/vnd.bpf"),
+			Mime::ApplicationVndBpf3 => write!(f, "application/vnd.bpf3"),
+			Mime::ApplicationVndBusinessobjects => write!(f, "application/vnd.businessobjects"),
+			Mime::ApplicationVndByuUapiJson => write!(f, "application/vnd.byu.uapi+json"),
+			Mime::ApplicationVndCabJscript => write!(f, "application/vnd.cab-jscript"),
+			Mime::ApplicationVndCanonCpdl => write!(f, "application/vnd.canon-cpdl"),
+			Mime::ApplicationVndCanonLips => write!(f, "application/vnd.canon-lips"),
+			Mime::ApplicationVndCapasystemsPgJson => write!(f, "application/vnd.capasystems-pg+json"),
+			Mime::ApplicationVndCendioThinlincClientconf => write!(f, "application/vnd.cendio.thinlinc.clientconf"),
+			Mime::ApplicationVndCenturySystemsTcpStream => write!(f, "application/vnd.century-systems.tcp_stream"),
+			Mime::ApplicationVndChemdrawXml => write!(f, "application/vnd.chemdraw+xml"),
+			Mime::ApplicationVndChessPgn => write!(f, "application/vnd.chess-pgn"),
+			Mime::ApplicationVndChipnutsKaraokeMmd => write!(f, "application/vnd.chipnuts.karaoke-mmd"),
+			Mime::ApplicationVndCiedi => write!(f, "application/vnd.ciedi"),
+			Mime::ApplicationVndCinderella => write!(f, "application/vnd.cinderella"),
+			Mime::ApplicationVndCirpackIsdnExt => write!(f, "application/vnd.cirpack.isdn-ext"),
+			Mime::ApplicationVndCitationstylesStyleXml => write!(f, "application/vnd.citationstyles.style+xml"),
+			Mime::ApplicationVndClaymore => write!(f, "application/vnd.claymore"),
+			Mime::ApplicationVndCloantoRp9 => write!(f, "application/vnd.cloanto.rp9"),
+			Mime::ApplicationVndClonkC4group => write!(f, "application/vnd.clonk.c4group"),
+			Mime::ApplicationVndCluetrustCartomobileConfig => write!(f, "application/vnd.cluetrust.cartomobile-config"),
+			Mime::ApplicationVndCluetrustCartomobileConfigPkg => write!(f, "application/vnd.cluetrust.cartomobile-config-pkg"),
+			Mime::ApplicationVndCncfHelmChartContentV1TarGzip => write!(f, "application/vnd.cncf.helm.chart.content.v1.tar+gzip"),
+			Mime::ApplicationVndCncfHelmChartProvenanceV1Prov => write!(f, "application/vnd.cncf.helm.chart.provenance.v1.prov"),
+			Mime::ApplicationVndCncfHelmConfigV1Json => write!(f, "application/vnd.cncf.helm.config.v1+json"),
+			Mime::ApplicationVndCoffeescript => write!(f, "application/vnd.coffeescript"),
+			Mime::ApplicationVndCollabioXodocumentsDocument => write!(f, "application/vnd.collabio.xodocuments.document"),
+			Mime::ApplicationVndCollabioXodocumentsDocumentTemplate => write!(f, "application/vnd.collabio.xodocuments.document-template"),
+			Mime::ApplicationVndCollabioXodocumentsPresentation => write!(f, "application/vnd.collabio.xodocuments.presentation"),
+			Mime::ApplicationVndCollabioXodocumentsPresentationTemplate => write!(f, "application/vnd.collabio.xodocuments.presentation-template"),
+			Mime::ApplicationVndCollabioXodocumentsSpreadsheet => write!(f, "application/vnd.collabio.xodocuments.spreadsheet"),
+			Mime::ApplicationVndCollabioXodocumentsSpreadsheetTemplate => write!(f, "application/vnd.collabio.xodocuments.spreadsheet-template"),
+			Mime::ApplicationVndCollectionDocJson => write!(f, "application/vnd.collection.doc+json"),
+			Mime::ApplicationVndCollectionJson => write!(f, "application/vnd.collection+json"),
+			Mime::ApplicationVndCollectionNextJson => write!(f, "application/vnd.collection.next+json"),
+			Mime::ApplicationVndComicbookRar => write!(f, "application/vnd.comicbook-rar"),
+			Mime::ApplicationVndComicbookZip => write!(f, "application/vnd.comicbook+zip"),
+			Mime::ApplicationVndCommerceBattelle => write!(f, "application/vnd.commerce-battelle"),
+			Mime::ApplicationVndCommonspace => write!(f, "application/vnd.commonspace"),
+			Mime::ApplicationVndCoreosIgnitionJson => write!(f, "application/vnd.coreos.ignition+json"),
+			Mime::ApplicationVndCosmocaller => write!(f, "application/vnd.cosmocaller"),
+			Mime::ApplicationVndContactCmsg => write!(f, "application/vnd.contact.cmsg"),
+			Mime::ApplicationVndCrickClicker => write!(f, "application/vnd.crick.clicker"),
+			Mime::ApplicationVndCrickClickerKeyboard => write!(f, "application/vnd.crick.clicker.keyboard"),
+			Mime::ApplicationVndCrickClickerPalette => write!(f, "application/vnd.crick.clicker.palette"),
+			Mime::ApplicationVndCrickClickerTemplate => write!(f, "application/vnd.crick.clicker.template"),
+			Mime::ApplicationVndCrickClickerWordbank => write!(f, "application/vnd.crick.clicker.wordbank"),
+			Mime::ApplicationVndCriticaltoolsWbsXml => write!(f, "application/vnd.criticaltools.wbs+xml"),
+			Mime::ApplicationVndCryptiiPipeJson => write!(f, "application/vnd.cryptii.pipe+json"),
+			Mime::ApplicationVndCryptoShadeFile => write!(f, "application/vnd.crypto-shade-file"),
+			Mime::ApplicationVndCryptomatorEncrypted => write!(f, "application/vnd.cryptomator.encrypted"),
+			Mime::ApplicationVndCryptomatorVault => write!(f, "application/vnd.cryptomator.vault"),
+			Mime::ApplicationVndCtcPosml => write!(f, "application/vnd.ctc-posml"),
+			Mime::ApplicationVndCtctWsXml => write!(f, "application/vnd.ctct.ws+xml"),
+			Mime::ApplicationVndCupsPdf => write!(f, "application/vnd.cups-pdf"),
+			Mime::ApplicationVndCupsPostscript => write!(f, "application/vnd.cups-postscript"),
+			Mime::ApplicationVndCupsPpd => write!(f, "application/vnd.cups-ppd"),
+			Mime::ApplicationVndCupsRaster => write!(f, "application/vnd.cups-raster"),
+			Mime::ApplicationVndCupsRaw => write!(f, "application/vnd.cups-raw"),
+			Mime::ApplicationVndCurl => write!(f, "application/vnd.curl"),
+			Mime::ApplicationVndCyanDeanRootXml => write!(f, "application/vnd.cyan.dean.root+xml"),
+			Mime::ApplicationVndCybank => write!(f, "application/vnd.cybank"),
+			Mime::ApplicationVndCyclonedxJson => write!(f, "application/vnd.cyclonedx+json"),
+			Mime::ApplicationVndCyclonedxXml => write!(f, "application/vnd.cyclonedx+xml"),
+			Mime::ApplicationVndD2lCoursepackage1p0Zip => write!(f, "application/vnd.d2l.coursepackage1p0+zip"),
+			Mime::ApplicationVndD3mDataset => write!(f, "application/vnd.d3m-dataset"),
+			Mime::ApplicationVndD3mProblem => write!(f, "application/vnd.d3m-problem"),
+			Mime::ApplicationVndDart => write!(f, "application/vnd.dart"),
+			Mime::ApplicationVndDataVisionRdz => write!(f, "application/vnd.data-vision.rdz"),
+			Mime::ApplicationVndDatalog => write!(f, "application/vnd.datalog"),
+			Mime::ApplicationVndDatapackageJson => write!(f, "application/vnd.datapackage+json"),
+			Mime::ApplicationVndDataresourceJson => write!(f, "application/vnd.dataresource+json"),
+			Mime::ApplicationVndDbf => write!(f, "application/vnd.dbf"),
+			Mime::ApplicationVndDebianBinaryPackage => write!(f, "application/vnd.debian.binary-package"),
+			Mime::ApplicationVndDeceData => write!(f, "application/vnd.dece.data"),
+			Mime::ApplicationVndDeceTtmlXml => write!(f, "application/vnd.dece.ttml+xml"),
+			Mime::ApplicationVndDeceUnspecified => write!(f, "application/vnd.dece.unspecified"),
+			Mime::ApplicationVndDeceZip => write!(f, "application/vnd.dece.zip"),
+			Mime::ApplicationVndDenovoFcselayoutLink => write!(f, "application/vnd.denovo.fcselayout-link"),
+			Mime::ApplicationVndDesmumeMovie => write!(f, "application/vnd.desmume.movie"),
+			Mime::ApplicationVndDirBiPlateDlNosuffix => write!(f, "application/vnd.dir-bi.plate-dl-nosuffix"),
+			Mime::ApplicationVndDmDelegationXml => write!(f, "application/vnd.dm.delegation+xml"),
+			Mime::ApplicationVndDna => write!(f, "application/vnd.dna"),
+			Mime::ApplicationVndDocumentJson => write!(f, "application/vnd.document+json"),
+			Mime::ApplicationVndDolbyMobile1 => write!(f, "application/vnd.dolby.mobile.1"),
+			Mime::ApplicationVndDolbyMobile2 => write!(f, "application/vnd.dolby.mobile.2"),
+			Mime::ApplicationVndDoremirScorecloudBinaryDocument => write!(f, "application/vnd.doremir.scorecloud-binary-document"),
+			Mime::ApplicationVndDpgraph => write!(f, "application/vnd.dpgraph"),
+			Mime::ApplicationVndDreamfactory => write!(f, "application/vnd.dreamfactory"),
+			Mime::ApplicationVndDriveJson => write!(f, "application/vnd.drive+json"),
+			Mime::ApplicationVndDtgLocal => write!(f, "application/vnd.dtg.local"),
+			Mime::ApplicationVndDtgLocalFlash => write!(f, "application/vnd.dtg.local.flash"),
+			Mime::ApplicationVndDtgLocalHtml => write!(f, "application/vnd.dtg.local.html"),
+			Mime::ApplicationVndDvbAit => write!(f, "application/vnd.dvb.ait"),
+			Mime::ApplicationVndDvbDvbislXml => write!(f, "application/vnd.dvb.dvbisl+xml"),
+			Mime::ApplicationVndDvbDvbj => write!(f, "application/vnd.dvb.dvbj"),
+			Mime::ApplicationVndDvbEsgcontainer => write!(f, "application/vnd.dvb.esgcontainer"),
+			Mime::ApplicationVndDvbIpdcdftnotifaccess => write!(f, "application/vnd.dvb.ipdcdftnotifaccess"),
+			Mime::ApplicationVndDvbIpdcesgaccess => write!(f, "application/vnd.dvb.ipdcesgaccess"),
+			Mime::ApplicationVndDvbIpdcesgaccess2 => write!(f, "application/vnd.dvb.ipdcesgaccess2"),
+			Mime::ApplicationVndDvbIpdcesgpdd => write!(f, "application/vnd.dvb.ipdcesgpdd"),
+			Mime::ApplicationVndDvbIpdcroaming => write!(f, "application/vnd.dvb.ipdcroaming"),
+			Mime::ApplicationVndDvbIptvAlfecBase => write!(f, "application/vnd.dvb.iptv.alfec-base"),
+			Mime::ApplicationVndDvbIptvAlfecEnhancement => write!(f, "application/vnd.dvb.iptv.alfec-enhancement"),
+			Mime::ApplicationVndDvbNotifAggregateRootXml => write!(f, "application/vnd.dvb.notif-aggregate-root+xml"),
+			Mime::ApplicationVndDvbNotifContainerXml => write!(f, "application/vnd.dvb.notif-container+xml"),
+			Mime::ApplicationVndDvbNotifGenericXml => write!(f, "application/vnd.dvb.notif-generic+xml"),
+			Mime::ApplicationVndDvbNotifIaMsglistXml => write!(f, "application/vnd.dvb.notif-ia-msglist+xml"),
+			Mime::ApplicationVndDvbNotifIaRegistrationRequestXml => write!(f, "application/vnd.dvb.notif-ia-registration-request+xml"),
+			Mime::ApplicationVndDvbNotifIaRegistrationResponseXml => write!(f, "application/vnd.dvb.notif-ia-registration-response+xml"),
+			Mime::ApplicationVndDvbNotifInitXml => write!(f, "application/vnd.dvb.notif-init+xml"),
+			Mime::ApplicationVndDvbPfr => write!(f, "application/vnd.dvb.pfr"),
+			Mime::ApplicationVndDvbService => write!(f, "application/vnd.dvb.service"),
+			Mime::ApplicationVndDxr => write!(f, "application/vnd.dxr"),
+			Mime::ApplicationVndDynageo => write!(f, "application/vnd.dynageo"),
+			Mime::ApplicationVndDzr => write!(f, "application/vnd.dzr"),
+			Mime::ApplicationVndEasykaraokeCdgdownload => write!(f, "application/vnd.easykaraoke.cdgdownload"),
+			Mime::ApplicationVndEcipRlp => write!(f, "application/vnd.ecip.rlp"),
+			Mime::ApplicationVndEcdisUpdate => write!(f, "application/vnd.ecdis-update"),
+			Mime::ApplicationVndEclipseDittoJson => write!(f, "application/vnd.eclipse.ditto+json"),
+			Mime::ApplicationVndEcowinChart => write!(f, "application/vnd.ecowin.chart"),
+			Mime::ApplicationVndEcowinFilerequest => write!(f, "application/vnd.ecowin.filerequest"),
+			Mime::ApplicationVndEcowinFileupdate => write!(f, "application/vnd.ecowin.fileupdate"),
+			Mime::ApplicationVndEcowinSeries => write!(f, "application/vnd.ecowin.series"),
+			Mime::ApplicationVndEcowinSeriesrequest => write!(f, "application/vnd.ecowin.seriesrequest"),
+			Mime::ApplicationVndEcowinSeriesupdate => write!(f, "application/vnd.ecowin.seriesupdate"),
+			Mime::ApplicationVndEfiImg => write!(f, "application/vnd.efi.img"),
+			Mime::ApplicationVndEfiIso => write!(f, "application/vnd.efi.iso"),
+			Mime::ApplicationVndElnZip => write!(f, "application/vnd.eln+zip"),
+			Mime::ApplicationVndEmclientAccessrequestXml => write!(f, "application/vnd.emclient.accessrequest+xml"),
+			Mime::ApplicationVndEnliven => write!(f, "application/vnd.enliven"),
+			Mime::ApplicationVndEnphaseEnvoy => write!(f, "application/vnd.enphase.envoy"),
+			Mime::ApplicationVndEprintsDataXml => write!(f, "application/vnd.eprints.data+xml"),
+			Mime::ApplicationVndEpsonEsf => write!(f, "application/vnd.epson.esf"),
+			Mime::ApplicationVndEpsonMsf => write!(f, "application/vnd.epson.msf"),
+			Mime::ApplicationVndEpsonQuickanime => write!(f, "application/vnd.epson.quickanime"),
+			Mime::ApplicationVndEpsonSalt => write!(f, "application/vnd.epson.salt"),
+			Mime::ApplicationVndEpsonSsf => write!(f, "application/vnd.epson.ssf"),
+			Mime::ApplicationVndEricssonQuickcall => write!(f, "application/vnd.ericsson.quickcall"),
+			Mime::ApplicationVndEspassEspassZip => write!(f, "application/vnd.espass-espass+zip"),
+			Mime::ApplicationVndEszigno3Xml => write!(f, "application/vnd.eszigno3+xml"),
+			Mime::ApplicationVndEtsiAocXml => write!(f, "application/vnd.etsi.aoc+xml"),
+			Mime::ApplicationVndEtsiAsicSZip => write!(f, "application/vnd.etsi.asic-s+zip"),
+			Mime::ApplicationVndEtsiAsicEZip => write!(f, "application/vnd.etsi.asic-e+zip"),
+			Mime::ApplicationVndEtsiCugXml => write!(f, "application/vnd.etsi.cug+xml"),
+			Mime::ApplicationVndEtsiIptvcommandXml => write!(f, "application/vnd.etsi.iptvcommand+xml"),
+			Mime::ApplicationVndEtsiIptvdiscoveryXml => write!(f, "application/vnd.etsi.iptvdiscovery+xml"),
+			Mime::ApplicationVndEtsiIptvprofileXml => write!(f, "application/vnd.etsi.iptvprofile+xml"),
+			Mime::ApplicationVndEtsiIptvsadBcXml => write!(f, "application/vnd.etsi.iptvsad-bc+xml"),
+			Mime::ApplicationVndEtsiIptvsadCodXml => write!(f, "application/vnd.etsi.iptvsad-cod+xml"),
+			Mime::ApplicationVndEtsiIptvsadNpvrXml => write!(f, "application/vnd.etsi.iptvsad-npvr+xml"),
+			Mime::ApplicationVndEtsiIptvserviceXml => write!(f, "application/vnd.etsi.iptvservice+xml"),
+			Mime::ApplicationVndEtsiIptvsyncXml => write!(f, "application/vnd.etsi.iptvsync+xml"),
+			Mime::ApplicationVndEtsiIptvueprofileXml => write!(f, "application/vnd.etsi.iptvueprofile+xml"),
+			Mime::ApplicationVndEtsiMcidXml => write!(f, "application/vnd.etsi.mcid+xml"),
+			Mime::ApplicationVndEtsiMheg5 => write!(f, "application/vnd.etsi.mheg5"),
+			Mime::ApplicationVndEtsiOverloadControlPolicyDatasetXml => write!(f, "application/vnd.etsi.overload-control-policy-dataset+xml"),
+			Mime::ApplicationVndEtsiPstnXml => write!(f, "application/vnd.etsi.pstn+xml"),
+			Mime::ApplicationVndEtsiSciXml => write!(f, "application/vnd.etsi.sci+xml"),
+			Mime::ApplicationVndEtsiSimservsXml => write!(f, "application/vnd.etsi.simservs+xml"),
+			Mime::ApplicationVndEtsiTimestampToken => write!(f, "application/vnd.etsi.timestamp-token"),
+			Mime::ApplicationVndEtsiTslXml => write!(f, "application/vnd.etsi.tsl+xml"),
+			Mime::ApplicationVndEtsiTslDer => write!(f, "application/vnd.etsi.tsl.der"),
+			Mime::ApplicationVndEuKasparianCarJson => write!(f, "application/vnd.eu.kasparian.car+json"),
+			Mime::ApplicationVndEudoraData => write!(f, "application/vnd.eudora.data"),
+			Mime::ApplicationVndEvolvEcigProfile => write!(f, "application/vnd.evolv.ecig.profile"),
+			Mime::ApplicationVndEvolvEcigSettings => write!(f, "application/vnd.evolv.ecig.settings"),
+			Mime::ApplicationVndEvolvEcigTheme => write!(f, "application/vnd.evolv.ecig.theme"),
+			Mime::ApplicationVndExstreamEmpowerZip => write!(f, "application/vnd.exstream-empower+zip"),
+			Mime::ApplicationVndExstreamPackage => write!(f, "application/vnd.exstream-package"),
+			Mime::ApplicationVndEzpixAlbum => write!(f, "application/vnd.ezpix-album"),
+			Mime::ApplicationVndEzpixPackage => write!(f, "application/vnd.ezpix-package"),
+			Mime::ApplicationVndFSecureMobile => write!(f, "application/vnd.f-secure.mobile"),
+			Mime::ApplicationVndFastcopyDiskImage => write!(f, "application/vnd.fastcopy-disk-image"),
+			Mime::ApplicationVndFamilysearchGedcomZip => write!(f, "application/vnd.familysearch.gedcom+zip"),
+			Mime::ApplicationVndFdsnMseed => write!(f, "application/vnd.fdsn.mseed"),
+			Mime::ApplicationVndFdsnSeed => write!(f, "application/vnd.fdsn.seed"),
+			Mime::ApplicationVndFfsns => write!(f, "application/vnd.ffsns"),
+			Mime::ApplicationVndFiclabFlbZip => write!(f, "application/vnd.ficlab.flb+zip"),
+			Mime::ApplicationVndFilmitZfc => write!(f, "application/vnd.filmit.zfc"),
+			Mime::ApplicationVndFints => write!(f, "application/vnd.fints"),
+			Mime::ApplicationVndFiremonkeysCloudcell => write!(f, "application/vnd.firemonkeys.cloudcell"),
+			Mime::ApplicationVndFlographit => write!(f, "application/vnd.FloGraphIt"),
+			Mime::ApplicationVndFluxtimeClip => write!(f, "application/vnd.fluxtime.clip"),
+			Mime::ApplicationVndFontFontforgeSfd => write!(f, "application/vnd.font-fontforge-sfd"),
+			Mime::ApplicationVndFramemaker => write!(f, "application/vnd.framemaker"),
+			Mime::ApplicationVndFscWeblaunch => write!(f, "application/vnd.fsc.weblaunch"),
+			Mime::ApplicationVndFujifilmFbDocuworks => write!(f, "application/vnd.fujifilm.fb.docuworks"),
+			Mime::ApplicationVndFujifilmFbDocuworksBinder => write!(f, "application/vnd.fujifilm.fb.docuworks.binder"),
+			Mime::ApplicationVndFujifilmFbDocuworksContainer => write!(f, "application/vnd.fujifilm.fb.docuworks.container"),
+			Mime::ApplicationVndFujifilmFbJfiXml => write!(f, "application/vnd.fujifilm.fb.jfi+xml"),
+			Mime::ApplicationVndFujitsuOasys => write!(f, "application/vnd.fujitsu.oasys"),
+			Mime::ApplicationVndFujitsuOasys2 => write!(f, "application/vnd.fujitsu.oasys2"),
+			Mime::ApplicationVndFujitsuOasys3 => write!(f, "application/vnd.fujitsu.oasys3"),
+			Mime::ApplicationVndFujitsuOasysgp => write!(f, "application/vnd.fujitsu.oasysgp"),
+			Mime::ApplicationVndFujitsuOasysprs => write!(f, "application/vnd.fujitsu.oasysprs"),
+			Mime::ApplicationVndFujixeroxArt4 => write!(f, "application/vnd.fujixerox.ART4"),
+			Mime::ApplicationVndFujixeroxArtEx => write!(f, "application/vnd.fujixerox.ART-EX"),
+			Mime::ApplicationVndFujixeroxDdd => write!(f, "application/vnd.fujixerox.ddd"),
+			Mime::ApplicationVndFujixeroxDocuworks => write!(f, "application/vnd.fujixerox.docuworks"),
+			Mime::ApplicationVndFujixeroxDocuworksBinder => write!(f, "application/vnd.fujixerox.docuworks.binder"),
+			Mime::ApplicationVndFujixeroxDocuworksContainer => write!(f, "application/vnd.fujixerox.docuworks.container"),
+			Mime::ApplicationVndFujixeroxHbpl => write!(f, "application/vnd.fujixerox.HBPL"),
+			Mime::ApplicationVndFutMisnet => write!(f, "application/vnd.fut-misnet"),
+			Mime::ApplicationVndFutoinCbor => write!(f, "application/vnd.futoin+cbor"),
+			Mime::ApplicationVndFutoinJson => write!(f, "application/vnd.futoin+json"),
+			Mime::ApplicationVndFuzzysheet => write!(f, "application/vnd.fuzzysheet"),
+			Mime::ApplicationVndGenomatixTuxedo => write!(f, "application/vnd.genomatix.tuxedo"),
+			Mime::ApplicationVndGenozip => write!(f, "application/vnd.genozip"),
+			Mime::ApplicationVndGenticsGrdJson => write!(f, "application/vnd.gentics.grd+json"),
+			Mime::ApplicationVndGentooCatmetadataXml => write!(f, "application/vnd.gentoo.catmetadata+xml"),
+			Mime::ApplicationVndGentooEbuild => write!(f, "application/vnd.gentoo.ebuild"),
+			Mime::ApplicationVndGentooEclass => write!(f, "application/vnd.gentoo.eclass"),
+			Mime::ApplicationVndGentooGpkg => write!(f, "application/vnd.gentoo.gpkg"),
+			Mime::ApplicationVndGentooManifest => write!(f, "application/vnd.gentoo.manifest"),
+			Mime::ApplicationVndGentooXpak => write!(f, "application/vnd.gentoo.xpak"),
+			Mime::ApplicationVndGentooPkgmetadataXml => write!(f, "application/vnd.gentoo.pkgmetadata+xml"),
+			Mime::ApplicationVndGeogebraFile => write!(f, "application/vnd.geogebra.file"),
+			Mime::ApplicationVndGeogebraSlides => write!(f, "application/vnd.geogebra.slides"),
+			Mime::ApplicationVndGeogebraTool => write!(f, "application/vnd.geogebra.tool"),
+			Mime::ApplicationVndGeometryExplorer => write!(f, "application/vnd.geometry-explorer"),
+			Mime::ApplicationVndGeonext => write!(f, "application/vnd.geonext"),
+			Mime::ApplicationVndGeoplan => write!(f, "application/vnd.geoplan"),
+			Mime::ApplicationVndGeospace => write!(f, "application/vnd.geospace"),
+			Mime::ApplicationVndGerber => write!(f, "application/vnd.gerber"),
+			Mime::ApplicationVndGlobalplatformCardContentMgt => write!(f, "application/vnd.globalplatform.card-content-mgt"),
+			Mime::ApplicationVndGlobalplatformCardContentMgtResponse => write!(f, "application/vnd.globalplatform.card-content-mgt-response"),
+			Mime::ApplicationVndGnuTalerExchangeJson => write!(f, "application/vnd.gnu.taler.exchange+json"),
+			Mime::ApplicationVndGnuTalerMerchantJson => write!(f, "application/vnd.gnu.taler.merchant+json"),
+			Mime::ApplicationVndGoogleEarthKmlXml => write!(f, "application/vnd.google-earth.kml+xml"),
+			Mime::ApplicationVndGoogleEarthKmz => write!(f, "application/vnd.google-earth.kmz"),
+			Mime::ApplicationVndGovSkEFormXml => write!(f, "application/vnd.gov.sk.e-form+xml"),
+			Mime::ApplicationVndGovSkEFormZip => write!(f, "application/vnd.gov.sk.e-form+zip"),
+			Mime::ApplicationVndGovSkXmldatacontainerXml => write!(f, "application/vnd.gov.sk.xmldatacontainer+xml"),
+			Mime::ApplicationVndGpxseeMapXml => write!(f, "application/vnd.gpxsee.map+xml"),
+			Mime::ApplicationVndGrafeq => write!(f, "application/vnd.grafeq"),
+			Mime::ApplicationVndGridmp => write!(f, "application/vnd.gridmp"),
+			Mime::ApplicationVndGrooveAccount => write!(f, "application/vnd.groove-account"),
+			Mime::ApplicationVndGrooveHelp => write!(f, "application/vnd.groove-help"),
+			Mime::ApplicationVndGrooveIdentityMessage => write!(f, "application/vnd.groove-identity-message"),
+			Mime::ApplicationVndGrooveInjector => write!(f, "application/vnd.groove-injector"),
+			Mime::ApplicationVndGrooveToolMessage => write!(f, "application/vnd.groove-tool-message"),
+			Mime::ApplicationVndGrooveToolTemplate => write!(f, "application/vnd.groove-tool-template"),
+			Mime::ApplicationVndGrooveVcard => write!(f, "application/vnd.groove-vcard"),
+			Mime::ApplicationVndHalJson => write!(f, "application/vnd.hal+json"),
+			Mime::ApplicationVndHalXml => write!(f, "application/vnd.hal+xml"),
+			Mime::ApplicationVndHandheldEntertainmentXml => write!(f, "application/vnd.HandHeld-Entertainment+xml"),
+			Mime::ApplicationVndHbci => write!(f, "application/vnd.hbci"),
+			Mime::ApplicationVndHcJson => write!(f, "application/vnd.hc+json"),
+			Mime::ApplicationVndHclBireports => write!(f, "application/vnd.hcl-bireports"),
+			Mime::ApplicationVndHdt => write!(f, "application/vnd.hdt"),
+			Mime::ApplicationVndHerokuJson => write!(f, "application/vnd.heroku+json"),
+			Mime::ApplicationVndHheLessonPlayer => write!(f, "application/vnd.hhe.lesson-player"),
+			Mime::ApplicationVndHpHpgl => write!(f, "application/vnd.hp-HPGL"),
+			Mime::ApplicationVndHpHpid => write!(f, "application/vnd.hp-hpid"),
+			Mime::ApplicationVndHpHps => write!(f, "application/vnd.hp-hps"),
+			Mime::ApplicationVndHpJlyt => write!(f, "application/vnd.hp-jlyt"),
+			Mime::ApplicationVndHpPcl => write!(f, "application/vnd.hp-PCL"),
+			Mime::ApplicationVndHpPclxl => write!(f, "application/vnd.hp-PCLXL"),
+			Mime::ApplicationVndHsl => write!(f, "application/vnd.hsl"),
+			Mime::ApplicationVndHttphone => write!(f, "application/vnd.httphone"),
+			Mime::ApplicationVndHydrostatixSofData => write!(f, "application/vnd.hydrostatix.sof-data"),
+			Mime::ApplicationVndHyperItemJson => write!(f, "application/vnd.hyper-item+json"),
+			Mime::ApplicationVndHyperJson => write!(f, "application/vnd.hyper+json"),
+			Mime::ApplicationVndHyperdriveJson => write!(f, "application/vnd.hyperdrive+json"),
+			Mime::ApplicationVndHzn3dCrossword => write!(f, "application/vnd.hzn-3d-crossword"),
+			Mime::ApplicationVndIbmElectronicMedia => write!(f, "application/vnd.ibm.electronic-media"),
+			Mime::ApplicationVndIbmMinipay => write!(f, "application/vnd.ibm.MiniPay"),
+			Mime::ApplicationVndIbmRightsManagement => write!(f, "application/vnd.ibm.rights-management"),
+			Mime::ApplicationVndIbmSecureContainer => write!(f, "application/vnd.ibm.secure-container"),
+			Mime::ApplicationVndIccprofile => write!(f, "application/vnd.iccprofile"),
+			Mime::ApplicationVndIeee1905 => write!(f, "application/vnd.ieee.1905"),
+			Mime::ApplicationVndIgloader => write!(f, "application/vnd.igloader"),
+			Mime::ApplicationVndImagemeterFolderZip => write!(f, "application/vnd.imagemeter.folder+zip"),
+			Mime::ApplicationVndImagemeterImageZip => write!(f, "application/vnd.imagemeter.image+zip"),
+			Mime::ApplicationVndImmervisionIvp => write!(f, "application/vnd.immervision-ivp"),
+			Mime::ApplicationVndImmervisionIvu => write!(f, "application/vnd.immervision-ivu"),
+			Mime::ApplicationVndImsImsccv1p1 => write!(f, "application/vnd.ims.imsccv1p1"),
+			Mime::ApplicationVndImsImsccv1p2 => write!(f, "application/vnd.ims.imsccv1p2"),
+			Mime::ApplicationVndImsImsccv1p3 => write!(f, "application/vnd.ims.imsccv1p3"),
+			Mime::ApplicationVndImsLisV2ResultJson => write!(f, "application/vnd.ims.lis.v2.result+json"),
+			Mime::ApplicationVndImsLtiV2ToolconsumerprofileJson => write!(f, "application/vnd.ims.lti.v2.toolconsumerprofile+json"),
+			Mime::ApplicationVndImsLtiV2ToolproxyIdJson => write!(f, "application/vnd.ims.lti.v2.toolproxy.id+json"),
+			Mime::ApplicationVndImsLtiV2ToolproxyJson => write!(f, "application/vnd.ims.lti.v2.toolproxy+json"),
+			Mime::ApplicationVndImsLtiV2ToolsettingsJson => write!(f, "application/vnd.ims.lti.v2.toolsettings+json"),
+			Mime::ApplicationVndImsLtiV2ToolsettingsSimpleJson => write!(f, "application/vnd.ims.lti.v2.toolsettings.simple+json"),
+			Mime::ApplicationVndInformedcontrolRmsXml => write!(f, "application/vnd.informedcontrol.rms+xml"),
+			Mime::ApplicationVndInfotechProject => write!(f, "application/vnd.infotech.project"),
+			Mime::ApplicationVndInfotechProjectXml => write!(f, "application/vnd.infotech.project+xml"),
+			Mime::ApplicationVndInnopathWampNotification => write!(f, "application/vnd.innopath.wamp.notification"),
+			Mime::ApplicationVndInsorsIgm => write!(f, "application/vnd.insors.igm"),
+			Mime::ApplicationVndInterconFormnet => write!(f, "application/vnd.intercon.formnet"),
+			Mime::ApplicationVndIntergeo => write!(f, "application/vnd.intergeo"),
+			Mime::ApplicationVndIntertrustDigibox => write!(f, "application/vnd.intertrust.digibox"),
+			Mime::ApplicationVndIntertrustNncp => write!(f, "application/vnd.intertrust.nncp"),
+			Mime::ApplicationVndIntuQbo => write!(f, "application/vnd.intu.qbo"),
+			Mime::ApplicationVndIntuQfx => write!(f, "application/vnd.intu.qfx"),
+			Mime::ApplicationVndIpfsIpnsRecord => write!(f, "application/vnd.ipfs.ipns-record"),
+			Mime::ApplicationVndIpldCar => write!(f, "application/vnd.ipld.car"),
+			Mime::ApplicationVndIpldDagCbor => write!(f, "application/vnd.ipld.dag-cbor"),
+			Mime::ApplicationVndIpldDagJson => write!(f, "application/vnd.ipld.dag-json"),
+			Mime::ApplicationVndIpldRaw => write!(f, "application/vnd.ipld.raw"),
+			Mime::ApplicationVndIptcG2CatalogitemXml => write!(f, "application/vnd.iptc.g2.catalogitem+xml"),
+			Mime::ApplicationVndIptcG2ConceptitemXml => write!(f, "application/vnd.iptc.g2.conceptitem+xml"),
+			Mime::ApplicationVndIptcG2KnowledgeitemXml => write!(f, "application/vnd.iptc.g2.knowledgeitem+xml"),
+			Mime::ApplicationVndIptcG2NewsitemXml => write!(f, "application/vnd.iptc.g2.newsitem+xml"),
+			Mime::ApplicationVndIptcG2NewsmessageXml => write!(f, "application/vnd.iptc.g2.newsmessage+xml"),
+			Mime::ApplicationVndIptcG2PackageitemXml => write!(f, "application/vnd.iptc.g2.packageitem+xml"),
+			Mime::ApplicationVndIptcG2PlanningitemXml => write!(f, "application/vnd.iptc.g2.planningitem+xml"),
+			Mime::ApplicationVndIpunpluggedRcprofile => write!(f, "application/vnd.ipunplugged.rcprofile"),
+			Mime::ApplicationVndIrepositoryPackageXml => write!(f, "application/vnd.irepository.package+xml"),
+			Mime::ApplicationVndIsXpr => write!(f, "application/vnd.is-xpr"),
+			Mime::ApplicationVndIsacFcs => write!(f, "application/vnd.isac.fcs"),
+			Mime::ApplicationVndJam => write!(f, "application/vnd.jam"),
+			Mime::ApplicationVndIso1178310Zip => write!(f, "application/vnd.iso11783-10+zip"),
+			Mime::ApplicationVndJapannetDirectoryService => write!(f, "application/vnd.japannet-directory-service"),
+			Mime::ApplicationVndJapannetJpnstoreWakeup => write!(f, "application/vnd.japannet-jpnstore-wakeup"),
+			Mime::ApplicationVndJapannetPaymentWakeup => write!(f, "application/vnd.japannet-payment-wakeup"),
+			Mime::ApplicationVndJapannetRegistration => write!(f, "application/vnd.japannet-registration"),
+			Mime::ApplicationVndJapannetRegistrationWakeup => write!(f, "application/vnd.japannet-registration-wakeup"),
+			Mime::ApplicationVndJapannetSetstoreWakeup => write!(f, "application/vnd.japannet-setstore-wakeup"),
+			Mime::ApplicationVndJapannetVerification => write!(f, "application/vnd.japannet-verification"),
+			Mime::ApplicationVndJapannetVerificationWakeup => write!(f, "application/vnd.japannet-verification-wakeup"),
+			Mime::ApplicationVndJcpJavameMidletRms => write!(f, "application/vnd.jcp.javame.midlet-rms"),
+			Mime::ApplicationVndJisp => write!(f, "application/vnd.jisp"),
+			Mime::ApplicationVndJoostJodaArchive => write!(f, "application/vnd.joost.joda-archive"),
+			Mime::ApplicationVndJskIsdnNgn => write!(f, "application/vnd.jsk.isdn-ngn"),
+			Mime::ApplicationVndKahootz => write!(f, "application/vnd.kahootz"),
+			Mime::ApplicationVndKdeKarbon => write!(f, "application/vnd.kde.karbon"),
+			Mime::ApplicationVndKdeKchart => write!(f, "application/vnd.kde.kchart"),
+			Mime::ApplicationVndKdeKformula => write!(f, "application/vnd.kde.kformula"),
+			Mime::ApplicationVndKdeKivio => write!(f, "application/vnd.kde.kivio"),
+			Mime::ApplicationVndKdeKontour => write!(f, "application/vnd.kde.kontour"),
+			Mime::ApplicationVndKdeKpresenter => write!(f, "application/vnd.kde.kpresenter"),
+			Mime::ApplicationVndKdeKspread => write!(f, "application/vnd.kde.kspread"),
+			Mime::ApplicationVndKdeKword => write!(f, "application/vnd.kde.kword"),
+			Mime::ApplicationVndKenameaapp => write!(f, "application/vnd.kenameaapp"),
+			Mime::ApplicationVndKidspiration => write!(f, "application/vnd.kidspiration"),
+			Mime::ApplicationVndKinar => write!(f, "application/vnd.Kinar"),
+			Mime::ApplicationVndKoan => write!(f, "application/vnd.koan"),
+			Mime::ApplicationVndKodakDescriptor => write!(f, "application/vnd.kodak-descriptor"),
+			Mime::ApplicationVndLas => write!(f, "application/vnd.las"),
+			Mime::ApplicationVndLasLasJson => write!(f, "application/vnd.las.las+json"),
+			Mime::ApplicationVndLasLasXml => write!(f, "application/vnd.las.las+xml"),
+			Mime::ApplicationVndLaszip => write!(f, "application/vnd.laszip"),
+			Mime::ApplicationVndLeapJson => write!(f, "application/vnd.leap+json"),
+			Mime::ApplicationVndLibertyRequestXml => write!(f, "application/vnd.liberty-request+xml"),
+			Mime::ApplicationVndLlamagraphicsLifeBalanceDesktop => write!(f, "application/vnd.llamagraphics.life-balance.desktop"),
+			Mime::ApplicationVndLlamagraphicsLifeBalanceExchangeXml => write!(f, "application/vnd.llamagraphics.life-balance.exchange+xml"),
+			Mime::ApplicationVndLogipipeCircuitZip => write!(f, "application/vnd.logipipe.circuit+zip"),
+			Mime::ApplicationVndLoom => write!(f, "application/vnd.loom"),
+			Mime::ApplicationVndLotus123 => write!(f, "application/vnd.lotus-1-2-3"),
+			Mime::ApplicationVndLotusApproach => write!(f, "application/vnd.lotus-approach"),
+			Mime::ApplicationVndLotusFreelance => write!(f, "application/vnd.lotus-freelance"),
+			Mime::ApplicationVndLotusNotes => write!(f, "application/vnd.lotus-notes"),
+			Mime::ApplicationVndLotusOrganizer => write!(f, "application/vnd.lotus-organizer"),
+			Mime::ApplicationVndLotusScreencam => write!(f, "application/vnd.lotus-screencam"),
+			Mime::ApplicationVndLotusWordpro => write!(f, "application/vnd.lotus-wordpro"),
+			Mime::ApplicationVndMacportsPortpkg => write!(f, "application/vnd.macports.portpkg"),
+			Mime::ApplicationVndMapboxVectorTile => write!(f, "application/vnd.mapbox-vector-tile"),
+			Mime::ApplicationVndMarlinDrmActiontokenXml => write!(f, "application/vnd.marlin.drm.actiontoken+xml"),
+			Mime::ApplicationVndMarlinDrmConftokenXml => write!(f, "application/vnd.marlin.drm.conftoken+xml"),
+			Mime::ApplicationVndMarlinDrmLicenseXml => write!(f, "application/vnd.marlin.drm.license+xml"),
+			Mime::ApplicationVndMarlinDrmMdcf => write!(f, "application/vnd.marlin.drm.mdcf"),
+			Mime::ApplicationVndMasonJson => write!(f, "application/vnd.mason+json"),
+			Mime::ApplicationVndMaxarArchive3tzZip => write!(f, "application/vnd.maxar.archive.3tz+zip"),
+			Mime::ApplicationVndMaxmindMaxmindDb => write!(f, "application/vnd.maxmind.maxmind-db"),
+			Mime::ApplicationVndMcd => write!(f, "application/vnd.mcd"),
+			Mime::ApplicationVndMdl => write!(f, "application/vnd.mdl"),
+			Mime::ApplicationVndMdlMbsdf => write!(f, "application/vnd.mdl-mbsdf"),
+			Mime::ApplicationVndMedcalcdata => write!(f, "application/vnd.medcalcdata"),
+			Mime::ApplicationVndMediastationCdkey => write!(f, "application/vnd.mediastation.cdkey"),
+			Mime::ApplicationVndMedicalholodeckRecordxr => write!(f, "application/vnd.medicalholodeck.recordxr"),
+			Mime::ApplicationVndMeridianSlingshot => write!(f, "application/vnd.meridian-slingshot"),
+			Mime::ApplicationVndMfer => write!(f, "application/vnd.MFER"),
+			Mime::ApplicationVndMfmp => write!(f, "application/vnd.mfmp"),
+			Mime::ApplicationVndMicroJson => write!(f, "application/vnd.micro+json"),
+			Mime::ApplicationVndMicrografxFlo => write!(f, "application/vnd.micrografx.flo"),
+			Mime::ApplicationVndMicrografxIgx => write!(f, "application/vnd.micrografx.igx"),
+			Mime::ApplicationVndMicrosoftPortableExecutable => write!(f, "application/vnd.microsoft.portable-executable"),
+			Mime::ApplicationVndMicrosoftWindowsThumbnailCache => write!(f, "application/vnd.microsoft.windows.thumbnail-cache"),
+			Mime::ApplicationVndMieleJson => write!(f, "application/vnd.miele+json"),
+			Mime::ApplicationVndMif => write!(f, "application/vnd.mif"),
+			Mime::ApplicationVndMinisoftHp3000Save => write!(f, "application/vnd.minisoft-hp3000-save"),
+			Mime::ApplicationVndMitsubishiMistyGuardTrustweb => write!(f, "application/vnd.mitsubishi.misty-guard.trustweb"),
+			Mime::ApplicationVndMobiusDaf => write!(f, "application/vnd.Mobius.DAF"),
+			Mime::ApplicationVndMobiusDis => write!(f, "application/vnd.Mobius.DIS"),
+			Mime::ApplicationVndMobiusMbk => write!(f, "application/vnd.Mobius.MBK"),
+			Mime::ApplicationVndMobiusMqy => write!(f, "application/vnd.Mobius.MQY"),
+			Mime::ApplicationVndMobiusMsl => write!(f, "application/vnd.Mobius.MSL"),
+			Mime::ApplicationVndMobiusPlc => write!(f, "application/vnd.Mobius.PLC"),
+			Mime::ApplicationVndMobiusTxf => write!(f, "application/vnd.Mobius.TXF"),
+			Mime::ApplicationVndModl => write!(f, "application/vnd.modl"),
+			Mime::ApplicationVndMophunApplication => write!(f, "application/vnd.mophun.application"),
+			Mime::ApplicationVndMophunCertificate => write!(f, "application/vnd.mophun.certificate"),
+			Mime::ApplicationVndMotorolaFlexsuite => write!(f, "application/vnd.motorola.flexsuite"),
+			Mime::ApplicationVndMotorolaFlexsuiteAdsi => write!(f, "application/vnd.motorola.flexsuite.adsi"),
+			Mime::ApplicationVndMotorolaFlexsuiteFis => write!(f, "application/vnd.motorola.flexsuite.fis"),
+			Mime::ApplicationVndMotorolaFlexsuiteGotap => write!(f, "application/vnd.motorola.flexsuite.gotap"),
+			Mime::ApplicationVndMotorolaFlexsuiteKmr => write!(f, "application/vnd.motorola.flexsuite.kmr"),
+			Mime::ApplicationVndMotorolaFlexsuiteTtc => write!(f, "application/vnd.motorola.flexsuite.ttc"),
+			Mime::ApplicationVndMotorolaFlexsuiteWem => write!(f, "application/vnd.motorola.flexsuite.wem"),
+			Mime::ApplicationVndMotorolaIprm => write!(f, "application/vnd.motorola.iprm"),
+			Mime::ApplicationVndMozillaXulXml => write!(f, "application/vnd.mozilla.xul+xml"),
+			Mime::ApplicationVndMsArtgalry => write!(f, "application/vnd.ms-artgalry"),
+			Mime::ApplicationVndMsAsf => write!(f, "application/vnd.ms-asf"),
+			Mime::ApplicationVndMsCabCompressed => write!(f, "application/vnd.ms-cab-compressed"),
+			Mime::ApplicationVndMs3mfdocument => write!(f, "application/vnd.ms-3mfdocument"),
+			Mime::ApplicationVndMsExcel => write!(f, "application/vnd.ms-excel"),
+			Mime::ApplicationVndMsExcelAddinMacroenabled12 => write!(f, "application/vnd.ms-excel.addin.macroEnabled.12"),
+			Mime::ApplicationVndMsExcelSheetBinaryMacroenabled12 => write!(f, "application/vnd.ms-excel.sheet.binary.macroEnabled.12"),
+			Mime::ApplicationVndMsExcelSheetMacroenabled12 => write!(f, "application/vnd.ms-excel.sheet.macroEnabled.12"),
+			Mime::ApplicationVndMsExcelTemplateMacroenabled12 => write!(f, "application/vnd.ms-excel.template.macroEnabled.12"),
+			Mime::ApplicationVndMsFontobject => write!(f, "application/vnd.ms-fontobject"),
+			Mime::ApplicationVndMsHtmlhelp => write!(f, "application/vnd.ms-htmlhelp"),
+			Mime::ApplicationVndMsIms => write!(f, "application/vnd.ms-ims"),
+			Mime::ApplicationVndMsLrm => write!(f, "application/vnd.ms-lrm"),
+			Mime::ApplicationVndMsOfficeActivexXml => write!(f, "application/vnd.ms-office.activeX+xml"),
+			Mime::ApplicationVndMsOfficetheme => write!(f, "application/vnd.ms-officetheme"),
+			Mime::ApplicationVndMsPlayreadyInitiatorXml => write!(f, "application/vnd.ms-playready.initiator+xml"),
+			Mime::ApplicationVndMsPowerpoint => write!(f, "application/vnd.ms-powerpoint"),
+			Mime::ApplicationVndMsPowerpointAddinMacroenabled12 => write!(f, "application/vnd.ms-powerpoint.addin.macroEnabled.12"),
+			Mime::ApplicationVndMsPowerpointPresentationMacroenabled12 => write!(f, "application/vnd.ms-powerpoint.presentation.macroEnabled.12"),
+			Mime::ApplicationVndMsPowerpointSlideMacroenabled12 => write!(f, "application/vnd.ms-powerpoint.slide.macroEnabled.12"),
+			Mime::ApplicationVndMsPowerpointSlideshowMacroenabled12 => write!(f, "application/vnd.ms-powerpoint.slideshow.macroEnabled.12"),
+			Mime::ApplicationVndMsPowerpointTemplateMacroenabled12 => write!(f, "application/vnd.ms-powerpoint.template.macroEnabled.12"),
+			Mime::ApplicationVndMsPrintdevicecapabilitiesXml => write!(f, "application/vnd.ms-PrintDeviceCapabilities+xml"),
+			Mime::ApplicationVndMsPrintschematicketXml => write!(f, "application/vnd.ms-PrintSchemaTicket+xml"),
+			Mime::ApplicationVndMsProject => write!(f, "application/vnd.ms-project"),
+			Mime::ApplicationVndMsTnef => write!(f, "application/vnd.ms-tnef"),
+			Mime::ApplicationVndMsWindowsDevicepairing => write!(f, "application/vnd.ms-windows.devicepairing"),
+			Mime::ApplicationVndMsWindowsNwprintingOob => write!(f, "application/vnd.ms-windows.nwprinting.oob"),
+			Mime::ApplicationVndMsWindowsPrinterpairing => write!(f, "application/vnd.ms-windows.printerpairing"),
+			Mime::ApplicationVndMsWindowsWsdOob => write!(f, "application/vnd.ms-windows.wsd.oob"),
+			Mime::ApplicationVndMsWmdrmLicChlgReq => write!(f, "application/vnd.ms-wmdrm.lic-chlg-req"),
+			Mime::ApplicationVndMsWmdrmLicResp => write!(f, "application/vnd.ms-wmdrm.lic-resp"),
+			Mime::ApplicationVndMsWmdrmMeterChlgReq => write!(f, "application/vnd.ms-wmdrm.meter-chlg-req"),
+			Mime::ApplicationVndMsWmdrmMeterResp => write!(f, "application/vnd.ms-wmdrm.meter-resp"),
+			Mime::ApplicationVndMsWordDocumentMacroenabled12 => write!(f, "application/vnd.ms-word.document.macroEnabled.12"),
+			Mime::ApplicationVndMsWordTemplateMacroenabled12 => write!(f, "application/vnd.ms-word.template.macroEnabled.12"),
+			Mime::ApplicationVndMsWorks => write!(f, "application/vnd.ms-works"),
+			Mime::ApplicationVndMsWpl => write!(f, "application/vnd.ms-wpl"),
+			Mime::ApplicationVndMsXpsdocument => write!(f, "application/vnd.ms-xpsdocument"),
+			Mime::ApplicationVndMsaDiskImage => write!(f, "application/vnd.msa-disk-image"),
+			Mime::ApplicationVndMseq => write!(f, "application/vnd.mseq"),
+			Mime::ApplicationVndMsign => write!(f, "application/vnd.msign"),
+			Mime::ApplicationVndMultiadCreator => write!(f, "application/vnd.multiad.creator"),
+			Mime::ApplicationVndMultiadCreatorCif => write!(f, "application/vnd.multiad.creator.cif"),
+			Mime::ApplicationVndMusician => write!(f, "application/vnd.musician"),
+			Mime::ApplicationVndMusicNiff => write!(f, "application/vnd.music-niff"),
+			Mime::ApplicationVndMuveeStyle => write!(f, "application/vnd.muvee.style"),
+			Mime::ApplicationVndMynfc => write!(f, "application/vnd.mynfc"),
+			Mime::ApplicationVndNacamarYbridJson => write!(f, "application/vnd.nacamar.ybrid+json"),
+			Mime::ApplicationVndNcdControl => write!(f, "application/vnd.ncd.control"),
+			Mime::ApplicationVndNcdReference => write!(f, "application/vnd.ncd.reference"),
+			Mime::ApplicationVndNearstInvJson => write!(f, "application/vnd.nearst.inv+json"),
+			Mime::ApplicationVndNebumindLine => write!(f, "application/vnd.nebumind.line"),
+			Mime::ApplicationVndNervana => write!(f, "application/vnd.nervana"),
+			Mime::ApplicationVndNetfpx => write!(f, "application/vnd.netfpx"),
+			Mime::ApplicationVndNeurolanguageNlu => write!(f, "application/vnd.neurolanguage.nlu"),
+			Mime::ApplicationVndNimn => write!(f, "application/vnd.nimn"),
+			Mime::ApplicationVndNintendoSnesRom => write!(f, "application/vnd.nintendo.snes.rom"),
+			Mime::ApplicationVndNintendoNitroRom => write!(f, "application/vnd.nintendo.nitro.rom"),
+			Mime::ApplicationVndNitf => write!(f, "application/vnd.nitf"),
+			Mime::ApplicationVndNoblenetDirectory => write!(f, "application/vnd.noblenet-directory"),
+			Mime::ApplicationVndNoblenetSealer => write!(f, "application/vnd.noblenet-sealer"),
+			Mime::ApplicationVndNoblenetWeb => write!(f, "application/vnd.noblenet-web"),
+			Mime::ApplicationVndNokiaCatalogs => write!(f, "application/vnd.nokia.catalogs"),
+			Mime::ApplicationVndNokiaConmlWbxml => write!(f, "application/vnd.nokia.conml+wbxml"),
+			Mime::ApplicationVndNokiaConmlXml => write!(f, "application/vnd.nokia.conml+xml"),
+			Mime::ApplicationVndNokiaIptvConfigXml => write!(f, "application/vnd.nokia.iptv.config+xml"),
+			Mime::ApplicationVndNokiaIsdsRadioPresets => write!(f, "application/vnd.nokia.iSDS-radio-presets"),
+			Mime::ApplicationVndNokiaLandmarkWbxml => write!(f, "application/vnd.nokia.landmark+wbxml"),
+			Mime::ApplicationVndNokiaLandmarkXml => write!(f, "application/vnd.nokia.landmark+xml"),
+			Mime::ApplicationVndNokiaLandmarkcollectionXml => write!(f, "application/vnd.nokia.landmarkcollection+xml"),
+			Mime::ApplicationVndNokiaNcd => write!(f, "application/vnd.nokia.ncd"),
+			Mime::ApplicationVndNokiaNGageAcXml => write!(f, "application/vnd.nokia.n-gage.ac+xml"),
+			Mime::ApplicationVndNokiaNGageData => write!(f, "application/vnd.nokia.n-gage.data"),
+			Mime::ApplicationVndNokiaPcdWbxml => write!(f, "application/vnd.nokia.pcd+wbxml"),
+			Mime::ApplicationVndNokiaPcdXml => write!(f, "application/vnd.nokia.pcd+xml"),
+			Mime::ApplicationVndNokiaRadioPreset => write!(f, "application/vnd.nokia.radio-preset"),
+			Mime::ApplicationVndNokiaRadioPresets => write!(f, "application/vnd.nokia.radio-presets"),
+			Mime::ApplicationVndNovadigmEdm => write!(f, "application/vnd.novadigm.EDM"),
+			Mime::ApplicationVndNovadigmEdx => write!(f, "application/vnd.novadigm.EDX"),
+			Mime::ApplicationVndNovadigmExt => write!(f, "application/vnd.novadigm.EXT"),
+			Mime::ApplicationVndNttLocalContentShare => write!(f, "application/vnd.ntt-local.content-share"),
+			Mime::ApplicationVndNttLocalFileTransfer => write!(f, "application/vnd.ntt-local.file-transfer"),
+			Mime::ApplicationVndNttLocalOgwRemoteAccess => write!(f, "application/vnd.ntt-local.ogw_remote-access"),
+			Mime::ApplicationVndNttLocalSipTaRemote => write!(f, "application/vnd.ntt-local.sip-ta_remote"),
+			Mime::ApplicationVndNttLocalSipTaTcpStream => write!(f, "application/vnd.ntt-local.sip-ta_tcp_stream"),
+			Mime::ApplicationVndOasisOpendocumentBase => write!(f, "application/vnd.oasis.opendocument.base"),
+			Mime::ApplicationVndOasisOpendocumentChart => write!(f, "application/vnd.oasis.opendocument.chart"),
+			Mime::ApplicationVndOasisOpendocumentChartTemplate => write!(f, "application/vnd.oasis.opendocument.chart-template"),
+			Mime::ApplicationVndOasisOpendocumentFormula => write!(f, "application/vnd.oasis.opendocument.formula"),
+			Mime::ApplicationVndOasisOpendocumentFormulaTemplate => write!(f, "application/vnd.oasis.opendocument.formula-template"),
+			Mime::ApplicationVndOasisOpendocumentGraphics => write!(f, "application/vnd.oasis.opendocument.graphics"),
+			Mime::ApplicationVndOasisOpendocumentGraphicsTemplate => write!(f, "application/vnd.oasis.opendocument.graphics-template"),
+			Mime::ApplicationVndOasisOpendocumentImage => write!(f, "application/vnd.oasis.opendocument.image"),
+			Mime::ApplicationVndOasisOpendocumentImageTemplate => write!(f, "application/vnd.oasis.opendocument.image-template"),
+			Mime::ApplicationVndOasisOpendocumentPresentation => write!(f, "application/vnd.oasis.opendocument.presentation"),
+			Mime::ApplicationVndOasisOpendocumentPresentationTemplate => write!(f, "application/vnd.oasis.opendocument.presentation-template"),
+			Mime::ApplicationVndOasisOpendocumentSpreadsheet => write!(f, "application/vnd.oasis.opendocument.spreadsheet"),
+			Mime::ApplicationVndOasisOpendocumentSpreadsheetTemplate => write!(f, "application/vnd.oasis.opendocument.spreadsheet-template"),
+			Mime::ApplicationVndOasisOpendocumentText => write!(f, "application/vnd.oasis.opendocument.text"),
+			Mime::ApplicationVndOasisOpendocumentTextMaster => write!(f, "application/vnd.oasis.opendocument.text-master"),
+			Mime::ApplicationVndOasisOpendocumentTextMasterTemplate => write!(f, "application/vnd.oasis.opendocument.text-master-template"),
+			Mime::ApplicationVndOasisOpendocumentTextTemplate => write!(f, "application/vnd.oasis.opendocument.text-template"),
+			Mime::ApplicationVndOasisOpendocumentTextWeb => write!(f, "application/vnd.oasis.opendocument.text-web"),
+			Mime::ApplicationVndObn => write!(f, "application/vnd.obn"),
+			Mime::ApplicationVndOcfCbor => write!(f, "application/vnd.ocf+cbor"),
+			Mime::ApplicationVndOciImageManifestV1Json => write!(f, "application/vnd.oci.image.manifest.v1+json"),
+			Mime::ApplicationVndOftnL10nJson => write!(f, "application/vnd.oftn.l10n+json"),
+			Mime::ApplicationVndOipfContentaccessdownloadXml => write!(f, "application/vnd.oipf.contentaccessdownload+xml"),
+			Mime::ApplicationVndOipfContentaccessstreamingXml => write!(f, "application/vnd.oipf.contentaccessstreaming+xml"),
+			Mime::ApplicationVndOipfCspgHexbinary => write!(f, "application/vnd.oipf.cspg-hexbinary"),
+			Mime::ApplicationVndOipfDaeSvgXml => write!(f, "application/vnd.oipf.dae.svg+xml"),
+			Mime::ApplicationVndOipfDaeXhtmlXml => write!(f, "application/vnd.oipf.dae.xhtml+xml"),
+			Mime::ApplicationVndOipfMippvcontrolmessageXml => write!(f, "application/vnd.oipf.mippvcontrolmessage+xml"),
+			Mime::ApplicationVndOipfPaeGem => write!(f, "application/vnd.oipf.pae.gem"),
+			Mime::ApplicationVndOipfSpdiscoveryXml => write!(f, "application/vnd.oipf.spdiscovery+xml"),
+			Mime::ApplicationVndOipfSpdlistXml => write!(f, "application/vnd.oipf.spdlist+xml"),
+			Mime::ApplicationVndOipfUeprofileXml => write!(f, "application/vnd.oipf.ueprofile+xml"),
+			Mime::ApplicationVndOipfUserprofileXml => write!(f, "application/vnd.oipf.userprofile+xml"),
+			Mime::ApplicationVndOlpcSugar => write!(f, "application/vnd.olpc-sugar"),
+			Mime::ApplicationVndOmaBcastAssociatedProcedureParameterXml => write!(f, "application/vnd.oma.bcast.associated-procedure-parameter+xml"),
+			Mime::ApplicationVndOmaBcastDrmTriggerXml => write!(f, "application/vnd.oma.bcast.drm-trigger+xml"),
+			Mime::ApplicationVndOmaBcastImdXml => write!(f, "application/vnd.oma.bcast.imd+xml"),
+			Mime::ApplicationVndOmaBcastLtkm => write!(f, "application/vnd.oma.bcast.ltkm"),
+			Mime::ApplicationVndOmaBcastNotificationXml => write!(f, "application/vnd.oma.bcast.notification+xml"),
+			Mime::ApplicationVndOmaBcastProvisioningtrigger => write!(f, "application/vnd.oma.bcast.provisioningtrigger"),
+			Mime::ApplicationVndOmaBcastSgboot => write!(f, "application/vnd.oma.bcast.sgboot"),
+			Mime::ApplicationVndOmaBcastSgddXml => write!(f, "application/vnd.oma.bcast.sgdd+xml"),
+			Mime::ApplicationVndOmaBcastSgdu => write!(f, "application/vnd.oma.bcast.sgdu"),
+			Mime::ApplicationVndOmaBcastSimpleSymbolContainer => write!(f, "application/vnd.oma.bcast.simple-symbol-container"),
+			Mime::ApplicationVndOmaBcastSmartcardTriggerXml => write!(f, "application/vnd.oma.bcast.smartcard-trigger+xml"),
+			Mime::ApplicationVndOmaBcastSprovXml => write!(f, "application/vnd.oma.bcast.sprov+xml"),
+			Mime::ApplicationVndOmaBcastStkm => write!(f, "application/vnd.oma.bcast.stkm"),
+			Mime::ApplicationVndOmaCabAddressBookXml => write!(f, "application/vnd.oma.cab-address-book+xml"),
+			Mime::ApplicationVndOmaCabFeatureHandlerXml => write!(f, "application/vnd.oma.cab-feature-handler+xml"),
+			Mime::ApplicationVndOmaCabPccXml => write!(f, "application/vnd.oma.cab-pcc+xml"),
+			Mime::ApplicationVndOmaCabSubsInviteXml => write!(f, "application/vnd.oma.cab-subs-invite+xml"),
+			Mime::ApplicationVndOmaCabUserPrefsXml => write!(f, "application/vnd.oma.cab-user-prefs+xml"),
+			Mime::ApplicationVndOmaDcd => write!(f, "application/vnd.oma.dcd"),
+			Mime::ApplicationVndOmaDcdc => write!(f, "application/vnd.oma.dcdc"),
+			Mime::ApplicationVndOmaDd2Xml => write!(f, "application/vnd.oma.dd2+xml"),
+			Mime::ApplicationVndOmaDrmRisdXml => write!(f, "application/vnd.oma.drm.risd+xml"),
+			Mime::ApplicationVndOmaGroupUsageListXml => write!(f, "application/vnd.oma.group-usage-list+xml"),
+			Mime::ApplicationVndOmaLwm2mCbor => write!(f, "application/vnd.oma.lwm2m+cbor"),
+			Mime::ApplicationVndOmaLwm2mJson => write!(f, "application/vnd.oma.lwm2m+json"),
+			Mime::ApplicationVndOmaLwm2mTlv => write!(f, "application/vnd.oma.lwm2m+tlv"),
+			Mime::ApplicationVndOmaPalXml => write!(f, "application/vnd.oma.pal+xml"),
+			Mime::ApplicationVndOmaPocDetailedProgressReportXml => write!(f, "application/vnd.oma.poc.detailed-progress-report+xml"),
+			Mime::ApplicationVndOmaPocFinalReportXml => write!(f, "application/vnd.oma.poc.final-report+xml"),
+			Mime::ApplicationVndOmaPocGroupsXml => write!(f, "application/vnd.oma.poc.groups+xml"),
+			Mime::ApplicationVndOmaPocInvocationDescriptorXml => write!(f, "application/vnd.oma.poc.invocation-descriptor+xml"),
+			Mime::ApplicationVndOmaPocOptimizedProgressReportXml => write!(f, "application/vnd.oma.poc.optimized-progress-report+xml"),
+			Mime::ApplicationVndOmaPush => write!(f, "application/vnd.oma.push"),
+			Mime::ApplicationVndOmaScidmMessagesXml => write!(f, "application/vnd.oma.scidm.messages+xml"),
+			Mime::ApplicationVndOmaXcapDirectoryXml => write!(f, "application/vnd.oma.xcap-directory+xml"),
+			Mime::ApplicationVndOmadsEmailXml => write!(f, "application/vnd.omads-email+xml"),
+			Mime::ApplicationVndOmadsFileXml => write!(f, "application/vnd.omads-file+xml"),
+			Mime::ApplicationVndOmadsFolderXml => write!(f, "application/vnd.omads-folder+xml"),
+			Mime::ApplicationVndOmalocSuplInit => write!(f, "application/vnd.omaloc-supl-init"),
+			Mime::ApplicationVndOmaScwsConfig => write!(f, "application/vnd.oma-scws-config"),
+			Mime::ApplicationVndOmaScwsHttpRequest => write!(f, "application/vnd.oma-scws-http-request"),
+			Mime::ApplicationVndOmaScwsHttpResponse => write!(f, "application/vnd.oma-scws-http-response"),
+			Mime::ApplicationVndOnepager => write!(f, "application/vnd.onepager"),
+			Mime::ApplicationVndOnepagertamp => write!(f, "application/vnd.onepagertamp"),
+			Mime::ApplicationVndOnepagertamx => write!(f, "application/vnd.onepagertamx"),
+			Mime::ApplicationVndOnepagertat => write!(f, "application/vnd.onepagertat"),
+			Mime::ApplicationVndOnepagertatp => write!(f, "application/vnd.onepagertatp"),
+			Mime::ApplicationVndOnepagertatx => write!(f, "application/vnd.onepagertatx"),
+			Mime::ApplicationVndOnvifMetadata => write!(f, "application/vnd.onvif.metadata"),
+			Mime::ApplicationVndOpenbloxGameBinary => write!(f, "application/vnd.openblox.game-binary"),
+			Mime::ApplicationVndOpenbloxGameXml => write!(f, "application/vnd.openblox.game+xml"),
+			Mime::ApplicationVndOpeneyeOeb => write!(f, "application/vnd.openeye.oeb"),
+			Mime::ApplicationVndOpenstreetmapDataXml => write!(f, "application/vnd.openstreetmap.data+xml"),
+			Mime::ApplicationVndOpentimestampsOts => write!(f, "application/vnd.opentimestamps.ots"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentCustomPropertiesXml => write!(f, "application/vnd.openxmlformats-officedocument.custom-properties+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentCustomxmlpropertiesXml => write!(f, "application/vnd.openxmlformats-officedocument.customXmlProperties+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentDrawingXml => write!(f, "application/vnd.openxmlformats-officedocument.drawing+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentDrawingmlChartXml => write!(f, "application/vnd.openxmlformats-officedocument.drawingml.chart+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentDrawingmlChartshapesXml => write!(f, "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentDrawingmlDiagramcolorsXml => write!(f, "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentDrawingmlDiagramdataXml => write!(f, "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentDrawingmlDiagramlayoutXml => write!(f, "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentDrawingmlDiagramstyleXml => write!(f, "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentExtendedPropertiesXml => write!(f, "application/vnd.openxmlformats-officedocument.extended-properties+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlCommentauthorsXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.commentAuthors+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlCommentsXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.comments+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlHandoutmasterXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.handoutMaster+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlNotesmasterXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlNotesslideXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlPresentation => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.presentation"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlPresentationMainXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlPrespropsXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.presProps+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlide => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.slide"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlideXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.slide+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlidelayoutXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlidemasterXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlideshow => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.slideshow"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlideshowMainXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlSlideupdateinfoXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.slideUpdateInfo+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlTablestylesXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlTagsXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.tags+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlTemplate => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.template"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlTemplateMainXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentPresentationmlViewpropsXml => write!(f, "application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlCalcchainXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlChartsheetXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlCommentsXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlConnectionsXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlDialogsheetXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlExternallinkXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlPivotcachedefinitionXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlPivotcacherecordsXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlPivottableXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlQuerytableXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlRevisionheadersXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlRevisionlogXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSharedstringsXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSheet => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSheetMainXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSheetmetadataXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlStylesXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlTableXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlTablesinglecellsXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlTemplate => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.template"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlTemplateMainXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlUsernamesXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlVolatiledependenciesXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.volatileDependencies+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlWorksheetXml => write!(f, "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentThemeXml => write!(f, "application/vnd.openxmlformats-officedocument.theme+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentThemeoverrideXml => write!(f, "application/vnd.openxmlformats-officedocument.themeOverride+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentVmldrawing => write!(f, "application/vnd.openxmlformats-officedocument.vmlDrawing"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlCommentsXml => write!(f, "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlDocument => write!(f, "application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlDocumentGlossaryXml => write!(f, "application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlDocumentMainXml => write!(f, "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlEndnotesXml => write!(f, "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlFonttableXml => write!(f, "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlFooterXml => write!(f, "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlFootnotesXml => write!(f, "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlNumberingXml => write!(f, "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlSettingsXml => write!(f, "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlStylesXml => write!(f, "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlTemplate => write!(f, "application/vnd.openxmlformats-officedocument.wordprocessingml.template"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlTemplateMainXml => write!(f, "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml"),
+			Mime::ApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlWebsettingsXml => write!(f, "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"),
+			Mime::ApplicationVndOpenxmlformatsPackageCorePropertiesXml => write!(f, "application/vnd.openxmlformats-package.core-properties+xml"),
+			Mime::ApplicationVndOpenxmlformatsPackageDigitalSignatureXmlsignatureXml => write!(f, "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"),
+			Mime::ApplicationVndOpenxmlformatsPackageRelationshipsXml => write!(f, "application/vnd.openxmlformats-package.relationships+xml"),
+			Mime::ApplicationVndOracleResourceJson => write!(f, "application/vnd.oracle.resource+json"),
+			Mime::ApplicationVndOrangeIndata => write!(f, "application/vnd.orange.indata"),
+			Mime::ApplicationVndOsaNetdeploy => write!(f, "application/vnd.osa.netdeploy"),
+			Mime::ApplicationVndOsgeoMapguidePackage => write!(f, "application/vnd.osgeo.mapguide.package"),
+			Mime::ApplicationVndOsgiBundle => write!(f, "application/vnd.osgi.bundle"),
+			Mime::ApplicationVndOsgiDp => write!(f, "application/vnd.osgi.dp"),
+			Mime::ApplicationVndOsgiSubsystem => write!(f, "application/vnd.osgi.subsystem"),
+			Mime::ApplicationVndOtpsCtKipXml => write!(f, "application/vnd.otps.ct-kip+xml"),
+			Mime::ApplicationVndOxliCountgraph => write!(f, "application/vnd.oxli.countgraph"),
+			Mime::ApplicationVndPagerdutyJson => write!(f, "application/vnd.pagerduty+json"),
+			Mime::ApplicationVndPalm => write!(f, "application/vnd.palm"),
+			Mime::ApplicationVndPanoply => write!(f, "application/vnd.panoply"),
+			Mime::ApplicationVndPaosXml => write!(f, "application/vnd.paos.xml"),
+			Mime::ApplicationVndPatentdive => write!(f, "application/vnd.patentdive"),
+			Mime::ApplicationVndPatientecommsdoc => write!(f, "application/vnd.patientecommsdoc"),
+			Mime::ApplicationVndPawaafile => write!(f, "application/vnd.pawaafile"),
+			Mime::ApplicationVndPcos => write!(f, "application/vnd.pcos"),
+			Mime::ApplicationVndPgFormat => write!(f, "application/vnd.pg.format"),
+			Mime::ApplicationVndPgOsasli => write!(f, "application/vnd.pg.osasli"),
+			Mime::ApplicationVndPiaccessApplicationLicence => write!(f, "application/vnd.piaccess.application-licence"),
+			Mime::ApplicationVndPicsel => write!(f, "application/vnd.picsel"),
+			Mime::ApplicationVndPmiWidget => write!(f, "application/vnd.pmi.widget"),
+			Mime::ApplicationVndPocGroupAdvertisementXml => write!(f, "application/vnd.poc.group-advertisement+xml"),
+			Mime::ApplicationVndPocketlearn => write!(f, "application/vnd.pocketlearn"),
+			Mime::ApplicationVndPowerbuilder6 => write!(f, "application/vnd.powerbuilder6"),
+			Mime::ApplicationVndPowerbuilder6S => write!(f, "application/vnd.powerbuilder6-s"),
+			Mime::ApplicationVndPowerbuilder7 => write!(f, "application/vnd.powerbuilder7"),
+			Mime::ApplicationVndPowerbuilder75 => write!(f, "application/vnd.powerbuilder75"),
+			Mime::ApplicationVndPowerbuilder75S => write!(f, "application/vnd.powerbuilder75-s"),
+			Mime::ApplicationVndPowerbuilder7S => write!(f, "application/vnd.powerbuilder7-s"),
+			Mime::ApplicationVndPreminet => write!(f, "application/vnd.preminet"),
+			Mime::ApplicationVndPreviewsystemsBox => write!(f, "application/vnd.previewsystems.box"),
+			Mime::ApplicationVndProteusMagazine => write!(f, "application/vnd.proteus.magazine"),
+			Mime::ApplicationVndPsfs => write!(f, "application/vnd.psfs"),
+			Mime::ApplicationVndPtMundusmundi => write!(f, "application/vnd.pt.mundusmundi"),
+			Mime::ApplicationVndPublishareDeltaTree => write!(f, "application/vnd.publishare-delta-tree"),
+			Mime::ApplicationVndPviPtid1 => write!(f, "application/vnd.pvi.ptid1"),
+			Mime::ApplicationVndPwgMultiplexed => write!(f, "application/vnd.pwg-multiplexed"),
+			Mime::ApplicationVndPwgXhtmlPrintXml => write!(f, "application/vnd.pwg-xhtml-print+xml"),
+			Mime::ApplicationVndQualcommBrewAppRes => write!(f, "application/vnd.qualcomm.brew-app-res"),
+			Mime::ApplicationVndQuarantainenet => write!(f, "application/vnd.quarantainenet"),
+			Mime::ApplicationVndQuarkQuarkxpress => write!(f, "application/vnd.Quark.QuarkXPress"),
+			Mime::ApplicationVndQuobjectQuoxdocument => write!(f, "application/vnd.quobject-quoxdocument"),
+			Mime::ApplicationVndRadisysMomlXml => write!(f, "application/vnd.radisys.moml+xml"),
+			Mime::ApplicationVndRadisysMsmlAuditConfXml => write!(f, "application/vnd.radisys.msml-audit-conf+xml"),
+			Mime::ApplicationVndRadisysMsmlAuditConnXml => write!(f, "application/vnd.radisys.msml-audit-conn+xml"),
+			Mime::ApplicationVndRadisysMsmlAuditDialogXml => write!(f, "application/vnd.radisys.msml-audit-dialog+xml"),
+			Mime::ApplicationVndRadisysMsmlAuditStreamXml => write!(f, "application/vnd.radisys.msml-audit-stream+xml"),
+			Mime::ApplicationVndRadisysMsmlAuditXml => write!(f, "application/vnd.radisys.msml-audit+xml"),
+			Mime::ApplicationVndRadisysMsmlConfXml => write!(f, "application/vnd.radisys.msml-conf+xml"),
+			Mime::ApplicationVndRadisysMsmlDialogBaseXml => write!(f, "application/vnd.radisys.msml-dialog-base+xml"),
+			Mime::ApplicationVndRadisysMsmlDialogFaxDetectXml => write!(f, "application/vnd.radisys.msml-dialog-fax-detect+xml"),
+			Mime::ApplicationVndRadisysMsmlDialogFaxSendrecvXml => write!(f, "application/vnd.radisys.msml-dialog-fax-sendrecv+xml"),
+			Mime::ApplicationVndRadisysMsmlDialogGroupXml => write!(f, "application/vnd.radisys.msml-dialog-group+xml"),
+			Mime::ApplicationVndRadisysMsmlDialogSpeechXml => write!(f, "application/vnd.radisys.msml-dialog-speech+xml"),
+			Mime::ApplicationVndRadisysMsmlDialogTransformXml => write!(f, "application/vnd.radisys.msml-dialog-transform+xml"),
+			Mime::ApplicationVndRadisysMsmlDialogXml => write!(f, "application/vnd.radisys.msml-dialog+xml"),
+			Mime::ApplicationVndRadisysMsmlXml => write!(f, "application/vnd.radisys.msml+xml"),
+			Mime::ApplicationVndRainstorData => write!(f, "application/vnd.rainstor.data"),
+			Mime::ApplicationVndRapid => write!(f, "application/vnd.rapid"),
+			Mime::ApplicationVndRar => write!(f, "application/vnd.rar"),
+			Mime::ApplicationVndRealvncBed => write!(f, "application/vnd.realvnc.bed"),
+			Mime::ApplicationVndRecordareMusicxml => write!(f, "application/vnd.recordare.musicxml"),
+			Mime::ApplicationVndRecordareMusicxmlXml => write!(f, "application/vnd.recordare.musicxml+xml"),
+			Mime::ApplicationVndRenlearnRlprint => write!(f, "application/vnd.RenLearn.rlprint"),
+			Mime::ApplicationVndResilientLogic => write!(f, "application/vnd.resilient.logic"),
+			Mime::ApplicationVndRestfulJson => write!(f, "application/vnd.restful+json"),
+			Mime::ApplicationVndRigCryptonote => write!(f, "application/vnd.rig.cryptonote"),
+			Mime::ApplicationVndRoute66Link66Xml => write!(f, "application/vnd.route66.link66+xml"),
+			Mime::ApplicationVndRs274x => write!(f, "application/vnd.rs-274x"),
+			Mime::ApplicationVndRuckusDownload => write!(f, "application/vnd.ruckus.download"),
+			Mime::ApplicationVndS3sms => write!(f, "application/vnd.s3sms"),
+			Mime::ApplicationVndSailingtrackerTrack => write!(f, "application/vnd.sailingtracker.track"),
+			Mime::ApplicationVndSar => write!(f, "application/vnd.sar"),
+			Mime::ApplicationVndSbmCid => write!(f, "application/vnd.sbm.cid"),
+			Mime::ApplicationVndSbmMid2 => write!(f, "application/vnd.sbm.mid2"),
+			Mime::ApplicationVndScribus => write!(f, "application/vnd.scribus"),
+			Mime::ApplicationVndSealed3df => write!(f, "application/vnd.sealed.3df"),
+			Mime::ApplicationVndSealedCsf => write!(f, "application/vnd.sealed.csf"),
+			Mime::ApplicationVndSealedDoc => write!(f, "application/vnd.sealed.doc"),
+			Mime::ApplicationVndSealedEml => write!(f, "application/vnd.sealed.eml"),
+			Mime::ApplicationVndSealedMht => write!(f, "application/vnd.sealed.mht"),
+			Mime::ApplicationVndSealedNet => write!(f, "application/vnd.sealed.net"),
+			Mime::ApplicationVndSealedPpt => write!(f, "application/vnd.sealed.ppt"),
+			Mime::ApplicationVndSealedTiff => write!(f, "application/vnd.sealed.tiff"),
+			Mime::ApplicationVndSealedXls => write!(f, "application/vnd.sealed.xls"),
+			Mime::ApplicationVndSealedmediaSoftsealHtml => write!(f, "application/vnd.sealedmedia.softseal.html"),
+			Mime::ApplicationVndSealedmediaSoftsealPdf => write!(f, "application/vnd.sealedmedia.softseal.pdf"),
+			Mime::ApplicationVndSeemail => write!(f, "application/vnd.seemail"),
+			Mime::ApplicationVndSeisJson => write!(f, "application/vnd.seis+json"),
+			Mime::ApplicationVndSema => write!(f, "application/vnd.sema"),
+			Mime::ApplicationVndSemd => write!(f, "application/vnd.semd"),
+			Mime::ApplicationVndSemf => write!(f, "application/vnd.semf"),
+			Mime::ApplicationVndShadeSaveFile => write!(f, "application/vnd.shade-save-file"),
+			Mime::ApplicationVndShanaInformedFormdata => write!(f, "application/vnd.shana.informed.formdata"),
+			Mime::ApplicationVndShanaInformedFormtemplate => write!(f, "application/vnd.shana.informed.formtemplate"),
+			Mime::ApplicationVndShanaInformedInterchange => write!(f, "application/vnd.shana.informed.interchange"),
+			Mime::ApplicationVndShanaInformedPackage => write!(f, "application/vnd.shana.informed.package"),
+			Mime::ApplicationVndShootproofJson => write!(f, "application/vnd.shootproof+json"),
+			Mime::ApplicationVndShopkickJson => write!(f, "application/vnd.shopkick+json"),
+			Mime::ApplicationVndShp => write!(f, "application/vnd.shp"),
+			Mime::ApplicationVndShx => write!(f, "application/vnd.shx"),
+			Mime::ApplicationVndSigrokSession => write!(f, "application/vnd.sigrok.session"),
+			Mime::ApplicationVndSimtechMindmapper => write!(f, "application/vnd.SimTech-MindMapper"),
+			Mime::ApplicationVndSirenJson => write!(f, "application/vnd.siren+json"),
+			Mime::ApplicationVndSmaf => write!(f, "application/vnd.smaf"),
+			Mime::ApplicationVndSmartNotebook => write!(f, "application/vnd.smart.notebook"),
+			Mime::ApplicationVndSmartTeacher => write!(f, "application/vnd.smart.teacher"),
+			Mime::ApplicationVndSmintioPortalsArchive => write!(f, "application/vnd.smintio.portals.archive"),
+			Mime::ApplicationVndSnesdevPageTable => write!(f, "application/vnd.snesdev-page-table"),
+			Mime::ApplicationVndSoftware602FillerFormXml => write!(f, "application/vnd.software602.filler.form+xml"),
+			Mime::ApplicationVndSoftware602FillerFormXmlZip => write!(f, "application/vnd.software602.filler.form-xml-zip"),
+			Mime::ApplicationVndSolentSdkmXml => write!(f, "application/vnd.solent.sdkm+xml"),
+			Mime::ApplicationVndSpotfireDxp => write!(f, "application/vnd.spotfire.dxp"),
+			Mime::ApplicationVndSpotfireSfs => write!(f, "application/vnd.spotfire.sfs"),
+			Mime::ApplicationVndSqlite3 => write!(f, "application/vnd.sqlite3"),
+			Mime::ApplicationVndSssCod => write!(f, "application/vnd.sss-cod"),
+			Mime::ApplicationVndSssDtf => write!(f, "application/vnd.sss-dtf"),
+			Mime::ApplicationVndSssNtf => write!(f, "application/vnd.sss-ntf"),
+			Mime::ApplicationVndStepmaniaPackage => write!(f, "application/vnd.stepmania.package"),
+			Mime::ApplicationVndStepmaniaStepchart => write!(f, "application/vnd.stepmania.stepchart"),
+			Mime::ApplicationVndStreetStream => write!(f, "application/vnd.street-stream"),
+			Mime::ApplicationVndSunWadlXml => write!(f, "application/vnd.sun.wadl+xml"),
+			Mime::ApplicationVndSusCalendar => write!(f, "application/vnd.sus-calendar"),
+			Mime::ApplicationVndSvd => write!(f, "application/vnd.svd"),
+			Mime::ApplicationVndSwiftviewIcs => write!(f, "application/vnd.swiftview-ics"),
+			Mime::ApplicationVndSybylMol2 => write!(f, "application/vnd.sybyl.mol2"),
+			Mime::ApplicationVndSycleXml => write!(f, "application/vnd.sycle+xml"),
+			Mime::ApplicationVndSyftJson => write!(f, "application/vnd.syft+json"),
+			Mime::ApplicationVndSyncmlDmNotification => write!(f, "application/vnd.syncml.dm.notification"),
+			Mime::ApplicationVndSyncmlDmddfXml => write!(f, "application/vnd.syncml.dmddf+xml"),
+			Mime::ApplicationVndSyncmlDmtndsWbxml => write!(f, "application/vnd.syncml.dmtnds+wbxml"),
+			Mime::ApplicationVndSyncmlDmtndsXml => write!(f, "application/vnd.syncml.dmtnds+xml"),
+			Mime::ApplicationVndSyncmlDmddfWbxml => write!(f, "application/vnd.syncml.dmddf+wbxml"),
+			Mime::ApplicationVndSyncmlDmWbxml => write!(f, "application/vnd.syncml.dm+wbxml"),
+			Mime::ApplicationVndSyncmlDmXml => write!(f, "application/vnd.syncml.dm+xml"),
+			Mime::ApplicationVndSyncmlDsNotification => write!(f, "application/vnd.syncml.ds.notification"),
+			Mime::ApplicationVndSyncmlXml => write!(f, "application/vnd.syncml+xml"),
+			Mime::ApplicationVndTableschemaJson => write!(f, "application/vnd.tableschema+json"),
+			Mime::ApplicationVndTaoIntentModuleArchive => write!(f, "application/vnd.tao.intent-module-archive"),
+			Mime::ApplicationVndTcpdumpPcap => write!(f, "application/vnd.tcpdump.pcap"),
+			Mime::ApplicationVndThinkCellPpttcJson => write!(f, "application/vnd.think-cell.ppttc+json"),
+			Mime::ApplicationVndTml => write!(f, "application/vnd.tml"),
+			Mime::ApplicationVndTmdMediaflexApiXml => write!(f, "application/vnd.tmd.mediaflex.api+xml"),
+			Mime::ApplicationVndTmobileLivetv => write!(f, "application/vnd.tmobile-livetv"),
+			Mime::ApplicationVndTriOnesource => write!(f, "application/vnd.tri.onesource"),
+			Mime::ApplicationVndTridTpt => write!(f, "application/vnd.trid.tpt"),
+			Mime::ApplicationVndTriscapeMxs => write!(f, "application/vnd.triscape.mxs"),
+			Mime::ApplicationVndTrueapp => write!(f, "application/vnd.trueapp"),
+			Mime::ApplicationVndTruedoc => write!(f, "application/vnd.truedoc"),
+			Mime::ApplicationVndUbisoftWebplayer => write!(f, "application/vnd.ubisoft.webplayer"),
+			Mime::ApplicationVndUfdl => write!(f, "application/vnd.ufdl"),
+			Mime::ApplicationVndUiqTheme => write!(f, "application/vnd.uiq.theme"),
+			Mime::ApplicationVndUmajin => write!(f, "application/vnd.umajin"),
+			Mime::ApplicationVndUnity => write!(f, "application/vnd.unity"),
+			Mime::ApplicationVndUomlXml => write!(f, "application/vnd.uoml+xml"),
+			Mime::ApplicationVndUplanetAlert => write!(f, "application/vnd.uplanet.alert"),
+			Mime::ApplicationVndUplanetAlertWbxml => write!(f, "application/vnd.uplanet.alert-wbxml"),
+			Mime::ApplicationVndUplanetBearerChoice => write!(f, "application/vnd.uplanet.bearer-choice"),
+			Mime::ApplicationVndUplanetBearerChoiceWbxml => write!(f, "application/vnd.uplanet.bearer-choice-wbxml"),
+			Mime::ApplicationVndUplanetCacheop => write!(f, "application/vnd.uplanet.cacheop"),
+			Mime::ApplicationVndUplanetCacheopWbxml => write!(f, "application/vnd.uplanet.cacheop-wbxml"),
+			Mime::ApplicationVndUplanetChannel => write!(f, "application/vnd.uplanet.channel"),
+			Mime::ApplicationVndUplanetChannelWbxml => write!(f, "application/vnd.uplanet.channel-wbxml"),
+			Mime::ApplicationVndUplanetList => write!(f, "application/vnd.uplanet.list"),
+			Mime::ApplicationVndUplanetListcmd => write!(f, "application/vnd.uplanet.listcmd"),
+			Mime::ApplicationVndUplanetListcmdWbxml => write!(f, "application/vnd.uplanet.listcmd-wbxml"),
+			Mime::ApplicationVndUplanetListWbxml => write!(f, "application/vnd.uplanet.list-wbxml"),
+			Mime::ApplicationVndUriMap => write!(f, "application/vnd.uri-map"),
+			Mime::ApplicationVndUplanetSignal => write!(f, "application/vnd.uplanet.signal"),
+			Mime::ApplicationVndValveSourceMaterial => write!(f, "application/vnd.valve.source.material"),
+			Mime::ApplicationVndVcx => write!(f, "application/vnd.vcx"),
+			Mime::ApplicationVndVdStudy => write!(f, "application/vnd.vd-study"),
+			Mime::ApplicationVndVectorworks => write!(f, "application/vnd.vectorworks"),
+			Mime::ApplicationVndVelJson => write!(f, "application/vnd.vel+json"),
+			Mime::ApplicationVndVerimatrixVcas => write!(f, "application/vnd.verimatrix.vcas"),
+			Mime::ApplicationVndVeritoneAionJson => write!(f, "application/vnd.veritone.aion+json"),
+			Mime::ApplicationVndVeryantThin => write!(f, "application/vnd.veryant.thin"),
+			Mime::ApplicationVndVesEncrypted => write!(f, "application/vnd.ves.encrypted"),
+			Mime::ApplicationVndVidsoftVidconference => write!(f, "application/vnd.vidsoft.vidconference"),
+			Mime::ApplicationVndVisio => write!(f, "application/vnd.visio"),
+			Mime::ApplicationVndVisionary => write!(f, "application/vnd.visionary"),
+			Mime::ApplicationVndVividenceScriptfile => write!(f, "application/vnd.vividence.scriptfile"),
+			Mime::ApplicationVndVsf => write!(f, "application/vnd.vsf"),
+			Mime::ApplicationVndWapSic => write!(f, "application/vnd.wap.sic"),
+			Mime::ApplicationVndWapSlc => write!(f, "application/vnd.wap.slc"),
+			Mime::ApplicationVndWapWbxml => write!(f, "application/vnd.wap.wbxml"),
+			Mime::ApplicationVndWapWmlc => write!(f, "application/vnd.wap.wmlc"),
+			Mime::ApplicationVndWapWmlscriptc => write!(f, "application/vnd.wap.wmlscriptc"),
+			Mime::ApplicationVndWasmflowWafl => write!(f, "application/vnd.wasmflow.wafl"),
+			Mime::ApplicationVndWebturbo => write!(f, "application/vnd.webturbo"),
+			Mime::ApplicationVndWfaDpp => write!(f, "application/vnd.wfa.dpp"),
+			Mime::ApplicationVndWfaP2p => write!(f, "application/vnd.wfa.p2p"),
+			Mime::ApplicationVndWfaWsc => write!(f, "application/vnd.wfa.wsc"),
+			Mime::ApplicationVndWindowsDevicepairing => write!(f, "application/vnd.windows.devicepairing"),
+			Mime::ApplicationVndWmc => write!(f, "application/vnd.wmc"),
+			Mime::ApplicationVndWmfBootstrap => write!(f, "application/vnd.wmf.bootstrap"),
+			Mime::ApplicationVndWolframMathematica => write!(f, "application/vnd.wolfram.mathematica"),
+			Mime::ApplicationVndWolframMathematicaPackage => write!(f, "application/vnd.wolfram.mathematica.package"),
+			Mime::ApplicationVndWolframPlayer => write!(f, "application/vnd.wolfram.player"),
+			Mime::ApplicationVndWordlift => write!(f, "application/vnd.wordlift"),
+			Mime::ApplicationVndWordperfect => write!(f, "application/vnd.wordperfect"),
+			Mime::ApplicationVndWqd => write!(f, "application/vnd.wqd"),
+			Mime::ApplicationVndWrqHp3000Labelled => write!(f, "application/vnd.wrq-hp3000-labelled"),
+			Mime::ApplicationVndWtStf => write!(f, "application/vnd.wt.stf"),
+			Mime::ApplicationVndWvCspXml => write!(f, "application/vnd.wv.csp+xml"),
+			Mime::ApplicationVndWvCspWbxml => write!(f, "application/vnd.wv.csp+wbxml"),
+			Mime::ApplicationVndWvSspXml => write!(f, "application/vnd.wv.ssp+xml"),
+			Mime::ApplicationVndXacmlJson => write!(f, "application/vnd.xacml+json"),
+			Mime::ApplicationVndXara => write!(f, "application/vnd.xara"),
+			Mime::ApplicationVndXfdl => write!(f, "application/vnd.xfdl"),
+			Mime::ApplicationVndXfdlWebform => write!(f, "application/vnd.xfdl.webform"),
+			Mime::ApplicationVndXmiXml => write!(f, "application/vnd.xmi+xml"),
+			Mime::ApplicationVndXmpieCpkg => write!(f, "application/vnd.xmpie.cpkg"),
+			Mime::ApplicationVndXmpieDpkg => write!(f, "application/vnd.xmpie.dpkg"),
+			Mime::ApplicationVndXmpiePlan => write!(f, "application/vnd.xmpie.plan"),
+			Mime::ApplicationVndXmpiePpkg => write!(f, "application/vnd.xmpie.ppkg"),
+			Mime::ApplicationVndXmpieXlim => write!(f, "application/vnd.xmpie.xlim"),
+			Mime::ApplicationVndYamahaHvDic => write!(f, "application/vnd.yamaha.hv-dic"),
+			Mime::ApplicationVndYamahaHvScript => write!(f, "application/vnd.yamaha.hv-script"),
+			Mime::ApplicationVndYamahaHvVoice => write!(f, "application/vnd.yamaha.hv-voice"),
+			Mime::ApplicationVndYamahaOpenscoreformatOsfpvgXml => write!(f, "application/vnd.yamaha.openscoreformat.osfpvg+xml"),
+			Mime::ApplicationVndYamahaOpenscoreformat => write!(f, "application/vnd.yamaha.openscoreformat"),
+			Mime::ApplicationVndYamahaRemoteSetup => write!(f, "application/vnd.yamaha.remote-setup"),
+			Mime::ApplicationVndYamahaSmafAudio => write!(f, "application/vnd.yamaha.smaf-audio"),
+			Mime::ApplicationVndYamahaSmafPhrase => write!(f, "application/vnd.yamaha.smaf-phrase"),
+			Mime::ApplicationVndYamahaThroughNgn => write!(f, "application/vnd.yamaha.through-ngn"),
+			Mime::ApplicationVndYamahaTunnelUdpencap => write!(f, "application/vnd.yamaha.tunnel-udpencap"),
+			Mime::ApplicationVndYaoweme => write!(f, "application/vnd.yaoweme"),
+			Mime::ApplicationVndYellowriverCustomMenu => write!(f, "application/vnd.yellowriver-custom-menu"),
+			Mime::ApplicationVndZul => write!(f, "application/vnd.zul"),
+			Mime::ApplicationVndZzazzDeckXml => write!(f, "application/vnd.zzazz.deck+xml"),
+			Mime::ApplicationVoicexmlXml => write!(f, "application/voicexml+xml"),
+			Mime::ApplicationVoucherCmsJson => write!(f, "application/voucher-cms+json"),
+			Mime::ApplicationVqRtcpxr => write!(f, "application/vq-rtcpxr"),
+			Mime::ApplicationWasm => write!(f, "application/wasm"),
+			Mime::ApplicationWatcherinfoXml => write!(f, "application/watcherinfo+xml"),
+			Mime::ApplicationWebpushOptionsJson => write!(f, "application/webpush-options+json"),
+			Mime::ApplicationWhoisppQuery => write!(f, "application/whoispp-query"),
+			Mime::ApplicationWhoisppResponse => write!(f, "application/whoispp-response"),
+			Mime::ApplicationWidget => write!(f, "application/widget"),
+			Mime::ApplicationWita => write!(f, "application/wita"),
+			Mime::ApplicationWordperfect51 => write!(f, "application/wordperfect5.1"),
+			Mime::ApplicationWsdlXml => write!(f, "application/wsdl+xml"),
+			Mime::ApplicationWspolicyXml => write!(f, "application/wspolicy+xml"),
+			Mime::ApplicationXPkiMessage => write!(f, "application/x-pki-message"),
+			Mime::ApplicationXWwwFormUrlencoded => write!(f, "application/x-www-form-urlencoded"),
+			Mime::ApplicationXX509CaCert => write!(f, "application/x-x509-ca-cert"),
+			Mime::ApplicationXX509CaRaCert => write!(f, "application/x-x509-ca-ra-cert"),
+			Mime::ApplicationXX509NextCaCert => write!(f, "application/x-x509-next-ca-cert"),
+			Mime::ApplicationX400Bp => write!(f, "application/x400-bp"),
+			Mime::ApplicationXacmlXml => write!(f, "application/xacml+xml"),
+			Mime::ApplicationXcapAttXml => write!(f, "application/xcap-att+xml"),
+			Mime::ApplicationXcapCapsXml => write!(f, "application/xcap-caps+xml"),
+			Mime::ApplicationXcapDiffXml => write!(f, "application/xcap-diff+xml"),
+			Mime::ApplicationXcapElXml => write!(f, "application/xcap-el+xml"),
+			Mime::ApplicationXcapErrorXml => write!(f, "application/xcap-error+xml"),
+			Mime::ApplicationXcapNsXml => write!(f, "application/xcap-ns+xml"),
+			Mime::ApplicationXconConferenceInfoDiffXml => write!(f, "application/xcon-conference-info-diff+xml"),
+			Mime::ApplicationXconConferenceInfoXml => write!(f, "application/xcon-conference-info+xml"),
+			Mime::ApplicationXencXml => write!(f, "application/xenc+xml"),
+			Mime::ApplicationXfdf => write!(f, "application/xfdf"),
+			Mime::ApplicationXhtmlXml => write!(f, "application/xhtml+xml"),
+			Mime::ApplicationXliffXml => write!(f, "application/xliff+xml"),
+			Mime::ApplicationXml => write!(f, "application/xml"),
+			Mime::ApplicationXmlDtd => write!(f, "application/xml-dtd"),
+			Mime::ApplicationXmlExternalParsedEntity => write!(f, "application/xml-external-parsed-entity"),
+			Mime::ApplicationXmlPatchXml => write!(f, "application/xml-patch+xml"),
+			Mime::ApplicationXmppXml => write!(f, "application/xmpp+xml"),
+			Mime::ApplicationXopXml => write!(f, "application/xop+xml"),
+			Mime::ApplicationXsltXml => write!(f, "application/xslt+xml"),
+			Mime::ApplicationXvXml => write!(f, "application/xv+xml"),
+			Mime::ApplicationYang => write!(f, "application/yang"),
+			Mime::ApplicationYangDataCbor => write!(f, "application/yang-data+cbor"),
+			Mime::ApplicationYangDataJson => write!(f, "application/yang-data+json"),
+			Mime::ApplicationYangDataXml => write!(f, "application/yang-data+xml"),
+			Mime::ApplicationYangPatchJson => write!(f, "application/yang-patch+json"),
+			Mime::ApplicationYangPatchXml => write!(f, "application/yang-patch+xml"),
+			Mime::ApplicationYinXml => write!(f, "application/yin+xml"),
+			Mime::ApplicationZip => write!(f, "application/zip"),
+			Mime::ApplicationZlib => write!(f, "application/zlib"),
+			Mime::ApplicationZstd => write!(f, "application/zstd"),
+			Mime::Audio1dInterleavedParityfec => write!(f, "audio/1d-interleaved-parityfec"),
+			Mime::Audio32kadpcm => write!(f, "audio/32kadpcm"),
+			Mime::Audio3gpp => write!(f, "audio/3gpp"),
+			Mime::Audio3gpp2 => write!(f, "audio/3gpp2"),
+			Mime::AudioAac => write!(f, "audio/aac"),
+			Mime::AudioAc3 => write!(f, "audio/ac3"),
+			Mime::AudioAmr => write!(f, "audio/AMR"),
+			Mime::AudioAmrWb => write!(f, "audio/AMR-WB"),
+			Mime::AudioAmrWbPlus => write!(f, "audio/amr-wb+"),
+			Mime::AudioAptx => write!(f, "audio/aptx"),
+			Mime::AudioAsc => write!(f, "audio/asc"),
+			Mime::AudioAtracAdvancedLossless => write!(f, "audio/ATRAC-ADVANCED-LOSSLESS"),
+			Mime::AudioAtracX => write!(f, "audio/ATRAC-X"),
+			Mime::AudioAtrac3 => write!(f, "audio/ATRAC3"),
+			Mime::AudioBasic => write!(f, "audio/basic"),
+			Mime::AudioBv16 => write!(f, "audio/BV16"),
+			Mime::AudioBv32 => write!(f, "audio/BV32"),
+			Mime::AudioClearmode => write!(f, "audio/clearmode"),
+			Mime::AudioCn => write!(f, "audio/CN"),
+			Mime::AudioDat12 => write!(f, "audio/DAT12"),
+			Mime::AudioDls => write!(f, "audio/dls"),
+			Mime::AudioDsrEs201108 => write!(f, "audio/dsr-es201108"),
+			Mime::AudioDsrEs202050 => write!(f, "audio/dsr-es202050"),
+			Mime::AudioDsrEs202211 => write!(f, "audio/dsr-es202211"),
+			Mime::AudioDsrEs202212 => write!(f, "audio/dsr-es202212"),
+			Mime::AudioDv => write!(f, "audio/DV"),
+			Mime::AudioDvi4 => write!(f, "audio/DVI4"),
+			Mime::AudioEac3 => write!(f, "audio/eac3"),
+			Mime::AudioEncaprtp => write!(f, "audio/encaprtp"),
+			Mime::AudioEvrc => write!(f, "audio/EVRC"),
+			Mime::AudioEvrcQcp => write!(f, "audio/EVRC-QCP"),
+			Mime::AudioEvrc0 => write!(f, "audio/EVRC0"),
+			Mime::AudioEvrc1 => write!(f, "audio/EVRC1"),
+			Mime::AudioEvrcb => write!(f, "audio/EVRCB"),
+			Mime::AudioEvrcb0 => write!(f, "audio/EVRCB0"),
+			Mime::AudioEvrcb1 => write!(f, "audio/EVRCB1"),
+			Mime::AudioEvrcnw => write!(f, "audio/EVRCNW"),
+			Mime::AudioEvrcnw0 => write!(f, "audio/EVRCNW0"),
+			Mime::AudioEvrcnw1 => write!(f, "audio/EVRCNW1"),
+			Mime::AudioEvrcwb => write!(f, "audio/EVRCWB"),
+			Mime::AudioEvrcwb0 => write!(f, "audio/EVRCWB0"),
+			Mime::AudioEvrcwb1 => write!(f, "audio/EVRCWB1"),
+			Mime::AudioEvs => write!(f, "audio/EVS"),
+			Mime::AudioExample => write!(f, "audio/example"),
+			Mime::AudioFlexfec => write!(f, "audio/flexfec"),
+			Mime::AudioFwdred => write!(f, "audio/fwdred"),
+			Mime::AudioG7110 => write!(f, "audio/G711-0"),
+			Mime::AudioG719 => write!(f, "audio/G719"),
+			Mime::AudioG7221 => write!(f, "audio/G7221"),
+			Mime::AudioG722 => write!(f, "audio/G722"),
+			Mime::AudioG723 => write!(f, "audio/G723"),
+			Mime::AudioG72616 => write!(f, "audio/G726-16"),
+			Mime::AudioG72624 => write!(f, "audio/G726-24"),
+			Mime::AudioG72632 => write!(f, "audio/G726-32"),
+			Mime::AudioG72640 => write!(f, "audio/G726-40"),
+			Mime::AudioG728 => write!(f, "audio/G728"),
+			Mime::AudioG729 => write!(f, "audio/G729"),
+			Mime::AudioG7291 => write!(f, "audio/G7291"),
+			Mime::AudioG729d => write!(f, "audio/G729D"),
+			Mime::AudioG729e => write!(f, "audio/G729E"),
+			Mime::AudioGsm => write!(f, "audio/GSM"),
+			Mime::AudioGsmEfr => write!(f, "audio/GSM-EFR"),
+			Mime::AudioGsmHr08 => write!(f, "audio/GSM-HR-08"),
+			Mime::AudioIlbc => write!(f, "audio/iLBC"),
+			Mime::AudioIpMrV25 => write!(f, "audio/ip-mr_v2.5"),
+			Mime::AudioL8 => write!(f, "audio/L8"),
+			Mime::AudioL16 => write!(f, "audio/L16"),
+			Mime::AudioL20 => write!(f, "audio/L20"),
+			Mime::AudioL24 => write!(f, "audio/L24"),
+			Mime::AudioLpc => write!(f, "audio/LPC"),
+			Mime::AudioMelp => write!(f, "audio/MELP"),
+			Mime::AudioMelp600 => write!(f, "audio/MELP600"),
+			Mime::AudioMelp1200 => write!(f, "audio/MELP1200"),
+			Mime::AudioMelp2400 => write!(f, "audio/MELP2400"),
+			Mime::AudioMhas => write!(f, "audio/mhas"),
+			Mime::AudioMobileXmf => write!(f, "audio/mobile-xmf"),
+			Mime::AudioMpa => write!(f, "audio/MPA"),
+			Mime::AudioMp4 => write!(f, "audio/mp4"),
+			Mime::AudioMp4aLatm => write!(f, "audio/MP4A-LATM"),
+			Mime::AudioMpaRobust => write!(f, "audio/mpa-robust"),
+			Mime::AudioMpeg => write!(f, "audio/mpeg"),
+			Mime::AudioMpeg4Generic => write!(f, "audio/mpeg4-generic"),
+			Mime::AudioOgg => write!(f, "audio/ogg"),
+			Mime::AudioOpus => write!(f, "audio/opus"),
+			Mime::AudioParityfec => write!(f, "audio/parityfec"),
+			Mime::AudioPcma => write!(f, "audio/PCMA"),
+			Mime::AudioPcmaWb => write!(f, "audio/PCMA-WB"),
+			Mime::AudioPcmu => write!(f, "audio/PCMU"),
+			Mime::AudioPcmuWb => write!(f, "audio/PCMU-WB"),
+			Mime::AudioPrsSid => write!(f, "audio/prs.sid"),
+			Mime::AudioQcelp => write!(f, "audio/QCELP"),
+			Mime::AudioRaptorfec => write!(f, "audio/raptorfec"),
+			Mime::AudioRed => write!(f, "audio/RED"),
+			Mime::AudioRtpEncAescm128 => write!(f, "audio/rtp-enc-aescm128"),
+			Mime::AudioRtploopback => write!(f, "audio/rtploopback"),
+			Mime::AudioRtpMidi => write!(f, "audio/rtp-midi"),
+			Mime::AudioRtx => write!(f, "audio/rtx"),
+			Mime::AudioScip => write!(f, "audio/scip"),
+			Mime::AudioSmv => write!(f, "audio/SMV"),
+			Mime::AudioSmv0 => write!(f, "audio/SMV0"),
+			Mime::AudioSmvQcp => write!(f, "audio/SMV-QCP"),
+			Mime::AudioSofa => write!(f, "audio/sofa"),
+			Mime::AudioSpMidi => write!(f, "audio/sp-midi"),
+			Mime::AudioSpeex => write!(f, "audio/speex"),
+			Mime::AudioT140c => write!(f, "audio/t140c"),
+			Mime::AudioT38 => write!(f, "audio/t38"),
+			Mime::AudioTelephoneEvent => write!(f, "audio/telephone-event"),
+			Mime::AudioTetraAcelp => write!(f, "audio/TETRA_ACELP"),
+			Mime::AudioTetraAcelpBb => write!(f, "audio/TETRA_ACELP_BB"),
+			Mime::AudioTone => write!(f, "audio/tone"),
+			Mime::AudioTsvcis => write!(f, "audio/TSVCIS"),
+			Mime::AudioUemclip => write!(f, "audio/UEMCLIP"),
+			Mime::AudioUlpfec => write!(f, "audio/ulpfec"),
+			Mime::AudioUsac => write!(f, "audio/usac"),
+			Mime::AudioVdvi => write!(f, "audio/VDVI"),
+			Mime::AudioVmrWb => write!(f, "audio/VMR-WB"),
+			Mime::AudioVnd3gppIufp => write!(f, "audio/vnd.3gpp.iufp"),
+			Mime::AudioVnd4sb => write!(f, "audio/vnd.4SB"),
+			Mime::AudioVndAudiokoz => write!(f, "audio/vnd.audiokoz"),
+			Mime::AudioVndCelp => write!(f, "audio/vnd.CELP"),
+			Mime::AudioVndCiscoNse => write!(f, "audio/vnd.cisco.nse"),
+			Mime::AudioVndCmlesRadioEvents => write!(f, "audio/vnd.cmles.radio-events"),
+			Mime::AudioVndCnsAnp1 => write!(f, "audio/vnd.cns.anp1"),
+			Mime::AudioVndCnsInf1 => write!(f, "audio/vnd.cns.inf1"),
+			Mime::AudioVndDeceAudio => write!(f, "audio/vnd.dece.audio"),
+			Mime::AudioVndDigitalWinds => write!(f, "audio/vnd.digital-winds"),
+			Mime::AudioVndDlnaAdts => write!(f, "audio/vnd.dlna.adts"),
+			Mime::AudioVndDolbyHeaac1 => write!(f, "audio/vnd.dolby.heaac.1"),
+			Mime::AudioVndDolbyHeaac2 => write!(f, "audio/vnd.dolby.heaac.2"),
+			Mime::AudioVndDolbyMlp => write!(f, "audio/vnd.dolby.mlp"),
+			Mime::AudioVndDolbyMps => write!(f, "audio/vnd.dolby.mps"),
+			Mime::AudioVndDolbyPl2 => write!(f, "audio/vnd.dolby.pl2"),
+			Mime::AudioVndDolbyPl2x => write!(f, "audio/vnd.dolby.pl2x"),
+			Mime::AudioVndDolbyPl2z => write!(f, "audio/vnd.dolby.pl2z"),
+			Mime::AudioVndDolbyPulse1 => write!(f, "audio/vnd.dolby.pulse.1"),
+			Mime::AudioVndDra => write!(f, "audio/vnd.dra"),
+			Mime::AudioVndDts => write!(f, "audio/vnd.dts"),
+			Mime::AudioVndDtsHd => write!(f, "audio/vnd.dts.hd"),
+			Mime::AudioVndDtsUhd => write!(f, "audio/vnd.dts.uhd"),
+			Mime::AudioVndDvbFile => write!(f, "audio/vnd.dvb.file"),
+			Mime::AudioVndEveradPlj => write!(f, "audio/vnd.everad.plj"),
+			Mime::AudioVndHnsAudio => write!(f, "audio/vnd.hns.audio"),
+			Mime::AudioVndLucentVoice => write!(f, "audio/vnd.lucent.voice"),
+			Mime::AudioVndMsPlayreadyMediaPya => write!(f, "audio/vnd.ms-playready.media.pya"),
+			Mime::AudioVndNokiaMobileXmf => write!(f, "audio/vnd.nokia.mobile-xmf"),
+			Mime::AudioVndNortelVbk => write!(f, "audio/vnd.nortel.vbk"),
+			Mime::AudioVndNueraEcelp4800 => write!(f, "audio/vnd.nuera.ecelp4800"),
+			Mime::AudioVndNueraEcelp7470 => write!(f, "audio/vnd.nuera.ecelp7470"),
+			Mime::AudioVndNueraEcelp9600 => write!(f, "audio/vnd.nuera.ecelp9600"),
+			Mime::AudioVndOctelSbc => write!(f, "audio/vnd.octel.sbc"),
+			Mime::AudioVndPresonusMultitrack => write!(f, "audio/vnd.presonus.multitrack"),
+			Mime::AudioVndRhetorex32kadpcm => write!(f, "audio/vnd.rhetorex.32kadpcm"),
+			Mime::AudioVndRip => write!(f, "audio/vnd.rip"),
+			Mime::AudioVndSealedmediaSoftsealMpeg => write!(f, "audio/vnd.sealedmedia.softseal.mpeg"),
+			Mime::AudioVndVmxCvsd => write!(f, "audio/vnd.vmx.cvsd"),
+			Mime::AudioVorbis => write!(f, "audio/vorbis"),
+			Mime::AudioVorbisConfig => write!(f, "audio/vorbis-config"),
+			Mime::FontCollection => write!(f, "font/collection"),
+			Mime::FontOtf => write!(f, "font/otf"),
+			Mime::FontSfnt => write!(f, "font/sfnt"),
+			Mime::FontTtf => write!(f, "font/ttf"),
+			Mime::FontWoff => write!(f, "font/woff"),
+			Mime::FontWoff2 => write!(f, "font/woff2"),
+			Mime::ImageAces => write!(f, "image/aces"),
+			Mime::ImageApng => write!(f, "image/apng"),
+			Mime::ImageAvci => write!(f, "image/avci"),
+			Mime::ImageAvcs => write!(f, "image/avcs"),
+			Mime::ImageAvif => write!(f, "image/avif"),
+			Mime::ImageBmp => write!(f, "image/bmp"),
+			Mime::ImageCgm => write!(f, "image/cgm"),
+			Mime::ImageDicomRle => write!(f, "image/dicom-rle"),
+			Mime::ImageDpx => write!(f, "image/dpx"),
+			Mime::ImageEmf => write!(f, "image/emf"),
+			Mime::ImageExample => write!(f, "image/example"),
+			Mime::ImageFits => write!(f, "image/fits"),
+			Mime::ImageG3fax => write!(f, "image/g3fax"),
+			Mime::ImageHeic => write!(f, "image/heic"),
+			Mime::ImageHeicSequence => write!(f, "image/heic-sequence"),
+			Mime::ImageHeif => write!(f, "image/heif"),
+			Mime::ImageHeifSequence => write!(f, "image/heif-sequence"),
+			Mime::ImageHej2k => write!(f, "image/hej2k"),
+			Mime::ImageHsj2 => write!(f, "image/hsj2"),
+			Mime::ImageJls => write!(f, "image/jls"),
+			Mime::ImageJp2 => write!(f, "image/jp2"),
+            Mime::ImageJpeg => write!(f, "image/jpeg"),
+			Mime::ImageJph => write!(f, "image/jph"),
+			Mime::ImageJphc => write!(f, "image/jphc"),
+			Mime::ImageJpm => write!(f, "image/jpm"),
+			Mime::ImageJpx => write!(f, "image/jpx"),
+			Mime::ImageJxr => write!(f, "image/jxr"),
+			Mime::ImageJxra => write!(f, "image/jxrA"),
+			Mime::ImageJxrs => write!(f, "image/jxrS"),
+			Mime::ImageJxs => write!(f, "image/jxs"),
+			Mime::ImageJxsc => write!(f, "image/jxsc"),
+			Mime::ImageJxsi => write!(f, "image/jxsi"),
+			Mime::ImageJxss => write!(f, "image/jxss"),
+			Mime::ImageKtx => write!(f, "image/ktx"),
+			Mime::ImageKtx2 => write!(f, "image/ktx2"),
+			Mime::ImageNaplps => write!(f, "image/naplps"),
+			Mime::ImagePng => write!(f, "image/png"),
+			Mime::ImagePrsBtif => write!(f, "image/prs.btif"),
+			Mime::ImagePrsPti => write!(f, "image/prs.pti"),
+			Mime::ImagePwgRaster => write!(f, "image/pwg-raster"),
+			Mime::ImageSvgXml => write!(f, "image/svg+xml"),
+			Mime::ImageT38 => write!(f, "image/t38"),
+			Mime::ImageTiff => write!(f, "image/tiff"),
+			Mime::ImageTiffFx => write!(f, "image/tiff-fx"),
+			Mime::ImageVndAdobePhotoshop => write!(f, "image/vnd.adobe.photoshop"),
+			Mime::ImageVndAirzipAcceleratorAzv => write!(f, "image/vnd.airzip.accelerator.azv"),
+			Mime::ImageVndCnsInf2 => write!(f, "image/vnd.cns.inf2"),
+			Mime::ImageVndDeceGraphic => write!(f, "image/vnd.dece.graphic"),
+			Mime::ImageVndDjvu => write!(f, "image/vnd.djvu"),
+			Mime::ImageVndDwg => write!(f, "image/vnd.dwg"),
+			Mime::ImageVndDxf => write!(f, "image/vnd.dxf"),
+			Mime::ImageVndDvbSubtitle => write!(f, "image/vnd.dvb.subtitle"),
+			Mime::ImageVndFastbidsheet => write!(f, "image/vnd.fastbidsheet"),
+			Mime::ImageVndFpx => write!(f, "image/vnd.fpx"),
+			Mime::ImageVndFst => write!(f, "image/vnd.fst"),
+			Mime::ImageVndFujixeroxEdmicsMmr => write!(f, "image/vnd.fujixerox.edmics-mmr"),
+			Mime::ImageVndFujixeroxEdmicsRlc => write!(f, "image/vnd.fujixerox.edmics-rlc"),
+			Mime::ImageVndGlobalgraphicsPgb => write!(f, "image/vnd.globalgraphics.pgb"),
+			Mime::ImageVndMicrosoftIcon => write!(f, "image/vnd.microsoft.icon"),
+			Mime::ImageVndMix => write!(f, "image/vnd.mix"),
+			Mime::ImageVndMsModi => write!(f, "image/vnd.ms-modi"),
+			Mime::ImageVndMozillaApng => write!(f, "image/vnd.mozilla.apng"),
+			Mime::ImageVndNetFpx => write!(f, "image/vnd.net-fpx"),
+			Mime::ImageVndPcoB16 => write!(f, "image/vnd.pco.b16"),
+			Mime::ImageVndRadiance => write!(f, "image/vnd.radiance"),
+			Mime::ImageVndSealedPng => write!(f, "image/vnd.sealed.png"),
+			Mime::ImageVndSealedmediaSoftsealGif => write!(f, "image/vnd.sealedmedia.softseal.gif"),
+			Mime::ImageVndSealedmediaSoftsealJpg => write!(f, "image/vnd.sealedmedia.softseal.jpg"),
+			Mime::ImageVndSvf => write!(f, "image/vnd.svf"),
+			Mime::ImageVndTencentTap => write!(f, "image/vnd.tencent.tap"),
+			Mime::ImageVndValveSourceTexture => write!(f, "image/vnd.valve.source.texture"),
+			Mime::ImageVndWapWbmp => write!(f, "image/vnd.wap.wbmp"),
+			Mime::ImageVndXiff => write!(f, "image/vnd.xiff"),
+			Mime::ImageVndZbrushPcx => write!(f, "image/vnd.zbrush.pcx"),
+			Mime::ImageWebp => write!(f, "image/webp"),
+			Mime::ImageWmf => write!(f, "image/wmf"),
+			Mime::MessageBhttp => write!(f, "message/bhttp"),
+			Mime::MessageCpim => write!(f, "message/CPIM"),
+			Mime::MessageDeliveryStatus => write!(f, "message/delivery-status"),
+			Mime::MessageDispositionNotification => write!(f, "message/disposition-notification"),
+			Mime::MessageExample => write!(f, "message/example"),
+			Mime::MessageFeedbackReport => write!(f, "message/feedback-report"),
+			Mime::MessageGlobal => write!(f, "message/global"),
+			Mime::MessageGlobalDeliveryStatus => write!(f, "message/global-delivery-status"),
+			Mime::MessageGlobalDispositionNotification => write!(f, "message/global-disposition-notification"),
+			Mime::MessageGlobalHeaders => write!(f, "message/global-headers"),
+			Mime::MessageHttp => write!(f, "message/http"),
+			Mime::MessageImdnXml => write!(f, "message/imdn+xml"),
+			Mime::MessageMls => write!(f, "message/mls"),
+			Mime::MessageOhttpReq => write!(f, "message/ohttp-req"),
+			Mime::MessageOhttpRes => write!(f, "message/ohttp-res"),
+			Mime::MessageSip => write!(f, "message/sip"),
+			Mime::MessageSipfrag => write!(f, "message/sipfrag"),
+			Mime::MessageTrackingStatus => write!(f, "message/tracking-status"),
+			Mime::MessageVndWfaWsc => write!(f, "message/vnd.wfa.wsc"),
+			Mime::Model3mf => write!(f, "model/3mf"),
+			Mime::ModelE57 => write!(f, "model/e57"),
+			Mime::ModelExample => write!(f, "model/example"),
+			Mime::ModelGltfBinary => write!(f, "model/gltf-binary"),
+			Mime::ModelGltfJson => write!(f, "model/gltf+json"),
+			Mime::ModelJt => write!(f, "model/JT"),
+			Mime::ModelIges => write!(f, "model/iges"),
+			Mime::ModelMtl => write!(f, "model/mtl"),
+			Mime::ModelObj => write!(f, "model/obj"),
+			Mime::ModelPrc => write!(f, "model/prc"),
+			Mime::ModelStep => write!(f, "model/step"),
+			Mime::ModelStepXml => write!(f, "model/step+xml"),
+			Mime::ModelStepZip => write!(f, "model/step+zip"),
+			Mime::ModelStepXmlZip => write!(f, "model/step-xml+zip"),
+			Mime::ModelStl => write!(f, "model/stl"),
+			Mime::ModelU3d => write!(f, "model/u3d"),
+			Mime::ModelVndBary => write!(f, "model/vnd.bary"),
+			Mime::ModelVndCld => write!(f, "model/vnd.cld"),
+			Mime::ModelVndColladaXml => write!(f, "model/vnd.collada+xml"),
+			Mime::ModelVndDwf => write!(f, "model/vnd.dwf"),
+			Mime::ModelVndFlatland3dml => write!(f, "model/vnd.flatland.3dml"),
+			Mime::ModelVndGdl => write!(f, "model/vnd.gdl"),
+			Mime::ModelVndGsGdl => write!(f, "model/vnd.gs-gdl"),
+			Mime::ModelVndGtw => write!(f, "model/vnd.gtw"),
+			Mime::ModelVndMomlXml => write!(f, "model/vnd.moml+xml"),
+			Mime::ModelVndMts => write!(f, "model/vnd.mts"),
+			Mime::ModelVndOpengex => write!(f, "model/vnd.opengex"),
+			Mime::ModelVndParasolidTransmitBinary => write!(f, "model/vnd.parasolid.transmit.binary"),
+			Mime::ModelVndParasolidTransmitText => write!(f, "model/vnd.parasolid.transmit.text"),
+			Mime::ModelVndPythaPyox => write!(f, "model/vnd.pytha.pyox"),
+			Mime::ModelVndRosetteAnnotatedDataModel => write!(f, "model/vnd.rosette.annotated-data-model"),
+			Mime::ModelVndSapVds => write!(f, "model/vnd.sap.vds"),
+			Mime::ModelVndUsda => write!(f, "model/vnd.usda"),
+			Mime::ModelVndUsdzZip => write!(f, "model/vnd.usdz+zip"),
+			Mime::ModelVndValveSourceCompiledMap => write!(f, "model/vnd.valve.source.compiled-map"),
+			Mime::ModelVndVtu => write!(f, "model/vnd.vtu"),
+			Mime::ModelX3dVrml => write!(f, "model/x3d-vrml"),
+			Mime::ModelX3dFastinfoset => write!(f, "model/x3d+fastinfoset"),
+			Mime::ModelX3dXml => write!(f, "model/x3d+xml"),
+			Mime::MultipartAppledouble => write!(f, "multipart/appledouble"),
+			Mime::MultipartByteranges => write!(f, "multipart/byteranges"),
+			Mime::MultipartEncrypted => write!(f, "multipart/encrypted"),
+			Mime::MultipartExample => write!(f, "multipart/example"),
+			Mime::MultipartFormData => write!(f, "multipart/form-data"),
+			Mime::MultipartHeaderSet => write!(f, "multipart/header-set"),
+			Mime::MultipartMultilingual => write!(f, "multipart/multilingual"),
+			Mime::MultipartRelated => write!(f, "multipart/related"),
+			Mime::MultipartReport => write!(f, "multipart/report"),
+			Mime::MultipartSigned => write!(f, "multipart/signed"),
+			Mime::MultipartVndBintMedPlus => write!(f, "multipart/vnd.bint.med-plus"),
+			Mime::MultipartVoiceMessage => write!(f, "multipart/voice-message"),
+			Mime::MultipartXMixedReplace => write!(f, "multipart/x-mixed-replace"),
+			Mime::Text1dInterleavedParityfec => write!(f, "text/1d-interleaved-parityfec"),
+			Mime::TextCacheManifest => write!(f, "text/cache-manifest"),
+			Mime::TextCalendar => write!(f, "text/calendar"),
+			Mime::TextCql => write!(f, "text/cql"),
+			Mime::TextCqlExpression => write!(f, "text/cql-expression"),
+			Mime::TextCqlIdentifier => write!(f, "text/cql-identifier"),
+			Mime::TextCss => write!(f, "text/css"),
+			Mime::TextCsv => write!(f, "text/csv"),
+			Mime::TextCsvSchema => write!(f, "text/csv-schema"),
+			Mime::TextDns => write!(f, "text/dns"),
+			Mime::TextEncaprtp => write!(f, "text/encaprtp"),
+			Mime::TextExample => write!(f, "text/example"),
+			Mime::TextFhirpath => write!(f, "text/fhirpath"),
+			Mime::TextFlexfec => write!(f, "text/flexfec"),
+			Mime::TextFwdred => write!(f, "text/fwdred"),
+			Mime::TextGff3 => write!(f, "text/gff3"),
+			Mime::TextGrammarRefList => write!(f, "text/grammar-ref-list"),
+			Mime::TextHl7v2 => write!(f, "text/hl7v2"),
+			Mime::TextHtml => write!(f, "text/html"),
+			Mime::TextJavascript => write!(f, "text/javascript"),
+			Mime::TextJcrCnd => write!(f, "text/jcr-cnd"),
+			Mime::TextMarkdown => write!(f, "text/markdown"),
+			Mime::TextMizar => write!(f, "text/mizar"),
+			Mime::TextN3 => write!(f, "text/n3"),
+			Mime::TextParameters => write!(f, "text/parameters"),
+			Mime::TextParityfec => write!(f, "text/parityfec"),
+            Mime::TextPlain => write!(f, "text/plain"),
+			Mime::TextProvenanceNotation => write!(f, "text/provenance-notation"),
+			Mime::TextPrsFallensteinRst => write!(f, "text/prs.fallenstein.rst"),
+			Mime::TextPrsLinesTag => write!(f, "text/prs.lines.tag"),
+			Mime::TextPrsPropLogic => write!(f, "text/prs.prop.logic"),
+			Mime::TextRaptorfec => write!(f, "text/raptorfec"),
+			Mime::TextRed => write!(f, "text/RED"),
+			Mime::TextRfc822Headers => write!(f, "text/rfc822-headers"),
+			Mime::TextRtf => write!(f, "text/rtf"),
+			Mime::TextRtpEncAescm128 => write!(f, "text/rtp-enc-aescm128"),
+			Mime::TextRtploopback => write!(f, "text/rtploopback"),
+			Mime::TextRtx => write!(f, "text/rtx"),
+			Mime::TextSgml => write!(f, "text/SGML"),
+			Mime::TextShaclc => write!(f, "text/shaclc"),
+			Mime::TextShex => write!(f, "text/shex"),
+			Mime::TextSpdx => write!(f, "text/spdx"),
+			Mime::TextStrings => write!(f, "text/strings"),
+			Mime::TextT140 => write!(f, "text/t140"),
+			Mime::TextTabSeparatedValues => write!(f, "text/tab-separated-values"),
+			Mime::TextTroff => write!(f, "text/troff"),
+			Mime::TextTurtle => write!(f, "text/turtle"),
+			Mime::TextUlpfec => write!(f, "text/ulpfec"),
+			Mime::TextUriList => write!(f, "text/uri-list"),
+			Mime::TextVcard => write!(f, "text/vcard"),
+			Mime::TextVndA => write!(f, "text/vnd.a"),
+			Mime::TextVndAbc => write!(f, "text/vnd.abc"),
+			Mime::TextVndAsciiArt => write!(f, "text/vnd.ascii-art"),
+			Mime::TextVndCurl => write!(f, "text/vnd.curl"),
+			Mime::TextVndDebianCopyright => write!(f, "text/vnd.debian.copyright"),
+			Mime::TextVndDmclientscript => write!(f, "text/vnd.DMClientScript"),
+			Mime::TextVndDvbSubtitle => write!(f, "text/vnd.dvb.subtitle"),
+			Mime::TextVndEsmertecThemeDescriptor => write!(f, "text/vnd.esmertec.theme-descriptor"),
+			Mime::TextVndExchangeable => write!(f, "text/vnd.exchangeable"),
+			Mime::TextVndFamilysearchGedcom => write!(f, "text/vnd.familysearch.gedcom"),
+			Mime::TextVndFiclabFlt => write!(f, "text/vnd.ficlab.flt"),
+			Mime::TextVndFly => write!(f, "text/vnd.fly"),
+			Mime::TextVndFmiFlexstor => write!(f, "text/vnd.fmi.flexstor"),
+			Mime::TextVndGml => write!(f, "text/vnd.gml"),
+			Mime::TextVndGraphviz => write!(f, "text/vnd.graphviz"),
+			Mime::TextVndHans => write!(f, "text/vnd.hans"),
+			Mime::TextVndHgl => write!(f, "text/vnd.hgl"),
+			Mime::TextVndIn3d3dml => write!(f, "text/vnd.in3d.3dml"),
+			Mime::TextVndIn3dSpot => write!(f, "text/vnd.in3d.spot"),
+			Mime::TextVndIptcNewsml => write!(f, "text/vnd.IPTC.NewsML"),
+			Mime::TextVndIptcNitf => write!(f, "text/vnd.IPTC.NITF"),
+			Mime::TextVndLatexZ => write!(f, "text/vnd.latex-z"),
+			Mime::TextVndMotorolaReflex => write!(f, "text/vnd.motorola.reflex"),
+			Mime::TextVndMsMediapackage => write!(f, "text/vnd.ms-mediapackage"),
+			Mime::TextVndNet2phoneCommcenterCommand => write!(f, "text/vnd.net2phone.commcenter.command"),
+			Mime::TextVndRadisysMsmlBasicLayout => write!(f, "text/vnd.radisys.msml-basic-layout"),
+			Mime::TextVndSenxWarpscript => write!(f, "text/vnd.senx.warpscript"),
+			Mime::TextVndSunJ2meAppDescriptor => write!(f, "text/vnd.sun.j2me.app-descriptor"),
+			Mime::TextVndSosi => write!(f, "text/vnd.sosi"),
+			Mime::TextVndTrolltechLinguist => write!(f, "text/vnd.trolltech.linguist"),
+			Mime::TextVndWapSi => write!(f, "text/vnd.wap.si"),
+			Mime::TextVndWapSl => write!(f, "text/vnd.wap.sl"),
+			Mime::TextVndWapWml => write!(f, "text/vnd.wap.wml"),
+			Mime::TextVndWapWmlscript => write!(f, "text/vnd.wap.wmlscript"),
+			Mime::TextVtt => write!(f, "text/vtt"),
+			Mime::TextWgsl => write!(f, "text/wgsl"),
+			Mime::TextXml => write!(f, "text/xml"),
+			Mime::TextXmlExternalParsedEntity => write!(f, "text/xml-external-parsed-entity"),
+			Mime::Video1dInterleavedParityfec => write!(f, "video/1d-interleaved-parityfec"),
+			Mime::Video3gpp => write!(f, "video/3gpp"),
+			Mime::Video3gpp2 => write!(f, "video/3gpp2"),
+			Mime::Video3gppTt => write!(f, "video/3gpp-tt"),
+			Mime::VideoAv1 => write!(f, "video/AV1"),
+			Mime::VideoBmpeg => write!(f, "video/BMPEG"),
+			Mime::VideoBt656 => write!(f, "video/BT656"),
+			Mime::VideoCelb => write!(f, "video/CelB"),
+			Mime::VideoDv => write!(f, "video/DV"),
+			Mime::VideoEncaprtp => write!(f, "video/encaprtp"),
+			Mime::VideoExample => write!(f, "video/example"),
+			Mime::VideoFfv1 => write!(f, "video/FFV1"),
+			Mime::VideoFlexfec => write!(f, "video/flexfec"),
+			Mime::VideoH261 => write!(f, "video/H261"),
+			Mime::VideoH263 => write!(f, "video/H263"),
+			Mime::VideoH2631998 => write!(f, "video/H263-1998"),
+			Mime::VideoH2632000 => write!(f, "video/H263-2000"),
+			Mime::VideoH264 => write!(f, "video/H264"),
+			Mime::VideoH264Rcdo => write!(f, "video/H264-RCDO"),
+			Mime::VideoH264Svc => write!(f, "video/H264-SVC"),
+			Mime::VideoH265 => write!(f, "video/H265"),
+			Mime::VideoH266 => write!(f, "video/H266"),
+			Mime::VideoIsoSegment => write!(f, "video/iso.segment"),
+			Mime::VideoJpeg => write!(f, "video/JPEG"),
+			Mime::VideoJpeg2000 => write!(f, "video/jpeg2000"),
+			Mime::VideoJxsv => write!(f, "video/jxsv"),
+			Mime::VideoMj2 => write!(f, "video/mj2"),
+			Mime::VideoMp1s => write!(f, "video/MP1S"),
+			Mime::VideoMp2p => write!(f, "video/MP2P"),
+			Mime::VideoMp2t => write!(f, "video/MP2T"),
+			Mime::VideoMp4 => write!(f, "video/mp4"),
+			Mime::VideoMp4vEs => write!(f, "video/MP4V-ES"),
+			Mime::VideoMpv => write!(f, "video/MPV"),
+			Mime::VideoMpeg4Generic => write!(f, "video/mpeg4-generic"),
+			Mime::VideoNv => write!(f, "video/nv"),
+			Mime::VideoOgg => write!(f, "video/ogg"),
+			Mime::VideoParityfec => write!(f, "video/parityfec"),
+			Mime::VideoPointer => write!(f, "video/pointer"),
+			Mime::VideoQuicktime => write!(f, "video/quicktime"),
+			Mime::VideoRaptorfec => write!(f, "video/raptorfec"),
+			Mime::VideoRaw => write!(f, "video/raw"),
+			Mime::VideoRtpEncAescm128 => write!(f, "video/rtp-enc-aescm128"),
+			Mime::VideoRtploopback => write!(f, "video/rtploopback"),
+			Mime::VideoRtx => write!(f, "video/rtx"),
+			Mime::VideoScip => write!(f, "video/scip"),
+			Mime::VideoSmpte291 => write!(f, "video/smpte291"),
+			Mime::VideoSmpte292m => write!(f, "video/SMPTE292M"),
+			Mime::VideoUlpfec => write!(f, "video/ulpfec"),
+			Mime::VideoVc1 => write!(f, "video/vc1"),
+			Mime::VideoVc2 => write!(f, "video/vc2"),
+			Mime::VideoVndCctv => write!(f, "video/vnd.CCTV"),
+			Mime::VideoVndDeceHd => write!(f, "video/vnd.dece.hd"),
+			Mime::VideoVndDeceMobile => write!(f, "video/vnd.dece.mobile"),
+			Mime::VideoVndDeceMp4 => write!(f, "video/vnd.dece.mp4"),
+			Mime::VideoVndDecePd => write!(f, "video/vnd.dece.pd"),
+			Mime::VideoVndDeceSd => write!(f, "video/vnd.dece.sd"),
+			Mime::VideoVndDeceVideo => write!(f, "video/vnd.dece.video"),
+			Mime::VideoVndDirectvMpeg => write!(f, "video/vnd.directv.mpeg"),
+			Mime::VideoVndDirectvMpegTts => write!(f, "video/vnd.directv.mpeg-tts"),
+			Mime::VideoVndDlnaMpegTts => write!(f, "video/vnd.dlna.mpeg-tts"),
+			Mime::VideoVndDvbFile => write!(f, "video/vnd.dvb.file"),
+			Mime::VideoVndFvt => write!(f, "video/vnd.fvt"),
+			Mime::VideoVndHnsVideo => write!(f, "video/vnd.hns.video"),
+			Mime::VideoVndIptvforum1dparityfec1010 => write!(f, "video/vnd.iptvforum.1dparityfec-1010"),
+			Mime::VideoVndIptvforum1dparityfec2005 => write!(f, "video/vnd.iptvforum.1dparityfec-2005"),
+			Mime::VideoVndIptvforum2dparityfec1010 => write!(f, "video/vnd.iptvforum.2dparityfec-1010"),
+			Mime::VideoVndIptvforum2dparityfec2005 => write!(f, "video/vnd.iptvforum.2dparityfec-2005"),
+			Mime::VideoVndIptvforumTtsavc => write!(f, "video/vnd.iptvforum.ttsavc"),
+			Mime::VideoVndIptvforumTtsmpeg2 => write!(f, "video/vnd.iptvforum.ttsmpeg2"),
+			Mime::VideoVndMotorolaVideo => write!(f, "video/vnd.motorola.video"),
+			Mime::VideoVndMotorolaVideop => write!(f, "video/vnd.motorola.videop"),
+			Mime::VideoVndMpegurl => write!(f, "video/vnd.mpegurl"),
+			Mime::VideoVndMsPlayreadyMediaPyv => write!(f, "video/vnd.ms-playready.media.pyv"),
+			Mime::VideoVndNokiaInterleavedMultimedia => write!(f, "video/vnd.nokia.interleaved-multimedia"),
+			Mime::VideoVndNokiaMp4vr => write!(f, "video/vnd.nokia.mp4vr"),
+			Mime::VideoVndNokiaVideovoip => write!(f, "video/vnd.nokia.videovoip"),
+			Mime::VideoVndObjectvideo => write!(f, "video/vnd.objectvideo"),
+			Mime::VideoVndRadgamettoolsBink => write!(f, "video/vnd.radgamettools.bink"),
+			Mime::VideoVndRadgamettoolsSmacker => write!(f, "video/vnd.radgamettools.smacker"),
+			Mime::VideoVndSealedMpeg1 => write!(f, "video/vnd.sealed.mpeg1"),
+			Mime::VideoVndSealedMpeg4 => write!(f, "video/vnd.sealed.mpeg4"),
+			Mime::VideoVndSealedSwf => write!(f, "video/vnd.sealed.swf"),
+			Mime::VideoVndSealedmediaSoftsealMov => write!(f, "video/vnd.sealedmedia.softseal.mov"),
+			Mime::VideoVndUvvuMp4 => write!(f, "video/vnd.uvvu.mp4"),
+			Mime::VideoVndYoutubeYt => write!(f, "video/vnd.youtube.yt"),
+			Mime::VideoVndVivo => write!(f, "video/vnd.vivo"),
+			Mime::VideoVp8 => write!(f, "video/VP8"),
+			Mime::VideoVp9 => write!(f, "video/VP9"),
+		}
+    }
+}
+
+#[derive(Debug)]
+pub struct ParseMimeError(i32);
+
+impl std::fmt::Display for ParseMimeError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+impl std::error::Error for ParseMimeError {}
+
+impl std::str::FromStr for Mime {
+    type Err = ParseMimeError;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match MIME_MAP.get(s).copied() {
+            Some(mimetype) => Ok(mimetype),
+            None => Err(ParseMimeError(1)),
+        }
+    }
+}
+
+impl Mime {
+    pub fn from_filename(filename: &str) -> Self {
+        match filename.split('.').last() {
+            Some(v) => match v {
+                "png" => Mime::ImagePng,
+                "jpg" => Mime::ImageJpeg,
+                "json" => Mime::ApplicationJson,
+                "html" => Mime::TextHtml,
+                "css" => Mime::TextCss,
+                &_ => Mime::TextPlain,
+            },
+            None => Mime::TextPlain,
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use crate::utils::mime::mime_enum::Mime;
+
+    #[test]
+    fn get_mime_test() {
+        assert_eq!("text/plain".parse::<Mime>().unwrap(), Mime::TextPlain)
+    }
+}
diff --git a/core/http/src/utils/mime/mod.rs b/core/http/src/utils/mime/mod.rs
new file mode 100644
index 0000000..bbf3a87
--- /dev/null
+++ b/core/http/src/utils/mime/mod.rs
@@ -0,0 +1,2 @@
+mod map;
+pub mod mime_enum;
diff --git a/generatersenum.py b/generatersenum.py
new file mode 100644
index 0000000..2c686bd
--- /dev/null
+++ b/generatersenum.py
@@ -0,0 +1,73 @@
+import csv
+
+
+def generate_rust_enum(csv_file):
+    rust_enum = "use phf::phf_map;\n\nenum Mime {\n"
+
+    with open(csv_file, "r") as file:
+        csv_data = csv.reader(file)
+        next(csv_data)  # Skip the header row
+
+        for row in csv_data:
+            if row[1] == "":
+                continue
+            if "DEPRECATED" in row[0]:
+                continue
+            name = format_enum_member(row[0:2])
+            rust_enum += f"\t{name},\n"
+
+    rust_enum += "}\n\n"
+    rust_enum += "impl std::fmt::Display for Mime {\n"
+    rust_enum += "\tfn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {\n"
+    rust_enum += "\t\tmatch self {\n"
+
+    with open(csv_file, "r") as file:
+        csv_data = csv.reader(file)
+        next(csv_data)  # Skip the header row
+        for row in csv_data:
+            if row[1] == "":
+                continue
+            if "DEPRECATED" in row[0]:
+                continue
+            name = format_enum_member(row[0:2])
+            rust_enum += f'\t\t\tMime::{name} => write!(f, "{row[1]}"),\n'
+
+    rust_enum += "\t\t}\n\t}\n}\n\n"
+
+    rust_enum += "static MimeMap: phf::Map<&'static str, Mime> = phf_map! {\n"
+    with open(csv_file, "r") as file:
+        csv_data = csv.reader(file)
+        next(csv_data)
+        for row in csv_data:
+            if row[1] == "":
+                continue
+            if "DEPRECATED" in row[0]:
+                continue
+            key = row[1]
+            value = format_enum_member(row[0:2])
+            rust_enum += f'\t"{key}" => Mime::{value},\n'
+    rust_enum += "};"
+
+    return rust_enum
+
+
+def format_enum_member(name):
+    prefix = "".join(name[1].split("/")[0:-1])
+    name = name[0].split("-")
+    words = []
+    parts = []
+    for part in name:
+        parts += part.split("+")
+    for part in parts:
+        words += part.split(".")
+
+    formatted_name = "".join(word.capitalize() for word in words)
+    if not formatted_name.startswith(prefix.capitalize()):
+        formatted_name = prefix.capitalize() + formatted_name
+    return formatted_name
+
+
+# Usage example
+csv_file = "mimes.csv"
+rust_enum_code = generate_rust_enum(csv_file)
+print(rust_enum_code)
diff --git a/site/Cargo.lock b/site/Cargo.lock
index c714959..84f675c 100644
--- a/site/Cargo.lock
+++ b/site/Cargo.lock
@@ -39,7 +39,7 @@ dependencies = [
 name = "http"
 version = "0.1.0"
 dependencies = [
- "mime",
+ "phf",
  "tokio",
 ]
 
@@ -59,12 +59,6 @@ dependencies = [
  "scopeguard",
 ]
 
-[[package]]
-name = "mime"
-version = "0.3.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
-
 [[package]]
 name = "mio"
 version = "0.8.7"
@@ -109,6 +103,48 @@ dependencies = [
  "windows-sys 0.45.0",
 ]
 
+[[package]]
+name = "phf"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c"
+dependencies = [
+ "phf_macros",
+ "phf_shared",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf"
+dependencies = [
+ "phf_shared",
+ "rand",
+]
+
+[[package]]
+name = "phf_macros"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92aacdc5f16768709a569e913f7451034034178b05bdc8acda226659a3dccc66"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676"
+dependencies = [
+ "siphasher",
+]
+
 [[package]]
 name = "pin-project-lite"
 version = "0.2.9"
@@ -133,6 +169,21 @@ dependencies = [
  "proc-macro2",
 ]
 
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+
 [[package]]
 name = "redox_syscall"
 version = "0.2.16"
@@ -157,6 +208,12 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "siphasher"
+version = "0.3.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
+
 [[package]]
 name = "site"
 version = "0.1.0"
@@ -181,6 +238,17 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
 [[package]]
 name = "syn"
 version = "2.0.18"
@@ -219,7 +287,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 2.0.18",
 ]
 
 [[package]]
diff --git a/small.csv b/small.csv
new file mode 100644
index 0000000..aa3809c
--- /dev/null
+++ b/small.csv
@@ -0,0 +1,20 @@
+Name, format, asdf
+vnd.motorola.video,video/vnd.motorola.video,[Tom_McGinty]
+vnd.motorola.videop,video/vnd.motorola.videop,[Tom_McGinty]
+vnd.mpegurl,video/vnd.mpegurl,[Heiko_Recktenwald]
+vnd.ms-playready.media.pyv,video/vnd.ms-playready.media.pyv,[Steve_DiAcetis]
+vnd.nokia.interleaved-multimedia,video/vnd.nokia.interleaved-multimedia,[Petteri_Kangaslampi]
+vnd.nokia.mp4vr,video/vnd.nokia.mp4vr,[Miska_M._Hannuksela]
+vnd.nokia.videovoip,video/vnd.nokia.videovoip,[Nokia]
+vnd.objectvideo,video/vnd.objectvideo,[John_Clark]
+vnd.radgamettools.bink,video/vnd.radgamettools.bink,[Henrik_Andersson]
+vnd.radgamettools.smacker,video/vnd.radgamettools.smacker,[Henrik_Andersson]
+vnd.sealed.mpeg1,video/vnd.sealed.mpeg1,[David_Petersen]
+vnd.sealed.mpeg4,video/vnd.sealed.mpeg4,[David_Petersen]
+vnd.sealed.swf,video/vnd.sealed.swf,[David_Petersen]
+vnd.sealedmedia.softseal.mov,video/vnd.sealedmedia.softseal.mov,[David_Petersen]
+vnd.uvvu.mp4,video/vnd.uvvu.mp4,[Michael_A_Dolan]
+vnd.youtube.yt,video/vnd.youtube.yt,[Google]
+vnd.vivo,video/vnd.vivo,[John_Wolfe]
+VP8,video/VP8,[RFC7741]
+VP9,video/VP9,[RFC-ietf-payload-vp9-16]
-- 
GitLab


From fe8dba588850c16b28b955a51c871504094e6fdc Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sun, 4 Jun 2023 20:58:42 +0200
Subject: [PATCH 25/65] Add multipart post text form support, check for
 `Content-Length` Header

---
 core/http/src/handlers/handlers.rs    |  45 ++++-----
 core/http/src/handling/request.rs     | 140 ++++++++++++++++++++++++--
 core/http/src/handling/response.rs    |   4 +-
 core/http/src/handling/routes.rs      |  32 +++++-
 core/http/src/setup.rs                |   1 +
 core/http/src/utils/mime/mime_enum.rs |   5 +
 site/404.html                         |   5 +-
 site/src/main.rs                      |   8 +-
 8 files changed, 196 insertions(+), 44 deletions(-)

diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
index f81441c..63172c5 100755
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -12,7 +12,7 @@ use crate::setup::MountPoint;
 
 pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint<'_>>) {
     let mut buf_reader = BufReader::new(&mut stream);
-    let mut http_request: Vec<String> = Vec::with_capacity(100);
+    let mut http_request: Vec<String> = Vec::with_capacity(30);
     loop {
         let mut buffer = String::new();
         if let Err(_) = buf_reader.read_line(&mut buffer).await {
@@ -74,26 +74,28 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
             if let Ok(size) = len {
                 size
             } else {
-                0
+                eprintln!("\x1b[31m`{}` must have a `Content-Length` header\x1b[0m", request.method);
+                len_not_defined(stream, Status::LengthRequired).await;
+                return;
             }
         } else {
+            if request.mandatory_body() {
+                eprintln!("\x1b[31m`{}` must have a `Content-Length` header\x1b[0m", request.method);
+                len_not_defined(stream, Status::LengthRequired).await;
+                return;
+            }
             0
         };
-
-        let mut buffer: Vec<u8> = vec![];
-        buf_reader.read_buf(&mut buffer).await.unwrap();
-        if buffer.len() != length {
-            let respone = len_not_defined(Status::LengthRequired);
-            let mut response = respone.0.as_bytes().to_vec();
-            response.extend_from_slice(&respone.1);
-            if let Err(e) = stream.write_all(&response).await {
-                eprintln!("\x1b[31mError {e} occured when trying to write answer to TCP-Stream for Client, aborting\x1b[0m");
+        if length != 0 {
+            let mut buffer: Vec<u8> = vec![];
+            buf_reader.read_buf(&mut buffer).await.unwrap();
+            if buffer.len() != length {
+                len_not_defined(stream, Status::LengthRequired).await;
                 return;
             }
-            return;
+            data.is_complete = true;
+            data.buffer = buffer;
         }
-        data.is_complete = true;
-        data.buffer = buffer;
     }
 
     let mut handled_response: Option<Outcome<Response, Status, Data>> = None;
@@ -165,14 +167,11 @@ fn failure_handler(status: Status) -> (String, Vec<u8>) {
     )
 }
 
-fn len_not_defined(status: Status) -> (String, Vec<u8>) {
+async fn len_not_defined(mut stream: TcpStream, status: Status) {
     let page_411 = NamedFile::open(PathBuf::from("411.html")).unwrap();
-    (
-        format!(
-            "HTTP/1.1 {status}\r\nContent-Length: {}\r\nContent-Type: {}\r\n\r\n",
-            page_411.get_len(),
-            page_411.get_mime()
-        ),
-        page_411.get_data(),
-    )
+    let mut response = format!("HTTP/1.1 {}\r\nContent-Length: {}\r\nContent-Type: {}\r\n\r\n", status, page_411.get_len(), page_411.get_mime()).as_bytes().to_vec();
+    response.extend_from_slice(&page_411.get_data());
+        if let Err(e) = stream.write_all(&response).await {
+            eprintln!("\x1b[31mError {e} occured when trying to write answer to TCP-Stream for Client, aborting\x1b[0m");
+        }
 }
diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index f90bacb..5f02d3d 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -2,10 +2,7 @@
 
 use std::{collections::HashMap, error::Error, fmt::Display};
 
-trait FromPost {}
-
-impl FromPost for &str {}
-impl FromPost for Vec<u8> {}
+use crate::utils::mime::mime_enum::Mime;
 
 use super::{
     methods::Method,
@@ -68,6 +65,12 @@ impl Request<'_> {
             _ => false,
         }
     }
+    pub fn mandatory_body(&self) -> bool {
+        match self.method {
+            Method::Post | Method::Put | Method::Patch => true,
+            _ => false,
+        }
+    }
     // pub fn get_post_form_key<T: FromRequest>(&self, data: Data) -> T {}
     pub fn get_get_form_keys(
         &self,
@@ -108,7 +111,132 @@ impl Request<'_> {
         }
         Ok(response)
     }
-    pub fn get_post_form_key(&self, key: &str, data: Data) {
-        todo!()
+    pub fn get_post_text_form_key(&self, key: &str, data: &Data) -> Result<String, ()> {
+        let mut post_type = self
+            .headers
+            .iter()
+            .find(|header| header.contains("Content-Type: "))
+            .unwrap()
+            .to_string();
+
+        post_type = post_type
+            .strip_prefix("Content-Type: ")
+            .unwrap()
+            .to_string();
+
+        let post_type: Vec<&str> = post_type.trim().split(';').collect();
+        let mime_type = post_type[0].parse::<Mime>().unwrap();
+
+        match mime_type {
+            Mime::ApplicationXWwwFormUrlencoded => {
+                let data = String::from_utf8(data.buffer.clone()).unwrap();
+                let kvps = data
+                    .split("&")
+                    .map(|kvp| kvp.split_once("=").unwrap())
+                    .collect::<HashMap<&str, &str>>();
+                if let Some(val) = kvps.get(key) {
+                    Ok(val.to_string())
+                } else {
+                    Err(())
+                }
+            }
+            Mime::MultipartFormData => {
+                let from_req = post_type[1..]
+                    .iter()
+                    .find(|val| val.contains("boundary="))
+                    .unwrap()
+                    .strip_prefix("boundary=")
+                    .unwrap();
+                let mut boundary = "--".as_bytes().to_vec();
+                boundary.extend_from_slice(from_req.trim_matches('"').as_bytes());
+                let mut end_boundary = boundary.clone();
+                end_boundary.extend_from_slice(b"--");
+                boundary.extend_from_slice(&[b'\r']);
+                let parts = data
+                    .buffer
+                    .split(|byte| byte == &b'\n')
+                    .collect::<Vec<&[u8]>>();
+
+                let mut boundary_found = false;
+                let mut key_found = false;
+                let mut value = vec![];
+                for part in parts {
+                    if part == [] {
+                        continue;
+                    }
+                    if (key_found && part == boundary) || part == end_boundary {
+                        break;
+                    }
+                    if !boundary_found && part == boundary {
+                        boundary_found = true;
+                        continue;
+                    }
+                    if part.starts_with(b"Content-Disposition: form-data; name=") {
+                        let headers = part
+                            .split(|byte| byte == &b';')
+                            .filter(|header| !header.is_empty())
+                            .collect::<Vec<_>>();
+                        if headers.len() < 2 {
+                            continue;
+                        }
+                        let name = headers[1].split(|byte| byte == &b'=').collect::<Vec<_>>();
+                        if name.len() != 2 {
+                            continue;
+                        }
+                        let mkey = String::from_utf8_lossy(name[1])
+                            .to_string()
+                            .trim_end()
+                            .trim_matches('"')
+                            .to_owned();
+                        key_found = key == mkey;
+                    } else if key_found == true {
+                        value.extend_from_slice(part);
+                        value.extend_from_slice(&[b'\n']);
+                    }
+                }
+                Ok(String::from_utf8_lossy(&value)
+                    .to_owned()
+                    .trim()
+                    .to_string())
+            }
+            _ => Err(()),
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use crate::handling::routes::Data;
+
+    use super::Request;
+
+    #[test]
+    fn try_post_text() {
+        let req = Request {
+            uri: "",
+            headers: vec!["Content-Type: multipart/form-data;boundary=\"boundary\"".to_string()],
+            method: crate::handling::methods::Method::Post,
+        };
+        let data = Data {
+            buffer: b"--boundary\r
+Content-Disposition: form-data; name=\"field1\"\r
+\r
+value1\r
+--boundary\r
+Content-Disposition: form-data; name=\"field2\"; filename=\"example.txt\"\n\r
+\r
+value2\r
+--boundary--"
+                .to_vec(),
+            is_complete: true,
+        };
+        assert_eq!(
+            "value1",
+            req.get_post_text_form_key("field1", &data).unwrap()
+        );
+        assert_eq!(
+            "value2",
+            req.get_post_text_form_key("field2", &data).unwrap()
+        );
     }
 }
diff --git a/core/http/src/handling/response.rs b/core/http/src/handling/response.rs
index 2f7fdcf..81a54af 100644
--- a/core/http/src/handling/response.rs
+++ b/core/http/src/handling/response.rs
@@ -21,10 +21,10 @@ pub trait ResponseBody: Send {
 
 impl ResponseBody for Body {
     fn get_data(&self) -> Vec<u8> {
-        self.body.clone()
+        self.body()
     }
     fn get_mime(&self) -> Mime {
-        Mime::TextPlain
+        self.mime_type()
     }
 
     fn get_len(&self) -> usize {
diff --git a/core/http/src/handling/routes.rs b/core/http/src/handling/routes.rs
index 9ded1ce..9fd3f77 100644
--- a/core/http/src/handling/routes.rs
+++ b/core/http/src/handling/routes.rs
@@ -1,7 +1,10 @@
-use super::{
-    methods::Method,
-    request::{MediaType, Request},
-    response::{Outcome, Response, Status},
+use crate::{
+    handling::{
+        methods::Method,
+        request::{MediaType, Request},
+        response::{Outcome, Response, Status},
+    },
+    utils::mime::mime_enum::Mime,
 };
 
 pub struct RoutInfo {
@@ -63,7 +66,26 @@ pub type Uri<'a> = &'a str;
 
 #[derive(Debug, Clone)]
 pub struct Body {
-    pub body: Vec<u8>,
+    body: Vec<u8>,
+    mime_type: Mime,
+}
+
+impl Body {
+    pub fn new(body: Vec<u8>, mime_type: Mime) -> Self {
+        Self { body, mime_type }
+    }
+    pub fn set_mime_type(&mut self, mime_type: Mime) {
+        self.mime_type = mime_type;
+    }
+    pub fn set_body(&mut self, body: Vec<u8>) {
+        self.body = body;
+    }
+    pub fn mime_type(&self) -> Mime {
+        self.mime_type
+    }
+    pub fn body(&self) -> Vec<u8> {
+        self.body.clone()
+    }
 }
 
 #[derive(Debug, Clone)]
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index 9f57e76..50f5144 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -66,6 +66,7 @@ impl<'a> Config {
         self
     }
     pub async fn launch(self) {
+        println!("Server launched from http://{}", self.address.local_addr().unwrap());
         let mut sigint = signal(SignalKind::interrupt()).unwrap();
         loop {
             select! {
diff --git a/core/http/src/utils/mime/mime_enum.rs b/core/http/src/utils/mime/mime_enum.rs
index fbf4415..0a6a068 100644
--- a/core/http/src/utils/mime/mime_enum.rs
+++ b/core/http/src/utils/mime/mime_enum.rs
@@ -4061,6 +4061,11 @@ impl std::str::FromStr for Mime {
     type Err = ParseMimeError;
 
     fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let s = if let Some(str) = s.split_once(';') {
+            str.0
+        } else {
+            s
+        };
         match MIME_MAP.get(s).copied() {
             Some(mimetype) => Ok(mimetype),
             None => Err(ParseMimeError(1)),
diff --git a/site/404.html b/site/404.html
index 0a1a4ed..7934c61 100644
--- a/site/404.html
+++ b/site/404.html
@@ -7,13 +7,10 @@
   <body>
     <h1>404</h1>
     <p>Hi from Rust</p>
-    <form action="/" method="POST">
+    <form action="/post/post" method="post">
       <label for="message">Enter your message:</label>
       <input type="text" id="message" name="message" />
       <button type="submit">Send</button>
-      <label for="message">Enter your message:</label>
-      <input type="text" id="asdf" name="message" />
-      <button type="submit">Send</button>
     </form>
     <form action="/static/hi" method="get">
       <label for="jump">Enter asdf</label>
diff --git a/site/src/main.rs b/site/src/main.rs
index deb31d6..1005312 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -58,12 +58,12 @@ fn fileserver(path: &str) -> Result<NamedFile, Status> {
     NamedFile::open(PathBuf::from("static/".to_string() + path))
 }
 
-fn post_hi_handler(_request: Request, data: Data) -> Outcome<Response, Status, Data> {
+fn post_hi_handler(request: Request, data: Data) -> Outcome<Response, Status, Data> {
     if data.is_empty() {
         return Outcome::Forward(data);
     }
-    let data = if let Ok(str) = String::from_utf8(data.buffer) {
-        str
+    let data = if let Ok(val) = request.get_post_text_form_key("message", &data) {
+        val
     } else {
         return Outcome::Failure(Status::BadRequest);
     };
@@ -111,7 +111,7 @@ async fn main() {
         rank: 0,
     };
 
-    http::build("192.168.178.32:8000")
+    http::build("127.0.0.1:8000")
         .await
         .mount("/", vec![fileserver, post_test, static_hi])
         .mount("/post/", vec![post_test])
-- 
GitLab


From 374dcc3e1e454421e0d18bd39f1cbe37410bb53b Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Mon, 5 Jun 2023 21:19:48 +0200
Subject: [PATCH 26/65] Update `get_post_form_text` to allow for an array of
 keys to search

---
 core/http/src/handling/request.rs | 70 +++++++++++++++++++++----------
 1 file changed, 48 insertions(+), 22 deletions(-)

diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index 5f02d3d..12947a6 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -72,9 +72,9 @@ impl Request<'_> {
         }
     }
     // pub fn get_post_form_key<T: FromRequest>(&self, data: Data) -> T {}
-    pub fn get_get_form_keys(
-        &self,
-        keys: Vec<&str>,
+    pub fn get_get_form_keys<'a>(
+        &'a self,
+        keys: &'a [&str],
     ) -> Result<HashMap<&str, &str>, ParseFormError> {
         let data = if let Some(val) = self.uri.split_once("?") {
             val
@@ -111,7 +111,11 @@ impl Request<'_> {
         }
         Ok(response)
     }
-    pub fn get_post_text_form_key(&self, key: &str, data: &Data) -> Result<String, ()> {
+    pub fn get_post_text_form_key(
+        &self,
+        keys: &[&str],
+        data: &Data,
+    ) -> Result<Vec<String>, ParseFormError> {
         let mut post_type = self
             .headers
             .iter()
@@ -134,11 +138,18 @@ impl Request<'_> {
                     .split("&")
                     .map(|kvp| kvp.split_once("=").unwrap())
                     .collect::<HashMap<&str, &str>>();
-                if let Some(val) = kvps.get(key) {
-                    Ok(val.to_string())
-                } else {
-                    Err(())
+
+                let mut result: Vec<String> = Vec::with_capacity(keys.len());
+                for key in keys {
+                    if let Some(val) = kvps.get(key) {
+                        result.push(val.to_string());
+                    } else {
+                        return Err(ParseFormError {
+                            error: ParseErrors::NoData,
+                        });
+                    }
                 }
+                Ok(result)
             }
             Mime::MultipartFormData => {
                 let from_req = post_type[1..]
@@ -158,16 +169,17 @@ impl Request<'_> {
                     .collect::<Vec<&[u8]>>();
 
                 let mut boundary_found = false;
-                let mut key_found = false;
-                let mut value = vec![];
+                let mut current_key: Option<usize> = None;
+                let mut result: Vec<Vec<u8>> = vec!["".into(); keys.len()];
                 for part in parts {
                     if part == [] {
                         continue;
                     }
-                    if (key_found && part == boundary) || part == end_boundary {
+                    if part == end_boundary {
                         break;
                     }
                     if !boundary_found && part == boundary {
+                        current_key = None;
                         boundary_found = true;
                         continue;
                     }
@@ -188,18 +200,27 @@ impl Request<'_> {
                             .trim_end()
                             .trim_matches('"')
                             .to_owned();
-                        key_found = key == mkey;
-                    } else if key_found == true {
-                        value.extend_from_slice(part);
-                        value.extend_from_slice(&[b'\n']);
+                        let mut index = 0;
+                        for i in keys {
+                            if *i == mkey {
+                                current_key = Some(index);
+                            }
+                            index += 1;
+                        }
+                        boundary_found = false;
+                    } else if let Some(key) = current_key {
+                        result[key].extend_from_slice(part);
+                        result[key].extend_from_slice(&[b'\n']);
                     }
                 }
-                Ok(String::from_utf8_lossy(&value)
-                    .to_owned()
-                    .trim()
-                    .to_string())
+                Ok(result
+                    .iter()
+                    .map(|arr| String::from_utf8(arr.to_vec()).unwrap().trim().into())
+                    .collect())
             }
-            _ => Err(()),
+            _ => Err(ParseFormError {
+                error: ParseErrors::BadData,
+            }),
         }
     }
 }
@@ -232,11 +253,16 @@ value2\r
         };
         assert_eq!(
             "value1",
-            req.get_post_text_form_key("field1", &data).unwrap()
+            req.get_post_text_form_key(&["field1"], &data).unwrap()[0]
         );
         assert_eq!(
             "value2",
-            req.get_post_text_form_key("field2", &data).unwrap()
+            req.get_post_text_form_key(&["field2"], &data).unwrap()[0]
         );
+        assert_eq!(
+            vec!["value1", "value2"],
+            req.get_post_text_form_key(&["field1", "field2"], &data)
+                .unwrap()
+        )
     }
 }
-- 
GitLab


From 91fb02ce5510ca1a8884d0f7d846471b6ae72d7d Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Tue, 6 Jun 2023 20:49:49 +0200
Subject: [PATCH 27/65] update the `get_get_form_data()` to return a
 Result<Hasmap<&str, Result<&str, ParseFormError>>, ParseFormError> for easier
 handling of not existant keys

---
 core/http/src/handling/request.rs | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index 12947a6..6fa46de 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -75,7 +75,7 @@ impl Request<'_> {
     pub fn get_get_form_keys<'a>(
         &'a self,
         keys: &'a [&str],
-    ) -> Result<HashMap<&str, &str>, ParseFormError> {
+    ) -> Result<HashMap<&str, Result<&str, ParseFormError>>, ParseFormError> {
         let data = if let Some(val) = self.uri.split_once("?") {
             val
         } else {
@@ -100,14 +100,14 @@ impl Request<'_> {
         }
         let mut response = HashMap::new();
         for key in keys {
-            let entry = if let Some(val) = values.get_key_value(key) {
-                val
+            let entry = if let Some(val) = values.get(key) {
+                Ok(*val)
             } else {
-                return Err(ParseFormError {
+                Err(ParseFormError {
                     error: ParseErrors::NoData,
-                });
+                })
             };
-            response.insert(*entry.0, *entry.1);
+            response.insert((*key).into(), entry);
         }
         Ok(response)
     }
-- 
GitLab


From 4fe55b1268cf02b2b6433c05d51227cc23b58a89 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Tue, 6 Jun 2023 22:29:36 +0200
Subject: [PATCH 28/65] Some rather small changes

---
 core/http/src/handling/request.rs | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index 6fa46de..09f5db6 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -71,7 +71,6 @@ impl Request<'_> {
             _ => false,
         }
     }
-    // pub fn get_post_form_key<T: FromRequest>(&self, data: Data) -> T {}
     pub fn get_get_form_keys<'a>(
         &'a self,
         keys: &'a [&str],
@@ -115,7 +114,7 @@ impl Request<'_> {
         &self,
         keys: &[&str],
         data: &Data,
-    ) -> Result<Vec<String>, ParseFormError> {
+    ) -> Result<HashMap<&str, Result<&str, ParseFormError>>, ParseFormError> {
         let mut post_type = self
             .headers
             .iter()
@@ -131,6 +130,7 @@ impl Request<'_> {
         let post_type: Vec<&str> = post_type.trim().split(';').collect();
         let mime_type = post_type[0].parse::<Mime>().unwrap();
 
+        let mut result = HashMap::new();
         match mime_type {
             Mime::ApplicationXWwwFormUrlencoded => {
                 let data = String::from_utf8(data.buffer.clone()).unwrap();
@@ -139,15 +139,15 @@ impl Request<'_> {
                     .map(|kvp| kvp.split_once("=").unwrap())
                     .collect::<HashMap<&str, &str>>();
 
-                let mut result: Vec<String> = Vec::with_capacity(keys.len());
                 for key in keys {
-                    if let Some(val) = kvps.get(key) {
-                        result.push(val.to_string());
+                    let entry = if let Some(val) = kvps.get(key) {
+                        Ok(*val)
                     } else {
-                        return Err(ParseFormError {
+                        Err(ParseFormError {
                             error: ParseErrors::NoData,
-                        });
-                    }
+                        })
+                    };
+                    result.insert(*key, entry);
                 }
                 Ok(result)
             }
@@ -158,7 +158,7 @@ impl Request<'_> {
                     .unwrap()
                     .strip_prefix("boundary=")
                     .unwrap();
-                let mut boundary = "--".as_bytes().to_vec();
+                let mut boundary = b"--".to_vec();
                 boundary.extend_from_slice(from_req.trim_matches('"').as_bytes());
                 let mut end_boundary = boundary.clone();
                 end_boundary.extend_from_slice(b"--");
-- 
GitLab


From 39889425fb4f96aef011ec7b4cb7b7eb5085de76 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Fri, 9 Jun 2023 21:17:37 +0200
Subject: [PATCH 29/65] Working on new get post data function

---
 core/http/src/handling/request.rs | 327 ++++++++++++++++++------------
 site/src/main.rs                  |  20 +-
 2 files changed, 202 insertions(+), 145 deletions(-)

diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index 09f5db6..8605de4 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -110,119 +110,176 @@ impl Request<'_> {
         }
         Ok(response)
     }
-    pub fn get_post_text_form_key(
+
+    pub fn get_post_data(
         &self,
         keys: &[&str],
         data: &Data,
-    ) -> Result<HashMap<&str, Result<&str, ParseFormError>>, ParseFormError> {
-        let mut post_type = self
+    ) -> Result<HashMap<&str, Result<Vec<u8>, ParseFormError>>, ParseFormError> {
+        let mut post_type = if let Some(val) = self
             .headers
             .iter()
             .find(|header| header.contains("Content-Type: "))
-            .unwrap()
-            .to_string();
-
-        post_type = post_type
-            .strip_prefix("Content-Type: ")
-            .unwrap()
-            .to_string();
-
-        let post_type: Vec<&str> = post_type.trim().split(';').collect();
-        let mime_type = post_type[0].parse::<Mime>().unwrap();
-
-        let mut result = HashMap::new();
-        match mime_type {
-            Mime::ApplicationXWwwFormUrlencoded => {
-                let data = String::from_utf8(data.buffer.clone()).unwrap();
-                let kvps = data
-                    .split("&")
-                    .map(|kvp| kvp.split_once("=").unwrap())
-                    .collect::<HashMap<&str, &str>>();
-
-                for key in keys {
-                    let entry = if let Some(val) = kvps.get(key) {
-                        Ok(*val)
-                    } else {
-                        Err(ParseFormError {
-                            error: ParseErrors::NoData,
-                        })
-                    };
-                    result.insert(*key, entry);
-                }
-                Ok(result)
+        {
+            if let Ok(Type) = val.strip_prefix("Content-Type: ").unwrap().trim().parse() {
+                Type
+            } else {
+                return Err(ParseFormError {
+                    error: ParseErrors::NoData,
+                });
             }
-            Mime::MultipartFormData => {
-                let from_req = post_type[1..]
-                    .iter()
-                    .find(|val| val.contains("boundary="))
-                    .unwrap()
-                    .strip_prefix("boundary=")
-                    .unwrap();
-                let mut boundary = b"--".to_vec();
-                boundary.extend_from_slice(from_req.trim_matches('"').as_bytes());
-                let mut end_boundary = boundary.clone();
-                end_boundary.extend_from_slice(b"--");
-                boundary.extend_from_slice(&[b'\r']);
-                let parts = data
-                    .buffer
-                    .split(|byte| byte == &b'\n')
-                    .collect::<Vec<&[u8]>>();
+        } else {
+            return Err(ParseFormError {
+                error: ParseErrors::NoData,
+            });
+        };
 
-                let mut boundary_found = false;
-                let mut current_key: Option<usize> = None;
-                let mut result: Vec<Vec<u8>> = vec!["".into(); keys.len()];
-                for part in parts {
-                    if part == [] {
-                        continue;
-                    }
-                    if part == end_boundary {
-                        break;
-                    }
-                    if !boundary_found && part == boundary {
-                        current_key = None;
-                        boundary_found = true;
-                        continue;
-                    }
-                    if part.starts_with(b"Content-Disposition: form-data; name=") {
-                        let headers = part
-                            .split(|byte| byte == &b';')
-                            .filter(|header| !header.is_empty())
-                            .collect::<Vec<_>>();
-                        if headers.len() < 2 {
-                            continue;
-                        }
-                        let name = headers[1].split(|byte| byte == &b'=').collect::<Vec<_>>();
-                        if name.len() != 2 {
-                            continue;
-                        }
-                        let mkey = String::from_utf8_lossy(name[1])
-                            .to_string()
-                            .trim_end()
-                            .trim_matches('"')
-                            .to_owned();
-                        let mut index = 0;
-                        for i in keys {
-                            if *i == mkey {
-                                current_key = Some(index);
-                            }
-                            index += 1;
-                        }
-                        boundary_found = false;
-                    } else if let Some(key) = current_key {
-                        result[key].extend_from_slice(part);
-                        result[key].extend_from_slice(&[b'\n']);
-                    }
-                }
-                Ok(result
-                    .iter()
-                    .map(|arr| String::from_utf8(arr.to_vec()).unwrap().trim().into())
-                    .collect())
-            }
+        let data = data.buffer.as_slice();
+        let mut keymap: HashMap<&str, Option<&[u8]>> = HashMap::with_capacity(keys.len());
+        for i in keys {
+            keymap.entry(i).or_default();
+        }
+        match post_type {
+            Mime::ApplicationXWwwFormUrlencoded => Ok(()),
             _ => Err(ParseFormError {
                 error: ParseErrors::BadData,
             }),
-        }
+        };
+        todo!()
     }
+
+    // pub fn get_post_text_form_key(
+    //     &self,
+    //     keys: &[&str],
+    //     data: &Data,
+    // ) -> Result<HashMap<&str, Result<&str, ParseFormError>>, ParseFormError> {
+    //     let mut post_type = self
+    //         .headers
+    //         .iter()
+    //         .find(|header| header.contains("Content-Type: "))
+    //         .unwrap()
+    //         .to_string();
+    //
+    //     post_type = post_type
+    //         .strip_prefix("Content-Type: ")
+    //         .unwrap()
+    //         .to_string();
+    //
+    //     let post_type: Vec<&str> = post_type.trim().split(';').collect();
+    //     let mime_type = post_type[0].parse().unwrap();
+    //
+    //     // let data = String::from_utf8(vec)
+    //
+    //     let mut result = HashMap::new();
+    //     match mime_type {
+    //         Mime::ApplicationXWwwFormUrlencoded => {
+    //             let data = String::from_utf8(data.buffer.clone()).unwrap();
+    //             let kvps = data
+    //                 .split("&")
+    //                 .map(|kvp| kvp.split_once("=").unwrap())
+    //                 .collect::<HashMap<&str, &str>>();
+    //
+    //             for key in keys {
+    //                 let entry = if let Some(val) = kvps.get(key) {
+    //                     Ok(*val)
+    //                 } else {
+    //                     Err(ParseFormError {
+    //                         error: ParseErrors::NoData,
+    //                     })
+    //                 };
+    //                 result.insert(*key, entry);
+    //             }
+    //             Ok(result)
+    //         }
+    //         Mime::MultipartFormData => {
+    //             let from_req = post_type[1..]
+    //                 .iter()
+    //                 .find(|val| val.contains("boundary="))
+    //                 .unwrap()
+    //                 .strip_prefix("boundary=")
+    //                 .unwrap();
+    //             let mut boundary = b"--".to_vec();
+    //             boundary.extend_from_slice(from_req.trim_matches('"').as_bytes());
+    //             let mut end_boundary = boundary.clone();
+    //             end_boundary.extend_from_slice(b"--");
+    //             boundary.extend_from_slice(&[b'\r']);
+    //             let parts = data
+    //                 .buffer
+    //                 .split(|byte| byte == &b'\n')
+    //                 .collect::<Vec<&[u8]>>();
+    //
+    //             let mut boundary_found = false;
+    //             let mut current_key: Option<&str> = None;
+    //             let mut result: HashMap<&str, Vec<u8>> = HashMap::new();
+    //             for part in parts {
+    //                 if part == [] {
+    //                     continue;
+    //                 }
+    //                 if part == end_boundary {
+    //                     break;
+    //                 }
+    //                 if !boundary_found && part == boundary {
+    //                     current_key = None;
+    //                     boundary_found = true;
+    //                     continue;
+    //                 }
+    //                 if part.starts_with(b"Content-Disposition: form-data; name=") {
+    //                     let headers = part
+    //                         .split(|byte| byte == &b';')
+    //                         .filter(|header| !header.is_empty())
+    //                         .collect::<Vec<_>>();
+    //                     if headers.len() < 2 {
+    //                         continue;
+    //                     }
+    //                     let name = headers[1].split(|byte| byte == &b'=').collect::<Vec<_>>();
+    //                     if name.len() != 2 {
+    //                         continue;
+    //                     }
+    //                     let mkey = String::from_utf8_lossy(name[1])
+    //                         .as_ref()
+    //                         .trim_end()
+    //                         .trim_matches('"')
+    //                         .to_owned();
+    //                     for i in keys {
+    //                         if *i == mkey {
+    //                             current_key = Some(&mkey);
+    //                         }
+    //                     }
+    //                     boundary_found = false;
+    //                 } else if let Some(key) = current_key {
+    //                     if None == result.get(key) {
+    //                         result.insert(key, part.to_vec());
+    //                         continue;
+    //                     }
+    //                     result.get_mut(key).unwrap().extend_from_slice(part);
+    //                 }
+    //             }
+    //             if result.len() == 0 {
+    //                 return Err(ParseFormError {
+    //                     error: ParseErrors::NoData,
+    //                 });
+    //             }
+    //             let return_result: HashMap<&str, Result<&str, ParseErrors>> =
+    //                 HashMap::with_capacity(keys.len());
+    //
+    //             for key in keys {
+    //                 let val = result.get(key).ok_or(ParseFormError {
+    //                     error: ParseErrors::NoData,
+    //                 }).map(|value| String::from_utf8(value))
+    //                 let val = if let Ok(str) = String::from_utf8(val) {
+    //                     Ok(str)
+    //                 } else {
+    //                     Err(ParseFormError {
+    //                         error: ParseErrors::BadData,
+    //                     })
+    //                 };
+    //             }
+    //         }
+    //         _ => Err(ParseFormError {
+    //             error: ParseErrors::BadData,
+    //         }),
+    //     }
+    // }
 }
 
 #[cfg(test)]
@@ -231,38 +288,38 @@ mod test {
 
     use super::Request;
 
-    #[test]
-    fn try_post_text() {
-        let req = Request {
-            uri: "",
-            headers: vec!["Content-Type: multipart/form-data;boundary=\"boundary\"".to_string()],
-            method: crate::handling::methods::Method::Post,
-        };
-        let data = Data {
-            buffer: b"--boundary\r
-Content-Disposition: form-data; name=\"field1\"\r
-\r
-value1\r
---boundary\r
-Content-Disposition: form-data; name=\"field2\"; filename=\"example.txt\"\n\r
-\r
-value2\r
---boundary--"
-                .to_vec(),
-            is_complete: true,
-        };
-        assert_eq!(
-            "value1",
-            req.get_post_text_form_key(&["field1"], &data).unwrap()[0]
-        );
-        assert_eq!(
-            "value2",
-            req.get_post_text_form_key(&["field2"], &data).unwrap()[0]
-        );
-        assert_eq!(
-            vec!["value1", "value2"],
-            req.get_post_text_form_key(&["field1", "field2"], &data)
-                .unwrap()
-        )
-    }
+    //     #[test]
+    //     fn try_post_text() {
+    //         let req = Request {
+    //             uri: "",
+    //             headers: vec!["Content-Type: multipart/form-data;boundary=\"boundary\"".to_string()],
+    //             method: crate::handling::methods::Method::Post,
+    //         };
+    //         let data = Data {
+    //             buffer: b"--boundary\r
+    // Content-Disposition: form-data; name=\"field1\"\r
+    // \r
+    // value1\r
+    // --boundary\r
+    // Content-Disposition: form-data; name=\"field2\"; filename=\"example.txt\"\n\r
+    // \r
+    // value2\r
+    // --boundary--"
+    //                 .to_vec(),
+    //             is_complete: true,
+    //         };
+    //         assert_eq!(
+    //             "value1",
+    //             req.get_post_text_form_key(&["field1"], &data).unwrap()[0]
+    //         );
+    //         assert_eq!(
+    //             "value2",
+    //             req.get_post_text_form_key(&["field2"], &data).unwrap()[0]
+    //         );
+    //         assert_eq!(
+    //             vec!["value1", "value2"],
+    //             req.get_post_text_form_key(&["field1", "field2"], &data)
+    //                 .unwrap()
+    //         )
+    //     }
 }
diff --git a/site/src/main.rs b/site/src/main.rs
index 1005312..2a16f43 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -3,17 +3,17 @@ use std::{collections::HashMap, path::PathBuf};
 use http::handling::{
     file_handlers::NamedFile,
     methods::Method,
-    request::Request,
+    request::{Request, ParseFormError},
     response::{Outcome, Response, ResponseBody, Status},
     routes::{Data, Route},
 };
 
-fn hashmap_to_string(map: &HashMap<&str, &str>) -> String {
+fn hashmap_to_string(map: &HashMap<&str, Result<&str, ParseFormError>>) -> String {
     let mut result = String::new();
     for (key, value) in map {
         result.push_str(key);
         result.push('=');
-        result.push_str(value);
+        result.push_str(value.as_ref().unwrap());
         result.push(';');
     }
     result.pop(); // Remove the trailing semicolon if desired
@@ -21,7 +21,7 @@ fn hashmap_to_string(map: &HashMap<&str, &str>) -> String {
 }
 
 fn handle_static_hi(request: Request<'_>, data: Data) -> Outcome<Response, Status, Data> {
-    let keys = if let Ok(keys) = request.get_get_form_keys(vec!["asdf", "jkl"]) {
+    let keys = if let Ok(keys) = request.get_get_form_keys(&["asdf", "jkl"]) {
         keys
     } else {
         return Outcome::Forward(data);
@@ -62,12 +62,12 @@ fn post_hi_handler(request: Request, data: Data) -> Outcome<Response, Status, Da
     if data.is_empty() {
         return Outcome::Forward(data);
     }
-    let data = if let Ok(val) = request.get_post_text_form_key("message", &data) {
-        val
-    } else {
-        return Outcome::Failure(Status::BadRequest);
-    };
-    let dat = post_hi(data);
+    // let data = if let Ok(val) = request.get_post_text_form_key("message", &data) {
+    //     val
+    // } else {
+    //     return Outcome::Failure(Status::BadRequest);
+    // };
+    let dat = post_hi(String::from_utf8(data.buffer).unwrap());
     Outcome::Success(Response {
         headers: vec![
             format!("Content-Length: {}", dat.len()),
-- 
GitLab


From d13f46590211d721046f7dadd233d6224b5674cb Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sat, 10 Jun 2023 21:34:37 +0200
Subject: [PATCH 30/65] working on post

---
 core/http/src/handling/request.rs | 120 +++++++++++++++++-------------
 core/http/src/setup.rs            |   2 +-
 2 files changed, 71 insertions(+), 51 deletions(-)

diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index 8605de4..a74685f 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -30,13 +30,13 @@ pub enum MediaType {
     Html,
 }
 
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
 pub enum ParseErrors {
     NoData,
     BadData,
 }
 
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
 pub struct ParseFormError {
     pub error: ParseErrors,
 }
@@ -111,18 +111,18 @@ impl Request<'_> {
         Ok(response)
     }
 
-    pub fn get_post_data(
-        &self,
-        keys: &[&str],
+    pub fn get_post_data<'a>(
+        &'a self,
+        keys: &[&'a str],
         data: &Data,
     ) -> Result<HashMap<&str, Result<Vec<u8>, ParseFormError>>, ParseFormError> {
-        let mut post_type = if let Some(val) = self
+        let post_type = if let Some(val) = self
             .headers
             .iter()
             .find(|header| header.contains("Content-Type: "))
         {
-            if let Ok(Type) = val.strip_prefix("Content-Type: ").unwrap().trim().parse() {
-                Type
+            if let Ok(mime_type) = val.strip_prefix("Content-Type: ").unwrap().trim().parse() {
+                mime_type
             } else {
                 return Err(ParseFormError {
                     error: ParseErrors::NoData,
@@ -135,17 +135,52 @@ impl Request<'_> {
         };
 
         let data = data.buffer.as_slice();
-        let mut keymap: HashMap<&str, Option<&[u8]>> = HashMap::with_capacity(keys.len());
-        for i in keys {
-            keymap.entry(i).or_default();
+        let mut keymap: HashMap<&str, Result<Vec<u8>, ParseFormError>> =
+            HashMap::with_capacity(keys.len());
+        for key in keys {
+            keymap.entry(key).or_insert(Err(ParseFormError {
+                error: ParseErrors::NoData,
+            }));
         }
         match post_type {
-            Mime::ApplicationXWwwFormUrlencoded => Ok(()),
-            _ => Err(ParseFormError {
-                error: ParseErrors::BadData,
-            }),
+            Mime::ApplicationXWwwFormUrlencoded => {
+                for kvp in data.split(|byte| *byte == b'&') {
+                    let kvp = kvp.split(|byte| *byte == b'=').collect::<Vec<&[u8]>>();
+                    let key = if let Some(kv) = kvp.get(0) {
+                        kv
+                    } else {
+                        return Err(ParseFormError {
+                            error: ParseErrors::BadData,
+                        });
+                    };
+                    let key = if let Ok(kv) = String::from_utf8(key.to_vec()) {
+                        kv
+                    } else {
+                        return Err(ParseFormError {
+                            error: ParseErrors::BadData,
+                        });
+                    };
+                    let value = kvp.get(1).ok_or(ParseFormError {
+                        error: ParseErrors::NoData,
+                    });
+                    let thing = if let Some(val) = keymap.get_mut(key.as_str()) {
+                        val
+                    } else {
+                        continue;
+                    };
+                    *thing = match value {
+                        Ok(val) => Ok(val.to_vec()),
+                        Err(err) => Err(err),
+                    }
+                }
+            }
+            _ => {
+                return Err(ParseFormError {
+                    error: ParseErrors::BadData,
+                })
+            }
         };
-        todo!()
+        Ok(keymap)
     }
 
     // pub fn get_post_text_form_key(
@@ -288,38 +323,23 @@ mod test {
 
     use super::Request;
 
-    //     #[test]
-    //     fn try_post_text() {
-    //         let req = Request {
-    //             uri: "",
-    //             headers: vec!["Content-Type: multipart/form-data;boundary=\"boundary\"".to_string()],
-    //             method: crate::handling::methods::Method::Post,
-    //         };
-    //         let data = Data {
-    //             buffer: b"--boundary\r
-    // Content-Disposition: form-data; name=\"field1\"\r
-    // \r
-    // value1\r
-    // --boundary\r
-    // Content-Disposition: form-data; name=\"field2\"; filename=\"example.txt\"\n\r
-    // \r
-    // value2\r
-    // --boundary--"
-    //                 .to_vec(),
-    //             is_complete: true,
-    //         };
-    //         assert_eq!(
-    //             "value1",
-    //             req.get_post_text_form_key(&["field1"], &data).unwrap()[0]
-    //         );
-    //         assert_eq!(
-    //             "value2",
-    //             req.get_post_text_form_key(&["field2"], &data).unwrap()[0]
-    //         );
-    //         assert_eq!(
-    //             vec!["value1", "value2"],
-    //             req.get_post_text_form_key(&["field1", "field2"], &data)
-    //                 .unwrap()
-    //         )
-    //     }
+    #[test]
+    fn try_post_text() {
+        let req = Request {
+            uri: "",
+            headers: vec!["Content-Type: application/x-www-form-urlencoded".to_string()],
+            method: crate::handling::methods::Method::Post,
+        };
+        let data = Data {
+            buffer: b"message=23&message1=24".to_vec(),
+            is_complete: true,
+        };
+        assert_eq!(
+            vec![&Ok(b"23".to_vec()), &Ok(b"24".to_vec())],
+            req.get_post_data(&["message", "message1"], &data)
+                .unwrap()
+                .values()
+                .collect::<Vec<_>>()
+        );
+    }
 }
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index 50f5144..4a3914b 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -96,7 +96,7 @@ pub async fn build(ip: &str) -> Config {
     let ip = ip[0];
     let workers = available_parallelism().unwrap().get();
     println!(
-        "\x1b[34mâš™ Configuration\x1b[0m
+"\x1b[34mâš™ Configuration\x1b[0m
   >> \x1b[34mIp\x1b[0m: {ip}
   >> \x1b[34mPort\x1b[0m: {port}
   >> \x1b[34mWorkers\x1b[0m: {workers}
-- 
GitLab


From 206fa32e55ebe2fa88abe91c8646d4880822b733 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Mon, 12 Jun 2023 20:57:22 +0200
Subject: [PATCH 31/65] finishing the `get_post_data()` function for binary
 Applicacation-x-www-urlencoded forms

---
 core/http/src/handling/request.rs | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index a74685f..5267de1 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -145,7 +145,10 @@ impl Request<'_> {
         match post_type {
             Mime::ApplicationXWwwFormUrlencoded => {
                 for kvp in data.split(|byte| *byte == b'&') {
-                    let kvp = kvp.split(|byte| *byte == b'=').collect::<Vec<&[u8]>>();
+                    let kvp = kvp
+                        .split(|byte| *byte == b'=')
+                        .map(|list| list.to_vec())
+                        .collect::<Vec<Vec<u8>>>();
                     let key = if let Some(kv) = kvp.get(0) {
                         kv
                     } else {
@@ -331,7 +334,7 @@ mod test {
             method: crate::handling::methods::Method::Post,
         };
         let data = Data {
-            buffer: b"message=23&message1=24".to_vec(),
+            buffer: b"message=24&message1=23".to_vec(),
             is_complete: true,
         };
         assert_eq!(
-- 
GitLab


From 9b412c1916f8532987dc070d0dfff90984ca5afc Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Tue, 13 Jun 2023 21:30:47 +0200
Subject: [PATCH 32/65] Add test for multipart form data and boundary getter in
 request.rs

---
 core/http/src/handling/request.rs | 64 ++++++++++++++++++++++++++-----
 1 file changed, 55 insertions(+), 9 deletions(-)

diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index 5267de1..760bd3c 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -116,16 +116,26 @@ impl Request<'_> {
         keys: &[&'a str],
         data: &Data,
     ) -> Result<HashMap<&str, Result<Vec<u8>, ParseFormError>>, ParseFormError> {
+        let boundary;
         let post_type = if let Some(val) = self
             .headers
             .iter()
             .find(|header| header.contains("Content-Type: "))
         {
-            if let Ok(mime_type) = val.strip_prefix("Content-Type: ").unwrap().trim().parse() {
-                mime_type
+            let content_type = val.trim().strip_prefix("Content-Type: ").unwrap();
+            let type_vec = content_type.split(';').collect::<Vec<&str>>();
+
+            boundary = if let Some(bound) = type_vec.iter().find(|part| part.contains("boundary="))
+            {
+                bound.strip_prefix("boundary=").unwrap().trim_matches('"')
+            } else {
+                ""
+            };
+            if let Ok(mime) = type_vec[0].trim().parse() {
+                mime
             } else {
                 return Err(ParseFormError {
-                    error: ParseErrors::NoData,
+                    error: ParseErrors::BadData,
                 });
             }
         } else {
@@ -177,6 +187,12 @@ impl Request<'_> {
                     }
                 }
             }
+            Mime::MultipartFormData => {
+                let mut temp_bound = "--".to_string();
+                temp_bound.push_str(boundary);
+                let end_boundary = format!("{temp_bound}--").as_bytes().to_owned();
+                let boundary = temp_bound.as_bytes();
+            }
             _ => {
                 return Err(ParseFormError {
                     error: ParseErrors::BadData,
@@ -334,15 +350,45 @@ mod test {
             method: crate::handling::methods::Method::Post,
         };
         let data = Data {
-            buffer: b"message=24&message1=23".to_vec(),
+            buffer: b"message=23&message1=24".to_vec(),
             is_complete: true,
         };
+        let map = req.get_post_data(&["message", "message1"], &data).unwrap();
+        assert_eq!(
+            &b"23".to_vec(),
+            map.get("message").unwrap().as_ref().unwrap()
+        );
+        assert_eq!(
+            &b"24".to_vec(),
+            map.get("message1").unwrap().as_ref().unwrap()
+        );
+        let req = Request {
+            uri: "",
+            headers: vec!["Content-Type: multipart/form-data;boundary=\"boundary\"".to_string()],
+            method: crate::handling::methods::Method::Post,
+        };
+        let data = Data {
+            buffer: b"--boundary
+Content-Disposition: form-data; name=\"field1\"
+
+value1
+--boundary
+Content-Disposition: form-data; name=\"field2\"; filename=\"example.txt\"
+
+value2
+--boundary--
+"
+            .to_vec(),
+            is_complete: true,
+        };
+        let map = req.get_post_data(&["field1, field2"], &data).unwrap();
+        assert_eq!(
+            &b"value1".to_vec(),
+            map.get("field1").unwrap().as_ref().unwrap()
+        );
         assert_eq!(
-            vec![&Ok(b"23".to_vec()), &Ok(b"24".to_vec())],
-            req.get_post_data(&["message", "message1"], &data)
-                .unwrap()
-                .values()
-                .collect::<Vec<_>>()
+            &b"value2".to_vec(),
+            map.get("field2").unwrap().as_ref().unwrap()
         );
     }
 }
-- 
GitLab


From 663495413df6bf632a63e574c9d1e7562145d3e7 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Wed, 14 Jun 2023 22:48:37 +0200
Subject: [PATCH 33/65] Finishing `get_post_data()` TODO: Add '\n' detector in
 thing

---
 core/http/src/handling/request.rs | 203 ++++++++++--------------------
 1 file changed, 63 insertions(+), 140 deletions(-)

diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index 760bd3c..030188e 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -115,7 +115,7 @@ impl Request<'_> {
         &'a self,
         keys: &[&'a str],
         data: &Data,
-    ) -> Result<HashMap<&str, Result<Vec<u8>, ParseFormError>>, ParseFormError> {
+    ) -> Result<HashMap<String, Result<Vec<u8>, ParseFormError>>, ParseFormError> {
         let boundary;
         let post_type = if let Some(val) = self
             .headers
@@ -145,13 +145,15 @@ impl Request<'_> {
         };
 
         let data = data.buffer.as_slice();
-        let mut keymap: HashMap<&str, Result<Vec<u8>, ParseFormError>> =
+        let mut keymap: HashMap<String, Result<Vec<u8>, ParseFormError>> =
             HashMap::with_capacity(keys.len());
+
         for key in keys {
-            keymap.entry(key).or_insert(Err(ParseFormError {
+            keymap.entry(key.to_string()).or_insert(Err(ParseFormError {
                 error: ParseErrors::NoData,
             }));
         }
+
         match post_type {
             Mime::ApplicationXWwwFormUrlencoded => {
                 for kvp in data.split(|byte| *byte == b'&') {
@@ -189,9 +191,63 @@ impl Request<'_> {
             }
             Mime::MultipartFormData => {
                 let mut temp_bound = "--".to_string();
-                temp_bound.push_str(boundary);
+                temp_bound.push_str(&format!("{boundary}"));
                 let end_boundary = format!("{temp_bound}--").as_bytes().to_owned();
                 let boundary = temp_bound.as_bytes();
+                let parts = data.split(|byte| byte == &b'\n').collect::<Vec<&[u8]>>();
+
+                let mut current_key: Option<String> = None;
+                let mut boundary_found = true;
+                for part in parts {
+                    if part == [] {
+                        continue;
+                    }
+                    if part == end_boundary {
+                        break;
+                    }
+                    if !boundary_found && part == boundary {
+                        boundary_found = true;
+                        current_key = None;
+                        continue;
+                    }
+                    if part.starts_with(b"Content-Disposition: form-data; name=") {
+                        let headers = part
+                            .split(|byte| byte == &b';')
+                            .filter(|header| !header.is_empty())
+                            .collect::<Vec<_>>();
+                        if headers.len() < 2 {
+                            continue;
+                        }
+                        let name = headers[1].split(|byte| byte == &b'=').collect::<Vec<_>>();
+                        if name.len() != 2 {
+                            continue;
+                        }
+                        let mkey = String::from_utf8_lossy(name[1])
+                            .as_ref()
+                            .trim_end()
+                            .trim_matches('"')
+                            .to_owned();
+
+                        if keymap.contains_key::<str>(&mkey) {
+                            current_key = Some(mkey.to_owned());
+                        }
+                        boundary_found = false;
+                        continue;
+                    } else if let Some(key) = &current_key {
+                        if let Some(val) = keymap.get::<str>(&key) {
+                            if let Err(_) = val {
+                                keymap.insert(key.to_string(), Ok(part.to_vec()));
+                                continue;
+                            }
+                            keymap
+                                .get_mut(key)
+                                .unwrap()
+                                .as_mut()
+                                .unwrap()
+                                .extend_from_slice(part);
+                        }
+                    }
+                }
             }
             _ => {
                 return Err(ParseFormError {
@@ -201,139 +257,6 @@ impl Request<'_> {
         };
         Ok(keymap)
     }
-
-    // pub fn get_post_text_form_key(
-    //     &self,
-    //     keys: &[&str],
-    //     data: &Data,
-    // ) -> Result<HashMap<&str, Result<&str, ParseFormError>>, ParseFormError> {
-    //     let mut post_type = self
-    //         .headers
-    //         .iter()
-    //         .find(|header| header.contains("Content-Type: "))
-    //         .unwrap()
-    //         .to_string();
-    //
-    //     post_type = post_type
-    //         .strip_prefix("Content-Type: ")
-    //         .unwrap()
-    //         .to_string();
-    //
-    //     let post_type: Vec<&str> = post_type.trim().split(';').collect();
-    //     let mime_type = post_type[0].parse().unwrap();
-    //
-    //     // let data = String::from_utf8(vec)
-    //
-    //     let mut result = HashMap::new();
-    //     match mime_type {
-    //         Mime::ApplicationXWwwFormUrlencoded => {
-    //             let data = String::from_utf8(data.buffer.clone()).unwrap();
-    //             let kvps = data
-    //                 .split("&")
-    //                 .map(|kvp| kvp.split_once("=").unwrap())
-    //                 .collect::<HashMap<&str, &str>>();
-    //
-    //             for key in keys {
-    //                 let entry = if let Some(val) = kvps.get(key) {
-    //                     Ok(*val)
-    //                 } else {
-    //                     Err(ParseFormError {
-    //                         error: ParseErrors::NoData,
-    //                     })
-    //                 };
-    //                 result.insert(*key, entry);
-    //             }
-    //             Ok(result)
-    //         }
-    //         Mime::MultipartFormData => {
-    //             let from_req = post_type[1..]
-    //                 .iter()
-    //                 .find(|val| val.contains("boundary="))
-    //                 .unwrap()
-    //                 .strip_prefix("boundary=")
-    //                 .unwrap();
-    //             let mut boundary = b"--".to_vec();
-    //             boundary.extend_from_slice(from_req.trim_matches('"').as_bytes());
-    //             let mut end_boundary = boundary.clone();
-    //             end_boundary.extend_from_slice(b"--");
-    //             boundary.extend_from_slice(&[b'\r']);
-    //             let parts = data
-    //                 .buffer
-    //                 .split(|byte| byte == &b'\n')
-    //                 .collect::<Vec<&[u8]>>();
-    //
-    //             let mut boundary_found = false;
-    //             let mut current_key: Option<&str> = None;
-    //             let mut result: HashMap<&str, Vec<u8>> = HashMap::new();
-    //             for part in parts {
-    //                 if part == [] {
-    //                     continue;
-    //                 }
-    //                 if part == end_boundary {
-    //                     break;
-    //                 }
-    //                 if !boundary_found && part == boundary {
-    //                     current_key = None;
-    //                     boundary_found = true;
-    //                     continue;
-    //                 }
-    //                 if part.starts_with(b"Content-Disposition: form-data; name=") {
-    //                     let headers = part
-    //                         .split(|byte| byte == &b';')
-    //                         .filter(|header| !header.is_empty())
-    //                         .collect::<Vec<_>>();
-    //                     if headers.len() < 2 {
-    //                         continue;
-    //                     }
-    //                     let name = headers[1].split(|byte| byte == &b'=').collect::<Vec<_>>();
-    //                     if name.len() != 2 {
-    //                         continue;
-    //                     }
-    //                     let mkey = String::from_utf8_lossy(name[1])
-    //                         .as_ref()
-    //                         .trim_end()
-    //                         .trim_matches('"')
-    //                         .to_owned();
-    //                     for i in keys {
-    //                         if *i == mkey {
-    //                             current_key = Some(&mkey);
-    //                         }
-    //                     }
-    //                     boundary_found = false;
-    //                 } else if let Some(key) = current_key {
-    //                     if None == result.get(key) {
-    //                         result.insert(key, part.to_vec());
-    //                         continue;
-    //                     }
-    //                     result.get_mut(key).unwrap().extend_from_slice(part);
-    //                 }
-    //             }
-    //             if result.len() == 0 {
-    //                 return Err(ParseFormError {
-    //                     error: ParseErrors::NoData,
-    //                 });
-    //             }
-    //             let return_result: HashMap<&str, Result<&str, ParseErrors>> =
-    //                 HashMap::with_capacity(keys.len());
-    //
-    //             for key in keys {
-    //                 let val = result.get(key).ok_or(ParseFormError {
-    //                     error: ParseErrors::NoData,
-    //                 }).map(|value| String::from_utf8(value))
-    //                 let val = if let Ok(str) = String::from_utf8(val) {
-    //                     Ok(str)
-    //                 } else {
-    //                     Err(ParseFormError {
-    //                         error: ParseErrors::BadData,
-    //                     })
-    //                 };
-    //             }
-    //         }
-    //         _ => Err(ParseFormError {
-    //             error: ParseErrors::BadData,
-    //         }),
-    //     }
-    // }
 }
 
 #[cfg(test)]
@@ -375,19 +298,19 @@ value1
 --boundary
 Content-Disposition: form-data; name=\"field2\"; filename=\"example.txt\"
 
-value2
+value2\n
 --boundary--
 "
             .to_vec(),
             is_complete: true,
         };
-        let map = req.get_post_data(&["field1, field2"], &data).unwrap();
+        let map = req.get_post_data(&["field1", "field2"], &data).unwrap();
         assert_eq!(
             &b"value1".to_vec(),
             map.get("field1").unwrap().as_ref().unwrap()
         );
         assert_eq!(
-            &b"value2".to_vec(),
+            &b"value2\n".to_vec(),
             map.get("field2").unwrap().as_ref().unwrap()
         );
     }
-- 
GitLab


From f85cfb4d5ea1f05a03dcbafbf88c14e6f2d5c4b1 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Thu, 15 Jun 2023 16:20:18 +0200
Subject: [PATCH 34/65] Complete `get_post_data()` implementation set maximum
 post body size to 4196 bytes

---
 core/http/src/handlers/handlers.rs |   9 +-
 core/http/src/handling/request.rs  | 162 +++++++++++++++++------------
 site/404.html                      |   2 +-
 site/src/main.rs                   |  11 +-
 4 files changed, 106 insertions(+), 78 deletions(-)

diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
index 63172c5..4459968 100755
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -10,6 +10,8 @@ use crate::handling::{
 };
 use crate::setup::MountPoint;
 
+static MAX_HTTPMESSAGE_SIZE: u16 = 4196;
+
 pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint<'_>>) {
     let mut buf_reader = BufReader::new(&mut stream);
     let mut http_request: Vec<String> = Vec::with_capacity(30);
@@ -61,6 +63,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
         buffer: vec![],
     };
     if request.can_have_body() {
+        println!("{:#?}", request.headers);
         let length = if let Some(len) = request
             .headers
             .iter()
@@ -87,9 +90,9 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
             0
         };
         if length != 0 {
-            let mut buffer: Vec<u8> = vec![];
-            buf_reader.read_buf(&mut buffer).await.unwrap();
-            if buffer.len() != length {
+            let mut buffer = vec![0u8; MAX_HTTPMESSAGE_SIZE.into()];
+            let read = buf_reader.read(&mut buffer).await.unwrap();
+            if read != length {
                 len_not_defined(stream, Status::LengthRequired).await;
                 return;
             }
diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index 030188e..ff7e338 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -4,6 +4,8 @@ use std::{collections::HashMap, error::Error, fmt::Display};
 
 use crate::utils::mime::mime_enum::Mime;
 
+static TWO_NEWLINES: u8 = 3;
+
 use super::{
     methods::Method,
     routes::{Data, Uri},
@@ -125,9 +127,13 @@ impl Request<'_> {
             let content_type = val.trim().strip_prefix("Content-Type: ").unwrap();
             let type_vec = content_type.split(';').collect::<Vec<&str>>();
 
-            boundary = if let Some(bound) = type_vec.iter().find(|part| part.contains("boundary="))
+            boundary = if let Some(bound) = type_vec.iter().find(|part| part.contains(" boundary="))
             {
-                bound.strip_prefix("boundary=").unwrap().trim_matches('"')
+                bound
+                    .strip_prefix(" boundary=")
+                    .unwrap()
+                    .trim_end()
+                    .trim_matches('"')
             } else {
                 ""
             };
@@ -192,62 +198,10 @@ impl Request<'_> {
             Mime::MultipartFormData => {
                 let mut temp_bound = "--".to_string();
                 temp_bound.push_str(&format!("{boundary}"));
-                let end_boundary = format!("{temp_bound}--").as_bytes().to_owned();
+                let end_boundary = format!("{temp_bound}--\r").as_bytes().to_owned();
+                temp_bound.push('\r');
                 let boundary = temp_bound.as_bytes();
-                let parts = data.split(|byte| byte == &b'\n').collect::<Vec<&[u8]>>();
-
-                let mut current_key: Option<String> = None;
-                let mut boundary_found = true;
-                for part in parts {
-                    if part == [] {
-                        continue;
-                    }
-                    if part == end_boundary {
-                        break;
-                    }
-                    if !boundary_found && part == boundary {
-                        boundary_found = true;
-                        current_key = None;
-                        continue;
-                    }
-                    if part.starts_with(b"Content-Disposition: form-data; name=") {
-                        let headers = part
-                            .split(|byte| byte == &b';')
-                            .filter(|header| !header.is_empty())
-                            .collect::<Vec<_>>();
-                        if headers.len() < 2 {
-                            continue;
-                        }
-                        let name = headers[1].split(|byte| byte == &b'=').collect::<Vec<_>>();
-                        if name.len() != 2 {
-                            continue;
-                        }
-                        let mkey = String::from_utf8_lossy(name[1])
-                            .as_ref()
-                            .trim_end()
-                            .trim_matches('"')
-                            .to_owned();
-
-                        if keymap.contains_key::<str>(&mkey) {
-                            current_key = Some(mkey.to_owned());
-                        }
-                        boundary_found = false;
-                        continue;
-                    } else if let Some(key) = &current_key {
-                        if let Some(val) = keymap.get::<str>(&key) {
-                            if let Err(_) = val {
-                                keymap.insert(key.to_string(), Ok(part.to_vec()));
-                                continue;
-                            }
-                            keymap
-                                .get_mut(key)
-                                .unwrap()
-                                .as_mut()
-                                .unwrap()
-                                .extend_from_slice(part);
-                        }
-                    }
-                }
+                Request::get_multipart(data, boundary, &end_boundary, &mut keymap);
             }
             _ => {
                 return Err(ParseFormError {
@@ -257,6 +211,77 @@ impl Request<'_> {
         };
         Ok(keymap)
     }
+    fn get_multipart(
+        data: &[u8],
+        boundary: &[u8],
+        end_boundary: &[u8],
+        map: &mut HashMap<String, Result<Vec<u8>, ParseFormError>>,
+    ) {
+        let parts = data.split(|byte| byte == &b'\n').collect::<Vec<&[u8]>>();
+        let mut current_part: Vec<&[u8]> = vec![];
+        let mut current_key: Option<String> = None;
+        let mut ignore_line = 0;
+        for part in parts {
+            if part == &[b'\r'] {
+                if let Some(_) = current_key {
+                    if ignore_line >= TWO_NEWLINES {
+                        current_part.push(&[b'\n']);
+                        continue;
+                    }
+                    ignore_line += 1;
+                }
+                continue;
+            }
+            if part == end_boundary {
+                if let Some(key) = &current_key {
+                    let mut part = current_part.join(&b'\n');
+                    if part.ends_with(&[b'\r']) {
+                        part.pop();
+                    }
+                    map.insert(key.to_string(), Ok(part));
+                }
+                break;
+            }
+            if part == boundary {
+                if let Some(key) = &current_key {
+                    let mut part = current_part.join(&b'\n');
+                    if part.ends_with(&[b'\r']) {
+                        part.pop();
+                    }
+                    map.insert(key.to_string(), Ok(part));
+                }
+                current_part = vec![];
+                current_key = None;
+                ignore_line = 0;
+                continue;
+            }
+            if part.starts_with(b"Content-Disposition: form-data; name=") {
+                let headers = part
+                    .split(|byte| byte == &b';')
+                    .filter(|header| !header.is_empty())
+                    .collect::<Vec<_>>();
+                if headers.len() < 2 {
+                    continue;
+                }
+                let name = headers[1].split(|byte| byte == &b'=').collect::<Vec<_>>();
+                if name.len() != 2 {
+                    continue;
+                }
+                let mkey = String::from_utf8_lossy(name[1])
+                    .as_ref()
+                    .trim_end()
+                    .trim_matches('"')
+                    .to_owned();
+
+                if map.contains_key::<str>(&mkey) {
+                    current_key = Some(mkey.to_owned());
+                }
+                continue;
+            } else if let Some(_) = &current_key {
+                current_part.push(part);
+            }
+        }
+    }
 }
 
 #[cfg(test)]
@@ -287,30 +312,31 @@ mod test {
         );
         let req = Request {
             uri: "",
-            headers: vec!["Content-Type: multipart/form-data;boundary=\"boundary\"".to_string()],
+            headers: vec!["Content-Type: multipart/form-data; boundary=\"boundary\"".to_string()],
             method: crate::handling::methods::Method::Post,
         };
         let data = Data {
-            buffer: b"--boundary
-Content-Disposition: form-data; name=\"field1\"
-
-value1
---boundary
-Content-Disposition: form-data; name=\"field2\"; filename=\"example.txt\"
-
-value2\n
---boundary--
+            buffer: b"--boundary\r
+Content-Disposition: form-data; name=\"field1\"\r
+\r
+value1\r
+--boundary\r
+Content-Disposition: form-data; name=\"field2\"; filename=\"example.txt\"\r
+\r
+va\nlue2\r
+--boundary--\r
 "
             .to_vec(),
             is_complete: true,
         };
         let map = req.get_post_data(&["field1", "field2"], &data).unwrap();
+
         assert_eq!(
             &b"value1".to_vec(),
             map.get("field1").unwrap().as_ref().unwrap()
         );
         assert_eq!(
-            &b"value2\n".to_vec(),
+            &b"va\nlue2".to_vec(),
             map.get("field2").unwrap().as_ref().unwrap()
         );
     }
diff --git a/site/404.html b/site/404.html
index 7934c61..b5a9b4a 100644
--- a/site/404.html
+++ b/site/404.html
@@ -7,7 +7,7 @@
   <body>
     <h1>404</h1>
     <p>Hi from Rust</p>
-    <form action="/post/post" method="post">
+    <form action="/post/post" method="post" enctype="multipart/form-data">
       <label for="message">Enter your message:</label>
       <input type="text" id="message" name="message" />
       <button type="submit">Send</button>
diff --git a/site/src/main.rs b/site/src/main.rs
index 2a16f43..af47897 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -62,12 +62,11 @@ fn post_hi_handler(request: Request, data: Data) -> Outcome<Response, Status, Da
     if data.is_empty() {
         return Outcome::Forward(data);
     }
-    // let data = if let Ok(val) = request.get_post_text_form_key("message", &data) {
-    //     val
-    // } else {
-    //     return Outcome::Failure(Status::BadRequest);
-    // };
-    let dat = post_hi(String::from_utf8(data.buffer).unwrap());
+    let dat = if let Ok(val) = request.get_post_data(&["message"], &data) {
+        post_hi(String::from_utf8_lossy(val.get("message").unwrap().as_ref().unwrap()).to_string())
+    } else {
+        return Outcome::Failure(Status::BadRequest);
+    };
     Outcome::Success(Response {
         headers: vec![
             format!("Content-Length: {}", dat.len()),
-- 
GitLab


From f29d3004ef1279097b0f55bef27fe95daf940425 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Fri, 16 Jun 2023 18:51:51 +0200
Subject: [PATCH 35/65] Started on working with Multipart data in multipart
 forms

---
 core/http/src/handlers/handlers.rs |  4 +---
 core/http/src/handling/request.rs  | 13 ++++++++++++-
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
index 4459968..0f724cd 100755
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -14,7 +14,7 @@ static MAX_HTTPMESSAGE_SIZE: u16 = 4196;
 
 pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint<'_>>) {
     let mut buf_reader = BufReader::new(&mut stream);
-    let mut http_request: Vec<String> = Vec::with_capacity(30);
+    let mut http_request: Vec<String> = Vec::with_capacity(10);
     loop {
         let mut buffer = String::new();
         if let Err(_) = buf_reader.read_line(&mut buffer).await {
@@ -27,8 +27,6 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
         http_request.push(buffer);
     }
 
-    // println!("{:#?}", http_request);
-
     let request_status_line = if let Some(status_line) = http_request.get(0).cloned() {
         status_line
     } else {
diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index ff7e338..ff4db83 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -2,6 +2,8 @@
 
 use std::{collections::HashMap, error::Error, fmt::Display};
 
+use tokio::io::BufReader;
+
 use crate::utils::mime::mime_enum::Mime;
 
 static TWO_NEWLINES: u8 = 3;
@@ -211,7 +213,16 @@ impl Request<'_> {
         };
         Ok(keymap)
     }
-    fn get_multipart(
+    fn decode_multipart<'a>(
+        data: &Data,
+        keys: &[&'a str],
+    ) -> HashMap<String, Result<Vec<u8>, ParseFormError>> {
+        let mut data = data.buffer.as_ref();
+        let mut buf_reader = BufReader::new(&mut data);
+        let mut http_request: Vec<String> = Vec::with_capacity(2);
+        todo!()
+    }
+    fn get_multipart_data(
         data: &[u8],
         boundary: &[u8],
         end_boundary: &[u8],
-- 
GitLab


From 61af39db1025cc51a83e04eaaf24d769a8aaaa7c Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sat, 17 Jun 2023 18:22:05 +0200
Subject: [PATCH 36/65] Create the FromRequest trait

---
 core/http/src/handlers/handlers.rs |  4 ++--
 core/http/src/handling/request.rs  | 33 +++++++++++++++++++-----------
 2 files changed, 23 insertions(+), 14 deletions(-)

diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
index 0f724cd..17812fc 100755
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -10,7 +10,7 @@ use crate::handling::{
 };
 use crate::setup::MountPoint;
 
-static MAX_HTTPMESSAGE_SIZE: u16 = 4196;
+static MAX_HTTP_MESSAGE_SIZE: u16 = 4196;
 
 pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint<'_>>) {
     let mut buf_reader = BufReader::new(&mut stream);
@@ -88,7 +88,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
             0
         };
         if length != 0 {
-            let mut buffer = vec![0u8; MAX_HTTPMESSAGE_SIZE.into()];
+            let mut buffer = vec![0u8; MAX_HTTP_MESSAGE_SIZE.into()];
             let read = buf_reader.read(&mut buffer).await.unwrap();
             if read != length {
                 len_not_defined(stream, Status::LengthRequired).await;
diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index ff4db83..171798a 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -2,8 +2,6 @@
 
 use std::{collections::HashMap, error::Error, fmt::Display};
 
-use tokio::io::BufReader;
-
 use crate::utils::mime::mime_enum::Mime;
 
 static TWO_NEWLINES: u8 = 3;
@@ -13,7 +11,27 @@ use super::{
     routes::{Data, Uri},
 };
 
+pub trait FromRequest: Send {
+    fn get_data(&self) -> &Self;
+    fn set_data(&mut self, data: &Self);
+    fn append(&mut self, data: &Self);
+}
+
+impl FromRequest for Vec<u8> {
+    fn get_data(&self) -> &Self {
+        &self
+    }
+
+    fn set_data(&mut self, data: &Self) {
+        *self = data.to_vec();
+    }
+    fn append(&mut self, data: &Self) {
+        self.extend_from_slice(data);
+    }
+}
+
 type HeaderMap = Vec<String>;
+
 #[derive(Clone)]
 pub struct Request<'a> {
     pub uri: Uri<'a>,
@@ -203,7 +221,7 @@ impl Request<'_> {
                 let end_boundary = format!("{temp_bound}--\r").as_bytes().to_owned();
                 temp_bound.push('\r');
                 let boundary = temp_bound.as_bytes();
-                Request::get_multipart(data, boundary, &end_boundary, &mut keymap);
+                Request::get_multipart_data(data, boundary, &end_boundary, &mut keymap);
             }
             _ => {
                 return Err(ParseFormError {
@@ -213,15 +231,6 @@ impl Request<'_> {
         };
         Ok(keymap)
     }
-    fn decode_multipart<'a>(
-        data: &Data,
-        keys: &[&'a str],
-    ) -> HashMap<String, Result<Vec<u8>, ParseFormError>> {
-        let mut data = data.buffer.as_ref();
-        let mut buf_reader = BufReader::new(&mut data);
-        let mut http_request: Vec<String> = Vec::with_capacity(2);
-        todo!()
-    }
     fn get_multipart_data(
         data: &[u8],
         boundary: &[u8],
-- 
GitLab


From 94944f321e09b9828101b2f5b953fd54bc2191fe Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Tue, 20 Jun 2023 22:22:21 +0200
Subject: [PATCH 37/65] Remove unnecessary println! and updated some of the
 code

Added TODO: file
---
 TODO.md                            | 9 +++++++++
 core/http/src/handlers/handlers.rs | 1 -
 core/http/src/handling/request.rs  | 2 +-
 3 files changed, 10 insertions(+), 2 deletions(-)
 create mode 100644 TODO.md

diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..c15fe15
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,9 @@
+1. If you collect an iterator which you don't index in, you don't need to collect it
+2. avoid temporary hashmaps
+3. rewrite POST request stuff TICK
+4. Client struct
+5. Mime-Display new implemented
+6. Remove unwraps
+7. Reusable allocations
+
+API design 3. No decisions for the caller
diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
index 17812fc..b0b2c19 100755
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -61,7 +61,6 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
         buffer: vec![],
     };
     if request.can_have_body() {
-        println!("{:#?}", request.headers);
         let length = if let Some(len) = request
             .headers
             .iter()
diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index 171798a..5731425 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -221,7 +221,7 @@ impl Request<'_> {
                 let end_boundary = format!("{temp_bound}--\r").as_bytes().to_owned();
                 temp_bound.push('\r');
                 let boundary = temp_bound.as_bytes();
-                Request::get_multipart_data(data, boundary, &end_boundary, &mut keymap);
+                Self::get_multipart_data(data, boundary, &end_boundary, &mut keymap);
             }
             _ => {
                 return Err(ParseFormError {
-- 
GitLab


From 31f29ad0df0af5bedad173bfa5e4114b33aabe86 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Wed, 21 Jun 2023 22:03:45 +0200
Subject: [PATCH 38/65] Start working on cookies

---
 core/http/src/handlers/handlers.rs | 5 ++++-
 core/http/src/handling/request.rs  | 3 +++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
index b0b2c19..df6ec34 100755
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -26,6 +26,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
         }
         http_request.push(buffer);
     }
+    println!("{:?}", http_request);
 
     let request_status_line = if let Some(status_line) = http_request.get(0).cloned() {
         status_line
@@ -33,6 +34,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
         eprintln!("\x1b[31mAborting due to missing headers\x1b[0m");
         return;
     };
+
     let request = Request {
         uri: if let Some(uri) = &request_status_line.split(" ").nth(1) {
             *uri
@@ -40,6 +42,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
             eprintln!("\x1b[31mAborting due to invalid status line\x1b[0m");
             return;
         },
+        cookies: None,
         headers: http_request,
         method: if let Some(method) = request_status_line
             .split(" ")
@@ -53,7 +56,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
         } else {
             eprintln!("\x1b[31mAborting due to invalid status line\x1b[0m");
             return;
-        }
+        },
     };
 
     let mut data = Data {
diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs
index 5731425..8841901 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request.rs
@@ -37,6 +37,7 @@ pub struct Request<'a> {
     pub uri: Uri<'a>,
     pub headers: HeaderMap,
     pub method: Method,
+    pub cookies: Option<Vec<&'a str>>,
     // pub connection: ConnectionMeta,
 }
 
@@ -316,6 +317,7 @@ mod test {
             uri: "",
             headers: vec!["Content-Type: application/x-www-form-urlencoded".to_string()],
             method: crate::handling::methods::Method::Post,
+            cookies: None,
         };
         let data = Data {
             buffer: b"message=23&message1=24".to_vec(),
@@ -334,6 +336,7 @@ mod test {
             uri: "",
             headers: vec!["Content-Type: multipart/form-data; boundary=\"boundary\"".to_string()],
             method: crate::handling::methods::Method::Post,
+            cookies: None,
         };
         let data = Data {
             buffer: b"--boundary\r
-- 
GitLab


From af4ab2e39df8ba1d49209303095bfcf3c969d0d9 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Fri, 23 Jun 2023 14:41:15 +0200
Subject: [PATCH 39/65] refactoring the request module, add cookie
 functionality

---
 core/http/src/handlers/handlers.rs            |  4 +-
 core/http/src/handling/request/cookies.rs     | 54 ++++++++++++
 core/http/src/handling/request/datatypes.rs   | 73 ++++++++++++++++
 core/http/src/handling/request/mod.rs         |  5 ++
 .../{request.rs => request/request_impl.rs}   | 84 ++-----------------
 5 files changed, 141 insertions(+), 79 deletions(-)
 create mode 100644 core/http/src/handling/request/cookies.rs
 create mode 100644 core/http/src/handling/request/datatypes.rs
 create mode 100644 core/http/src/handling/request/mod.rs
 rename core/http/src/handling/{request.rs => request/request_impl.rs} (84%)

diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs
index df6ec34..32376bc 100755
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handlers.rs
@@ -4,7 +4,7 @@ use tokio::{io::{AsyncReadExt, BufReader, AsyncBufReadExt, AsyncWriteExt}, net::
 
 use crate::handling::{
     file_handlers::NamedFile,
-    request::Request,
+    request::{Request, extract_cookies_from_vec},
     response::{Outcome, Response, ResponseBody, Status},
     routes::Data, methods::Method,
 };
@@ -42,7 +42,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
             eprintln!("\x1b[31mAborting due to invalid status line\x1b[0m");
             return;
         },
-        cookies: None,
+        cookies: extract_cookies_from_vec(&mut http_request),
         headers: http_request,
         method: if let Some(method) = request_status_line
             .split(" ")
diff --git a/core/http/src/handling/request/cookies.rs b/core/http/src/handling/request/cookies.rs
new file mode 100644
index 0000000..c9d0fcd
--- /dev/null
+++ b/core/http/src/handling/request/cookies.rs
@@ -0,0 +1,54 @@
+use std::collections::HashMap;
+
+pub fn extract_cookies_from_vec(headers: &mut Vec<String>) -> Option<HashMap<String, String>> {
+    let mut cookies: HashMap<String, String> = HashMap::new();
+    let mut cookies_string = if let Some(index) = headers
+        .iter()
+        .position(|header| header.starts_with("Cookie: "))
+    {
+        headers.remove(index)
+    } else {
+        return None;
+    };
+    cookies_string = cookies_string
+        .strip_prefix("Cookie: ")
+        .unwrap()
+        .trim()
+        .to_string();
+    for cookie in cookies_string.split(';') {
+        let Some((name, cookie)) = cookie.split_once('=') else {
+            return None;
+        };
+        cookies
+            .entry(name.trim().to_string())
+            .or_insert(cookie.trim().to_string());
+    }
+    Some(cookies)
+}
+
+#[cfg(test)]
+mod test {
+    use crate::handling::request::extract_cookies_from_vec;
+
+    #[test]
+    fn test_cookies() {
+        let mut request_vec = vec![
+            "GET / HTTP/1.1".to_string(),
+            "Accept: sdf".to_string(),
+            "Cookie: io=23; f=as".to_string(),
+            "Format: gzip".to_string(),
+        ];
+        let right_finished_vec = vec![
+            "GET / HTTP/1.1".to_string(),
+            "Accept: sdf".to_string(),
+            "Format: gzip".to_string(),
+        ];
+
+        let mut wrong = vec!["GET / HTTP/1.1".to_string()];
+        assert_eq!(None, extract_cookies_from_vec(&mut wrong));
+        let cookies = extract_cookies_from_vec(&mut request_vec);
+        assert_eq!(right_finished_vec, request_vec);
+        assert_eq!("23", cookies.clone().unwrap().get("io").unwrap());
+        assert_eq!("as", cookies.unwrap().get("f").unwrap());
+    }
+}
diff --git a/core/http/src/handling/request/datatypes.rs b/core/http/src/handling/request/datatypes.rs
new file mode 100644
index 0000000..68e32d5
--- /dev/null
+++ b/core/http/src/handling/request/datatypes.rs
@@ -0,0 +1,73 @@
+use std::{collections::HashMap, error::Error, fmt::Display};
+
+use crate::handling::{methods::Method, routes::Uri};
+
+pub trait FromRequest: Send {
+    fn get_data(&self) -> &Self;
+    fn set_data(&mut self, data: &Self);
+    fn append(&mut self, data: &Self);
+}
+
+impl FromRequest for Vec<u8> {
+    fn get_data(&self) -> &Self {
+        &self
+    }
+
+    fn set_data(&mut self, data: &Self) {
+        *self = data.to_vec();
+    }
+    fn append(&mut self, data: &Self) {
+        self.extend_from_slice(data);
+    }
+}
+
+type HeaderMap = Vec<String>;
+
+#[derive(Clone)]
+pub struct Request<'a> {
+    pub uri: Uri<'a>,
+    pub headers: HeaderMap,
+    pub method: Method,
+    pub cookies: Option<HashMap<String, String>>,
+    // pub connection: ConnectionMeta,
+}
+
+// struct ConnectionMeta {
+//     remote: Option<SocketAddr>,
+//     // certificates
+// }
+
+#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub enum MediaType {
+    Json,
+    Plain,
+    Html,
+}
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub enum ParseErrors {
+    NoData,
+    BadData,
+}
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct ParseFormError {
+    pub error: ParseErrors,
+}
+
+impl Display for ParseFormError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", self.error)
+    }
+}
+
+impl Display for ParseErrors {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            ParseErrors::NoData => write!(f, "No Data at key"),
+            ParseErrors::BadData => write!(f, "Bad Data at key"),
+        }
+    }
+}
+
+impl Error for ParseFormError {}
diff --git a/core/http/src/handling/request/mod.rs b/core/http/src/handling/request/mod.rs
new file mode 100644
index 0000000..23c9f1a
--- /dev/null
+++ b/core/http/src/handling/request/mod.rs
@@ -0,0 +1,5 @@
+mod cookies;
+mod datatypes;
+mod request_impl;
+pub use cookies::extract_cookies_from_vec;
+pub use datatypes::{MediaType, ParseFormError, Request};
diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request/request_impl.rs
similarity index 84%
rename from core/http/src/handling/request.rs
rename to core/http/src/handling/request/request_impl.rs
index 8841901..2c582ea 100644
--- a/core/http/src/handling/request.rs
+++ b/core/http/src/handling/request/request_impl.rs
@@ -1,85 +1,15 @@
 // use std::net::SocketAddr;
 
-use std::{collections::HashMap, error::Error, fmt::Display};
+use std::collections::HashMap;
 
-use crate::utils::mime::mime_enum::Mime;
-
-static TWO_NEWLINES: u8 = 3;
-
-use super::{
-    methods::Method,
-    routes::{Data, Uri},
+use crate::{
+    handling::{methods::Method, routes::Data},
+    utils::mime::mime_enum::Mime,
 };
 
-pub trait FromRequest: Send {
-    fn get_data(&self) -> &Self;
-    fn set_data(&mut self, data: &Self);
-    fn append(&mut self, data: &Self);
-}
-
-impl FromRequest for Vec<u8> {
-    fn get_data(&self) -> &Self {
-        &self
-    }
-
-    fn set_data(&mut self, data: &Self) {
-        *self = data.to_vec();
-    }
-    fn append(&mut self, data: &Self) {
-        self.extend_from_slice(data);
-    }
-}
-
-type HeaderMap = Vec<String>;
-
-#[derive(Clone)]
-pub struct Request<'a> {
-    pub uri: Uri<'a>,
-    pub headers: HeaderMap,
-    pub method: Method,
-    pub cookies: Option<Vec<&'a str>>,
-    // pub connection: ConnectionMeta,
-}
-
-// struct ConnectionMeta {
-//     remote: Option<SocketAddr>,
-//     // certificates
-// }
+use super::datatypes::{ParseErrors, ParseFormError, Request};
 
-#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub enum MediaType {
-    Json,
-    Plain,
-    Html,
-}
-
-#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
-pub enum ParseErrors {
-    NoData,
-    BadData,
-}
-
-#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
-pub struct ParseFormError {
-    pub error: ParseErrors,
-}
-
-impl Display for ParseFormError {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "{}", self.error)
-    }
-}
-
-impl Display for ParseErrors {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        match self {
-            ParseErrors::NoData => write!(f, "No Data at key"),
-            ParseErrors::BadData => write!(f, "Bad Data at key"),
-        }
-    }
-}
-
-impl Error for ParseFormError {}
+static TWO_NEWLINES: u8 = 3;
 
 impl Request<'_> {
     pub fn can_have_body(&self) -> bool {
@@ -98,7 +28,7 @@ impl Request<'_> {
         &'a self,
         keys: &'a [&str],
     ) -> Result<HashMap<&str, Result<&str, ParseFormError>>, ParseFormError> {
-        let data = if let Some(val) = self.uri.split_once("?") {
+        let data = if let Some(val) = self.uri.split_once('?') {
             val
         } else {
             return Err(ParseFormError {
-- 
GitLab


From 3a080227419c8ba78515be1c1717e3dcfd61919b Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Fri, 23 Jun 2023 15:14:24 +0200
Subject: [PATCH 40/65] Add some documentation

---
 core/http/src/handling/request/cookies.rs |  1 +
 core/http/src/setup.rs                    | 28 +++++++++++++++++++++++
 2 files changed, 29 insertions(+)
 mode change 100644 => 100755 core/http/src/setup.rs

diff --git a/core/http/src/handling/request/cookies.rs b/core/http/src/handling/request/cookies.rs
index c9d0fcd..c11bd45 100644
--- a/core/http/src/handling/request/cookies.rs
+++ b/core/http/src/handling/request/cookies.rs
@@ -45,6 +45,7 @@ mod test {
         ];
 
         let mut wrong = vec!["GET / HTTP/1.1".to_string()];
+
         assert_eq!(None, extract_cookies_from_vec(&mut wrong));
         let cookies = extract_cookies_from_vec(&mut request_vec);
         assert_eq!(right_finished_vec, request_vec);
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
old mode 100644
new mode 100755
index 4a3914b..c7f4522
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -65,6 +65,18 @@ impl<'a> Config {
         }
         self
     }
+    /// # Launches/Starts the webserver
+    /// Launches a Webserver Configuration
+    /// 
+    /// Is Async
+    ///
+    /// Is Blocking -> Can be interrupted with ^C
+    ///
+    /// # Panics
+    /// Panics if there are no Mountpoints in the Confiuration to lauch, as well as when the there
+    /// is no interrupt signal
+    ///
+    /// Panics if .
     pub async fn launch(self) {
         println!("Server launched from http://{}", self.address.local_addr().unwrap());
         let mut sigint = signal(SignalKind::interrupt()).unwrap();
@@ -82,6 +94,22 @@ impl<'a> Config {
         }
     }
 }
+/// # Creates a Webserver Config which can be launched with the launch function
+/// Takes the IP and Port as an argument
+///
+/// Prints out the configuration test
+///
+/// Is async
+///
+/// # Example
+/// ```
+/// async fn example() {
+///     let _ = http::build("127.0.0.1:8000");
+/// }
+/// ```
+/// # Panics
+/// Panics if the IP is not bindable, or other forms of system errors or it's not a valid
+/// IP-Address
 pub async fn build(ip: &str) -> Config {
     let listener = if let Ok(listener) = TcpListener::bind(ip).await {
         listener
-- 
GitLab


From 29bec6fc8f7380dda275cae4e02e91cf040a970a Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sat, 24 Jun 2023 13:27:50 +0200
Subject: [PATCH 41/65] Refactoring the Request struct into it's own seperated
 module with seprate impl's, fixing some code, ...

---
 .../src/handlers/{handlers.rs => handler.rs}  |  13 +-
 core/http/src/handlers/mod.rs                 |   2 +-
 core/http/src/handling/request/cookies.rs     |  52 ++--
 core/http/src/handling/request/datatypes.rs   |   6 +-
 core/http/src/handling/request/form_utils.rs  | 250 ++++++++++++++++
 core/http/src/handling/request/mod.rs         |   3 +-
 .../http/src/handling/request/request_impl.rs | 282 +-----------------
 .../http/src/handling/request/request_mime.rs |  59 ++++
 core/http/src/setup.rs                        |   4 +-
 site/src/main.rs                              |   1 +
 10 files changed, 355 insertions(+), 317 deletions(-)
 rename core/http/src/handlers/{handlers.rs => handler.rs} (96%)
 mode change 100755 => 100644
 create mode 100644 core/http/src/handling/request/form_utils.rs
 create mode 100644 core/http/src/handling/request/request_mime.rs
 mode change 100755 => 100644 core/http/src/setup.rs

diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handler.rs
old mode 100755
new mode 100644
similarity index 96%
rename from core/http/src/handlers/handlers.rs
rename to core/http/src/handlers/handler.rs
index 32376bc..67d5117
--- a/core/http/src/handlers/handlers.rs
+++ b/core/http/src/handlers/handler.rs
@@ -4,7 +4,7 @@ use tokio::{io::{AsyncReadExt, BufReader, AsyncBufReadExt, AsyncWriteExt}, net::
 
 use crate::handling::{
     file_handlers::NamedFile,
-    request::{Request, extract_cookies_from_vec},
+    request::Request,
     response::{Outcome, Response, ResponseBody, Status},
     routes::Data, methods::Method,
 };
@@ -26,7 +26,6 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
         }
         http_request.push(buffer);
     }
-    println!("{:?}", http_request);
 
     let request_status_line = if let Some(status_line) = http_request.get(0).cloned() {
         status_line
@@ -35,15 +34,16 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
         return;
     };
 
-    let request = Request {
+    let mut request = Request {
         uri: if let Some(uri) = &request_status_line.split(" ").nth(1) {
             *uri
         } else {
             eprintln!("\x1b[31mAborting due to invalid status line\x1b[0m");
             return;
         },
-        cookies: extract_cookies_from_vec(&mut http_request),
+        cookies: Request::extract_cookies_from_vec(&mut http_request),
         headers: http_request,
+        mime_type: None,
         method: if let Some(method) = request_status_line
             .split(" ")
             .next() {
@@ -90,6 +90,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
             0
         };
         if length != 0 {
+            request.mime_type = Request::extract_mime_from_vec(&mut request.headers);
             let mut buffer = vec![0u8; MAX_HTTP_MESSAGE_SIZE.into()];
             let read = buf_reader.read(&mut buffer).await.unwrap();
             if read != length {
@@ -152,9 +153,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
     resp.extend_from_slice(&response.1);
     if let Err(e) = stream.write_all(&resp).await {
         eprintln!("\x1b[31mError {e} occured when trying to write answer to TCP-Stream for Client, aborting\x1b[0m");
-        return;
-    }
-    return;
+    } 
 }
 
 fn failure_handler(status: Status) -> (String, Vec<u8>) {
diff --git a/core/http/src/handlers/mod.rs b/core/http/src/handlers/mod.rs
index c3d4495..062ae9d 100644
--- a/core/http/src/handlers/mod.rs
+++ b/core/http/src/handlers/mod.rs
@@ -1 +1 @@
-pub mod handlers;
+pub mod handler;
diff --git a/core/http/src/handling/request/cookies.rs b/core/http/src/handling/request/cookies.rs
index c11bd45..d078c76 100644
--- a/core/http/src/handling/request/cookies.rs
+++ b/core/http/src/handling/request/cookies.rs
@@ -1,34 +1,38 @@
 use std::collections::HashMap;
 
-pub fn extract_cookies_from_vec(headers: &mut Vec<String>) -> Option<HashMap<String, String>> {
-    let mut cookies: HashMap<String, String> = HashMap::new();
-    let mut cookies_string = if let Some(index) = headers
-        .iter()
-        .position(|header| header.starts_with("Cookie: "))
-    {
-        headers.remove(index)
-    } else {
-        return None;
-    };
-    cookies_string = cookies_string
-        .strip_prefix("Cookie: ")
-        .unwrap()
-        .trim()
-        .to_string();
-    for cookie in cookies_string.split(';') {
-        let Some((name, cookie)) = cookie.split_once('=') else {
+use super::Request;
+
+impl Request<'_> {
+    pub fn extract_cookies_from_vec(headers: &mut Vec<String>) -> Option<HashMap<String, String>> {
+        let mut cookies: HashMap<String, String> = HashMap::new();
+        let mut cookies_string = if let Some(index) = headers
+            .iter()
+            .position(|header| header.starts_with("Cookie: "))
+        {
+            headers.remove(index)
+        } else {
             return None;
         };
-        cookies
-            .entry(name.trim().to_string())
-            .or_insert(cookie.trim().to_string());
+        cookies_string = cookies_string
+            .strip_prefix("Cookie: ")
+            .unwrap()
+            .trim()
+            .to_string();
+        for cookie in cookies_string.split(';') {
+            let Some((name, cookie)) = cookie.split_once('=') else {
+                return None;
+            };
+            cookies
+                .entry(name.trim().to_string())
+                .or_insert(cookie.trim().to_string());
+        }
+        Some(cookies)
     }
-    Some(cookies)
 }
 
 #[cfg(test)]
 mod test {
-    use crate::handling::request::extract_cookies_from_vec;
+    use crate::handling::request::Request;
 
     #[test]
     fn test_cookies() {
@@ -46,8 +50,8 @@ mod test {
 
         let mut wrong = vec!["GET / HTTP/1.1".to_string()];
 
-        assert_eq!(None, extract_cookies_from_vec(&mut wrong));
-        let cookies = extract_cookies_from_vec(&mut request_vec);
+        assert_eq!(None, Request::extract_cookies_from_vec(&mut wrong));
+        let cookies = Request::extract_cookies_from_vec(&mut request_vec);
         assert_eq!(right_finished_vec, request_vec);
         assert_eq!("23", cookies.clone().unwrap().get("io").unwrap());
         assert_eq!("as", cookies.unwrap().get("f").unwrap());
diff --git a/core/http/src/handling/request/datatypes.rs b/core/http/src/handling/request/datatypes.rs
index 68e32d5..6b72da9 100644
--- a/core/http/src/handling/request/datatypes.rs
+++ b/core/http/src/handling/request/datatypes.rs
@@ -1,6 +1,9 @@
 use std::{collections::HashMap, error::Error, fmt::Display};
 
-use crate::handling::{methods::Method, routes::Uri};
+use crate::{
+    handling::{methods::Method, routes::Uri},
+    utils::mime::mime_enum::Mime,
+};
 
 pub trait FromRequest: Send {
     fn get_data(&self) -> &Self;
@@ -29,6 +32,7 @@ pub struct Request<'a> {
     pub headers: HeaderMap,
     pub method: Method,
     pub cookies: Option<HashMap<String, String>>,
+    pub mime_type: Option<Mime>,
     // pub connection: ConnectionMeta,
 }
 
diff --git a/core/http/src/handling/request/form_utils.rs b/core/http/src/handling/request/form_utils.rs
new file mode 100644
index 0000000..fef8a4f
--- /dev/null
+++ b/core/http/src/handling/request/form_utils.rs
@@ -0,0 +1,250 @@
+use std::collections::HashMap;
+
+use crate::{handling::routes::Data, utils::mime::mime_enum::Mime};
+
+use super::{datatypes::ParseErrors, ParseFormError, Request};
+static TWO_NEWLINES: u8 = 3;
+
+impl Request<'_> {
+    pub fn get_get_form_keys<'a>(
+        &'a self,
+        keys: &'a [&str],
+    ) -> Result<HashMap<&str, Result<&str, ParseFormError>>, ParseFormError> {
+        let data = if let Some(val) = self.uri.split_once('?') {
+            val
+        } else {
+            return Err(ParseFormError {
+                error: ParseErrors::NoData,
+            });
+        };
+        let data = data
+            .1
+            .split("&")
+            .map(|kvp| kvp.split_once("="))
+            .collect::<Vec<Option<(&str, &str)>>>();
+
+        let mut values: HashMap<&str, &str> = HashMap::new();
+        for kvp in data {
+            let kvp = if let Some(kvp) = kvp {
+                kvp
+            } else {
+                continue;
+            };
+            values.insert(kvp.0, kvp.1);
+        }
+        let mut response = HashMap::new();
+        for key in keys {
+            let entry = if let Some(val) = values.get(key) {
+                Ok(*val)
+            } else {
+                Err(ParseFormError {
+                    error: ParseErrors::NoData,
+                })
+            };
+            response.insert((*key).into(), entry);
+        }
+        Ok(response)
+    }
+    pub fn get_post_data<'a>(
+        &'a self,
+        keys: &[&'a str],
+        data: &Data,
+    ) -> Result<HashMap<String, Result<Vec<u8>, ParseFormError>>, ParseFormError> {
+        let data = data.buffer.as_slice();
+        let mut keymap: HashMap<String, Result<Vec<u8>, ParseFormError>> =
+            HashMap::with_capacity(keys.len());
+
+        for key in keys {
+            keymap.entry(key.to_string()).or_insert(Err(ParseFormError {
+                error: ParseErrors::NoData,
+            }));
+        }
+        let Some(mime_type) = self.mime_type else {
+            return Err(ParseFormError { error: ParseErrors::BadData });
+        };
+
+        match mime_type {
+            Mime::ApplicationXWwwFormUrlencoded => {
+                let Ok(data) = String::from_utf8(data.to_vec()) else {
+                    return Err(ParseFormError { error: ParseErrors::BadData });
+                };
+                for kvp in data.split('&') {
+                    let Some(mut kvp) = kvp.split_once('=') else {
+                        return Err(ParseFormError { error: ParseErrors::BadData });
+                    };
+
+                    let Some(thing) = keymap.get_mut(kvp.0) else {
+                        continue;
+                    };
+                    kvp.1 = kvp.1.trim_end_matches('\0');
+
+                    *thing = Ok(kvp.1.as_bytes().to_vec());
+                }
+            }
+            Mime::MultipartFormData => {
+                let Some(post_type) = self
+                        .headers
+                        .iter()
+                        .find(|header| header.contains("Content-Type: ")) else {
+                    return Err(ParseFormError { error: ParseErrors::BadData });
+                };
+
+                let content_type = post_type.trim().strip_prefix("Content-Type: ").unwrap();
+                let Some(mut boundary) = content_type.split(';').find(|element| element.trim().starts_with("boundary=")) else {
+                    return Err(ParseFormError { error: ParseErrors::BadData });
+                };
+                boundary = boundary
+                    .trim()
+                    .strip_prefix("boundary=")
+                    .unwrap()
+                    .trim_matches('"');
+                let mut temp_bound = "--".to_string();
+                temp_bound.push_str(&format!("{boundary}"));
+                let end_boundary = format!("{temp_bound}--\r").as_bytes().to_owned();
+                temp_bound.push('\r');
+                let boundary = temp_bound.as_bytes();
+                Self::get_multipart_data(data, boundary, &end_boundary, &mut keymap);
+            }
+            _ => {
+                return Err(ParseFormError {
+                    error: ParseErrors::BadData,
+                })
+            }
+        };
+        Ok(keymap)
+    }
+    fn get_multipart_data(
+        data: &[u8],
+        boundary: &[u8],
+        end_boundary: &[u8],
+        map: &mut HashMap<String, Result<Vec<u8>, ParseFormError>>,
+    ) {
+        let mut current_part: Vec<&[u8]> = vec![];
+        let mut current_key: Option<String> = None;
+        let mut ignore_line = 0;
+        for part in data.split(|byte| byte == &b'\n') {
+            if part == &[b'\r'] {
+                if let Some(_) = current_key {
+                    if ignore_line >= TWO_NEWLINES {
+                        current_part.push(&[b'\n']);
+                        continue;
+                    }
+                    ignore_line += 1;
+                }
+                continue;
+            }
+            if part == end_boundary {
+                if let Some(key) = &current_key {
+                    let mut part = current_part.join(&b'\n');
+                    if part.ends_with(&[b'\r']) {
+                        part.pop();
+                    }
+                    map.insert(key.to_string(), Ok(part));
+                }
+                break;
+            }
+            if part == boundary {
+                if let Some(key) = &current_key {
+                    let mut part = current_part.join(&b'\n');
+                    if part.ends_with(&[b'\r']) {
+                        part.pop();
+                    }
+                    map.insert(key.to_string(), Ok(part));
+                }
+                current_part = vec![];
+                current_key = None;
+                ignore_line = 0;
+                continue;
+            }
+            if part.starts_with(b"Content-Disposition: form-data; name=") {
+                let headers = part
+                    .split(|byte| byte == &b';')
+                    .filter(|header| !header.is_empty())
+                    .collect::<Vec<_>>();
+                if headers.len() < 2 {
+                    continue;
+                }
+                let name = headers[1].split(|byte| byte == &b'=').collect::<Vec<_>>();
+                if name.len() != 2 {
+                    continue;
+                }
+                let mkey = String::from_utf8_lossy(name[1])
+                    .as_ref()
+                    .trim_end()
+                    .trim_matches('"')
+                    .to_owned();
+
+                if map.contains_key::<str>(&mkey) {
+                    current_key = Some(mkey.to_owned());
+                }
+                continue;
+            } else if let Some(_) = &current_key {
+                current_part.push(part);
+            }
+        }
+    }
+}
+#[cfg(test)]
+mod test {
+    use crate::{
+        handling::routes::Data,
+        utils::mime::mime_enum::Mime::{ApplicationXWwwFormUrlencoded, MultipartFormData},
+    };
+
+    use super::Request;
+
+    #[test]
+    fn try_post_text() {
+        let req = Request {
+            uri: "",
+            headers: vec!["Content-Type: application/x-www-form-urlencoded".to_string()],
+            method: crate::handling::methods::Method::Post,
+            cookies: None,
+            mime_type: Some(ApplicationXWwwFormUrlencoded),
+        };
+        let data = Data {
+            buffer: b"message=23&message1=24".to_vec(),
+            is_complete: true,
+        };
+        let map = req.get_post_data(&["message", "message1"], &data).unwrap();
+        assert_eq!(
+            &b"23".to_vec(),
+            map.get("message").unwrap().as_ref().unwrap()
+        );
+        assert_eq!(
+            &b"24".to_vec(),
+            map.get("message1").unwrap().as_ref().unwrap()
+        );
+        let req = Request {
+            uri: "",
+            headers: vec!["Content-Type: multipart/form-data; boundary=\"boundary\"".to_string()],
+            method: crate::handling::methods::Method::Post,
+            cookies: None,
+            mime_type: Some(MultipartFormData),
+        };
+        let data = Data {
+            buffer: b"--boundary\r
+Content-Disposition: form-data; name=\"field1\"\r
+\r
+value1\r
+--boundary\r
+Content-Disposition: form-data; name=\"field2\"; filename=\"example.txt\"\r
+\r
+va\nlue2\r
+--boundary--\r
+"
+            .to_vec(),
+            is_complete: true,
+        };
+        let map = req.get_post_data(&["field1", "field2"], &data).unwrap();
+
+        assert_eq!(
+            &b"value1".to_vec(),
+            map.get("field1").unwrap().as_ref().unwrap()
+        );
+        assert_eq!(
+            &b"va\nlue2".to_vec(),
+            map.get("field2").unwrap().as_ref().unwrap()
+        );
+    }
+}
diff --git a/core/http/src/handling/request/mod.rs b/core/http/src/handling/request/mod.rs
index 23c9f1a..54da4ad 100644
--- a/core/http/src/handling/request/mod.rs
+++ b/core/http/src/handling/request/mod.rs
@@ -1,5 +1,6 @@
 mod cookies;
 mod datatypes;
+mod form_utils;
 mod request_impl;
-pub use cookies::extract_cookies_from_vec;
+mod request_mime;
 pub use datatypes::{MediaType, ParseFormError, Request};
diff --git a/core/http/src/handling/request/request_impl.rs b/core/http/src/handling/request/request_impl.rs
index 2c582ea..747cd23 100644
--- a/core/http/src/handling/request/request_impl.rs
+++ b/core/http/src/handling/request/request_impl.rs
@@ -1,15 +1,6 @@
-// use std::net::SocketAddr;
+use crate::handling::methods::Method;
 
-use std::collections::HashMap;
-
-use crate::{
-    handling::{methods::Method, routes::Data},
-    utils::mime::mime_enum::Mime,
-};
-
-use super::datatypes::{ParseErrors, ParseFormError, Request};
-
-static TWO_NEWLINES: u8 = 3;
+use super::Request;
 
 impl Request<'_> {
     pub fn can_have_body(&self) -> bool {
@@ -24,273 +15,4 @@ impl Request<'_> {
             _ => false,
         }
     }
-    pub fn get_get_form_keys<'a>(
-        &'a self,
-        keys: &'a [&str],
-    ) -> Result<HashMap<&str, Result<&str, ParseFormError>>, ParseFormError> {
-        let data = if let Some(val) = self.uri.split_once('?') {
-            val
-        } else {
-            return Err(ParseFormError {
-                error: ParseErrors::NoData,
-            });
-        };
-        let data = data
-            .1
-            .split("&")
-            .map(|kvp| kvp.split_once("="))
-            .collect::<Vec<Option<(&str, &str)>>>();
-
-        let mut values: HashMap<&str, &str> = HashMap::new();
-        for kvp in data {
-            let kvp = if let Some(kvp) = kvp {
-                kvp
-            } else {
-                continue;
-            };
-            values.insert(kvp.0, kvp.1);
-        }
-        let mut response = HashMap::new();
-        for key in keys {
-            let entry = if let Some(val) = values.get(key) {
-                Ok(*val)
-            } else {
-                Err(ParseFormError {
-                    error: ParseErrors::NoData,
-                })
-            };
-            response.insert((*key).into(), entry);
-        }
-        Ok(response)
-    }
-
-    pub fn get_post_data<'a>(
-        &'a self,
-        keys: &[&'a str],
-        data: &Data,
-    ) -> Result<HashMap<String, Result<Vec<u8>, ParseFormError>>, ParseFormError> {
-        let boundary;
-        let post_type = if let Some(val) = self
-            .headers
-            .iter()
-            .find(|header| header.contains("Content-Type: "))
-        {
-            let content_type = val.trim().strip_prefix("Content-Type: ").unwrap();
-            let type_vec = content_type.split(';').collect::<Vec<&str>>();
-
-            boundary = if let Some(bound) = type_vec.iter().find(|part| part.contains(" boundary="))
-            {
-                bound
-                    .strip_prefix(" boundary=")
-                    .unwrap()
-                    .trim_end()
-                    .trim_matches('"')
-            } else {
-                ""
-            };
-            if let Ok(mime) = type_vec[0].trim().parse() {
-                mime
-            } else {
-                return Err(ParseFormError {
-                    error: ParseErrors::BadData,
-                });
-            }
-        } else {
-            return Err(ParseFormError {
-                error: ParseErrors::NoData,
-            });
-        };
-
-        let data = data.buffer.as_slice();
-        let mut keymap: HashMap<String, Result<Vec<u8>, ParseFormError>> =
-            HashMap::with_capacity(keys.len());
-
-        for key in keys {
-            keymap.entry(key.to_string()).or_insert(Err(ParseFormError {
-                error: ParseErrors::NoData,
-            }));
-        }
-
-        match post_type {
-            Mime::ApplicationXWwwFormUrlencoded => {
-                for kvp in data.split(|byte| *byte == b'&') {
-                    let kvp = kvp
-                        .split(|byte| *byte == b'=')
-                        .map(|list| list.to_vec())
-                        .collect::<Vec<Vec<u8>>>();
-                    let key = if let Some(kv) = kvp.get(0) {
-                        kv
-                    } else {
-                        return Err(ParseFormError {
-                            error: ParseErrors::BadData,
-                        });
-                    };
-                    let key = if let Ok(kv) = String::from_utf8(key.to_vec()) {
-                        kv
-                    } else {
-                        return Err(ParseFormError {
-                            error: ParseErrors::BadData,
-                        });
-                    };
-                    let value = kvp.get(1).ok_or(ParseFormError {
-                        error: ParseErrors::NoData,
-                    });
-                    let thing = if let Some(val) = keymap.get_mut(key.as_str()) {
-                        val
-                    } else {
-                        continue;
-                    };
-                    *thing = match value {
-                        Ok(val) => Ok(val.to_vec()),
-                        Err(err) => Err(err),
-                    }
-                }
-            }
-            Mime::MultipartFormData => {
-                let mut temp_bound = "--".to_string();
-                temp_bound.push_str(&format!("{boundary}"));
-                let end_boundary = format!("{temp_bound}--\r").as_bytes().to_owned();
-                temp_bound.push('\r');
-                let boundary = temp_bound.as_bytes();
-                Self::get_multipart_data(data, boundary, &end_boundary, &mut keymap);
-            }
-            _ => {
-                return Err(ParseFormError {
-                    error: ParseErrors::BadData,
-                })
-            }
-        };
-        Ok(keymap)
-    }
-    fn get_multipart_data(
-        data: &[u8],
-        boundary: &[u8],
-        end_boundary: &[u8],
-        map: &mut HashMap<String, Result<Vec<u8>, ParseFormError>>,
-    ) {
-        let parts = data.split(|byte| byte == &b'\n').collect::<Vec<&[u8]>>();
-        let mut current_part: Vec<&[u8]> = vec![];
-        let mut current_key: Option<String> = None;
-        let mut ignore_line = 0;
-        for part in parts {
-            if part == &[b'\r'] {
-                if let Some(_) = current_key {
-                    if ignore_line >= TWO_NEWLINES {
-                        current_part.push(&[b'\n']);
-                        continue;
-                    }
-                    ignore_line += 1;
-                }
-                continue;
-            }
-            if part == end_boundary {
-                if let Some(key) = &current_key {
-                    let mut part = current_part.join(&b'\n');
-                    if part.ends_with(&[b'\r']) {
-                        part.pop();
-                    }
-                    map.insert(key.to_string(), Ok(part));
-                }
-                break;
-            }
-            if part == boundary {
-                if let Some(key) = &current_key {
-                    let mut part = current_part.join(&b'\n');
-                    if part.ends_with(&[b'\r']) {
-                        part.pop();
-                    }
-                    map.insert(key.to_string(), Ok(part));
-                }
-                current_part = vec![];
-                current_key = None;
-                ignore_line = 0;
-                continue;
-            }
-            if part.starts_with(b"Content-Disposition: form-data; name=") {
-                let headers = part
-                    .split(|byte| byte == &b';')
-                    .filter(|header| !header.is_empty())
-                    .collect::<Vec<_>>();
-                if headers.len() < 2 {
-                    continue;
-                }
-                let name = headers[1].split(|byte| byte == &b'=').collect::<Vec<_>>();
-                if name.len() != 2 {
-                    continue;
-                }
-                let mkey = String::from_utf8_lossy(name[1])
-                    .as_ref()
-                    .trim_end()
-                    .trim_matches('"')
-                    .to_owned();
-
-                if map.contains_key::<str>(&mkey) {
-                    current_key = Some(mkey.to_owned());
-                }
-                continue;
-            } else if let Some(_) = &current_key {
-                current_part.push(part);
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use crate::handling::routes::Data;
-
-    use super::Request;
-
-    #[test]
-    fn try_post_text() {
-        let req = Request {
-            uri: "",
-            headers: vec!["Content-Type: application/x-www-form-urlencoded".to_string()],
-            method: crate::handling::methods::Method::Post,
-            cookies: None,
-        };
-        let data = Data {
-            buffer: b"message=23&message1=24".to_vec(),
-            is_complete: true,
-        };
-        let map = req.get_post_data(&["message", "message1"], &data).unwrap();
-        assert_eq!(
-            &b"23".to_vec(),
-            map.get("message").unwrap().as_ref().unwrap()
-        );
-        assert_eq!(
-            &b"24".to_vec(),
-            map.get("message1").unwrap().as_ref().unwrap()
-        );
-        let req = Request {
-            uri: "",
-            headers: vec!["Content-Type: multipart/form-data; boundary=\"boundary\"".to_string()],
-            method: crate::handling::methods::Method::Post,
-            cookies: None,
-        };
-        let data = Data {
-            buffer: b"--boundary\r
-Content-Disposition: form-data; name=\"field1\"\r
-\r
-value1\r
---boundary\r
-Content-Disposition: form-data; name=\"field2\"; filename=\"example.txt\"\r
-\r
-va\nlue2\r
---boundary--\r
-"
-            .to_vec(),
-            is_complete: true,
-        };
-        let map = req.get_post_data(&["field1", "field2"], &data).unwrap();
-
-        assert_eq!(
-            &b"value1".to_vec(),
-            map.get("field1").unwrap().as_ref().unwrap()
-        );
-        assert_eq!(
-            &b"va\nlue2".to_vec(),
-            map.get("field2").unwrap().as_ref().unwrap()
-        );
-    }
 }
diff --git a/core/http/src/handling/request/request_mime.rs b/core/http/src/handling/request/request_mime.rs
new file mode 100644
index 0000000..4fb9f3f
--- /dev/null
+++ b/core/http/src/handling/request/request_mime.rs
@@ -0,0 +1,59 @@
+use crate::utils::mime::mime_enum::Mime;
+
+use super::datatypes::Request;
+
+impl Request<'_> {
+    pub fn extract_mime_from_vec(headers: &Vec<String>) -> Option<Mime> {
+        let Some(content_type_header) = headers
+            .iter()
+            .find(|header| header.starts_with("Content-Type: ")) else {
+            return None;
+        };
+        let content_type_string = content_type_header
+            .strip_prefix("Content-Type: ")
+            .unwrap()
+            .to_string();
+
+        let mime;
+        match content_type_string.split_once(';') {
+            Some(sub) => {
+                mime = if let Ok(a) = sub.0.trim().parse() {
+                    a
+                } else {
+                    return None;
+                };
+            }
+            None => {
+                mime = if let Ok(a) = content_type_string.trim().parse() {
+                    a
+                } else {
+                    return None;
+                };
+            }
+        }
+        Some(mime)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use crate::{handling::request::Request, utils::mime::mime_enum::Mime};
+
+    #[test]
+    pub fn test_mime_parse_from_header_vec() {
+        let mut right = vec![
+            "GET / 23".to_string(),
+            "SDF:LKJSD:F".to_string(),
+            "Content-Type: text/plain".to_string(),
+            "SDF".to_string(),
+        ];
+        let mut wrong = vec!["SDF:LKJSD:F".to_string(), "SDF".to_string()];
+
+        assert_eq!(None, Request::extract_mime_from_vec(&mut wrong));
+        assert_eq!(
+            Mime::TextPlain,
+            Request::extract_mime_from_vec(&mut right).unwrap()
+        );
+        assert_eq!(None, Request::extract_mime_from_vec(&mut right));
+    }
+}
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
old mode 100755
new mode 100644
index c7f4522..30e2bf7
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -3,7 +3,7 @@ use std::thread::available_parallelism;
 use tokio::{net::TcpListener, signal::unix::{SignalKind, signal}, select};
 
 use crate::{
-    handlers::handlers::handle_connection,
+    handlers::handler::handle_connection,
     handling::routes::{Route, Uri},
 };
 
@@ -75,8 +75,6 @@ impl<'a> Config {
     /// # Panics
     /// Panics if there are no Mountpoints in the Confiuration to lauch, as well as when the there
     /// is no interrupt signal
-    ///
-    /// Panics if .
     pub async fn launch(self) {
         println!("Server launched from http://{}", self.address.local_addr().unwrap());
         let mut sigint = signal(SignalKind::interrupt()).unwrap();
diff --git a/site/src/main.rs b/site/src/main.rs
index af47897..f1fda07 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -62,6 +62,7 @@ fn post_hi_handler(request: Request, data: Data) -> Outcome<Response, Status, Da
     if data.is_empty() {
         return Outcome::Forward(data);
     }
+    println!("{:?}", request.get_post_data(&["message"], &data));
     let dat = if let Ok(val) = request.get_post_data(&["message"], &data) {
         post_hi(String::from_utf8_lossy(val.get("message").unwrap().as_ref().unwrap()).to_string())
     } else {
-- 
GitLab


From aaceb700447fce812554eb7417cf561561817858 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sat, 24 Jun 2023 13:49:47 +0200
Subject: [PATCH 42/65] Fixing all `cargo clippy` warnings / making code better

---
 core/http/src/handlers/handler.rs              | 10 +++++-----
 core/http/src/handling/file_handlers.rs        |  6 +++---
 core/http/src/handling/request/datatypes.rs    |  2 +-
 core/http/src/handling/request/form_utils.rs   | 14 +++++++-------
 core/http/src/handling/request/request_impl.rs | 13 +++++--------
 core/http/src/handling/request/request_mime.rs | 15 +++++++--------
 core/http/src/handling/routes.rs               | 10 +++++-----
 core/http/src/setup.rs                         | 14 ++++++--------
 8 files changed, 39 insertions(+), 45 deletions(-)

diff --git a/core/http/src/handlers/handler.rs b/core/http/src/handlers/handler.rs
index 67d5117..99f8300 100644
--- a/core/http/src/handlers/handler.rs
+++ b/core/http/src/handlers/handler.rs
@@ -17,7 +17,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
     let mut http_request: Vec<String> = Vec::with_capacity(10);
     loop {
         let mut buffer = String::new();
-        if let Err(_) = buf_reader.read_line(&mut buffer).await {
+        if buf_reader.read_line(&mut buffer).await.is_err() {
             eprintln!("\x1b[31mAborting due to invalid UTF-8 in request header\x1b[0m");
             return;
         }
@@ -35,8 +35,8 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
     };
 
     let mut request = Request {
-        uri: if let Some(uri) = &request_status_line.split(" ").nth(1) {
-            *uri
+        uri: if let Some(uri) = &request_status_line.split(' ').nth(1) {
+            uri
         } else {
             eprintln!("\x1b[31mAborting due to invalid status line\x1b[0m");
             return;
@@ -45,7 +45,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
         headers: http_request,
         mime_type: None,
         method: if let Some(method) = request_status_line
-            .split(" ")
+            .split(' ')
             .next() {
             if let Ok(ok) = method.parse() {
                 ok
@@ -90,7 +90,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
             0
         };
         if length != 0 {
-            request.mime_type = Request::extract_mime_from_vec(&mut request.headers);
+            request.mime_type = Request::extract_mime_from_vec(&request.headers);
             let mut buffer = vec![0u8; MAX_HTTP_MESSAGE_SIZE.into()];
             let read = buf_reader.read(&mut buffer).await.unwrap();
             if read != length {
diff --git a/core/http/src/handling/file_handlers.rs b/core/http/src/handling/file_handlers.rs
index 9e34054..8ca0019 100644
--- a/core/http/src/handling/file_handlers.rs
+++ b/core/http/src/handling/file_handlers.rs
@@ -18,7 +18,7 @@ impl ResponseBody for NamedFile {
     }
 
     fn get_mime(&self) -> Mime {
-        self.content_type.clone()
+        self.content_type
     }
 
     fn get_len(&self) -> usize {
@@ -48,8 +48,8 @@ fn proove_path(path: PathBuf) -> PathBuf {
     PathBuf::from(
         path.to_str()
             .unwrap()
-            .split("/")
-            .filter(|&val| val != ".." && val != "")
+            .split('/')
+            .filter(|&val| val != ".." && !val.is_empty())
             .collect::<Vec<&str>>()
             .join("/"),
     )
diff --git a/core/http/src/handling/request/datatypes.rs b/core/http/src/handling/request/datatypes.rs
index 6b72da9..45f7b7f 100644
--- a/core/http/src/handling/request/datatypes.rs
+++ b/core/http/src/handling/request/datatypes.rs
@@ -13,7 +13,7 @@ pub trait FromRequest: Send {
 
 impl FromRequest for Vec<u8> {
     fn get_data(&self) -> &Self {
-        &self
+        self
     }
 
     fn set_data(&mut self, data: &Self) {
diff --git a/core/http/src/handling/request/form_utils.rs b/core/http/src/handling/request/form_utils.rs
index fef8a4f..4163710 100644
--- a/core/http/src/handling/request/form_utils.rs
+++ b/core/http/src/handling/request/form_utils.rs
@@ -19,8 +19,8 @@ impl Request<'_> {
         };
         let data = data
             .1
-            .split("&")
-            .map(|kvp| kvp.split_once("="))
+            .split('&')
+            .map(|kvp| kvp.split_once('='))
             .collect::<Vec<Option<(&str, &str)>>>();
 
         let mut values: HashMap<&str, &str> = HashMap::new();
@@ -41,7 +41,7 @@ impl Request<'_> {
                     error: ParseErrors::NoData,
                 })
             };
-            response.insert((*key).into(), entry);
+            response.insert(*key, entry);
         }
         Ok(response)
     }
@@ -99,7 +99,7 @@ impl Request<'_> {
                     .unwrap()
                     .trim_matches('"');
                 let mut temp_bound = "--".to_string();
-                temp_bound.push_str(&format!("{boundary}"));
+                temp_bound.push_str(boundary);
                 let end_boundary = format!("{temp_bound}--\r").as_bytes().to_owned();
                 temp_bound.push('\r');
                 let boundary = temp_bound.as_bytes();
@@ -123,8 +123,8 @@ impl Request<'_> {
         let mut current_key: Option<String> = None;
         let mut ignore_line = 0;
         for part in data.split(|byte| byte == &b'\n') {
-            if part == &[b'\r'] {
-                if let Some(_) = current_key {
+            if part == [b'\r'] {
+                if current_key.is_some() {
                     if ignore_line >= TWO_NEWLINES {
                         current_part.push(&[b'\n']);
                         continue;
@@ -178,7 +178,7 @@ impl Request<'_> {
                     current_key = Some(mkey.to_owned());
                 }
                 continue;
-            } else if let Some(_) = &current_key {
+            } else if current_key.is_some() {
                 current_part.push(part);
             }
         }
diff --git a/core/http/src/handling/request/request_impl.rs b/core/http/src/handling/request/request_impl.rs
index 747cd23..2d2f7cb 100644
--- a/core/http/src/handling/request/request_impl.rs
+++ b/core/http/src/handling/request/request_impl.rs
@@ -4,15 +4,12 @@ use super::Request;
 
 impl Request<'_> {
     pub fn can_have_body(&self) -> bool {
-        match self.method {
-            Method::Post | Method::Put | Method::Patch | Method::Delete => true,
-            _ => false,
-        }
+        matches!(
+            self.method,
+            Method::Post | Method::Put | Method::Patch | Method::Delete
+        )
     }
     pub fn mandatory_body(&self) -> bool {
-        match self.method {
-            Method::Post | Method::Put | Method::Patch => true,
-            _ => false,
-        }
+        matches!(self.method, Method::Post | Method::Put | Method::Patch)
     }
 }
diff --git a/core/http/src/handling/request/request_mime.rs b/core/http/src/handling/request/request_mime.rs
index 4fb9f3f..94ebc4c 100644
--- a/core/http/src/handling/request/request_mime.rs
+++ b/core/http/src/handling/request/request_mime.rs
@@ -3,7 +3,7 @@ use crate::utils::mime::mime_enum::Mime;
 use super::datatypes::Request;
 
 impl Request<'_> {
-    pub fn extract_mime_from_vec(headers: &Vec<String>) -> Option<Mime> {
+    pub fn extract_mime_from_vec(headers: &[String]) -> Option<Mime> {
         let Some(content_type_header) = headers
             .iter()
             .find(|header| header.starts_with("Content-Type: ")) else {
@@ -14,23 +14,22 @@ impl Request<'_> {
             .unwrap()
             .to_string();
 
-        let mime;
-        match content_type_string.split_once(';') {
+        let mime = match content_type_string.split_once(';') {
             Some(sub) => {
-                mime = if let Ok(a) = sub.0.trim().parse() {
+                if let Ok(a) = sub.0.trim().parse() {
                     a
                 } else {
                     return None;
-                };
+                }
             }
             None => {
-                mime = if let Ok(a) = content_type_string.trim().parse() {
+                if let Ok(a) = content_type_string.trim().parse() {
                     a
                 } else {
                     return None;
-                };
+                }
             }
-        }
+        };
         Some(mime)
     }
 }
diff --git a/core/http/src/handling/routes.rs b/core/http/src/handling/routes.rs
index 9fd3f77..a85261a 100644
--- a/core/http/src/handling/routes.rs
+++ b/core/http/src/handling/routes.rs
@@ -39,19 +39,19 @@ impl Route<'_> {
         }
     }
     pub fn compare_uri(&self, uri: Uri) -> bool {
-        let mut iter_comp_str = uri.split("/");
-        for true_str in self.uri.split("/") {
+        let mut iter_comp_str = uri.split('/');
+        for true_str in self.uri.split('/') {
             let comp_str = if let Some(str) = iter_comp_str.next() {
                 str
             } else {
                 return false;
             };
-            if (true_str.starts_with("<") && true_str.ends_with("..>"))
-                || (comp_str.starts_with(true_str) && comp_str.contains("?"))
+            if (true_str.starts_with('<') && true_str.ends_with("..>"))
+                || (comp_str.starts_with(true_str) && comp_str.contains('?'))
             {
                 return true;
             }
-            if true_str.starts_with("<") && true_str.ends_with(">") {
+            if true_str.starts_with('<') && true_str.ends_with('>') {
                 continue;
             }
             if true_str != comp_str {
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index 30e2bf7..417cf3d 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -21,9 +21,8 @@ pub struct Config {
 impl<'a> Config {
     fn check_mountpoint_taken(&self, to_insert: Uri) -> bool {
         if let Some(to_check) = &self.mountpoints {
-            let len = to_check.len();
-            for i in 0..len {
-                if to_check[i].mountpoint == to_insert {
+            for i in to_check.iter() {
+                if i.mountpoint == to_insert {
                     return true; // Found a duplicate &str
                 }
             }
@@ -38,10 +37,9 @@ impl<'a> Config {
         routes.sort_by(|a, b| a.rank.cmp(&b.rank));
         let mut mount_message = format!("  >> \x1b[35m{}\x1b[0m\n", mountpoint);
         for (index, route) in routes.iter().enumerate() {
-            let indent_sign;
-            match index {
-                i if i == routes.len() - 1 => indent_sign = "└─",
-                _ => indent_sign = "├─",
+            let indent_sign = match index {
+                i if i == routes.len() - 1 => "└─",
+                _ => "├─",
             };
 
             mount_message += &format!(
@@ -114,7 +112,7 @@ pub async fn build(ip: &str) -> Config {
     } else {
         panic!("\x1b[31mCould't bind Listener to address\x1b[0m");
     };
-    let ip = ip.splitn(2, ":").collect::<Vec<&str>>();
+    let ip = ip.splitn(2, ':').collect::<Vec<&str>>();
     if ip.len() != 2 {
         panic!("Invalid IP Address");
     }
-- 
GitLab


From 901adb2c57f7cfa256a59e53457db5d958450318 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sun, 25 Jun 2023 21:53:57 +0200
Subject: [PATCH 43/65] Add documentation for `request.mime_from_headers()` and
 `extract_cookies_from_vec()`. Update `mime_from_headers()` to take a mutable
 reference to self

---
 core/http/src/handlers/handler.rs             |   2 +-
 core/http/src/handling/request/cookies.rs     |  35 ++++++
 .../http/src/handling/request/request_mime.rs | 113 ++++++++++++------
 core/http/src/lib.rs                          |   2 +-
 4 files changed, 115 insertions(+), 37 deletions(-)

diff --git a/core/http/src/handlers/handler.rs b/core/http/src/handlers/handler.rs
index 99f8300..9596f52 100644
--- a/core/http/src/handlers/handler.rs
+++ b/core/http/src/handlers/handler.rs
@@ -90,7 +90,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
             0
         };
         if length != 0 {
-            request.mime_type = Request::extract_mime_from_vec(&request.headers);
+            request.mime_from_headers();
             let mut buffer = vec![0u8; MAX_HTTP_MESSAGE_SIZE.into()];
             let read = buf_reader.read(&mut buffer).await.unwrap();
             if read != length {
diff --git a/core/http/src/handling/request/cookies.rs b/core/http/src/handling/request/cookies.rs
index d078c76..b386086 100644
--- a/core/http/src/handling/request/cookies.rs
+++ b/core/http/src/handling/request/cookies.rs
@@ -3,6 +3,41 @@ use std::collections::HashMap;
 use super::Request;
 
 impl Request<'_> {
+    /// Extracts the cookies from a Vector and gives back an optional HashMap of Strings
+    ///
+    /// Returns none if there are no cookies or there is a problem with the cookies, for example
+    /// missing a value.
+    ///
+    /// Removes the `Cookie: ` Header from the Vector of headers
+    ///
+    /// # Examples
+    /// ```
+    /// use http::handling::request::Request;
+    ///
+    ///
+    /// let mut request_vec = vec![
+    ///     "GET / HTTP/1.1".to_string(),
+    ///     "Accept: sdf".to_string(),
+    ///     "Cookie: io=23; f=as".to_string(),
+    ///     "Format: gzip".to_string(),
+    /// ];
+    /// let right_finished_vec = vec![
+    ///     "GET / HTTP/1.1".to_string(),
+    ///     "Accept: sdf".to_string(),
+    ///     "Format: gzip".to_string(),
+    /// ];
+    ///
+    /// let mut wrong = vec!["GET / HTTP/1.1".to_string()];
+    ///
+    /// assert_eq!(None, Request::extract_cookies_from_vec(&mut wrong));
+    /// let cookies = Request::extract_cookies_from_vec(&mut request_vec);
+    /// assert_eq!(right_finished_vec, request_vec);
+    /// assert_eq!("23", cookies.clone().unwrap().get("io").unwrap());
+    /// assert_eq!("as", cookies.unwrap().get("f").unwrap());
+    /// ```
+    ///
+    /// # Panics
+    /// No Panics
     pub fn extract_cookies_from_vec(headers: &mut Vec<String>) -> Option<HashMap<String, String>> {
         let mut cookies: HashMap<String, String> = HashMap::new();
         let mut cookies_string = if let Some(index) = headers
diff --git a/core/http/src/handling/request/request_mime.rs b/core/http/src/handling/request/request_mime.rs
index 94ebc4c..03ac55a 100644
--- a/core/http/src/handling/request/request_mime.rs
+++ b/core/http/src/handling/request/request_mime.rs
@@ -1,58 +1,101 @@
-use crate::utils::mime::mime_enum::Mime;
-
 use super::datatypes::Request;
 
 impl Request<'_> {
-    pub fn extract_mime_from_vec(headers: &[String]) -> Option<Mime> {
-        let Some(content_type_header) = headers
+    /// Sets the `mime_type` of this [`Request`] from the headers.
+    ///
+    /// The mime_type can remain none if there isn't a `Content-Type: ` header
+    ///
+    /// # Example
+    /// ```
+    /// use http::{
+    ///     handling::{methods::Method, request::Request},
+    ///     utils::mime::mime_enum::Mime,
+    /// };
+    ///
+    /// let mut request = Request {
+    ///     uri: "thing",
+    ///     headers: vec![
+    ///         "GET / 23".to_string(),
+    ///         "SDF:LKJSD:F".to_string(),
+    ///         "Content-Type: text/plain".to_string(),
+    ///         "SDF".to_string(),
+    ///     ],
+    ///     method: Method::Get,
+    ///     cookies: None,
+    ///     mime_type: None,
+    /// };
+    /// let mut wrong = Request {
+    ///     uri: "thing",
+    ///     headers: vec![
+    ///         "GET / 23".to_string(),
+    ///         "SDF:LKJSD:F".to_string(),
+    ///         "SDF".to_string(),
+    ///     ],
+    ///     method: Method::Get,
+    ///     cookies: None,
+    ///     mime_type: None,
+    /// };
+    /// request.mime_from_headers();
+    /// wrong.mime_from_headers();
+    /// assert_eq!(None, wrong.mime_type);
+    /// assert_eq!(Mime::TextPlain, request.mime_type.unwrap());
+    /// ```
+    /// # Panics
+    /// No Panics
+    pub fn mime_from_headers(&mut self) {
+        let Some(content_type_header) = self.headers
             .iter()
             .find(|header| header.starts_with("Content-Type: ")) else {
-            return None;
+            return;
         };
         let content_type_string = content_type_header
             .strip_prefix("Content-Type: ")
             .unwrap()
             .to_string();
 
-        let mime = match content_type_string.split_once(';') {
-            Some(sub) => {
-                if let Ok(a) = sub.0.trim().parse() {
-                    a
-                } else {
-                    return None;
-                }
-            }
-            None => {
-                if let Ok(a) = content_type_string.trim().parse() {
-                    a
-                } else {
-                    return None;
-                }
-            }
+        self.mime_type = match content_type_string.split_once(';') {
+            Some(sub) => sub.0.trim().parse().ok(),
+            None => content_type_string.trim().parse().ok(),
         };
-        Some(mime)
     }
 }
 
 #[cfg(test)]
 mod test {
-    use crate::{handling::request::Request, utils::mime::mime_enum::Mime};
+    use crate::{
+        handling::{methods::Method, request::Request},
+        utils::mime::mime_enum::Mime,
+    };
 
     #[test]
     pub fn test_mime_parse_from_header_vec() {
-        let mut right = vec![
-            "GET / 23".to_string(),
-            "SDF:LKJSD:F".to_string(),
-            "Content-Type: text/plain".to_string(),
-            "SDF".to_string(),
-        ];
-        let mut wrong = vec!["SDF:LKJSD:F".to_string(), "SDF".to_string()];
+        let mut request = Request {
+            uri: "thing",
+            headers: vec![
+                "GET / 23".to_string(),
+                "SDF:LKJSD:F".to_string(),
+                "Content-Type: text/plain".to_string(),
+                "SDF".to_string(),
+            ],
+            method: Method::Get,
+            cookies: None,
+            mime_type: None,
+        };
 
-        assert_eq!(None, Request::extract_mime_from_vec(&mut wrong));
-        assert_eq!(
-            Mime::TextPlain,
-            Request::extract_mime_from_vec(&mut right).unwrap()
-        );
-        assert_eq!(None, Request::extract_mime_from_vec(&mut right));
+        let mut wrong = Request {
+            uri: "thing",
+            headers: vec![
+                "GET / 23".to_string(),
+                "SDF:LKJSD:F".to_string(),
+                "SDF".to_string(),
+            ],
+            method: Method::Get,
+            cookies: None,
+            mime_type: None,
+        };
+        request.mime_from_headers();
+        wrong.mime_from_headers();
+        assert_eq!(None, wrong.mime_type);
+        assert_eq!(Mime::TextPlain, request.mime_type.unwrap());
     }
 }
diff --git a/core/http/src/lib.rs b/core/http/src/lib.rs
index a51c899..1d6353a 100644
--- a/core/http/src/lib.rs
+++ b/core/http/src/lib.rs
@@ -2,7 +2,7 @@ pub mod handlers;
 pub mod handling;
 mod setup;
 
-mod utils;
+pub mod utils;
 
 #[cfg(test)]
 mod tests {}
-- 
GitLab


From 9e2911847edd441a82d68660b5d871e8d8d7ae67 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Thu, 29 Jun 2023 21:58:41 +0200
Subject: [PATCH 44/65] New Documentation and changing Request mime type to
 (Mime, String) for the whole data of the content-type

---
 core/http/src/handling/request/datatypes.rs   |   9 +-
 core/http/src/handling/request/form_utils.rs  | 117 +++++++++++++++---
 .../http/src/handling/request/request_mime.rs |  25 ++--
 3 files changed, 125 insertions(+), 26 deletions(-)

diff --git a/core/http/src/handling/request/datatypes.rs b/core/http/src/handling/request/datatypes.rs
index 45f7b7f..f490137 100644
--- a/core/http/src/handling/request/datatypes.rs
+++ b/core/http/src/handling/request/datatypes.rs
@@ -26,13 +26,20 @@ impl FromRequest for Vec<u8> {
 
 type HeaderMap = Vec<String>;
 
+/// A struct to handle Requests
+///
 #[derive(Clone)]
 pub struct Request<'a> {
+    /// The requested Uri
     pub uri: Uri<'a>,
+    /// All headers of the request that haven't been parsed
     pub headers: HeaderMap,
+    /// The methods Request represented with the [Method]
     pub method: Method,
+    /// An optional HashMap representation of all Cookies of the request
     pub cookies: Option<HashMap<String, String>>,
-    pub mime_type: Option<Mime>,
+    /// If the has a body it represents the [Mime]-type of the body
+    pub mime_type: Option<(Mime, String)>,
     // pub connection: ConnectionMeta,
 }
 
diff --git a/core/http/src/handling/request/form_utils.rs b/core/http/src/handling/request/form_utils.rs
index 4163710..d70b2bc 100644
--- a/core/http/src/handling/request/form_utils.rs
+++ b/core/http/src/handling/request/form_utils.rs
@@ -6,6 +6,55 @@ use super::{datatypes::ParseErrors, ParseFormError, Request};
 static TWO_NEWLINES: u8 = 3;
 
 impl Request<'_> {
+    /// # Gets data from a get_form as a HashMap
+    ///
+    /// # Errors
+    /// Gives back a [ParseFormError], top level, if there is lacking data
+    ///
+    /// If everything is fine on the top level it gives back a HashMap of keys and Results, that
+    /// indicate wether the key exists with the [ParseFormError] with an error of
+    /// [ParseErrors::NoData] or wether the key is corrupt with the [ParseErrors::BadData]-Variant
+    ///
+    /// # Examples
+    /// ```
+    /// let request = Request {
+    ///     uri: "/form?name=Name&age=Age",
+    ///     headers: vec![],
+    ///     method: Method::Get,
+    ///     cookies: None,
+    ///     mime_type: None,
+    /// };
+    /// let right = request.get_get_form_keys(&["name", "age"]).unwrap();
+    /// assert_eq!(&"Name", right.get("name").unwrap().as_ref().unwrap());
+    /// assert_eq!(&"Age", right.get("age").unwrap().as_ref().unwrap());
+    ///
+    /// let wrong_request = Request {
+    ///     uri: "/form",
+    ///     ..request.clone()
+    /// };
+    /// assert_eq!(
+    ///     Err(ParseFormError {
+    ///         error: ParseErrors::NoData
+    ///     }),
+    ///     wrong_request.get_get_form_keys(&["name", "age"])
+    /// );
+    ///
+    /// let bad_data = Request {
+    ///     uri: "/form?age=",
+    ///     ..request.clone()
+    /// };
+    /// let wrong = bad_data.get_get_form_keys(&["name", "age"]).unwrap();
+    /// assert_eq!(
+    ///     &Err(ParseFormError {
+    ///         error: ParseErrors::NoData
+    ///     }),
+    ///     wrong.get("name").unwrap()
+    /// );
+    /// assert_eq!(&Ok(""), wrong.get("age").unwrap());
+    /// ```
+    ///
+    /// # Panics
+    /// No Panics
     pub fn get_get_form_keys<'a>(
         &'a self,
         keys: &'a [&str],
@@ -59,11 +108,11 @@ impl Request<'_> {
                 error: ParseErrors::NoData,
             }));
         }
-        let Some(mime_type) = self.mime_type else {
+        let Some(ref mime_type) = self.mime_type else {
             return Err(ParseFormError { error: ParseErrors::BadData });
         };
 
-        match mime_type {
+        match mime_type.0 {
             Mime::ApplicationXWwwFormUrlencoded => {
                 let Ok(data) = String::from_utf8(data.to_vec()) else {
                     return Err(ParseFormError { error: ParseErrors::BadData });
@@ -82,15 +131,7 @@ impl Request<'_> {
                 }
             }
             Mime::MultipartFormData => {
-                let Some(post_type) = self
-                        .headers
-                        .iter()
-                        .find(|header| header.contains("Content-Type: ")) else {
-                    return Err(ParseFormError { error: ParseErrors::BadData });
-                };
-
-                let content_type = post_type.trim().strip_prefix("Content-Type: ").unwrap();
-                let Some(mut boundary) = content_type.split(';').find(|element| element.trim().starts_with("boundary=")) else {
+                let Some(mut boundary) = mime_type.1.split(';').find(|element| element.trim().starts_with("boundary=")) else {
                     return Err(ParseFormError { error: ParseErrors::BadData });
                 };
                 boundary = boundary
@@ -187,20 +228,61 @@ impl Request<'_> {
 #[cfg(test)]
 mod test {
     use crate::{
-        handling::routes::Data,
+        handling::{
+            methods::Method,
+            request::{datatypes::ParseErrors, ParseFormError},
+            routes::Data,
+        },
         utils::mime::mime_enum::Mime::{ApplicationXWwwFormUrlencoded, MultipartFormData},
     };
 
     use super::Request;
+    #[test]
+    fn try_get_test() {
+        let request = Request {
+            uri: "/form?name=Name&age=Age",
+            headers: vec![],
+            method: Method::Get,
+            cookies: None,
+            mime_type: None,
+        };
+        let right = request.get_get_form_keys(&["name", "age"]).unwrap();
+        assert_eq!(&"Name", right.get("name").unwrap().as_ref().unwrap());
+        assert_eq!(&"Age", right.get("age").unwrap().as_ref().unwrap());
+
+        let wrong_request = Request {
+            uri: "/form",
+            ..request.clone()
+        };
+        assert_eq!(
+            Err(ParseFormError {
+                error: ParseErrors::NoData
+            }),
+            wrong_request.get_get_form_keys(&["name", "age"])
+        );
+
+        let bad_data = Request {
+            uri: "/form?age=",
+            ..request.clone()
+        };
+        let wrong = bad_data.get_get_form_keys(&["name", "age"]).unwrap();
+        assert_eq!(
+            &Err(ParseFormError {
+                error: ParseErrors::NoData
+            }),
+            wrong.get("name").unwrap()
+        );
+        assert_eq!(&Ok(""), wrong.get("age").unwrap());
+    }
 
     #[test]
     fn try_post_text() {
         let req = Request {
             uri: "",
             headers: vec!["Content-Type: application/x-www-form-urlencoded".to_string()],
-            method: crate::handling::methods::Method::Post,
+            method: Method::Post,
             cookies: None,
-            mime_type: Some(ApplicationXWwwFormUrlencoded),
+            mime_type: Some((ApplicationXWwwFormUrlencoded, "".into())),
         };
         let data = Data {
             buffer: b"message=23&message1=24".to_vec(),
@@ -218,9 +300,12 @@ mod test {
         let req = Request {
             uri: "",
             headers: vec!["Content-Type: multipart/form-data; boundary=\"boundary\"".to_string()],
-            method: crate::handling::methods::Method::Post,
+            method: Method::Post,
             cookies: None,
-            mime_type: Some(MultipartFormData),
+            mime_type: Some((
+                MultipartFormData,
+                "charset=UTF-8; boundary=\"boundary\"".into(),
+            )),
         };
         let data = Data {
             buffer: b"--boundary\r
diff --git a/core/http/src/handling/request/request_mime.rs b/core/http/src/handling/request/request_mime.rs
index 03ac55a..7551bb7 100644
--- a/core/http/src/handling/request/request_mime.rs
+++ b/core/http/src/handling/request/request_mime.rs
@@ -1,6 +1,6 @@
 use super::datatypes::Request;
 
-impl Request<'_> {
+impl<'a> Request<'a> {
     /// Sets the `mime_type` of this [`Request`] from the headers.
     ///
     /// The mime_type can remain none if there isn't a `Content-Type: ` header
@@ -17,7 +17,7 @@ impl Request<'_> {
     ///     headers: vec![
     ///         "GET / 23".to_string(),
     ///         "SDF:LKJSD:F".to_string(),
-    ///         "Content-Type: text/plain".to_string(),
+    ///         "Content-Type: text/plain; charset=UTF-8".to_string(),
     ///         "SDF".to_string(),
     ///     ],
     ///     method: Method::Get,
@@ -38,7 +38,7 @@ impl Request<'_> {
     /// request.mime_from_headers();
     /// wrong.mime_from_headers();
     /// assert_eq!(None, wrong.mime_type);
-    /// assert_eq!(Mime::TextPlain, request.mime_type.unwrap());
+    /// assert_eq!((Mime::TextPlain, " charset=UTF-8".to_string()), request.mime_type.unwrap());
     /// ```
     /// # Panics
     /// No Panics
@@ -48,14 +48,21 @@ impl Request<'_> {
             .find(|header| header.starts_with("Content-Type: ")) else {
             return;
         };
-        let content_type_string = content_type_header
+        let content_type_string: &str = content_type_header
             .strip_prefix("Content-Type: ")
             .unwrap()
-            .to_string();
+            .trim();
 
-        self.mime_type = match content_type_string.split_once(';') {
-            Some(sub) => sub.0.trim().parse().ok(),
-            None => content_type_string.trim().parse().ok(),
+        self.mime_type = if let Some(content_type) = content_type_string.split_once(';') {
+            let Ok(mime) = content_type.0.trim().parse() else {
+                return;
+            };
+            Some((mime, content_type.1.to_owned()))
+        } else {
+            let Ok(mime) = content_type_string.parse() else {
+                    return;
+                };
+            Some((mime, "".to_owned()))
         };
     }
 }
@@ -96,6 +103,6 @@ mod test {
         request.mime_from_headers();
         wrong.mime_from_headers();
         assert_eq!(None, wrong.mime_type);
-        assert_eq!(Mime::TextPlain, request.mime_type.unwrap());
+        assert_eq!((Mime::TextPlain, "".to_owned()), request.mime_type.unwrap());
     }
 }
-- 
GitLab


From 94752493d1a03d7c7c3172a53279855e9c99203d Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Fri, 30 Jun 2023 19:23:38 +0200
Subject: [PATCH 45/65] Add write and build function to result, add basis for
 cookie setting possibility, divide the response module;

---
 core/http/src/handlers/handler.rs             | 69 +++++++++----------
 core/http/src/handling/request/form_utils.rs  |  6 ++
 core/http/src/handling/request/mod.rs         |  2 +-
 core/http/src/handling/response/cookie.rs     |  0
 core/http/src/handling/response/datatypes.rs  | 45 ++++++++++++
 core/http/src/handling/response/mod.rs        | 12 ++++
 core/http/src/handling/response/response.rs   | 32 +++++++++
 .../{response.rs => response/status.rs}       | 66 ------------------
 core/http/src/handling/response/traits.rs     | 48 +++++++++++++
 site/src/main.rs                              | 20 ++----
 10 files changed, 185 insertions(+), 115 deletions(-)
 create mode 100644 core/http/src/handling/response/cookie.rs
 create mode 100644 core/http/src/handling/response/datatypes.rs
 create mode 100644 core/http/src/handling/response/mod.rs
 create mode 100644 core/http/src/handling/response/response.rs
 rename core/http/src/handling/{response.rs => response/status.rs} (84%)
 create mode 100644 core/http/src/handling/response/traits.rs

diff --git a/core/http/src/handlers/handler.rs b/core/http/src/handlers/handler.rs
index 9596f52..3c46159 100644
--- a/core/http/src/handlers/handler.rs
+++ b/core/http/src/handlers/handler.rs
@@ -1,12 +1,12 @@
-use std::path::PathBuf;
+use std::{path::PathBuf, io};
 
-use tokio::{io::{AsyncReadExt, BufReader, AsyncBufReadExt, AsyncWriteExt}, net::TcpStream};
+use tokio::{io::{AsyncReadExt, BufReader, AsyncBufReadExt}, net::TcpStream};
 
 use crate::handling::{
     file_handlers::NamedFile,
     request::Request,
     response::{Outcome, Response, ResponseBody, Status},
-    routes::Data, methods::Method,
+    routes::{Data, Body}, methods::Method,
 };
 use crate::setup::MountPoint;
 
@@ -78,13 +78,17 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
                 size
             } else {
                 eprintln!("\x1b[31m`{}` must have a `Content-Length` header\x1b[0m", request.method);
-                len_not_defined(stream, Status::LengthRequired).await;
+                if let Err(e) = len_not_defined(stream, Status::LengthRequired).await {
+                    error_occured_when_writing(e)
+                };
                 return;
             }
         } else {
             if request.mandatory_body() {
                 eprintln!("\x1b[31m`{}` must have a `Content-Length` header\x1b[0m", request.method);
-                len_not_defined(stream, Status::LengthRequired).await;
+                if let Err(e) = len_not_defined(stream, Status::LengthRequired).await {
+                    error_occured_when_writing(e)
+                };
                 return;
             }
             0
@@ -94,7 +98,9 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
             let mut buffer = vec![0u8; MAX_HTTP_MESSAGE_SIZE.into()];
             let read = buf_reader.read(&mut buffer).await.unwrap();
             if read != length {
-                len_not_defined(stream, Status::LengthRequired).await;
+                if let Err(e) = len_not_defined(stream, Status::LengthRequired).await {
+                    error_occured_when_writing(e)
+                };
                 return;
             }
             data.is_complete = true;
@@ -133,47 +139,40 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
 
     let response = match handled_response {
         Some(val) => match val {
-            Outcome::Success(success) => (
-                format!("HTTP/1.1 {}\r\n", success.status.unwrap_or(Status::Ok))
-                    + &success.headers.join("\r\n")
-                    + "\r\n\r\n",
-                if request.method == Method::Head {
-                    vec![]
-                } else {
-                    success.body.get_data()
-                }
-            ),
+            Outcome::Success(success) => success
+            ,
             Outcome::Failure(error) => failure_handler(error),
             Outcome::Forward(_) => failure_handler(Status::NotFound),
         },
         None => failure_handler(Status::NotFound),
     };
 
-    let mut resp = response.0.as_bytes().to_vec();
-    resp.extend_from_slice(&response.1);
-    if let Err(e) = stream.write_all(&resp).await {
+    if let Err(e) = response.write(stream, Some(request)).await {
         eprintln!("\x1b[31mError {e} occured when trying to write answer to TCP-Stream for Client, aborting\x1b[0m");
     } 
 }
 
-fn failure_handler(status: Status) -> (String, Vec<u8>) {
+fn failure_handler<'a>(status: Status) -> Response<'a> {
     let page_404 = NamedFile::open(PathBuf::from("404.html")).unwrap();
-    (
-        format!(
-            "HTTP/1.1 {}\r\nContent-Length: {}\r\nContent-Type: {}\r\n\r\n",
-            status,
-            page_404.get_len(),
-            page_404.get_mime()
-        ),
-        page_404.get_data(),
-    )
+    Response {
+        cookies: None,
+        headers: vec![],
+        status: Some(status),
+        body: Box::new(Body::new(page_404.get_data(), page_404.get_mime())),
+    }
 }
 
-async fn len_not_defined(mut stream: TcpStream, status: Status) {
+async fn len_not_defined(stream: TcpStream, status: Status) -> io::Result<()>{
     let page_411 = NamedFile::open(PathBuf::from("411.html")).unwrap();
-    let mut response = format!("HTTP/1.1 {}\r\nContent-Length: {}\r\nContent-Type: {}\r\n\r\n", status, page_411.get_len(), page_411.get_mime()).as_bytes().to_vec();
-    response.extend_from_slice(&page_411.get_data());
-        if let Err(e) = stream.write_all(&response).await {
-            eprintln!("\x1b[31mError {e} occured when trying to write answer to TCP-Stream for Client, aborting\x1b[0m");
-        }
+    Response {
+        cookies: None,
+        headers: vec![],
+        status: Some(status),
+        body: Box::new(Body::new(page_411.get_data(), page_411.get_mime())),
+    }.write(stream, None).await?;
+    Ok(())
+}
+
+fn error_occured_when_writing(e: io::Error) {
+    eprintln!("\x1b[31mError {e} occured when trying to write answer to TCP-Stream for Client, aborting\x1b[0m");
 }
diff --git a/core/http/src/handling/request/form_utils.rs b/core/http/src/handling/request/form_utils.rs
index d70b2bc..cab16eb 100644
--- a/core/http/src/handling/request/form_utils.rs
+++ b/core/http/src/handling/request/form_utils.rs
@@ -17,6 +17,12 @@ impl Request<'_> {
     ///
     /// # Examples
     /// ```
+    /// use http::handling::request::Request;
+    /// use http::handling::request::ParseFormError;
+    /// use http::handling::request::ParseErrors;
+    /// use http::handling::methods::Method;
+    ///
+    ///
     /// let request = Request {
     ///     uri: "/form?name=Name&age=Age",
     ///     headers: vec![],
diff --git a/core/http/src/handling/request/mod.rs b/core/http/src/handling/request/mod.rs
index 54da4ad..f04c57a 100644
--- a/core/http/src/handling/request/mod.rs
+++ b/core/http/src/handling/request/mod.rs
@@ -3,4 +3,4 @@ mod datatypes;
 mod form_utils;
 mod request_impl;
 mod request_mime;
-pub use datatypes::{MediaType, ParseFormError, Request};
+pub use datatypes::{MediaType, ParseErrors, ParseFormError, Request};
diff --git a/core/http/src/handling/response/cookie.rs b/core/http/src/handling/response/cookie.rs
new file mode 100644
index 0000000..e69de29
diff --git a/core/http/src/handling/response/datatypes.rs b/core/http/src/handling/response/datatypes.rs
new file mode 100644
index 0000000..503929a
--- /dev/null
+++ b/core/http/src/handling/response/datatypes.rs
@@ -0,0 +1,45 @@
+use std::time::Duration;
+
+use super::{ResponseBody, Status};
+
+type HeaderMap = Vec<String>;
+
+#[derive(Debug)]
+pub enum Outcome<S, E, F> {
+    Success(S),
+    Failure(E),
+    Forward(F),
+}
+
+pub enum SameSite {
+    None,
+    Lax,
+    Strict,
+}
+
+pub struct Cookie<'a> {
+    /// Storage for the cookie string. Only used if this structure was derived
+    /// from a string that was subsequently parsed.
+    cookie_string: &'a str,
+    name: &'a str,
+    value: &'a str,
+    // expires: Option<Tm>,
+    max_age: Option<Duration>,
+    /// The cookie's domain, if any.
+    domain: Option<&'a str>,
+    /// The cookie's path domain, if any.
+    path: Option<&'a str>,
+    /// Whether this cookie was marked Secure.
+    secure: Option<bool>,
+    /// Whether this cookie was marked HttpOnly.
+    http_only: Option<bool>,
+    /// The draft `SameSite` attribute.
+    same_site: Option<SameSite>,
+}
+
+pub struct Response<'a> {
+    pub headers: HeaderMap,
+    pub cookies: Option<Cookie<'a>>,
+    pub status: Option<Status>,
+    pub body: Box<dyn ResponseBody>,
+}
diff --git a/core/http/src/handling/response/mod.rs b/core/http/src/handling/response/mod.rs
new file mode 100644
index 0000000..017bc15
--- /dev/null
+++ b/core/http/src/handling/response/mod.rs
@@ -0,0 +1,12 @@
+mod cookie;
+mod datatypes;
+mod response;
+mod status;
+mod traits;
+
+pub use datatypes::Cookie;
+pub use datatypes::Outcome;
+pub use datatypes::Response;
+pub use datatypes::SameSite;
+pub use status::Status;
+pub use traits::ResponseBody;
diff --git a/core/http/src/handling/response/response.rs b/core/http/src/handling/response/response.rs
new file mode 100644
index 0000000..dfdb909
--- /dev/null
+++ b/core/http/src/handling/response/response.rs
@@ -0,0 +1,32 @@
+use std::io::Result;
+
+use tokio::{net::TcpStream, io::AsyncWriteExt};
+
+use crate::handling::{methods::Method, request::Request, response::Status};
+
+use super::Response;
+
+impl Response<'_> {
+    pub fn build(self, request: Option<Request>) -> Vec<u8> {
+        let mut compiled_headers = format!("HTTP/1.1 {}\r\nContent-Length: {}\r\nContent-Type: {}\r\n", self.status.unwrap_or(Status::Ok), self.body.get_len(), self.body.get_mime())
+            + &self.headers.join("\r\n")
+            + "\r\n";
+        let is_head = if let Some(req) = request {
+            req.method == Method::Head
+        } else {
+            false
+        };
+        let compiled_body = if is_head {
+            vec![]
+        } else {
+            self.body.get_data()
+        };
+        let compiled_out = unsafe { compiled_headers.as_mut_vec() };
+        compiled_out.extend_from_slice(&compiled_body);
+        compiled_out.to_vec()
+    }
+    pub async fn write(self, mut stream: TcpStream, request: Option<Request<'_>>) -> Result<()> {
+        let resp = self.build(request);
+        stream.write_all(&resp).await?;
+        Ok(())
+}}
diff --git a/core/http/src/handling/response.rs b/core/http/src/handling/response/status.rs
similarity index 84%
rename from core/http/src/handling/response.rs
rename to core/http/src/handling/response/status.rs
index 81a54af..9f825af 100644
--- a/core/http/src/handling/response.rs
+++ b/core/http/src/handling/response/status.rs
@@ -1,71 +1,5 @@
 use std::fmt::Display;
 
-use crate::utils::mime::mime_enum::Mime;
-
-use super::routes::Body;
-
-type HeaderMap = Vec<String>;
-
-#[derive(Debug)]
-pub enum Outcome<S, E, F> {
-    Success(S),
-    Failure(E),
-    Forward(F),
-}
-
-pub trait ResponseBody: Send {
-    fn get_data(&self) -> Vec<u8>;
-    fn get_mime(&self) -> Mime;
-    fn get_len(&self) -> usize;
-}
-
-impl ResponseBody for Body {
-    fn get_data(&self) -> Vec<u8> {
-        self.body()
-    }
-    fn get_mime(&self) -> Mime {
-        self.mime_type()
-    }
-
-    fn get_len(&self) -> usize {
-        self.get_data().len()
-    }
-}
-
-impl ResponseBody for &str {
-    fn get_data(&self) -> Vec<u8> {
-        self.as_bytes().to_vec()
-    }
-
-    fn get_mime(&self) -> Mime {
-        Mime::TextPlain
-    }
-
-    fn get_len(&self) -> usize {
-        self.len()
-    }
-}
-
-impl ResponseBody for String {
-    fn get_data(&self) -> Vec<u8> {
-        self.as_bytes().to_vec()
-    }
-
-    fn get_mime(&self) -> Mime {
-        Mime::TextPlain
-    }
-
-    fn get_len(&self) -> usize {
-        self.len()
-    }
-}
-
-pub struct Response {
-    pub headers: HeaderMap,
-    pub status: Option<Status>,
-    pub body: Box<dyn ResponseBody>,
-}
-
 #[derive(Debug)]
 pub enum Status {
     Continue,
diff --git a/core/http/src/handling/response/traits.rs b/core/http/src/handling/response/traits.rs
new file mode 100644
index 0000000..96ac87c
--- /dev/null
+++ b/core/http/src/handling/response/traits.rs
@@ -0,0 +1,48 @@
+use crate::{handling::routes::Body, utils::mime::mime_enum::Mime};
+
+pub trait ResponseBody: Send {
+    fn get_data(&self) -> Vec<u8>;
+    fn get_mime(&self) -> Mime;
+    fn get_len(&self) -> usize;
+}
+
+impl ResponseBody for Body {
+    fn get_data(&self) -> Vec<u8> {
+        self.body()
+    }
+    fn get_mime(&self) -> Mime {
+        self.mime_type()
+    }
+
+    fn get_len(&self) -> usize {
+        self.get_data().len()
+    }
+}
+
+impl ResponseBody for &str {
+    fn get_data(&self) -> Vec<u8> {
+        self.as_bytes().to_vec()
+    }
+
+    fn get_mime(&self) -> Mime {
+        Mime::TextPlain
+    }
+
+    fn get_len(&self) -> usize {
+        self.len()
+    }
+}
+
+impl ResponseBody for String {
+    fn get_data(&self) -> Vec<u8> {
+        self.as_bytes().to_vec()
+    }
+
+    fn get_mime(&self) -> Mime {
+        Mime::TextPlain
+    }
+
+    fn get_len(&self) -> usize {
+        self.len()
+    }
+}
diff --git a/site/src/main.rs b/site/src/main.rs
index f1fda07..f677a34 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -4,7 +4,7 @@ use http::handling::{
     file_handlers::NamedFile,
     methods::Method,
     request::{Request, ParseFormError},
-    response::{Outcome, Response, ResponseBody, Status},
+    response::{Outcome, Response, Status},
     routes::{Data, Route},
 };
 
@@ -28,10 +28,8 @@ fn handle_static_hi(request: Request<'_>, data: Data) -> Outcome<Response, Statu
     };
     let response = hashmap_to_string(&keys);
     Outcome::Success(Response {
-        headers: vec![
-            format!("Content-Length: {}", response.len()),
-            format!("Content-Type: text/plain"),
-        ],
+        headers: vec![],
+        cookies: None,
         status: Some(Status::Ok),
         body: Box::new(response),
     })
@@ -42,10 +40,8 @@ fn handler(request: Request<'_>, _data: Data) -> Outcome<Response, Status, Data>
     let response = fileserver(request.uri.strip_prefix("static/").unwrap());
     let response = match response {
         Ok(dat) => Response {
-            headers: vec![
-                format!("Content-Length: {}", dat.get_len()),
-                format!("Content-Type: {}", dat.get_mime()),
-            ],
+            headers: vec![],
+            cookies: None,
             status: Some(Status::Ok),
             body: Box::new(dat),
         },
@@ -69,10 +65,8 @@ fn post_hi_handler(request: Request, data: Data) -> Outcome<Response, Status, Da
         return Outcome::Failure(Status::BadRequest);
     };
     Outcome::Success(Response {
-        headers: vec![
-            format!("Content-Length: {}", dat.len()),
-            format!("Content-Type: text/plain"),
-        ],
+        headers: vec![],
+        cookies: None,
         status: Some(Status::Ok),
         body: Box::new(dat),
     })
-- 
GitLab


From 40488db2e4c370bff605a48dcacda94155044855 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sat, 1 Jul 2023 22:09:24 +0200
Subject: [PATCH 46/65] Add basic cookie utility prototypes

---
 core/http/src/handling/response/cookie.rs      |  0
 .../cookie_management/cookie_builder.rs        |  1 +
 .../handling/response/cookie_management/mod.rs |  1 +
 core/http/src/handling/response/datatypes.rs   | 18 +++++++++---------
 core/http/src/handling/response/mod.rs         |  2 +-
 5 files changed, 12 insertions(+), 10 deletions(-)
 delete mode 100644 core/http/src/handling/response/cookie.rs
 create mode 100644 core/http/src/handling/response/cookie_management/cookie_builder.rs
 create mode 100644 core/http/src/handling/response/cookie_management/mod.rs

diff --git a/core/http/src/handling/response/cookie.rs b/core/http/src/handling/response/cookie.rs
deleted file mode 100644
index e69de29..0000000
diff --git a/core/http/src/handling/response/cookie_management/cookie_builder.rs b/core/http/src/handling/response/cookie_management/cookie_builder.rs
new file mode 100644
index 0000000..0a800f1
--- /dev/null
+++ b/core/http/src/handling/response/cookie_management/cookie_builder.rs
@@ -0,0 +1 @@
+struct CookieBuilder {}
diff --git a/core/http/src/handling/response/cookie_management/mod.rs b/core/http/src/handling/response/cookie_management/mod.rs
new file mode 100644
index 0000000..ee6df23
--- /dev/null
+++ b/core/http/src/handling/response/cookie_management/mod.rs
@@ -0,0 +1 @@
+mod cookie_builder;
diff --git a/core/http/src/handling/response/datatypes.rs b/core/http/src/handling/response/datatypes.rs
index 503929a..669005e 100644
--- a/core/http/src/handling/response/datatypes.rs
+++ b/core/http/src/handling/response/datatypes.rs
@@ -20,21 +20,21 @@ pub enum SameSite {
 pub struct Cookie<'a> {
     /// Storage for the cookie string. Only used if this structure was derived
     /// from a string that was subsequently parsed.
-    cookie_string: &'a str,
-    name: &'a str,
-    value: &'a str,
+    pub(crate) cookie_string: Option<&'a str>,
+    pub(crate) name: &'a str,
+    pub(crate) value: &'a str,
     // expires: Option<Tm>,
-    max_age: Option<Duration>,
+    pub(crate) max_age: Option<Duration>,
     /// The cookie's domain, if any.
-    domain: Option<&'a str>,
+    pub(crate) domain: Option<&'a str>,
     /// The cookie's path domain, if any.
-    path: Option<&'a str>,
+    pub(crate) path: Option<&'a str>,
     /// Whether this cookie was marked Secure.
-    secure: Option<bool>,
+    pub(crate) secure: Option<bool>,
     /// Whether this cookie was marked HttpOnly.
-    http_only: Option<bool>,
+    pub(crate) http_only: Option<bool>,
     /// The draft `SameSite` attribute.
-    same_site: Option<SameSite>,
+    pub(crate) same_site: Option<SameSite>,
 }
 
 pub struct Response<'a> {
diff --git a/core/http/src/handling/response/mod.rs b/core/http/src/handling/response/mod.rs
index 017bc15..1fdc875 100644
--- a/core/http/src/handling/response/mod.rs
+++ b/core/http/src/handling/response/mod.rs
@@ -1,4 +1,4 @@
-mod cookie;
+mod cookie_management;
 mod datatypes;
 mod response;
 mod status;
-- 
GitLab


From 36d979d71e7dce8649028eefa2b175fd07a93cb2 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sun, 2 Jul 2023 13:02:41 +0200
Subject: [PATCH 47/65] introducing cookie builder, performance adjustment with
 requets.rs -> build

---
 core/http/src/handlers/handler.rs             | 40 ++++++-----
 core/http/src/handling/request/datatypes.rs   |  2 +-
 .../response/cookie_management/cookie.rs      | 28 ++++++++
 .../cookie_management/cookie_builder.rs       | 66 ++++++++++++++++++-
 .../response/cookie_management/mod.rs         |  4 ++
 core/http/src/handling/response/datatypes.rs  | 30 +--------
 core/http/src/handling/response/mod.rs        |  4 +-
 core/http/src/handling/response/response.rs   | 17 +++--
 core/http/src/setup.rs                        | 15 +++--
 9 files changed, 148 insertions(+), 58 deletions(-)
 create mode 100644 core/http/src/handling/response/cookie_management/cookie.rs

diff --git a/core/http/src/handlers/handler.rs b/core/http/src/handlers/handler.rs
index 3c46159..67897c4 100644
--- a/core/http/src/handlers/handler.rs
+++ b/core/http/src/handlers/handler.rs
@@ -1,12 +1,16 @@
-use std::{path::PathBuf, io};
+use std::{io, path::PathBuf};
 
-use tokio::{io::{AsyncReadExt, BufReader, AsyncBufReadExt}, net::TcpStream};
+use tokio::{
+    io::{AsyncBufReadExt, AsyncReadExt, BufReader},
+    net::TcpStream,
+};
 
 use crate::handling::{
     file_handlers::NamedFile,
+    methods::Method,
     request::Request,
     response::{Outcome, Response, ResponseBody, Status},
-    routes::{Data, Body}, methods::Method,
+    routes::{Body, Data},
 };
 use crate::setup::MountPoint;
 
@@ -44,9 +48,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
         cookies: Request::extract_cookies_from_vec(&mut http_request),
         headers: http_request,
         mime_type: None,
-        method: if let Some(method) = request_status_line
-            .split(' ')
-            .next() {
+        method: if let Some(method) = request_status_line.split(' ').next() {
             if let Ok(ok) = method.parse() {
                 ok
             } else {
@@ -77,7 +79,10 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
             if let Ok(size) = len {
                 size
             } else {
-                eprintln!("\x1b[31m`{}` must have a `Content-Length` header\x1b[0m", request.method);
+                eprintln!(
+                    "\x1b[31m`{}` must have a `Content-Length` header\x1b[0m",
+                    request.method
+                );
                 if let Err(e) = len_not_defined(stream, Status::LengthRequired).await {
                     error_occured_when_writing(e)
                 };
@@ -85,7 +90,10 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
             }
         } else {
             if request.mandatory_body() {
-                eprintln!("\x1b[31m`{}` must have a `Content-Length` header\x1b[0m", request.method);
+                eprintln!(
+                    "\x1b[31m`{}` must have a `Content-Length` header\x1b[0m",
+                    request.method
+                );
                 if let Err(e) = len_not_defined(stream, Status::LengthRequired).await {
                     error_occured_when_writing(e)
                 };
@@ -115,8 +123,9 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
         }
         let mounted_request_uri = request.uri.strip_prefix(mountpoint.mountpoint).unwrap();
         for route in mountpoint.routes {
-            if (route.method != request.method) && 
-            ((route.method != Method::Get) && (request.method == Method::Head)) {
+            if (route.method != request.method)
+                && ((route.method != Method::Get) && (request.method == Method::Head))
+            {
                 continue;
             }
             if !route.compare_uri(mounted_request_uri) {
@@ -139,8 +148,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
 
     let response = match handled_response {
         Some(val) => match val {
-            Outcome::Success(success) => success
-            ,
+            Outcome::Success(success) => success,
             Outcome::Failure(error) => failure_handler(error),
             Outcome::Forward(_) => failure_handler(Status::NotFound),
         },
@@ -149,7 +157,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
 
     if let Err(e) = response.write(stream, Some(request)).await {
         eprintln!("\x1b[31mError {e} occured when trying to write answer to TCP-Stream for Client, aborting\x1b[0m");
-    } 
+    }
 }
 
 fn failure_handler<'a>(status: Status) -> Response<'a> {
@@ -162,14 +170,16 @@ fn failure_handler<'a>(status: Status) -> Response<'a> {
     }
 }
 
-async fn len_not_defined(stream: TcpStream, status: Status) -> io::Result<()>{
+async fn len_not_defined(stream: TcpStream, status: Status) -> io::Result<()> {
     let page_411 = NamedFile::open(PathBuf::from("411.html")).unwrap();
     Response {
         cookies: None,
         headers: vec![],
         status: Some(status),
         body: Box::new(Body::new(page_411.get_data(), page_411.get_mime())),
-    }.write(stream, None).await?;
+    }
+    .write(stream, None)
+    .await?;
     Ok(())
 }
 
diff --git a/core/http/src/handling/request/datatypes.rs b/core/http/src/handling/request/datatypes.rs
index f490137..acde6d8 100644
--- a/core/http/src/handling/request/datatypes.rs
+++ b/core/http/src/handling/request/datatypes.rs
@@ -1,4 +1,4 @@
-use std::{collections::HashMap, error::Error, fmt::Display};
+use std::{borrow::Cow, collections::HashMap, error::Error, fmt::Display};
 
 use crate::{
     handling::{methods::Method, routes::Uri},
diff --git a/core/http/src/handling/response/cookie_management/cookie.rs b/core/http/src/handling/response/cookie_management/cookie.rs
new file mode 100644
index 0000000..cfe3501
--- /dev/null
+++ b/core/http/src/handling/response/cookie_management/cookie.rs
@@ -0,0 +1,28 @@
+use std::time::Duration;
+
+pub struct Cookie<'a> {
+    /// Storage for the cookie string. Only used if this structure was derived
+    /// from a string that was subsequently parsed.
+    pub(crate) cookie_string: Option<&'a str>,
+    pub(crate) name: &'a str,
+    pub(crate) value: &'a str,
+    // expires: Option<Tm>,
+    pub(crate) max_age: Option<Duration>,
+    /// The cookie's domain, if any.
+    pub(crate) domain: Option<&'a str>,
+    /// The cookie's path domain, if any.
+    pub(crate) path: Option<&'a str>,
+    /// Whether this cookie was marked Secure.
+    pub(crate) secure: Option<bool>,
+    /// Whether this cookie was marked HttpOnly.
+    pub(crate) http_only: Option<bool>,
+    /// The draft `SameSite` attribute.
+    pub(crate) same_site: Option<SameSite>,
+    pub(crate) expires: Option<&'a str>,
+}
+
+pub enum SameSite {
+    None,
+    Lax,
+    Strict,
+}
diff --git a/core/http/src/handling/response/cookie_management/cookie_builder.rs b/core/http/src/handling/response/cookie_management/cookie_builder.rs
index 0a800f1..ead2df0 100644
--- a/core/http/src/handling/response/cookie_management/cookie_builder.rs
+++ b/core/http/src/handling/response/cookie_management/cookie_builder.rs
@@ -1 +1,65 @@
-struct CookieBuilder {}
+use std::time::Duration;
+
+use super::{Cookie, SameSite};
+
+pub struct CookieBuilder<'a> {
+    inner: Cookie<'a>,
+}
+
+impl<'a> CookieBuilder<'a> {
+    pub fn build(name: &'a str, value: &'a str) -> Self {
+        CookieBuilder {
+            inner: Cookie {
+                cookie_string: None,
+                name,
+                value,
+                max_age: None,
+                domain: None,
+                path: None,
+                secure: None,
+                http_only: None,
+                same_site: None,
+                expires: None,
+            },
+        }
+    }
+    pub fn finish(self) -> Cookie<'a> {
+        self.inner
+    }
+    pub fn max_age(mut self, duration: Duration) -> Self {
+        self.inner.max_age = Some(duration);
+        self
+    }
+    pub fn domain(mut self, domain: &'a str) -> Self {
+        self.inner.domain = Some(domain);
+        self
+    }
+    pub fn path(mut self, path: &'a str) -> Self {
+        self.inner.path = Some(path);
+        self
+    }
+    pub fn secure(mut self, secure: bool) -> Self {
+        self.inner.secure = Some(secure);
+        self
+    }
+    pub fn http_only(mut self, http_only: bool) -> Self {
+        self.inner.http_only = Some(http_only);
+        self
+    }
+    pub fn same_site(mut self, same_site: SameSite) -> Self {
+        self.inner.same_site = Some(same_site);
+        self
+    }
+    pub fn expires(mut self, expire: &'a str) -> Self {
+        self.inner.expires = Some(expire);
+        self
+    }
+    pub fn name(mut self, name: &'a str) -> Self {
+        self.inner.name = name;
+        self
+    }
+    pub fn value(mut self, value: &'a str) -> Self {
+        self.inner.value = value;
+        self
+    }
+}
diff --git a/core/http/src/handling/response/cookie_management/mod.rs b/core/http/src/handling/response/cookie_management/mod.rs
index ee6df23..06d6b85 100644
--- a/core/http/src/handling/response/cookie_management/mod.rs
+++ b/core/http/src/handling/response/cookie_management/mod.rs
@@ -1 +1,5 @@
+mod cookie;
 mod cookie_builder;
+
+pub use cookie::Cookie;
+pub use cookie::SameSite;
diff --git a/core/http/src/handling/response/datatypes.rs b/core/http/src/handling/response/datatypes.rs
index 669005e..c174a5d 100644
--- a/core/http/src/handling/response/datatypes.rs
+++ b/core/http/src/handling/response/datatypes.rs
@@ -1,6 +1,4 @@
-use std::time::Duration;
-
-use super::{ResponseBody, Status};
+use super::{Cookie, ResponseBody, Status};
 
 type HeaderMap = Vec<String>;
 
@@ -11,32 +9,6 @@ pub enum Outcome<S, E, F> {
     Forward(F),
 }
 
-pub enum SameSite {
-    None,
-    Lax,
-    Strict,
-}
-
-pub struct Cookie<'a> {
-    /// Storage for the cookie string. Only used if this structure was derived
-    /// from a string that was subsequently parsed.
-    pub(crate) cookie_string: Option<&'a str>,
-    pub(crate) name: &'a str,
-    pub(crate) value: &'a str,
-    // expires: Option<Tm>,
-    pub(crate) max_age: Option<Duration>,
-    /// The cookie's domain, if any.
-    pub(crate) domain: Option<&'a str>,
-    /// The cookie's path domain, if any.
-    pub(crate) path: Option<&'a str>,
-    /// Whether this cookie was marked Secure.
-    pub(crate) secure: Option<bool>,
-    /// Whether this cookie was marked HttpOnly.
-    pub(crate) http_only: Option<bool>,
-    /// The draft `SameSite` attribute.
-    pub(crate) same_site: Option<SameSite>,
-}
-
 pub struct Response<'a> {
     pub headers: HeaderMap,
     pub cookies: Option<Cookie<'a>>,
diff --git a/core/http/src/handling/response/mod.rs b/core/http/src/handling/response/mod.rs
index 1fdc875..ede6a42 100644
--- a/core/http/src/handling/response/mod.rs
+++ b/core/http/src/handling/response/mod.rs
@@ -4,9 +4,9 @@ mod response;
 mod status;
 mod traits;
 
-pub use datatypes::Cookie;
+pub use cookie_management::Cookie;
+pub use cookie_management::SameSite;
 pub use datatypes::Outcome;
 pub use datatypes::Response;
-pub use datatypes::SameSite;
 pub use status::Status;
 pub use traits::ResponseBody;
diff --git a/core/http/src/handling/response/response.rs b/core/http/src/handling/response/response.rs
index dfdb909..b986d5c 100644
--- a/core/http/src/handling/response/response.rs
+++ b/core/http/src/handling/response/response.rs
@@ -1,6 +1,6 @@
 use std::io::Result;
 
-use tokio::{net::TcpStream, io::AsyncWriteExt};
+use tokio::{io::AsyncWriteExt, net::TcpStream};
 
 use crate::handling::{methods::Method, request::Request, response::Status};
 
@@ -8,8 +8,12 @@ use super::Response;
 
 impl Response<'_> {
     pub fn build(self, request: Option<Request>) -> Vec<u8> {
-        let mut compiled_headers = format!("HTTP/1.1 {}\r\nContent-Length: {}\r\nContent-Type: {}\r\n", self.status.unwrap_or(Status::Ok), self.body.get_len(), self.body.get_mime())
-            + &self.headers.join("\r\n")
+        let compiled_headers = format!(
+            "HTTP/1.1 {}\r\nContent-Length: {}\r\nContent-Type: {}\r\n",
+            self.status.unwrap_or(Status::Ok),
+            self.body.get_len(),
+            self.body.get_mime()
+        ) + &self.headers.join("\r\n")
             + "\r\n";
         let is_head = if let Some(req) = request {
             req.method == Method::Head
@@ -21,12 +25,13 @@ impl Response<'_> {
         } else {
             self.body.get_data()
         };
-        let compiled_out = unsafe { compiled_headers.as_mut_vec() };
+        let mut compiled_out: Vec<u8> = compiled_headers.into();
         compiled_out.extend_from_slice(&compiled_body);
-        compiled_out.to_vec()
+        compiled_out
     }
     pub async fn write(self, mut stream: TcpStream, request: Option<Request<'_>>) -> Result<()> {
         let resp = self.build(request);
         stream.write_all(&resp).await?;
         Ok(())
-}}
+    }
+}
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index 417cf3d..1f061c6 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -1,6 +1,10 @@
 use std::thread::available_parallelism;
 
-use tokio::{net::TcpListener, signal::unix::{SignalKind, signal}, select};
+use tokio::{
+    net::TcpListener,
+    select,
+    signal::unix::{signal, SignalKind},
+};
 
 use crate::{
     handlers::handler::handle_connection,
@@ -65,7 +69,7 @@ impl<'a> Config {
     }
     /// # Launches/Starts the webserver
     /// Launches a Webserver Configuration
-    /// 
+    ///
     /// Is Async
     ///
     /// Is Blocking -> Can be interrupted with ^C
@@ -74,7 +78,10 @@ impl<'a> Config {
     /// Panics if there are no Mountpoints in the Confiuration to lauch, as well as when the there
     /// is no interrupt signal
     pub async fn launch(self) {
-        println!("Server launched from http://{}", self.address.local_addr().unwrap());
+        println!(
+            "Server launched from http://{}",
+            self.address.local_addr().unwrap()
+        );
         let mut sigint = signal(SignalKind::interrupt()).unwrap();
         loop {
             select! {
@@ -120,7 +127,7 @@ pub async fn build(ip: &str) -> Config {
     let ip = ip[0];
     let workers = available_parallelism().unwrap().get();
     println!(
-"\x1b[34mâš™ Configuration\x1b[0m
+        "\x1b[34mâš™ Configuration\x1b[0m
   >> \x1b[34mIp\x1b[0m: {ip}
   >> \x1b[34mPort\x1b[0m: {port}
   >> \x1b[34mWorkers\x1b[0m: {workers}
-- 
GitLab


From 6c90900d4933b4f84463dbfcfb80d973b502425b Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Mon, 3 Jul 2023 14:57:00 +0200
Subject: [PATCH 48/65] prototyping for cookies further, working on UrlEncoded
 text

---
 core/http/src/handling/file_handlers.rs       |   2 +-
 core/http/src/handling/request/cookies.rs     |   1 +
 core/http/src/handling/request/datatypes.rs   |   4 +-
 core/http/src/handling/request/form_utils.rs  |   4 +-
 .../http/src/handling/request/request_mime.rs |   4 +-
 .../response/cookie_management/cookie.rs      |  18 +++
 .../cookie_management/cookie_builder.rs       |   5 +
 core/http/src/handling/response/traits.rs     |   2 +-
 core/http/src/handling/routes.rs              |   2 +-
 core/http/src/utils/mime/mod.rs               |   5 +-
 core/http/src/utils/mod.rs                    |   1 +
 core/http/src/utils/urlencoded/datatypes.rs   |  26 ++++
 core/http/src/utils/urlencoded/endecode.rs    | 140 ++++++++++++++++++
 core/http/src/utils/urlencoded/mod.rs         |   2 +
 14 files changed, 206 insertions(+), 10 deletions(-)
 create mode 100644 core/http/src/utils/urlencoded/datatypes.rs
 create mode 100644 core/http/src/utils/urlencoded/endecode.rs
 create mode 100644 core/http/src/utils/urlencoded/mod.rs

diff --git a/core/http/src/handling/file_handlers.rs b/core/http/src/handling/file_handlers.rs
index 8ca0019..7a0b080 100644
--- a/core/http/src/handling/file_handlers.rs
+++ b/core/http/src/handling/file_handlers.rs
@@ -2,7 +2,7 @@ use std::{fs, path::PathBuf};
 
 use crate::{
     handling::response::{ResponseBody, Status},
-    utils::mime::mime_enum::Mime,
+    utils::mime::Mime,
 };
 
 #[derive(Debug)]
diff --git a/core/http/src/handling/request/cookies.rs b/core/http/src/handling/request/cookies.rs
index b386086..cd3c4ca 100644
--- a/core/http/src/handling/request/cookies.rs
+++ b/core/http/src/handling/request/cookies.rs
@@ -52,6 +52,7 @@ impl Request<'_> {
             .strip_prefix("Cookie: ")
             .unwrap()
             .trim()
+            .trim_matches('"')
             .to_string();
         for cookie in cookies_string.split(';') {
             let Some((name, cookie)) = cookie.split_once('=') else {
diff --git a/core/http/src/handling/request/datatypes.rs b/core/http/src/handling/request/datatypes.rs
index acde6d8..df96177 100644
--- a/core/http/src/handling/request/datatypes.rs
+++ b/core/http/src/handling/request/datatypes.rs
@@ -1,8 +1,8 @@
-use std::{borrow::Cow, collections::HashMap, error::Error, fmt::Display};
+use std::{collections::HashMap, error::Error, fmt::Display};
 
 use crate::{
     handling::{methods::Method, routes::Uri},
-    utils::mime::mime_enum::Mime,
+    utils::mime::Mime,
 };
 
 pub trait FromRequest: Send {
diff --git a/core/http/src/handling/request/form_utils.rs b/core/http/src/handling/request/form_utils.rs
index cab16eb..9aa300c 100644
--- a/core/http/src/handling/request/form_utils.rs
+++ b/core/http/src/handling/request/form_utils.rs
@@ -1,6 +1,6 @@
 use std::collections::HashMap;
 
-use crate::{handling::routes::Data, utils::mime::mime_enum::Mime};
+use crate::{handling::routes::Data, utils::mime::Mime};
 
 use super::{datatypes::ParseErrors, ParseFormError, Request};
 static TWO_NEWLINES: u8 = 3;
@@ -239,7 +239,7 @@ mod test {
             request::{datatypes::ParseErrors, ParseFormError},
             routes::Data,
         },
-        utils::mime::mime_enum::Mime::{ApplicationXWwwFormUrlencoded, MultipartFormData},
+        utils::mime::Mime::{ApplicationXWwwFormUrlencoded, MultipartFormData},
     };
 
     use super::Request;
diff --git a/core/http/src/handling/request/request_mime.rs b/core/http/src/handling/request/request_mime.rs
index 7551bb7..56188d1 100644
--- a/core/http/src/handling/request/request_mime.rs
+++ b/core/http/src/handling/request/request_mime.rs
@@ -9,7 +9,7 @@ impl<'a> Request<'a> {
     /// ```
     /// use http::{
     ///     handling::{methods::Method, request::Request},
-    ///     utils::mime::mime_enum::Mime,
+    ///     utils::mime::Mime,
     /// };
     ///
     /// let mut request = Request {
@@ -71,7 +71,7 @@ impl<'a> Request<'a> {
 mod test {
     use crate::{
         handling::{methods::Method, request::Request},
-        utils::mime::mime_enum::Mime,
+        utils::mime::Mime,
     };
 
     #[test]
diff --git a/core/http/src/handling/response/cookie_management/cookie.rs b/core/http/src/handling/response/cookie_management/cookie.rs
index cfe3501..4e072eb 100644
--- a/core/http/src/handling/response/cookie_management/cookie.rs
+++ b/core/http/src/handling/response/cookie_management/cookie.rs
@@ -19,10 +19,28 @@ pub struct Cookie<'a> {
     /// The draft `SameSite` attribute.
     pub(crate) same_site: Option<SameSite>,
     pub(crate) expires: Option<&'a str>,
+    pub(crate) partitioned: Option<bool>,
 }
 
+#[derive(Debug)]
 pub enum SameSite {
     None,
     Lax,
     Strict,
 }
+
+impl std::fmt::Display for SameSite {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            Self::None => write!(f, "SameSite=None; Secure"),
+            Self::Lax => write!(f, "SameSite=Lax"),
+            Self::Strict => write!(f, "SameSite=Strict"),
+        }
+    }
+}
+
+impl std::fmt::Display for Cookie<'_> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        todo!()
+    }
+}
diff --git a/core/http/src/handling/response/cookie_management/cookie_builder.rs b/core/http/src/handling/response/cookie_management/cookie_builder.rs
index ead2df0..431160a 100644
--- a/core/http/src/handling/response/cookie_management/cookie_builder.rs
+++ b/core/http/src/handling/response/cookie_management/cookie_builder.rs
@@ -20,6 +20,7 @@ impl<'a> CookieBuilder<'a> {
                 http_only: None,
                 same_site: None,
                 expires: None,
+                partitioned: None,
             },
         }
     }
@@ -54,6 +55,10 @@ impl<'a> CookieBuilder<'a> {
         self.inner.expires = Some(expire);
         self
     }
+    pub fn partitioned(mut self, partitioned: bool) -> Self {
+        self.inner.partitioned = Some(partitioned);
+        self
+    }
     pub fn name(mut self, name: &'a str) -> Self {
         self.inner.name = name;
         self
diff --git a/core/http/src/handling/response/traits.rs b/core/http/src/handling/response/traits.rs
index 96ac87c..fc7eb09 100644
--- a/core/http/src/handling/response/traits.rs
+++ b/core/http/src/handling/response/traits.rs
@@ -1,4 +1,4 @@
-use crate::{handling::routes::Body, utils::mime::mime_enum::Mime};
+use crate::{handling::routes::Body, utils::mime::Mime};
 
 pub trait ResponseBody: Send {
     fn get_data(&self) -> Vec<u8>;
diff --git a/core/http/src/handling/routes.rs b/core/http/src/handling/routes.rs
index a85261a..e4246b8 100644
--- a/core/http/src/handling/routes.rs
+++ b/core/http/src/handling/routes.rs
@@ -4,7 +4,7 @@ use crate::{
         request::{MediaType, Request},
         response::{Outcome, Response, Status},
     },
-    utils::mime::mime_enum::Mime,
+    utils::mime::Mime,
 };
 
 pub struct RoutInfo {
diff --git a/core/http/src/utils/mime/mod.rs b/core/http/src/utils/mime/mod.rs
index bbf3a87..4421654 100644
--- a/core/http/src/utils/mime/mod.rs
+++ b/core/http/src/utils/mime/mod.rs
@@ -1,2 +1,5 @@
 mod map;
-pub mod mime_enum;
+mod mime_enum;
+pub use map::MIME_MAP;
+pub use mime_enum::Mime;
+pub use mime_enum::ParseMimeError;
diff --git a/core/http/src/utils/mod.rs b/core/http/src/utils/mod.rs
index 909a531..98498d0 100644
--- a/core/http/src/utils/mod.rs
+++ b/core/http/src/utils/mod.rs
@@ -1 +1,2 @@
 pub mod mime;
+pub mod urlencoded;
diff --git a/core/http/src/utils/urlencoded/datatypes.rs b/core/http/src/utils/urlencoded/datatypes.rs
new file mode 100644
index 0000000..c370ddf
--- /dev/null
+++ b/core/http/src/utils/urlencoded/datatypes.rs
@@ -0,0 +1,26 @@
+use std::borrow::Cow;
+
+use super::endecode::EnDecodable;
+
+pub struct UrlEncodeData<'a> {
+    encoded: Cow<'a, str>,
+    raw: Cow<'a, str>,
+}
+
+impl UrlEncodeData<'_> {
+    pub fn from_raw(raw: &str) -> Self {
+        todo!()
+    }
+    pub fn from_encoded(encoded: &str) -> Self {
+        todo!()
+    }
+}
+
+impl EnDecodable for UrlEncodeData<'_> {
+    fn encode(&self) -> Cow<'_, str> {
+        self.raw.encode()
+    }
+    fn decode(&self) -> Result<Cow<'_, str>, ()> {
+        self.encoded.decode()
+    }
+}
diff --git a/core/http/src/utils/urlencoded/endecode.rs b/core/http/src/utils/urlencoded/endecode.rs
new file mode 100644
index 0000000..0e7fe2c
--- /dev/null
+++ b/core/http/src/utils/urlencoded/endecode.rs
@@ -0,0 +1,140 @@
+use std::borrow::Cow;
+
+static BASE16_HEXA_DECIMAL: u8 = 16;
+pub trait EnDecodable {
+    fn encode(&self) -> Cow<'_, str>;
+    fn decode(&self) -> Result<Cow<'_, str>, ()>;
+}
+
+impl EnDecodable for Cow<'_, str> {
+    fn encode(&self) -> Cow<'_, str> {
+        self.bytes()
+            .map(|byte| {
+                if !byte.is_ascii_alphanumeric() {
+                    format!("%{:02X}", byte)
+                } else {
+                    String::from_utf8([byte].to_vec()).unwrap()
+                }
+            })
+            .collect()
+    }
+    fn decode(&self) -> Result<Cow<'_, str>, ()> {
+        let mut first = true;
+        let mut result = String::with_capacity(self.len());
+        for i in self.split('%') {
+            if first {
+                first = false;
+                result += i;
+                continue;
+            }
+            let Ok(char) = u8::from_str_radix(i[0..2].as_ref(), BASE16_HEXA_DECIMAL.into()) else {
+                return Err(());
+            };
+            unsafe {
+                result.as_mut_vec().push(char);
+            }
+            result = result + &i[2..];
+        }
+        Ok(result.into())
+    }
+}
+
+impl EnDecodable for &str {
+    fn encode(&self) -> Cow<'_, str> {
+        self.bytes()
+            .map(|byte| {
+                if !byte.is_ascii_alphanumeric() {
+                    format!("%{:02X}", byte)
+                } else {
+                    String::from_utf8([byte].to_vec()).unwrap()
+                }
+            })
+            .collect()
+    }
+
+    fn decode(&self) -> Result<Cow<'_, str>, ()> {
+        let mut first = true;
+        let mut result = String::with_capacity(self.len());
+        for i in self.split('%') {
+            if first {
+                first = false;
+                result += i;
+                continue;
+            }
+            let Ok(char) = u8::from_str_radix(i[0..2].as_ref(), BASE16_HEXA_DECIMAL.into()) else {
+                return Err(());
+            };
+            unsafe {
+                result.as_mut_vec().push(char);
+            }
+            result = result + &i[2..];
+        }
+        Ok(result.into())
+    }
+}
+
+impl EnDecodable for String {
+    fn encode(&self) -> Cow<'_, str> {
+        self.bytes()
+            .map(|byte| {
+                if !byte.is_ascii_alphanumeric() {
+                    format!("%{:02X}", byte)
+                } else {
+                    String::from_utf8([byte].to_vec()).unwrap()
+                }
+            })
+            .collect()
+    }
+    fn decode(&self) -> Result<Cow<'_, str>, ()> {
+        let mut first = true;
+        let mut result = String::with_capacity(self.len());
+        for i in self.split('%') {
+            if first {
+                first = false;
+                result += i;
+                continue;
+            }
+            let Ok(char) = u8::from_str_radix(i[0..2].as_ref(), BASE16_HEXA_DECIMAL.into()) else {
+                return Err(());
+            };
+            unsafe {
+                result.as_mut_vec().push(char);
+            }
+            result = result + &i[2..];
+        }
+        Ok(result.into())
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::borrow::Cow;
+
+    use crate::utils::urlencoded::endecode::EnDecodable;
+
+    #[test]
+    fn urlencoded_test() {
+        assert_eq!(
+            "Darius%20is%20the%20biggest%20genius%2FGenie%2FHuman%20extraordin%C3%A4ire",
+            Cow::Borrowed("Darius is the biggest genius/Genie/Human extraordinäire").encode()
+        )
+    }
+    #[test]
+    fn urldecoded_test() {
+        assert_eq!(
+            "Darius is the biggest genius/Genie/Human extraordinäire",
+            Cow::Borrowed(
+                "Darius%20is%20the%20biggest%20genius%2FGenie%2FHuman%20extraordin%C3%A4ire"
+            )
+            .decode()
+            .unwrap()
+        );
+        assert_eq!(
+            Err(()),
+            Cow::Borrowed(
+                "Darius%2iis%20the%20biggest%20genius%2FGenie%2FHuman%20extraordin%C3%A4ire"
+            )
+            .decode()
+        );
+    }
+}
diff --git a/core/http/src/utils/urlencoded/mod.rs b/core/http/src/utils/urlencoded/mod.rs
new file mode 100644
index 0000000..43ea58f
--- /dev/null
+++ b/core/http/src/utils/urlencoded/mod.rs
@@ -0,0 +1,2 @@
+mod datatypes;
+mod endecode;
-- 
GitLab


From 929f96ebca64977d492a63f2118da0871967a153 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Tue, 4 Jul 2023 22:03:01 +0200
Subject: [PATCH 49/65] converting the request uri to a urlencoded datatype
 many errors WIP

---
 core/http/src/handlers/handler.rs             |  13 +-
 core/http/src/handling/request/cookies.rs     |   2 +-
 core/http/src/handling/request/datatypes.rs   |   6 +-
 core/http/src/handling/request/form_utils.rs  |  22 ++-
 .../http/src/handling/request/request_impl.rs |   2 +-
 .../http/src/handling/request/request_mime.rs |   8 +-
 core/http/src/handling/response/response.rs   |   2 +-
 core/http/src/utils/urlencoded/datatypes.rs   |  51 +++++--
 core/http/src/utils/urlencoded/endecode.rs    | 142 ++++++------------
 core/http/src/utils/urlencoded/mod.rs         |   3 +
 10 files changed, 116 insertions(+), 135 deletions(-)

diff --git a/core/http/src/handlers/handler.rs b/core/http/src/handlers/handler.rs
index 67897c4..9aded69 100644
--- a/core/http/src/handlers/handler.rs
+++ b/core/http/src/handlers/handler.rs
@@ -5,13 +5,13 @@ use tokio::{
     net::TcpStream,
 };
 
-use crate::handling::{
+use crate::{handling::{
     file_handlers::NamedFile,
     methods::Method,
     request::Request,
     response::{Outcome, Response, ResponseBody, Status},
     routes::{Body, Data},
-};
+}, utils::urlencoded::UrlEncodeData};
 use crate::setup::MountPoint;
 
 static MAX_HTTP_MESSAGE_SIZE: u16 = 4196;
@@ -40,7 +40,12 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
 
     let mut request = Request {
         uri: if let Some(uri) = &request_status_line.split(' ').nth(1) {
-            uri
+            if let Ok(uri) = UrlEncodeData::from_encoded(uri) {
+                uri
+            } else {
+                eprintln!("\x1b[31mAborting due to invalid uri\x1b[0m");
+                return;
+            }
         } else {
             eprintln!("\x1b[31mAborting due to invalid status line\x1b[0m");
             return;
@@ -118,7 +123,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
 
     let mut handled_response: Option<Outcome<Response, Status, Data>> = None;
     for mountpoint in mountpoints {
-        if !request.uri.starts_with(mountpoint.mountpoint) {
+        if !request.uri.raw().starts_with(mountpoint.mountpoint) {
             continue;
         }
         let mounted_request_uri = request.uri.strip_prefix(mountpoint.mountpoint).unwrap();
diff --git a/core/http/src/handling/request/cookies.rs b/core/http/src/handling/request/cookies.rs
index cd3c4ca..7f75fc1 100644
--- a/core/http/src/handling/request/cookies.rs
+++ b/core/http/src/handling/request/cookies.rs
@@ -2,7 +2,7 @@ use std::collections::HashMap;
 
 use super::Request;
 
-impl Request<'_> {
+impl Request {
     /// Extracts the cookies from a Vector and gives back an optional HashMap of Strings
     ///
     /// Returns none if there are no cookies or there is a problem with the cookies, for example
diff --git a/core/http/src/handling/request/datatypes.rs b/core/http/src/handling/request/datatypes.rs
index df96177..6d37b1f 100644
--- a/core/http/src/handling/request/datatypes.rs
+++ b/core/http/src/handling/request/datatypes.rs
@@ -2,7 +2,7 @@ use std::{collections::HashMap, error::Error, fmt::Display};
 
 use crate::{
     handling::{methods::Method, routes::Uri},
-    utils::mime::Mime,
+    utils::{mime::Mime, urlencoded::UrlEncodeData},
 };
 
 pub trait FromRequest: Send {
@@ -29,9 +29,9 @@ type HeaderMap = Vec<String>;
 /// A struct to handle Requests
 ///
 #[derive(Clone)]
-pub struct Request<'a> {
+pub struct Request {
     /// The requested Uri
-    pub uri: Uri<'a>,
+    pub uri: UrlEncodeData,
     /// All headers of the request that haven't been parsed
     pub headers: HeaderMap,
     /// The methods Request represented with the [Method]
diff --git a/core/http/src/handling/request/form_utils.rs b/core/http/src/handling/request/form_utils.rs
index 9aa300c..1579c11 100644
--- a/core/http/src/handling/request/form_utils.rs
+++ b/core/http/src/handling/request/form_utils.rs
@@ -1,11 +1,14 @@
 use std::collections::HashMap;
 
-use crate::{handling::routes::Data, utils::mime::Mime};
+use crate::{
+    handling::routes::Data,
+    utils::{mime::Mime, urlencoded::DeCodable},
+};
 
 use super::{datatypes::ParseErrors, ParseFormError, Request};
 static TWO_NEWLINES: u8 = 3;
 
-impl Request<'_> {
+impl Request {
     /// # Gets data from a get_form as a HashMap
     ///
     /// # Errors
@@ -124,16 +127,19 @@ impl Request<'_> {
                     return Err(ParseFormError { error: ParseErrors::BadData });
                 };
                 for kvp in data.split('&') {
-                    let Some(mut kvp) = kvp.split_once('=') else {
+                    let Some(kvp) = kvp.split_once('=') else {
                         return Err(ParseFormError { error: ParseErrors::BadData });
                     };
-
-                    let Some(thing) = keymap.get_mut(kvp.0) else {
+                    let Ok(key) = kvp.0.decode() else {
+                        return Err(ParseFormError { error: ParseErrors::BadData });
+                    };
+                    let Ok(value) = kvp.1.trim_end_matches('\0').decode() else {
+                        return Err(ParseFormError { error: ParseErrors::BadData });
+                    };
+                    let Some(thing) = keymap.get_mut(&key) else {
                         continue;
                     };
-                    kvp.1 = kvp.1.trim_end_matches('\0');
-
-                    *thing = Ok(kvp.1.as_bytes().to_vec());
+                    *thing = Ok(value.into());
                 }
             }
             Mime::MultipartFormData => {
diff --git a/core/http/src/handling/request/request_impl.rs b/core/http/src/handling/request/request_impl.rs
index 2d2f7cb..2eb6fd0 100644
--- a/core/http/src/handling/request/request_impl.rs
+++ b/core/http/src/handling/request/request_impl.rs
@@ -2,7 +2,7 @@ use crate::handling::methods::Method;
 
 use super::Request;
 
-impl Request<'_> {
+impl Request {
     pub fn can_have_body(&self) -> bool {
         matches!(
             self.method,
diff --git a/core/http/src/handling/request/request_mime.rs b/core/http/src/handling/request/request_mime.rs
index 56188d1..c37045e 100644
--- a/core/http/src/handling/request/request_mime.rs
+++ b/core/http/src/handling/request/request_mime.rs
@@ -1,6 +1,6 @@
 use super::datatypes::Request;
 
-impl<'a> Request<'a> {
+impl Request {
     /// Sets the `mime_type` of this [`Request`] from the headers.
     ///
     /// The mime_type can remain none if there isn't a `Content-Type: ` header
@@ -71,13 +71,13 @@ impl<'a> Request<'a> {
 mod test {
     use crate::{
         handling::{methods::Method, request::Request},
-        utils::mime::Mime,
+        utils::{mime::Mime, urlencoded::UrlEncodeData},
     };
 
     #[test]
     pub fn test_mime_parse_from_header_vec() {
         let mut request = Request {
-            uri: "thing",
+            uri: UrlEncodeData::from_raw("thing"),
             headers: vec![
                 "GET / 23".to_string(),
                 "SDF:LKJSD:F".to_string(),
@@ -90,7 +90,7 @@ mod test {
         };
 
         let mut wrong = Request {
-            uri: "thing",
+            uri: UrlEncodeData::from_raw("thing"),
             headers: vec![
                 "GET / 23".to_string(),
                 "SDF:LKJSD:F".to_string(),
diff --git a/core/http/src/handling/response/response.rs b/core/http/src/handling/response/response.rs
index b986d5c..3284d02 100644
--- a/core/http/src/handling/response/response.rs
+++ b/core/http/src/handling/response/response.rs
@@ -29,7 +29,7 @@ impl Response<'_> {
         compiled_out.extend_from_slice(&compiled_body);
         compiled_out
     }
-    pub async fn write(self, mut stream: TcpStream, request: Option<Request<'_>>) -> Result<()> {
+    pub async fn write(self, mut stream: TcpStream, request: Option<Request>) -> Result<()> {
         let resp = self.build(request);
         stream.write_all(&resp).await?;
         Ok(())
diff --git a/core/http/src/utils/urlencoded/datatypes.rs b/core/http/src/utils/urlencoded/datatypes.rs
index c370ddf..97dc0a9 100644
--- a/core/http/src/utils/urlencoded/datatypes.rs
+++ b/core/http/src/utils/urlencoded/datatypes.rs
@@ -1,26 +1,45 @@
-use std::borrow::Cow;
+use std::{borrow::Cow, string::FromUtf8Error};
 
-use super::endecode::EnDecodable;
+use crate::utils::urlencoded::endecode::EnCodable;
 
-pub struct UrlEncodeData<'a> {
-    encoded: Cow<'a, str>,
-    raw: Cow<'a, str>,
+use super::endecode::DeCodable;
+
+#[derive(Clone)]
+pub struct UrlEncodeData {
+    encoded: String,
+    raw: Vec<u8>,
+    raw_string: Option<String>,
 }
 
-impl UrlEncodeData<'_> {
-    pub fn from_raw(raw: &str) -> Self {
-        todo!()
+impl UrlEncodeData {
+    pub fn from_raw<T: AsRef<[u8]>>(raw: T) -> Result<Self, FromUtf8Error> {
+        Ok(Self {
+            raw: raw.as_ref().to_owned(),
+            encoded: raw.as_ref().encode(),
+            raw_string: String::from_utf8(raw.as_ref().into()).ok(),
+        })
     }
-    pub fn from_encoded(encoded: &str) -> Self {
-        todo!()
+    pub fn from_encoded(encoded: &str) -> Result<Self, ()> {
+        Ok(Self {
+            encoded: encoded.to_owned(),
+            raw: encoded.decode()?,
+            raw_string: String::from_utf8(encoded.decode()?).ok(),
+        })
     }
-}
 
-impl EnDecodable for UrlEncodeData<'_> {
-    fn encode(&self) -> Cow<'_, str> {
-        self.raw.encode()
+    pub fn encoded(&self) -> &str {
+        self.encoded.as_ref()
+    }
+    pub fn raw(&self) -> &[u8] {
+        self.raw.as_ref()
     }
-    fn decode(&self) -> Result<Cow<'_, str>, ()> {
-        self.encoded.decode()
+    pub fn raw_string(&self) -> Option<&str> {
+        self.raw_string.as_ref().map(|x| x.as_str())
+    }
+}
+
+impl std::fmt::Display for UrlEncodeData {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", self.encoded)
     }
 }
diff --git a/core/http/src/utils/urlencoded/endecode.rs b/core/http/src/utils/urlencoded/endecode.rs
index 0e7fe2c..83e2261 100644
--- a/core/http/src/utils/urlencoded/endecode.rs
+++ b/core/http/src/utils/urlencoded/endecode.rs
@@ -1,140 +1,88 @@
-use std::borrow::Cow;
-
 static BASE16_HEXA_DECIMAL: u8 = 16;
-pub trait EnDecodable {
-    fn encode(&self) -> Cow<'_, str>;
-    fn decode(&self) -> Result<Cow<'_, str>, ()>;
+static BASE16_HEXA_DECIMAL_POSSIBLE_VALUE_PER_DIGIT: u8 = 15;
+static BASE16_HEXA_DECIMAL_DIGIT_BITS: u8 = 4;
+
+pub trait EnCodable {
+    fn encode(&self) -> String;
 }
 
-impl EnDecodable for Cow<'_, str> {
-    fn encode(&self) -> Cow<'_, str> {
-        self.bytes()
-            .map(|byte| {
-                if !byte.is_ascii_alphanumeric() {
-                    format!("%{:02X}", byte)
-                } else {
-                    String::from_utf8([byte].to_vec()).unwrap()
-                }
-            })
-            .collect()
-    }
-    fn decode(&self) -> Result<Cow<'_, str>, ()> {
-        let mut first = true;
+pub trait DeCodable {
+    fn decode(&self) -> Result<Vec<u8>, ()>;
+}
+
+impl EnCodable for [u8] {
+    fn encode(self: &[u8]) -> String {
         let mut result = String::with_capacity(self.len());
-        for i in self.split('%') {
-            if first {
-                first = false;
-                result += i;
-                continue;
+        let result_vec = unsafe { result.as_mut_vec() };
+        self.iter().for_each(|byte| {
+            if !matches!(byte, b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z' | b'-' | b'_' | b'.' | b'~')
+            {
+                result_vec.push(b'%');
+                result_vec.push(hex_to_digit(byte >> BASE16_HEXA_DECIMAL_DIGIT_BITS));
+                result_vec.push(hex_to_digit(
+                    byte & BASE16_HEXA_DECIMAL_POSSIBLE_VALUE_PER_DIGIT,
+                ));
+            } else {
+                result_vec.push(*byte)
             }
-            let Ok(char) = u8::from_str_radix(i[0..2].as_ref(), BASE16_HEXA_DECIMAL.into()) else {
-                return Err(());
-            };
-            unsafe {
-                result.as_mut_vec().push(char);
-            }
-            result = result + &i[2..];
-        }
-        Ok(result.into())
+        });
+        result
     }
 }
-
-impl EnDecodable for &str {
-    fn encode(&self) -> Cow<'_, str> {
-        self.bytes()
-            .map(|byte| {
-                if !byte.is_ascii_alphanumeric() {
-                    format!("%{:02X}", byte)
-                } else {
-                    String::from_utf8([byte].to_vec()).unwrap()
-                }
-            })
-            .collect()
-    }
-
-    fn decode(&self) -> Result<Cow<'_, str>, ()> {
+impl DeCodable for &str {
+    fn decode(&self) -> Result<Vec<u8>, ()> {
         let mut first = true;
-        let mut result = String::with_capacity(self.len());
+        let mut result = Vec::with_capacity(self.len());
+
         for i in self.split('%') {
             if first {
                 first = false;
-                result += i;
+                result.extend_from_slice(i.as_bytes());
                 continue;
             }
             let Ok(char) = u8::from_str_radix(i[0..2].as_ref(), BASE16_HEXA_DECIMAL.into()) else {
-                return Err(());
+                    return Err(());
             };
-            unsafe {
-                result.as_mut_vec().push(char);
-            }
-            result = result + &i[2..];
+            result.push(char);
+            result.extend_from_slice(i[2..].as_bytes());
         }
-        Ok(result.into())
+        Ok(result)
     }
 }
 
-impl EnDecodable for String {
-    fn encode(&self) -> Cow<'_, str> {
-        self.bytes()
-            .map(|byte| {
-                if !byte.is_ascii_alphanumeric() {
-                    format!("%{:02X}", byte)
-                } else {
-                    String::from_utf8([byte].to_vec()).unwrap()
-                }
-            })
-            .collect()
-    }
-    fn decode(&self) -> Result<Cow<'_, str>, ()> {
-        let mut first = true;
-        let mut result = String::with_capacity(self.len());
-        for i in self.split('%') {
-            if first {
-                first = false;
-                result += i;
-                continue;
-            }
-            let Ok(char) = u8::from_str_radix(i[0..2].as_ref(), BASE16_HEXA_DECIMAL.into()) else {
-                return Err(());
-            };
-            unsafe {
-                result.as_mut_vec().push(char);
-            }
-            result = result + &i[2..];
-        }
-        Ok(result.into())
+fn hex_to_digit(digit: u8) -> u8 {
+    match digit {
+        0..=9 => b'0' + digit,
+        10..=255 => b'A' + digit - 10,
     }
 }
 
 #[cfg(test)]
 mod test {
-    use std::borrow::Cow;
-
-    use crate::utils::urlencoded::endecode::EnDecodable;
+    use crate::utils::urlencoded::endecode::DeCodable;
+    use crate::utils::urlencoded::endecode::EnCodable;
 
     #[test]
     fn urlencoded_test() {
         assert_eq!(
             "Darius%20is%20the%20biggest%20genius%2FGenie%2FHuman%20extraordin%C3%A4ire",
-            Cow::Borrowed("Darius is the biggest genius/Genie/Human extraordinäire").encode()
-        )
+            b"Darius is the biggest genius/Genie/Human extraordin\xC3\xA4ire".encode()
+        );
     }
     #[test]
     fn urldecoded_test() {
         assert_eq!(
             "Darius is the biggest genius/Genie/Human extraordinäire",
-            Cow::Borrowed(
+            String::from_utf8(
                 "Darius%20is%20the%20biggest%20genius%2FGenie%2FHuman%20extraordin%C3%A4ire"
+                    .decode()
+                    .unwrap()
             )
-            .decode()
             .unwrap()
         );
         assert_eq!(
             Err(()),
-            Cow::Borrowed(
-                "Darius%2iis%20the%20biggest%20genius%2FGenie%2FHuman%20extraordin%C3%A4ire"
-            )
-            .decode()
+            "Darius%2iis%20the%20biggest%20genius%2FGenie%2FHuman%20extraordin%C3%A4ire".decode()
         );
     }
 }
diff --git a/core/http/src/utils/urlencoded/mod.rs b/core/http/src/utils/urlencoded/mod.rs
index 43ea58f..6511cfc 100644
--- a/core/http/src/utils/urlencoded/mod.rs
+++ b/core/http/src/utils/urlencoded/mod.rs
@@ -1,2 +1,5 @@
 mod datatypes;
 mod endecode;
+pub use datatypes::UrlEncodeData;
+pub use endecode::DeCodable;
+pub use endecode::EnCodable;
-- 
GitLab


From 35c2138d0352275fc9ac47e782846574f0adc09f Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sat, 8 Jul 2023 14:36:14 +0200
Subject: [PATCH 50/65] FIX finish conversion to URLEncoded for URIs and UTF-8
 support.

---
 core/http/src/handlers/handler.rs             | 11 +++---
 core/http/src/handling/request/form_utils.rs  | 23 +++++++++----
 .../response/cookie_management/cookie.rs      | 16 ++++-----
 .../cookie_management/cookie_builder.rs       | 34 +++++++++----------
 core/http/src/handling/response/datatypes.rs  |  4 +--
 core/http/src/handling/response/response.rs   |  2 +-
 core/http/src/utils/urlencoded/datatypes.rs   |  8 ++---
 core/http/src/utils/urlencoded/endecode.rs    |  6 +++-
 site/src/main.rs                              |  6 ++--
 9 files changed, 62 insertions(+), 48 deletions(-)

diff --git a/core/http/src/handlers/handler.rs b/core/http/src/handlers/handler.rs
index 9aded69..8b02188 100644
--- a/core/http/src/handlers/handler.rs
+++ b/core/http/src/handlers/handler.rs
@@ -123,10 +123,13 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
 
     let mut handled_response: Option<Outcome<Response, Status, Data>> = None;
     for mountpoint in mountpoints {
-        if !request.uri.raw().starts_with(mountpoint.mountpoint) {
+        if request.uri.raw_string().is_none() {
+            return;
+        }
+        if !request.uri.raw_string().unwrap().starts_with(mountpoint.mountpoint) {
             continue;
         }
-        let mounted_request_uri = request.uri.strip_prefix(mountpoint.mountpoint).unwrap();
+        let mounted_request_uri = request.uri.raw_string().unwrap().strip_prefix(mountpoint.mountpoint).unwrap();
         for route in mountpoint.routes {
             if (route.method != request.method)
                 && ((route.method != Method::Get) && (request.method == Method::Head))
@@ -138,7 +141,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
             }
             handled_response = Some((route.handler)(
                 Request {
-                    uri: mounted_request_uri,
+                    uri: UrlEncodeData::from_raw(mounted_request_uri),
                     ..request.clone()
                 },
                 data.clone(),
@@ -165,7 +168,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
     }
 }
 
-fn failure_handler<'a>(status: Status) -> Response<'a> {
+fn failure_handler<'a>(status: Status) -> Response {
     let page_404 = NamedFile::open(PathBuf::from("404.html")).unwrap();
     Response {
         cookies: None,
diff --git a/core/http/src/handling/request/form_utils.rs b/core/http/src/handling/request/form_utils.rs
index 1579c11..b1e3a76 100644
--- a/core/http/src/handling/request/form_utils.rs
+++ b/core/http/src/handling/request/form_utils.rs
@@ -68,7 +68,10 @@ impl Request {
         &'a self,
         keys: &'a [&str],
     ) -> Result<HashMap<&str, Result<&str, ParseFormError>>, ParseFormError> {
-        let data = if let Some(val) = self.uri.split_once('?') {
+        let Some(uri) = self.uri.raw_string() else {
+            return Err(ParseFormError { error: ParseErrors::BadData  });
+        };
+        let data = if let Some(val) = uri.split_once('?') {
             val
         } else {
             return Err(ParseFormError {
@@ -133,6 +136,9 @@ impl Request {
                     let Ok(key) = kvp.0.decode() else {
                         return Err(ParseFormError { error: ParseErrors::BadData });
                     };
+                    let Ok(key) = String::from_utf8(key) else {
+                        return Err(ParseFormError { error: ParseErrors::BadData });
+                    };
                     let Ok(value) = kvp.1.trim_end_matches('\0').decode() else {
                         return Err(ParseFormError { error: ParseErrors::BadData });
                     };
@@ -245,14 +251,17 @@ mod test {
             request::{datatypes::ParseErrors, ParseFormError},
             routes::Data,
         },
-        utils::mime::Mime::{ApplicationXWwwFormUrlencoded, MultipartFormData},
+        utils::{
+            mime::Mime::{ApplicationXWwwFormUrlencoded, MultipartFormData},
+            urlencoded::UrlEncodeData,
+        },
     };
 
     use super::Request;
     #[test]
     fn try_get_test() {
         let request = Request {
-            uri: "/form?name=Name&age=Age",
+            uri: UrlEncodeData::from_encoded("/form?name=Name&age=Age").unwrap(),
             headers: vec![],
             method: Method::Get,
             cookies: None,
@@ -263,7 +272,7 @@ mod test {
         assert_eq!(&"Age", right.get("age").unwrap().as_ref().unwrap());
 
         let wrong_request = Request {
-            uri: "/form",
+            uri: UrlEncodeData::from_encoded("/form").unwrap(),
             ..request.clone()
         };
         assert_eq!(
@@ -274,7 +283,7 @@ mod test {
         );
 
         let bad_data = Request {
-            uri: "/form?age=",
+            uri: UrlEncodeData::from_encoded("/form?age=").unwrap(),
             ..request.clone()
         };
         let wrong = bad_data.get_get_form_keys(&["name", "age"]).unwrap();
@@ -290,7 +299,7 @@ mod test {
     #[test]
     fn try_post_text() {
         let req = Request {
-            uri: "",
+            uri: UrlEncodeData::from_encoded("").unwrap(),
             headers: vec!["Content-Type: application/x-www-form-urlencoded".to_string()],
             method: Method::Post,
             cookies: None,
@@ -310,7 +319,7 @@ mod test {
             map.get("message1").unwrap().as_ref().unwrap()
         );
         let req = Request {
-            uri: "",
+            uri: UrlEncodeData::from_encoded("").unwrap(),
             headers: vec!["Content-Type: multipart/form-data; boundary=\"boundary\"".to_string()],
             method: Method::Post,
             cookies: None,
diff --git a/core/http/src/handling/response/cookie_management/cookie.rs b/core/http/src/handling/response/cookie_management/cookie.rs
index 4e072eb..e96f825 100644
--- a/core/http/src/handling/response/cookie_management/cookie.rs
+++ b/core/http/src/handling/response/cookie_management/cookie.rs
@@ -1,24 +1,24 @@
 use std::time::Duration;
 
-pub struct Cookie<'a> {
+pub struct Cookie {
     /// Storage for the cookie string. Only used if this structure was derived
     /// from a string that was subsequently parsed.
-    pub(crate) cookie_string: Option<&'a str>,
-    pub(crate) name: &'a str,
-    pub(crate) value: &'a str,
+    pub(crate) cookie_string: Option<String>,
+    pub(crate) name: String,
+    pub(crate) value: String,
     // expires: Option<Tm>,
     pub(crate) max_age: Option<Duration>,
     /// The cookie's domain, if any.
-    pub(crate) domain: Option<&'a str>,
+    pub(crate) domain: Option<String>,
     /// The cookie's path domain, if any.
-    pub(crate) path: Option<&'a str>,
+    pub(crate) path: Option<String>,
     /// Whether this cookie was marked Secure.
     pub(crate) secure: Option<bool>,
     /// Whether this cookie was marked HttpOnly.
     pub(crate) http_only: Option<bool>,
     /// The draft `SameSite` attribute.
     pub(crate) same_site: Option<SameSite>,
-    pub(crate) expires: Option<&'a str>,
+    pub(crate) expires: Option<String>,
     pub(crate) partitioned: Option<bool>,
 }
 
@@ -39,7 +39,7 @@ impl std::fmt::Display for SameSite {
     }
 }
 
-impl std::fmt::Display for Cookie<'_> {
+impl std::fmt::Display for Cookie {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         todo!()
     }
diff --git a/core/http/src/handling/response/cookie_management/cookie_builder.rs b/core/http/src/handling/response/cookie_management/cookie_builder.rs
index 431160a..e71eb44 100644
--- a/core/http/src/handling/response/cookie_management/cookie_builder.rs
+++ b/core/http/src/handling/response/cookie_management/cookie_builder.rs
@@ -2,17 +2,17 @@ use std::time::Duration;
 
 use super::{Cookie, SameSite};
 
-pub struct CookieBuilder<'a> {
-    inner: Cookie<'a>,
+pub struct CookieBuilder {
+    inner: Cookie,
 }
 
-impl<'a> CookieBuilder<'a> {
-    pub fn build(name: &'a str, value: &'a str) -> Self {
+impl CookieBuilder {
+    pub fn build(name: &str, value: &str) -> Self {
         CookieBuilder {
             inner: Cookie {
                 cookie_string: None,
-                name,
-                value,
+                name: name.to_owned(),
+                value: value.to_owned(),
                 max_age: None,
                 domain: None,
                 path: None,
@@ -24,19 +24,19 @@ impl<'a> CookieBuilder<'a> {
             },
         }
     }
-    pub fn finish(self) -> Cookie<'a> {
+    pub fn finish(self) -> Cookie {
         self.inner
     }
     pub fn max_age(mut self, duration: Duration) -> Self {
         self.inner.max_age = Some(duration);
         self
     }
-    pub fn domain(mut self, domain: &'a str) -> Self {
-        self.inner.domain = Some(domain);
+    pub fn domain(mut self, domain: &str) -> Self {
+        self.inner.domain = Some(domain.to_owned());
         self
     }
-    pub fn path(mut self, path: &'a str) -> Self {
-        self.inner.path = Some(path);
+    pub fn path(mut self, path: &str) -> Self {
+        self.inner.path = Some(path.to_owned());
         self
     }
     pub fn secure(mut self, secure: bool) -> Self {
@@ -51,20 +51,20 @@ impl<'a> CookieBuilder<'a> {
         self.inner.same_site = Some(same_site);
         self
     }
-    pub fn expires(mut self, expire: &'a str) -> Self {
-        self.inner.expires = Some(expire);
+    pub fn expires(mut self, expire: &str) -> Self {
+        self.inner.expires = Some(expire.to_owned());
         self
     }
     pub fn partitioned(mut self, partitioned: bool) -> Self {
         self.inner.partitioned = Some(partitioned);
         self
     }
-    pub fn name(mut self, name: &'a str) -> Self {
-        self.inner.name = name;
+    pub fn name(mut self, name: &str) -> Self {
+        self.inner.name = name.to_owned();
         self
     }
-    pub fn value(mut self, value: &'a str) -> Self {
-        self.inner.value = value;
+    pub fn value(mut self, value: &str) -> Self {
+        self.inner.value = value.to_owned();
         self
     }
 }
diff --git a/core/http/src/handling/response/datatypes.rs b/core/http/src/handling/response/datatypes.rs
index c174a5d..7800deb 100644
--- a/core/http/src/handling/response/datatypes.rs
+++ b/core/http/src/handling/response/datatypes.rs
@@ -9,9 +9,9 @@ pub enum Outcome<S, E, F> {
     Forward(F),
 }
 
-pub struct Response<'a> {
+pub struct Response {
     pub headers: HeaderMap,
-    pub cookies: Option<Cookie<'a>>,
+    pub cookies: Option<Cookie>,
     pub status: Option<Status>,
     pub body: Box<dyn ResponseBody>,
 }
diff --git a/core/http/src/handling/response/response.rs b/core/http/src/handling/response/response.rs
index 3284d02..23d2b09 100644
--- a/core/http/src/handling/response/response.rs
+++ b/core/http/src/handling/response/response.rs
@@ -6,7 +6,7 @@ use crate::handling::{methods::Method, request::Request, response::Status};
 
 use super::Response;
 
-impl Response<'_> {
+impl Response<> {
     pub fn build(self, request: Option<Request>) -> Vec<u8> {
         let compiled_headers = format!(
             "HTTP/1.1 {}\r\nContent-Length: {}\r\nContent-Type: {}\r\n",
diff --git a/core/http/src/utils/urlencoded/datatypes.rs b/core/http/src/utils/urlencoded/datatypes.rs
index 97dc0a9..6829e6b 100644
--- a/core/http/src/utils/urlencoded/datatypes.rs
+++ b/core/http/src/utils/urlencoded/datatypes.rs
@@ -1,5 +1,3 @@
-use std::{borrow::Cow, string::FromUtf8Error};
-
 use crate::utils::urlencoded::endecode::EnCodable;
 
 use super::endecode::DeCodable;
@@ -12,12 +10,12 @@ pub struct UrlEncodeData {
 }
 
 impl UrlEncodeData {
-    pub fn from_raw<T: AsRef<[u8]>>(raw: T) -> Result<Self, FromUtf8Error> {
-        Ok(Self {
+    pub fn from_raw<T: AsRef<[u8]>>(raw: T) -> Self {
+        Self {
             raw: raw.as_ref().to_owned(),
             encoded: raw.as_ref().encode(),
             raw_string: String::from_utf8(raw.as_ref().into()).ok(),
-        })
+        }
     }
     pub fn from_encoded(encoded: &str) -> Result<Self, ()> {
         Ok(Self {
diff --git a/core/http/src/utils/urlencoded/endecode.rs b/core/http/src/utils/urlencoded/endecode.rs
index 83e2261..389eb28 100644
--- a/core/http/src/utils/urlencoded/endecode.rs
+++ b/core/http/src/utils/urlencoded/endecode.rs
@@ -40,7 +40,7 @@ impl DeCodable for &str {
                 result.extend_from_slice(i.as_bytes());
                 continue;
             }
-            let Ok(char) = u8::from_str_radix(i[0..2].as_ref(), BASE16_HEXA_DECIMAL.into()) else {
+            let Ok(char) = u8::from_str_radix(i[0..=1].as_ref(), BASE16_HEXA_DECIMAL.into()) else {
                     return Err(());
             };
             result.push(char);
@@ -84,5 +84,9 @@ mod test {
             Err(()),
             "Darius%2iis%20the%20biggest%20genius%2FGenie%2FHuman%20extraordin%C3%A4ire".decode()
         );
+        assert_eq!(
+            "hi?asdf=sadf%%&jkl=s",
+            String::from_utf8("hi?asdf=sadf%25%25&jkl=s".decode().unwrap()).unwrap()
+        )
     }
 }
diff --git a/site/src/main.rs b/site/src/main.rs
index f677a34..22e7900 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -20,7 +20,7 @@ fn hashmap_to_string(map: &HashMap<&str, Result<&str, ParseFormError>>) -> Strin
     result
 }
 
-fn handle_static_hi(request: Request<'_>, data: Data) -> Outcome<Response, Status, Data> {
+fn handle_static_hi(request: Request<>, data: Data) -> Outcome<Response, Status, Data> {
     let keys = if let Ok(keys) = request.get_get_form_keys(&["asdf", "jkl"]) {
         keys
     } else {
@@ -36,8 +36,8 @@ fn handle_static_hi(request: Request<'_>, data: Data) -> Outcome<Response, Statu
     // Outcome::Forward(data)
 }
 
-fn handler(request: Request<'_>, _data: Data) -> Outcome<Response, Status, Data> {
-    let response = fileserver(request.uri.strip_prefix("static/").unwrap());
+fn handler(request: Request<>, _data: Data) -> Outcome<Response, Status, Data> {
+    let response = fileserver(request.uri.raw_string().unwrap().strip_prefix("static/").unwrap());
     let response = match response {
         Ok(dat) => Response {
             headers: vec![],
-- 
GitLab


From 02b280583dcbe74fb07d8ae0c844260d814d9bc5 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Mon, 10 Jul 2023 12:27:11 +0200
Subject: [PATCH 51/65] Add Doc for ResponseBody trait end correct Doc for
 request_cookies and request_form_utils

---
 core/http/src/handling/request/datatypes.rs   |  2 +-
 core/http/src/handling/request/form_utils.rs  | 12 +++++-----
 .../http/src/handling/request/request_mime.rs |  6 ++---
 core/http/src/handling/response/traits.rs     | 22 +++++++++++++++++++
 4 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/core/http/src/handling/request/datatypes.rs b/core/http/src/handling/request/datatypes.rs
index 6d37b1f..e8b0303 100644
--- a/core/http/src/handling/request/datatypes.rs
+++ b/core/http/src/handling/request/datatypes.rs
@@ -1,7 +1,7 @@
 use std::{collections::HashMap, error::Error, fmt::Display};
 
 use crate::{
-    handling::{methods::Method, routes::Uri},
+    handling::methods::Method,
     utils::{mime::Mime, urlencoded::UrlEncodeData},
 };
 
diff --git a/core/http/src/handling/request/form_utils.rs b/core/http/src/handling/request/form_utils.rs
index b1e3a76..7991f4d 100644
--- a/core/http/src/handling/request/form_utils.rs
+++ b/core/http/src/handling/request/form_utils.rs
@@ -20,14 +20,12 @@ impl Request {
     ///
     /// # Examples
     /// ```
-    /// use http::handling::request::Request;
-    /// use http::handling::request::ParseFormError;
-    /// use http::handling::request::ParseErrors;
-    /// use http::handling::methods::Method;
+    /// use http::handling::{request::{Request, ParseFormError, ParseErrors}, methods::Method};
+    /// use http::utils::urlencoded::UrlEncodeData;
     ///
     ///
     /// let request = Request {
-    ///     uri: "/form?name=Name&age=Age",
+    ///     uri: UrlEncodeData::from_encoded("/form?name=Name&age=Age").unwrap(),
     ///     headers: vec![],
     ///     method: Method::Get,
     ///     cookies: None,
@@ -38,7 +36,7 @@ impl Request {
     /// assert_eq!(&"Age", right.get("age").unwrap().as_ref().unwrap());
     ///
     /// let wrong_request = Request {
-    ///     uri: "/form",
+    ///     uri: UrlEncodeData::from_encoded("/form").unwrap(),
     ///     ..request.clone()
     /// };
     /// assert_eq!(
@@ -49,7 +47,7 @@ impl Request {
     /// );
     ///
     /// let bad_data = Request {
-    ///     uri: "/form?age=",
+    ///     uri: UrlEncodeData::from_encoded("/form?age=").unwrap(),
     ///     ..request.clone()
     /// };
     /// let wrong = bad_data.get_get_form_keys(&["name", "age"]).unwrap();
diff --git a/core/http/src/handling/request/request_mime.rs b/core/http/src/handling/request/request_mime.rs
index c37045e..75ad1e5 100644
--- a/core/http/src/handling/request/request_mime.rs
+++ b/core/http/src/handling/request/request_mime.rs
@@ -9,11 +9,11 @@ impl Request {
     /// ```
     /// use http::{
     ///     handling::{methods::Method, request::Request},
-    ///     utils::mime::Mime,
+    ///     utils::{mime::Mime, urlencoded::UrlEncodeData},
     /// };
     ///
     /// let mut request = Request {
-    ///     uri: "thing",
+    ///     uri: UrlEncodeData::from_encoded("thing").unwrap(),
     ///     headers: vec![
     ///         "GET / 23".to_string(),
     ///         "SDF:LKJSD:F".to_string(),
@@ -25,7 +25,7 @@ impl Request {
     ///     mime_type: None,
     /// };
     /// let mut wrong = Request {
-    ///     uri: "thing",
+    ///     uri: UrlEncodeData::from_encoded("thing").unwrap(),
     ///     headers: vec![
     ///         "GET / 23".to_string(),
     ///         "SDF:LKJSD:F".to_string(),
diff --git a/core/http/src/handling/response/traits.rs b/core/http/src/handling/response/traits.rs
index fc7eb09..700c392 100644
--- a/core/http/src/handling/response/traits.rs
+++ b/core/http/src/handling/response/traits.rs
@@ -1,8 +1,30 @@
 use crate::{handling::routes::Body, utils::mime::Mime};
 
 pub trait ResponseBody: Send {
+    /// Get a cloned version of the data as a [Vec<u8>]
+    /// # Ecamples
+    /// ```
+    /// use http::handling::response::ResponseBody;
+    /// let data = "DATA";
+    /// assert_eq!(b"DATA".to_vec(), data.get_data());
+    /// ```
     fn get_data(&self) -> Vec<u8>;
+    /// get the miem type of the data as a [Mime]
+    /// # Examples
+    /// ```
+    /// use http::handling::response::ResponseBody;
+    /// use http::utils::mime::Mime;
+    /// let data = "DATA";
+    /// assert_eq!(Mime::TextPlain, data.get_mime());
+    /// ```
     fn get_mime(&self) -> Mime;
+    /// get the length in bytes of the data as a [usize]
+    /// # Examples
+    /// ```
+    /// use http::handling::response::ResponseBody;
+    /// let data = "DATA";
+    /// assert_eq!(4, data.get_len());
+    /// ```
     fn get_len(&self) -> usize;
 }
 
-- 
GitLab


From 47cf59bdcc14bf8258287a255934b09594d46f70 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Mon, 10 Jul 2023 12:46:37 +0200
Subject: [PATCH 52/65] Add some documentation

---
 core/http/src/handling/response/traits.rs |  2 +-
 core/http/src/handling/routes.rs          | 28 +++++++++++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/core/http/src/handling/response/traits.rs b/core/http/src/handling/response/traits.rs
index 700c392..bc0aed5 100644
--- a/core/http/src/handling/response/traits.rs
+++ b/core/http/src/handling/response/traits.rs
@@ -1,7 +1,7 @@
 use crate::{handling::routes::Body, utils::mime::Mime};
 
 pub trait ResponseBody: Send {
-    /// Get a cloned version of the data as a [Vec<u8>]
+    /// Get a cloned version of the data as a [`Vec<u8>`]
     /// # Ecamples
     /// ```
     /// use http::handling::response::ResponseBody;
diff --git a/core/http/src/handling/routes.rs b/core/http/src/handling/routes.rs
index e4246b8..a31dc80 100644
--- a/core/http/src/handling/routes.rs
+++ b/core/http/src/handling/routes.rs
@@ -16,13 +16,34 @@ pub struct RoutInfo {
     rank: Option<isize>,
 }
 
+/// A struct to define Routes on the Server
 #[derive(Clone, Copy)]
 pub struct Route<'a> {
+    /// An optional name of the route
     pub name: Option<&'static str>,
+    /// The [Method] via which the route is accesable
     pub method: Method,
+    /// The Uri of the route, allows special cases:
+    /// # Examples
+    /// ```
+    /// "/home"; // Only /home
+    /// "/<home>/something";
+    /// // Variable content the users provides this acts for /<anything>/something
+    /// "/<home..>";
+    /// // All Information after this sequence is irrelvent
+    /// // Matches: /a, /a/b/c ...
+    /// ```
     pub uri: Uri<'a>,
+    /// The Handler function for this route, which gets called when the request need the route.
+    /// Inputs to the function are an [Request] and the [Data] which represents the body of the
+    /// [Request]. The Outcome is expected to be an [Outcome], which is a [Response], A [Status] if
+    /// something went wrong and a [Status] page is need or a [Outcome::Forward] of the requests
+    /// [Data] for the next [Route] to take care of.
     pub handler: fn(Request, Data) -> Outcome<Response, Status, Data>,
+    /// The Rank of the Route, dependent on its specificness. so the rank of a uri `"/home"` would be
+    /// ranked high, whereas a uri of `"/<anything..>"` would be ranked the lowest
     pub rank: isize,
+    /// The Specific answer format of the [Route] as a [MediaType]. Optional
     pub format: Option<MediaType>,
 }
 
@@ -38,6 +59,7 @@ impl Route<'_> {
             format: routeinfo.format,
         }
     }
+    /// Matches a [Request] Uri with a [Route] Uri. Respecting special cases like `?` and `<a..>`
     pub fn compare_uri(&self, uri: Uri) -> bool {
         let mut iter_comp_str = uri.split('/');
         for true_str in self.uri.split('/') {
@@ -65,8 +87,11 @@ impl Route<'_> {
 pub type Uri<'a> = &'a str;
 
 #[derive(Debug, Clone)]
+/// A basic Body type for respones
 pub struct Body {
+    /// The Response body
     body: Vec<u8>,
+    /// The Mime Type
     mime_type: Mime,
 }
 
@@ -89,8 +114,11 @@ impl Body {
 }
 
 #[derive(Debug, Clone)]
+/// Data of the Body of a [Request]
 pub struct Data {
+    /// The Data
     pub buffer: Vec<u8>,
+    /// For Split Data if it is complete
     pub is_complete: bool,
 }
 
-- 
GitLab


From 74b8a2fc3415f11b5f8a625b4650ab2cb9541056 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Tue, 11 Jul 2023 14:17:59 +0200
Subject: [PATCH 53/65] Add documentation

---
 core/http/src/handlers/handler.rs             | 17 ++++-
 core/http/src/handling/file_handlers.rs       | 21 ++++++
 core/http/src/handling/methods.rs             |  1 +
 core/http/src/handling/request/datatypes.rs   | 24 ++-----
 .../http/src/handling/request/request_impl.rs |  2 +
 .../response/cookie_management/cookie.rs      | 10 +++
 .../cookie_management/cookie_builder.rs       | 11 ++++
 .../response/cookie_management/mod.rs         |  1 +
 core/http/src/handling/response/datatypes.rs  | 22 +++++++
 core/http/src/handling/response/mod.rs        |  1 +
 core/http/src/handling/response/response.rs   |  5 +-
 core/http/src/handling/response/status.rs     | 66 +++++++++++--------
 core/http/src/handling/response/traits.rs     |  1 +
 core/http/src/handling/routes.rs              | 35 +++++++++-
 core/http/src/setup.rs                        | 12 ++++
 core/http/src/utils/mime/map.rs               |  1 +
 core/http/src/utils/mime/mime_enum.rs         |  2 +
 core/http/src/utils/urlencoded/datatypes.rs   | 13 ++++
 core/http/src/utils/urlencoded/endecode.rs    | 14 +++-
 19 files changed, 208 insertions(+), 51 deletions(-)

diff --git a/core/http/src/handlers/handler.rs b/core/http/src/handlers/handler.rs
index 8b02188..7ffa9e9 100644
--- a/core/http/src/handlers/handler.rs
+++ b/core/http/src/handlers/handler.rs
@@ -14,8 +14,20 @@ use crate::{handling::{
 }, utils::urlencoded::UrlEncodeData};
 use crate::setup::MountPoint;
 
+/// The Maximal size of the Body of an HTTP-Message in bytes
 static MAX_HTTP_MESSAGE_SIZE: u16 = 4196;
 
+/// Function which handles a TCP Connection according to http-Standards by taking in a
+/// [tokio::net::TcpStream] and a [`Vec<MountPoint<'_>>`]. 
+///
+/// Firstly validates the headers and body, Aborts with error messages if it finds faults.
+///
+/// Secondly matches the request with a route in the mountpoint Vector and executes its handler
+/// function. If it fails, checks for another, if nothing is found writes back a
+/// [Status::NotFound]. If the handler function could respond it uses the [Response] of the handler
+///
+/// # Panics
+/// No Panics
 pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint<'_>>) {
     let mut buf_reader = BufReader::new(&mut stream);
     let mut http_request: Vec<String> = Vec::with_capacity(10);
@@ -168,7 +180,8 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin
     }
 }
 
-fn failure_handler<'a>(status: Status) -> Response {
+/// Dumb function that renders a 404 page from any status given. but still writes that status code.
+fn failure_handler(status: Status) -> Response {
     let page_404 = NamedFile::open(PathBuf::from("404.html")).unwrap();
     Response {
         cookies: None,
@@ -178,6 +191,7 @@ fn failure_handler<'a>(status: Status) -> Response {
     }
 }
 
+/// Handler for len_not_defined errors. writes back directly
 async fn len_not_defined(stream: TcpStream, status: Status) -> io::Result<()> {
     let page_411 = NamedFile::open(PathBuf::from("411.html")).unwrap();
     Response {
@@ -191,6 +205,7 @@ async fn len_not_defined(stream: TcpStream, status: Status) -> io::Result<()> {
     Ok(())
 }
 
+/// takes in an io error and writes it back in the server console to the user if writing failed
 fn error_occured_when_writing(e: io::Error) {
     eprintln!("\x1b[31mError {e} occured when trying to write answer to TCP-Stream for Client, aborting\x1b[0m");
 }
diff --git a/core/http/src/handling/file_handlers.rs b/core/http/src/handling/file_handlers.rs
index 7a0b080..2d4d39b 100644
--- a/core/http/src/handling/file_handlers.rs
+++ b/core/http/src/handling/file_handlers.rs
@@ -6,9 +6,14 @@ use crate::{
 };
 
 #[derive(Debug)]
+/// Struct to handle files on the server side.
+/// Validates paths ignores actions like `..`
 pub struct NamedFile {
+    /// The length of the file in bytes, format: [usize]
     pub content_len: usize,
+    /// The Mime Type of the file as a [Mime]
     pub content_type: Mime,
+    /// The content of the file as a [`Vec<u8>`]
     pub content: Vec<u8>,
 }
 
@@ -27,6 +32,17 @@ impl ResponseBody for NamedFile {
 }
 
 impl NamedFile {
+    /// Reads in a file as a [NamedFile]. Ignores seqences like `..`
+    ///
+    /// # Panics
+    ///
+    /// Panics if a [PathBuf] can't be convertet to a [str]
+    ///
+    /// # Errors
+    ///
+    /// Can give a [Status::NotFound] if it can't find the file
+    ///
+    /// This function will return an error if .
     pub fn open(path: PathBuf) -> Result<NamedFile, Status> {
         let path = proove_path(path);
         let data = fs::read(&path);
@@ -44,6 +60,11 @@ impl NamedFile {
     }
 }
 
+/// Validates a path so that seqences like `//` and `..` are omitted
+///
+/// # Panics
+///
+/// Panics if it can't convert a [PathBuf] to a [str]
 fn proove_path(path: PathBuf) -> PathBuf {
     PathBuf::from(
         path.to_str()
diff --git a/core/http/src/handling/methods.rs b/core/http/src/handling/methods.rs
index 5ca6211..a13e498 100644
--- a/core/http/src/handling/methods.rs
+++ b/core/http/src/handling/methods.rs
@@ -1,6 +1,7 @@
 use std::{fmt::Display, str::FromStr};
 
 #[derive(PartialEq, Eq, Clone, Debug, Copy, PartialOrd, Ord)]
+/// All HTTP Methods
 pub enum Method {
     Get,
     Head,
diff --git a/core/http/src/handling/request/datatypes.rs b/core/http/src/handling/request/datatypes.rs
index e8b0303..44f1cf3 100644
--- a/core/http/src/handling/request/datatypes.rs
+++ b/core/http/src/handling/request/datatypes.rs
@@ -5,25 +5,6 @@ use crate::{
     utils::{mime::Mime, urlencoded::UrlEncodeData},
 };
 
-pub trait FromRequest: Send {
-    fn get_data(&self) -> &Self;
-    fn set_data(&mut self, data: &Self);
-    fn append(&mut self, data: &Self);
-}
-
-impl FromRequest for Vec<u8> {
-    fn get_data(&self) -> &Self {
-        self
-    }
-
-    fn set_data(&mut self, data: &Self) {
-        *self = data.to_vec();
-    }
-    fn append(&mut self, data: &Self) {
-        self.extend_from_slice(data);
-    }
-}
-
 type HeaderMap = Vec<String>;
 
 /// A struct to handle Requests
@@ -49,9 +30,13 @@ pub struct Request {
 // }
 
 #[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord)]
+/// Media Types in which a Route can be requested to ansewr, optional for routes
 pub enum MediaType {
+    /// Json Data
     Json,
+    /// Plain Text
     Plain,
+    /// HTML Text
     Html,
 }
 
@@ -62,6 +47,7 @@ pub enum ParseErrors {
 }
 
 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
+/// Errors that Occur when a Form can't be parsed
 pub struct ParseFormError {
     pub error: ParseErrors,
 }
diff --git a/core/http/src/handling/request/request_impl.rs b/core/http/src/handling/request/request_impl.rs
index 2eb6fd0..01d6e44 100644
--- a/core/http/src/handling/request/request_impl.rs
+++ b/core/http/src/handling/request/request_impl.rs
@@ -3,12 +3,14 @@ use crate::handling::methods::Method;
 use super::Request;
 
 impl Request {
+    /// Checks if the request can have a body
     pub fn can_have_body(&self) -> bool {
         matches!(
             self.method,
             Method::Post | Method::Put | Method::Patch | Method::Delete
         )
     }
+    /// Checks if a body is mandatory for the Request
     pub fn mandatory_body(&self) -> bool {
         matches!(self.method, Method::Post | Method::Put | Method::Patch)
     }
diff --git a/core/http/src/handling/response/cookie_management/cookie.rs b/core/http/src/handling/response/cookie_management/cookie.rs
index e96f825..58d2a0d 100644
--- a/core/http/src/handling/response/cookie_management/cookie.rs
+++ b/core/http/src/handling/response/cookie_management/cookie.rs
@@ -1,5 +1,13 @@
 use std::time::Duration;
 
+/// Structure representing a Cookie
+/// # Creating a Cookie:
+/// ```
+/// use http::handling::response::Cookie;
+/// use http::handling::response::CookieBuilder;
+///
+/// let cookie = CookieBuilder::build("name", "value").finish();
+/// ```
 pub struct Cookie {
     /// Storage for the cookie string. Only used if this structure was derived
     /// from a string that was subsequently parsed.
@@ -23,7 +31,9 @@ pub struct Cookie {
 }
 
 #[derive(Debug)]
+/// SameSite Paremeters
 pub enum SameSite {
+    /// Requires Secure
     None,
     Lax,
     Strict,
diff --git a/core/http/src/handling/response/cookie_management/cookie_builder.rs b/core/http/src/handling/response/cookie_management/cookie_builder.rs
index e71eb44..a38f92c 100644
--- a/core/http/src/handling/response/cookie_management/cookie_builder.rs
+++ b/core/http/src/handling/response/cookie_management/cookie_builder.rs
@@ -2,11 +2,22 @@ use std::time::Duration;
 
 use super::{Cookie, SameSite};
 
+/// Builder wrapper for a Cookie
+///
+/// # Example
+/// ```
+/// use http::handling::response::Cookie;
+/// use http::handling::response::CookieBuilder;
+///
+/// let cookie = CookieBuilder::build("name", "value").path("/").finish();
+/// ```
 pub struct CookieBuilder {
+    /// Cookie under the hood
     inner: Cookie,
 }
 
 impl CookieBuilder {
+    /// Builds a basic CookieBuilder from a name and a value
     pub fn build(name: &str, value: &str) -> Self {
         CookieBuilder {
             inner: Cookie {
diff --git a/core/http/src/handling/response/cookie_management/mod.rs b/core/http/src/handling/response/cookie_management/mod.rs
index 06d6b85..50f34ea 100644
--- a/core/http/src/handling/response/cookie_management/mod.rs
+++ b/core/http/src/handling/response/cookie_management/mod.rs
@@ -3,3 +3,4 @@ mod cookie_builder;
 
 pub use cookie::Cookie;
 pub use cookie::SameSite;
+pub use cookie_builder::CookieBuilder;
diff --git a/core/http/src/handling/response/datatypes.rs b/core/http/src/handling/response/datatypes.rs
index 7800deb..9225ced 100644
--- a/core/http/src/handling/response/datatypes.rs
+++ b/core/http/src/handling/response/datatypes.rs
@@ -3,15 +3,37 @@ use super::{Cookie, ResponseBody, Status};
 type HeaderMap = Vec<String>;
 
 #[derive(Debug)]
+/// Enum for the result of a Handling Function, where...
+///
+/// [Outcome::Success] represents that the route
+/// was successful and the Answer is contained in \[S\].
+/// [Outcome::Failure] represents that it was unsuccessful and nobody else is going to be
+/// successful. \[E\] represnts the Error Code.
+/// [Outcome::Forward] represents that some requirements weren't met for a route to be working with
+/// the request so the next one that matches should cover that \[F\] represents the maybe processed
+/// data of the request.
+///
+/// # Example
+/// ```
+/// use http::handling::{response::{Outcome, Response, Status}, routes::Data, request::Request};
+/// fn handler(request: Request, _data: Data) -> Outcome<Response, Status, Data> {
+///     todo!()
+/// }
+/// ```
 pub enum Outcome<S, E, F> {
     Success(S),
     Failure(E),
     Forward(F),
 }
 
+/// Response is a wrapper for http responses.
 pub struct Response {
+    /// the [`Vec<String>`] of headers unrelated to `Content-Type` and `Content-Length`
     pub headers: HeaderMap,
+    /// Optional Cookie in the response
     pub cookies: Option<Cookie>,
+    /// Status code of the response
     pub status: Option<Status>,
+    /// Response body and `Content-Type` and `Content-Length` headers.
     pub body: Box<dyn ResponseBody>,
 }
diff --git a/core/http/src/handling/response/mod.rs b/core/http/src/handling/response/mod.rs
index ede6a42..535eaa8 100644
--- a/core/http/src/handling/response/mod.rs
+++ b/core/http/src/handling/response/mod.rs
@@ -5,6 +5,7 @@ mod status;
 mod traits;
 
 pub use cookie_management::Cookie;
+pub use cookie_management::CookieBuilder;
 pub use cookie_management::SameSite;
 pub use datatypes::Outcome;
 pub use datatypes::Response;
diff --git a/core/http/src/handling/response/response.rs b/core/http/src/handling/response/response.rs
index 23d2b09..62de6e9 100644
--- a/core/http/src/handling/response/response.rs
+++ b/core/http/src/handling/response/response.rs
@@ -6,7 +6,9 @@ use crate::handling::{methods::Method, request::Request, response::Status};
 
 use super::Response;
 
-impl Response<> {
+impl Response {
+    /// Builds a [`Vec<u8>`] valid http response from a [Response] and consumes it. Optionally
+    /// takes in a request for things like [Method::Head]
     pub fn build(self, request: Option<Request>) -> Vec<u8> {
         let compiled_headers = format!(
             "HTTP/1.1 {}\r\nContent-Length: {}\r\nContent-Type: {}\r\n",
@@ -29,6 +31,7 @@ impl Response<> {
         compiled_out.extend_from_slice(&compiled_body);
         compiled_out
     }
+    /// Builds and writes The http-Response, consumes the  [tokio::net::TcpStream] [Request] and [Response]
     pub async fn write(self, mut stream: TcpStream, request: Option<Request>) -> Result<()> {
         let resp = self.build(request);
         stream.write_all(&resp).await?;
diff --git a/core/http/src/handling/response/status.rs b/core/http/src/handling/response/status.rs
index 9f825af..dfc56a5 100644
--- a/core/http/src/handling/response/status.rs
+++ b/core/http/src/handling/response/status.rs
@@ -1,11 +1,14 @@
 use std::fmt::Display;
 
 #[derive(Debug)]
+/// Enum With every http status for complete documentation [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)
 pub enum Status {
     Continue,
     SwitchingProtocols,
-    WebDavProcessing,
-    ExperimentalEarlyHints,
+    /// WebDAV
+    Processing,
+    /// Experimental
+    EarlyHints,
     Ok,
     Created,
     Accepted,
@@ -13,21 +16,26 @@ pub enum Status {
     NoContent,
     ResetContent,
     PartialContent,
-    WebDavMultiStatus,
-    WebDavAlreadyReported,
+    /// WebDAV
+    MultiStatus,
+    /// WebDAV
+    AlreadyReported,
     HttpDataEncodingImUsed,
     MultipleChoices,
     MovedPermanently,
     Found,
     SeeOther,
     NotModfiied,
-    DeprecatedUseProxy,
-    UnusedUnused,
+    /// Deprecated
+    UseProxy,
+    /// Deprecated
+    Unused,
     TemporaryRedirect,
     PermanentRedirect,
     BadRequest,
     Unauthorized,
-    ExperimentalPaymentRequired,
+    /// Experimental
+    PaymentRequired,
     Forbidden,
     NotFound,
     MethodNotAllowed,
@@ -45,10 +53,14 @@ pub enum Status {
     ExpectationFailed,
     ImATeapot,
     MisdirectedRequest,
-    WebDavUnprocessableContent,
-    WebDavLocked,
-    WebDavFailedDependency,
-    ExperimenalTooEarly,
+    /// WebDAV
+    UnprocessableContent,
+    /// WebDAV
+    Locked,
+    /// WebDAV
+    FailedDependency,
+    /// Experimental
+    TooEarly,
     UpgradeRequred,
     PreconditionRequired,
     TooManyRequests,
@@ -61,8 +73,10 @@ pub enum Status {
     GetawayTimeout,
     HttpVersionNotSupported,
     VariantAlsoNegotiates,
-    WebDavInsufficientStorage,
-    WebDavLoopDetected,
+    /// WebDAV
+    InsufficientStorage,
+    /// WebDAV
+    LoopDetected,
     NotExtended,
     NetworkAuthenticationRequired,
 }
@@ -72,8 +86,8 @@ impl Display for Status {
         match self {
             Status::Continue => write!(f, "100 Continue"),
             Status::SwitchingProtocols => write!(f, "101 Switching Protocols"),
-            Status::WebDavProcessing => write!(f, "102 Processing"),
-            Status::ExperimentalEarlyHints => write!(f, "103 Early Hints"),
+            Status::Processing => write!(f, "102 Processing"),
+            Status::EarlyHints => write!(f, "103 Early Hints"),
             Status::Ok => write!(f, "200 OK"),
             Status::Created => write!(f, "201 Created"),
             Status::Accepted => write!(f, "202 Accepted"),
@@ -81,8 +95,8 @@ impl Display for Status {
             Status::NoContent => write!(f, "204 No Content"),
             Status::ResetContent => write!(f, "205 Reset Content"),
             Status::PartialContent => write!(f, "206 Partial Content"),
-            Status::WebDavMultiStatus => write!(f, "207 Mutli-Status"),
-            Status::WebDavAlreadyReported => write!(f, "208 Already Reported"),
+            Status::MultiStatus => write!(f, "207 Mutli-Status"),
+            Status::AlreadyReported => write!(f, "208 Already Reported"),
             Status::HttpDataEncodingImUsed => write!(f, "226 IM Used"),
             Status::MultipleChoices => write!(f, "300 Multiple Choices"),
             Status::MovedPermanently => write!(f, "301 Moved Permanently"),
@@ -91,11 +105,11 @@ impl Display for Status {
             Status::NotModfiied => write!(f, "304 Not Modified"),
             Status::TemporaryRedirect => write!(f, "307 Temporary Redirect"),
             Status::PermanentRedirect => write!(f, "308 Permanent Redirect"),
-            Status::DeprecatedUseProxy => write!(f, "305 Use Proxy"),
-            Status::UnusedUnused => write!(f, "306 unused"),
+            Status::UseProxy => write!(f, "305 Use Proxy"),
+            Status::Unused => write!(f, "306 unused"),
             Status::BadRequest => write!(f, "400 Bad Request"),
             Status::Unauthorized => write!(f, "401 Unauthorized"),
-            Status::ExperimentalPaymentRequired => write!(f, "402 Payment Required"),
+            Status::PaymentRequired => write!(f, "402 Payment Required"),
             Status::Forbidden => write!(f, "403 Forbidden"),
             Status::NotFound => write!(f, "404 Not Found"),
             Status::MethodNotAllowed => write!(f, "405 Method Not Allowed"),
@@ -115,10 +129,10 @@ impl Display for Status {
             Status::ExpectationFailed => write!(f, "417 Expectation Failed"),
             Status::ImATeapot => write!(f, "418 I'm a Teapot"),
             Status::MisdirectedRequest => write!(f, "421 Misdirected Request"),
-            Status::WebDavUnprocessableContent => write!(f, "422 Unprocessable Content"),
-            Status::WebDavLocked => write!(f, "423 Locked"),
-            Status::WebDavFailedDependency => write!(f, "424 Failed Dependency"),
-            Status::ExperimenalTooEarly => write!(f, "425 Too Early"),
+            Status::UnprocessableContent => write!(f, "422 Unprocessable Content"),
+            Status::Locked => write!(f, "423 Locked"),
+            Status::FailedDependency => write!(f, "424 Failed Dependency"),
+            Status::TooEarly => write!(f, "425 Too Early"),
             Status::UpgradeRequred => write!(f, "426 Upgrade Required"),
             Status::PreconditionRequired => write!(f, "428 Precondition Required"),
             Status::TooManyRequests => write!(f, "429 Too Many Requests"),
@@ -135,8 +149,8 @@ impl Display for Status {
             Status::GetawayTimeout => write!(f, "504 Getaway Timeout"),
             Status::HttpVersionNotSupported => write!(f, "505 HTTP Version Not Supported"),
             Status::VariantAlsoNegotiates => write!(f, "506 Variant Also Negotiates"),
-            Status::WebDavInsufficientStorage => write!(f, "507 Insufficient Storage"),
-            Status::WebDavLoopDetected => write!(f, "508 Loop Detected"),
+            Status::InsufficientStorage => write!(f, "507 Insufficient Storage"),
+            Status::LoopDetected => write!(f, "508 Loop Detected"),
             Status::NotExtended => write!(f, "510 Not Extendend"),
             Status::NetworkAuthenticationRequired => {
                 write!(f, "511 Network Authentication Required")
diff --git a/core/http/src/handling/response/traits.rs b/core/http/src/handling/response/traits.rs
index bc0aed5..6e96ddf 100644
--- a/core/http/src/handling/response/traits.rs
+++ b/core/http/src/handling/response/traits.rs
@@ -1,5 +1,6 @@
 use crate::{handling::routes::Body, utils::mime::Mime};
 
+/// Trait for using datatypes as response bodies
 pub trait ResponseBody: Send {
     /// Get a cloned version of the data as a [`Vec<u8>`]
     /// # Ecamples
diff --git a/core/http/src/handling/routes.rs b/core/http/src/handling/routes.rs
index a31dc80..02a81a3 100644
--- a/core/http/src/handling/routes.rs
+++ b/core/http/src/handling/routes.rs
@@ -7,12 +7,34 @@ use crate::{
     utils::mime::Mime,
 };
 
-pub struct RoutInfo {
+/// A RouteBuilder struct
+pub struct RoutBuilder {
+    /// An optional name of the route
     name: Option<&'static str>,
+    /// The [Method] via which the route is accesable
     method: Method,
+    /// The path of the route, allows special cases:
+    /// # Examples
+    /// ```
+    /// "/home"; // Only /home
+    /// "/<home>/something";
+    /// // Variable content the users provides this acts for /<anything>/something
+    /// "/<home..>";
+    /// // All Information after this sequence is irrelvent
+    /// // Matches: /a, /a/b/c ...
+    /// ```
     path: &'static str,
+    /// The Handler function for this route, which gets called when the request need the route.
+    /// Inputs to the function are an [Request] and the [Data] which represents the body of the
+    /// [Request]. The Outcome is expected to be an [Outcome], which is a [Response], A [Status] if
+    /// something went wrong and a [Status] page is need or a [Outcome::Forward] of the requests
+    /// [Data] for the next [Route] to take care of.
     handler: fn(Request, Data) -> Outcome<Response, Status, Data>,
+    /// The Specific answer format of the [Route] as a [MediaType]. Optional
     format: Option<MediaType>,
+    /// The Optional Rank of the Route, dependent on its specificness. so the rank of a uri `"/home"` would be
+    /// ranked high, whereas a uri of `"/<anything..>"` would be ranked the lowest
+    /// If not given generated based on parematers.
     rank: Option<isize>,
 }
 
@@ -48,7 +70,9 @@ pub struct Route<'a> {
 }
 
 impl Route<'_> {
-    pub fn from(routeinfo: RoutInfo) -> Self {
+    /// generates a Route from a Routebuilder
+    //TODO: ranking
+    pub fn from(routeinfo: RoutBuilder) -> Self {
         let rank = routeinfo.rank.unwrap_or(0);
         Route {
             name: routeinfo.name,
@@ -84,6 +108,7 @@ impl Route<'_> {
     }
 }
 
+/// Alias for using a &'a str for Uri
 pub type Uri<'a> = &'a str;
 
 #[derive(Debug, Clone)]
@@ -96,18 +121,23 @@ pub struct Body {
 }
 
 impl Body {
+    /// New body of a Response
     pub fn new(body: Vec<u8>, mime_type: Mime) -> Self {
         Self { body, mime_type }
     }
+    /// Sets the `mime_type` of the Body
     pub fn set_mime_type(&mut self, mime_type: Mime) {
         self.mime_type = mime_type;
     }
+    /// Reassigns the body
     pub fn set_body(&mut self, body: Vec<u8>) {
         self.body = body;
     }
+    /// mime_type of the body
     pub fn mime_type(&self) -> Mime {
         self.mime_type
     }
+    /// cloned body as [`Vec<u8>`]
     pub fn body(&self) -> Vec<u8> {
         self.body.clone()
     }
@@ -123,6 +153,7 @@ pub struct Data {
 }
 
 impl Data {
+    /// Checks if the buffer.oen() is -0
     pub fn is_empty(&self) -> bool {
         self.buffer.len() == 0
     }
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index 1f061c6..31669bb 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -12,17 +12,27 @@ use crate::{
 };
 
 #[derive(Clone)]
+/// Represnts a [MountPoint] that can be mounted in the config
 pub struct MountPoint<'a> {
+    /// The prefix of the [MountPoint]
     pub mountpoint: Uri<'a>,
+    /// All Routes mounted on the [MountPoint]. The Routes are all prefixed by the mountpoints
+    /// mountpoint
     pub routes: Vec<Route<'a>>,
 }
 
+/// A server configuration that is run
 pub struct Config {
+    /// Contains an Optional [`Vec<MountPoint>`]. which contains all [MountPoint]s on the Server.
+    /// Which contain all the [Route]s
     mountpoints: Option<Vec<MountPoint<'static>>>,
+    /// Contains a [tokio::net::TcpListener] that is bound for the server
     address: TcpListener,
 }
 
 impl<'a> Config {
+    /// Utility that checks if the given mointpoint is already taken. takes in the uri of the to be
+    /// mounted mountpoint
     fn check_mountpoint_taken(&self, to_insert: Uri) -> bool {
         if let Some(to_check) = &self.mountpoints {
             for i in to_check.iter() {
@@ -33,6 +43,8 @@ impl<'a> Config {
         };
         false
     }
+    /// mounts a [MountPoint] on the [Config] takes in a blank [MountPoint] and the [Route]s to be
+    /// mounted, mounts them and inserts the new [MountPoint]. Also sorts by rank.
     pub fn mount(mut self, mountpoint: Uri<'static>, mut routes: Vec<Route<'static>>) -> Self {
         if self.check_mountpoint_taken(mountpoint) {
             eprintln!("\x1b[31mTrying to reassign a mountpoint, mountpoint `{mountpoint}` already taken.\x1b[0m");
diff --git a/core/http/src/utils/mime/map.rs b/core/http/src/utils/mime/map.rs
index 7117314..7cb4db2 100644
--- a/core/http/src/utils/mime/map.rs
+++ b/core/http/src/utils/mime/map.rs
@@ -1,5 +1,6 @@
 use super::mime_enum::Mime;
 
+/// Map with the string version of the Mime types and the values being corresponding [Mime]s
 pub static MIME_MAP: phf::Map<&'static str, Mime> = phf::phf_map! {
     "application/1d-interleaved-parityfec" => Mime::Application1dInterleavedParityfec,
     "application/3gpdash-qoe-report+xml" => Mime::Application3gpdashQoeReportXml,
diff --git a/core/http/src/utils/mime/mime_enum.rs b/core/http/src/utils/mime/mime_enum.rs
index 0a6a068..12c63d6 100644
--- a/core/http/src/utils/mime/mime_enum.rs
+++ b/core/http/src/utils/mime/mime_enum.rs
@@ -1,6 +1,7 @@
 use super::map::MIME_MAP;
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
+/// An Enum of all Mime types
 pub enum Mime {
     Application1dInterleavedParityfec,
     Application3gpdashQoeReportXml,
@@ -4074,6 +4075,7 @@ impl std::str::FromStr for Mime {
 }
 
 impl Mime {
+    /// Gets the mime type from filename, defaults to [Mime::TextPlain]
     pub fn from_filename(filename: &str) -> Self {
         match filename.split('.').last() {
             Some(v) => match v {
diff --git a/core/http/src/utils/urlencoded/datatypes.rs b/core/http/src/utils/urlencoded/datatypes.rs
index 6829e6b..cbb24c2 100644
--- a/core/http/src/utils/urlencoded/datatypes.rs
+++ b/core/http/src/utils/urlencoded/datatypes.rs
@@ -3,13 +3,18 @@ use crate::utils::urlencoded::endecode::EnCodable;
 use super::endecode::DeCodable;
 
 #[derive(Clone)]
+/// A way to store UrlEncoded data
 pub struct UrlEncodeData {
+    /// Encoded string
     encoded: String,
+    /// raw data, unencoded
     raw: Vec<u8>,
+    /// raw string if it exists
     raw_string: Option<String>,
 }
 
 impl UrlEncodeData {
+    /// Generates a [UrlEncodeData] from any raw data that can be a slice of [u8]
     pub fn from_raw<T: AsRef<[u8]>>(raw: T) -> Self {
         Self {
             raw: raw.as_ref().to_owned(),
@@ -17,6 +22,11 @@ impl UrlEncodeData {
             raw_string: String::from_utf8(raw.as_ref().into()).ok(),
         }
     }
+    /// Generates a [UrlEncodeData] from a correctly encoded string
+    ///
+    /// # Errors
+    ///
+    /// errors if the encoded data is wrongly encoded -> %<invalid_character>
     pub fn from_encoded(encoded: &str) -> Result<Self, ()> {
         Ok(Self {
             encoded: encoded.to_owned(),
@@ -25,12 +35,15 @@ impl UrlEncodeData {
         })
     }
 
+    /// Gets a reference to the encoded data
     pub fn encoded(&self) -> &str {
         self.encoded.as_ref()
     }
+    /// Get a reference to the raw [u8] slice
     pub fn raw(&self) -> &[u8] {
         self.raw.as_ref()
     }
+    /// Gets an Optional string slice to the raw data
     pub fn raw_string(&self) -> Option<&str> {
         self.raw_string.as_ref().map(|x| x.as_str())
     }
diff --git a/core/http/src/utils/urlencoded/endecode.rs b/core/http/src/utils/urlencoded/endecode.rs
index 389eb28..9fba4cb 100644
--- a/core/http/src/utils/urlencoded/endecode.rs
+++ b/core/http/src/utils/urlencoded/endecode.rs
@@ -1,12 +1,20 @@
-static BASE16_HEXA_DECIMAL: u8 = 16;
-static BASE16_HEXA_DECIMAL_POSSIBLE_VALUE_PER_DIGIT: u8 = 15;
+/// Base of the HexaDecimal Number system
+static BASE16_HEXA_DECIMAL: u8 = 0x10;
+/// Highest possible Value per digit
+static BASE16_HEXA_DECIMAL_POSSIBLE_VALUE_PER_DIGIT: u8 = 0xF;
+/// Bits of a hexa decimal number
 static BASE16_HEXA_DECIMAL_DIGIT_BITS: u8 = 4;
 
 pub trait EnCodable {
+    /// Encodes the give data into a Percent Encoded [String]
     fn encode(&self) -> String;
 }
 
 pub trait DeCodable {
+    /// Decodes the given data into a [`Vec<u8>`]
+    ///
+    /// # Errors
+    /// Errors if the encoding isn't right
     fn decode(&self) -> Result<Vec<u8>, ()>;
 }
 
@@ -50,6 +58,8 @@ impl DeCodable for &str {
     }
 }
 
+/// converts a [u8] digit into the ascii code of its counterpart. The digit shouldn't be bigger
+/// than [BASE16_HEXA_DECIMAL_POSSIBLE_VALUE_PER_DIGIT]
 fn hex_to_digit(digit: u8) -> u8 {
     match digit {
         0..=9 => b'0' + digit,
-- 
GitLab


From e43effce7c049a2de71a224d20948deeb9acb56d Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Wed, 12 Jul 2023 19:20:27 +0200
Subject: [PATCH 54/65] Add Display for cookie. Implement Encode trait for T:
 AsRef<[u8]>

---
 .../response/cookie_management/cookie.rs      | 103 +++++++++++++++++-
 .../cookie_management/cookie_builder.rs       |  28 ++---
 core/http/src/utils/urlencoded/endecode.rs    |   6 +
 3 files changed, 118 insertions(+), 19 deletions(-)

diff --git a/core/http/src/handling/response/cookie_management/cookie.rs b/core/http/src/handling/response/cookie_management/cookie.rs
index 58d2a0d..3005eb3 100644
--- a/core/http/src/handling/response/cookie_management/cookie.rs
+++ b/core/http/src/handling/response/cookie_management/cookie.rs
@@ -1,4 +1,6 @@
-use std::time::Duration;
+use std::{error::Error, str::FromStr, time::Duration};
+
+use crate::handling::response::CookieBuilder;
 
 /// Structure representing a Cookie
 /// # Creating a Cookie:
@@ -21,16 +23,16 @@ pub struct Cookie {
     /// The cookie's path domain, if any.
     pub(crate) path: Option<String>,
     /// Whether this cookie was marked Secure.
-    pub(crate) secure: Option<bool>,
+    pub(crate) secure: bool,
     /// Whether this cookie was marked HttpOnly.
-    pub(crate) http_only: Option<bool>,
+    pub(crate) http_only: bool,
     /// The draft `SameSite` attribute.
     pub(crate) same_site: Option<SameSite>,
     pub(crate) expires: Option<String>,
-    pub(crate) partitioned: Option<bool>,
+    pub(crate) partitioned: bool,
 }
 
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
 /// SameSite Paremeters
 pub enum SameSite {
     /// Requires Secure
@@ -42,7 +44,7 @@ pub enum SameSite {
 impl std::fmt::Display for SameSite {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match self {
-            Self::None => write!(f, "SameSite=None; Secure"),
+            Self::None => write!(f, "SameSite=None"),
             Self::Lax => write!(f, "SameSite=Lax"),
             Self::Strict => write!(f, "SameSite=Strict"),
         }
@@ -51,6 +53,95 @@ impl std::fmt::Display for SameSite {
 
 impl std::fmt::Display for Cookie {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let mut appendix = String::from("");
+        if self.secure {
+            appendix += "; Secure";
+        }
+        if self.http_only {
+            appendix += "; HttpOnly";
+        }
+        if self.partitioned {
+            appendix += "; Partitioned";
+        }
+        if let Some(max_age) = &self.max_age {
+            appendix += &format!("; Max-Age={}", max_age.as_secs());
+        }
+        if let Some(domain) = &self.domain {
+            appendix += &format!("; Domain={}", domain);
+        }
+        if let Some(path) = &self.path {
+            appendix += &format!("; Path={}", path);
+        }
+        if let Some(same_site) = &self.same_site {
+            appendix += &format!("; {}", same_site);
+            if !self.secure && *same_site == SameSite::None {
+                appendix += &format!("; Secure");
+            }
+        }
+        if let Some(expires) = &self.expires {
+            appendix += &format!("; Expires={}", expires)
+        }
+        write!(f, "Set-Cookie: {}={}{}", self.name, self.value, appendix)
+    }
+}
+
+impl Error for ParseCookieError {}
+
+#[derive(Debug)]
+pub struct ParseCookieError {
+    inner: CookieError,
+}
+
+#[derive(Debug, PartialEq, PartialOrd, Eq, Ord)]
+pub enum CookieError {
+    MissingEqual,
+}
+
+impl std::fmt::Display for ParseCookieError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "ParseCookieError {{ error: {:?} }}", self.inner)
+    }
+}
+
+impl FromStr for Cookie {
+    type Err = ParseCookieError;
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
         todo!()
     }
 }
+
+#[cfg(test)]
+mod test {
+    use std::time::Duration;
+
+    use crate::handling::response::CookieBuilder;
+
+    use super::SameSite;
+
+    #[test]
+    fn test_cookie_to_string() {
+        let test_cookie1 = CookieBuilder::build("a", "cookie").finish().to_string();
+        let test_cookie1_res = "Set-Cookie: a=cookie";
+        let test_cookie2 = CookieBuilder::build("a", "secure_cookie")
+            .secure(true)
+            .finish()
+            .to_string();
+        let test_cookie2_res = "Set-Cookie: a=secure_cookie; Secure";
+        let test_cookie3 = CookieBuilder::build("ab", "ss")
+            .max_age(Duration::from_secs(24))
+            .domain("codecraft.com")
+            .path("/")
+            .same_site(SameSite::None)
+            .http_only(true)
+            .partitioned(true)
+            .expires("Monday")
+            .finish()
+            .to_string();
+        let test_cookie3_res = "Set-Cookie: ab=ss; HttpOnly; Partitioned; \
+            Max-Age=24; Domain=codecraft.com; Path=/; SameSite=None; Secure; Expires=Monday";
+
+        assert_eq!(test_cookie1_res, test_cookie1);
+        assert_eq!(test_cookie2_res, test_cookie2);
+        assert_eq!(test_cookie3_res, test_cookie3);
+    }
+}
diff --git a/core/http/src/handling/response/cookie_management/cookie_builder.rs b/core/http/src/handling/response/cookie_management/cookie_builder.rs
index a38f92c..41bdc97 100644
--- a/core/http/src/handling/response/cookie_management/cookie_builder.rs
+++ b/core/http/src/handling/response/cookie_management/cookie_builder.rs
@@ -1,5 +1,7 @@
 use std::time::Duration;
 
+use crate::utils::urlencoded::EnCodable;
+
 use super::{Cookie, SameSite};
 
 /// Builder wrapper for a Cookie
@@ -22,16 +24,16 @@ impl CookieBuilder {
         CookieBuilder {
             inner: Cookie {
                 cookie_string: None,
-                name: name.to_owned(),
-                value: value.to_owned(),
+                name: name.encode(),
+                value: value.encode(),
                 max_age: None,
                 domain: None,
                 path: None,
-                secure: None,
-                http_only: None,
+                secure: false,
+                http_only: false,
                 same_site: None,
                 expires: None,
-                partitioned: None,
+                partitioned: false,
             },
         }
     }
@@ -43,19 +45,19 @@ impl CookieBuilder {
         self
     }
     pub fn domain(mut self, domain: &str) -> Self {
-        self.inner.domain = Some(domain.to_owned());
+        self.inner.domain = Some(domain.encode());
         self
     }
     pub fn path(mut self, path: &str) -> Self {
-        self.inner.path = Some(path.to_owned());
+        self.inner.path = Some(path.encode());
         self
     }
     pub fn secure(mut self, secure: bool) -> Self {
-        self.inner.secure = Some(secure);
+        self.inner.secure = secure;
         self
     }
     pub fn http_only(mut self, http_only: bool) -> Self {
-        self.inner.http_only = Some(http_only);
+        self.inner.http_only = http_only;
         self
     }
     pub fn same_site(mut self, same_site: SameSite) -> Self {
@@ -63,19 +65,19 @@ impl CookieBuilder {
         self
     }
     pub fn expires(mut self, expire: &str) -> Self {
-        self.inner.expires = Some(expire.to_owned());
+        self.inner.expires = Some(expire.encode());
         self
     }
     pub fn partitioned(mut self, partitioned: bool) -> Self {
-        self.inner.partitioned = Some(partitioned);
+        self.inner.partitioned = partitioned;
         self
     }
     pub fn name(mut self, name: &str) -> Self {
-        self.inner.name = name.to_owned();
+        self.inner.name = name.encode();
         self
     }
     pub fn value(mut self, value: &str) -> Self {
-        self.inner.value = value.to_owned();
+        self.inner.value = value.encode();
         self
     }
 }
diff --git a/core/http/src/utils/urlencoded/endecode.rs b/core/http/src/utils/urlencoded/endecode.rs
index 9fba4cb..8dd45d6 100644
--- a/core/http/src/utils/urlencoded/endecode.rs
+++ b/core/http/src/utils/urlencoded/endecode.rs
@@ -18,6 +18,12 @@ pub trait DeCodable {
     fn decode(&self) -> Result<Vec<u8>, ()>;
 }
 
+impl<T: AsRef<[u8]>> EnCodable for T {
+    fn encode(&self) -> String {
+        self.as_ref().encode()
+    }
+}
+
 impl EnCodable for [u8] {
     fn encode(self: &[u8]) -> String {
         let mut result = String::with_capacity(self.len());
-- 
GitLab


From b9320218a6da2a008c13fd8c24a28a349420717e Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Thu, 13 Jul 2023 23:12:32 +0200
Subject: [PATCH 55/65] small performance increase

---
 core/http/src/handling/request/form_utils.rs                | 2 +-
 core/http/src/handling/response/cookie_management/cookie.rs | 2 --
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/core/http/src/handling/request/form_utils.rs b/core/http/src/handling/request/form_utils.rs
index 7991f4d..67ada47 100644
--- a/core/http/src/handling/request/form_utils.rs
+++ b/core/http/src/handling/request/form_utils.rs
@@ -157,7 +157,7 @@ impl Request {
                     .trim_matches('"');
                 let mut temp_bound = "--".to_string();
                 temp_bound.push_str(boundary);
-                let end_boundary = format!("{temp_bound}--\r").as_bytes().to_owned();
+                let end_boundary: Vec<u8> = format!("{temp_bound}--\r").into();
                 temp_bound.push('\r');
                 let boundary = temp_bound.as_bytes();
                 Self::get_multipart_data(data, boundary, &end_boundary, &mut keymap);
diff --git a/core/http/src/handling/response/cookie_management/cookie.rs b/core/http/src/handling/response/cookie_management/cookie.rs
index 3005eb3..bbb5ac3 100644
--- a/core/http/src/handling/response/cookie_management/cookie.rs
+++ b/core/http/src/handling/response/cookie_management/cookie.rs
@@ -1,7 +1,5 @@
 use std::{error::Error, str::FromStr, time::Duration};
 
-use crate::handling::response::CookieBuilder;
-
 /// Structure representing a Cookie
 /// # Creating a Cookie:
 /// ```
-- 
GitLab


From f4d6db30e0bbde2a4ce20f2fc4f4b3fa40cabc6f Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Fri, 14 Jul 2023 23:35:50 +0200
Subject: [PATCH 56/65] Start the from_str implementation of Cookie

---
 .../response/cookie_management/cookie.rs      | 56 +++++++++++++++++--
 .../cookie_management/cookie_builder.rs       |  1 +
 core/http/src/utils/urlencoded/datatypes.rs   |  4 +-
 3 files changed, 53 insertions(+), 8 deletions(-)

diff --git a/core/http/src/handling/response/cookie_management/cookie.rs b/core/http/src/handling/response/cookie_management/cookie.rs
index bbb5ac3..6de43e0 100644
--- a/core/http/src/handling/response/cookie_management/cookie.rs
+++ b/core/http/src/handling/response/cookie_management/cookie.rs
@@ -1,5 +1,7 @@
 use std::{error::Error, str::FromStr, time::Duration};
 
+use crate::{handling::response::CookieBuilder, utils::urlencoded::DeCodable};
+
 /// Structure representing a Cookie
 /// # Creating a Cookie:
 /// ```
@@ -8,6 +10,7 @@ use std::{error::Error, str::FromStr, time::Duration};
 ///
 /// let cookie = CookieBuilder::build("name", "value").finish();
 /// ```
+#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
 pub struct Cookie {
     /// Storage for the cookie string. Only used if this structure was derived
     /// from a string that was subsequently parsed.
@@ -93,6 +96,7 @@ pub struct ParseCookieError {
 #[derive(Debug, PartialEq, PartialOrd, Eq, Ord)]
 pub enum CookieError {
     MissingEqual,
+    InvalidAttribute,
 }
 
 impl std::fmt::Display for ParseCookieError {
@@ -104,7 +108,44 @@ impl std::fmt::Display for ParseCookieError {
 impl FromStr for Cookie {
     type Err = ParseCookieError;
     fn from_str(s: &str) -> Result<Self, Self::Err> {
-        todo!()
+        let mut final_result = CookieBuilder::build("", "");
+        let mut first = true;
+        for part in s.split(';') {
+            let trimmed_part = part.trim();
+            if first {
+                let Some(name_val) = part.split_once('=') else {
+                    return Err(Self::Err { inner: CookieError::MissingEqual  });
+                };
+                unsafe {
+                    final_result = CookieBuilder::build(
+                        &String::from_utf8_unchecked(if let Ok(name) = name_val.0.decode() {
+                            name
+                        } else {
+                            name_val.0.into()
+                        }),
+                        &String::from_utf8_unchecked(if let Ok(value) = name_val.1.decode() {
+                            value
+                        } else {
+                            name_val.1.into()
+                        }),
+                    );
+                }
+                first = false;
+                break;
+            }
+            final_result = match trimmed_part {
+                "Secure" => final_result.secure(true),
+                "HttpOnly" => final_result.http_only(true),
+                "Partitioned" => final_result.partitioned(true),
+                _ => {
+                    return Err(Self::Err {
+                        inner: CookieError::InvalidAttribute,
+                    });
+                }
+            }
+        }
+        println!("{:?}", final_result);
+        Ok(final_result.finish())
     }
 }
 
@@ -112,7 +153,7 @@ impl FromStr for Cookie {
 mod test {
     use std::time::Duration;
 
-    use crate::handling::response::CookieBuilder;
+    use crate::handling::response::{Cookie, CookieBuilder};
 
     use super::SameSite;
 
@@ -133,13 +174,16 @@ mod test {
             .http_only(true)
             .partitioned(true)
             .expires("Monday")
-            .finish()
-            .to_string();
+            .finish();
         let test_cookie3_res = "Set-Cookie: ab=ss; HttpOnly; Partitioned; \
-            Max-Age=24; Domain=codecraft.com; Path=/; SameSite=None; Secure; Expires=Monday";
+            Max-Age=24; Domain=codecraft.com; Path=%2F; SameSite=None; Secure; Expires=Monday";
+
+        let test_cookie4_res = "ab=ss; HttpOnly; Partitioned; \
+            Max-Age=24; Domain=codecraft.com; Path=%2F; SameSite=None; Secure; Expires=Monday";
 
         assert_eq!(test_cookie1_res, test_cookie1);
         assert_eq!(test_cookie2_res, test_cookie2);
-        assert_eq!(test_cookie3_res, test_cookie3);
+        assert_eq!(test_cookie3_res, test_cookie3.to_string());
+        assert_eq!(test_cookie4_res.parse::<Cookie>().unwrap(), test_cookie3);
     }
 }
diff --git a/core/http/src/handling/response/cookie_management/cookie_builder.rs b/core/http/src/handling/response/cookie_management/cookie_builder.rs
index 41bdc97..5a3dac3 100644
--- a/core/http/src/handling/response/cookie_management/cookie_builder.rs
+++ b/core/http/src/handling/response/cookie_management/cookie_builder.rs
@@ -13,6 +13,7 @@ use super::{Cookie, SameSite};
 ///
 /// let cookie = CookieBuilder::build("name", "value").path("/").finish();
 /// ```
+#[derive(Debug)]
 pub struct CookieBuilder {
     /// Cookie under the hood
     inner: Cookie,
diff --git a/core/http/src/utils/urlencoded/datatypes.rs b/core/http/src/utils/urlencoded/datatypes.rs
index cbb24c2..2db1e18 100644
--- a/core/http/src/utils/urlencoded/datatypes.rs
+++ b/core/http/src/utils/urlencoded/datatypes.rs
@@ -18,7 +18,7 @@ impl UrlEncodeData {
     pub fn from_raw<T: AsRef<[u8]>>(raw: T) -> Self {
         Self {
             raw: raw.as_ref().to_owned(),
-            encoded: raw.as_ref().encode(),
+            encoded: raw.encode(),
             raw_string: String::from_utf8(raw.as_ref().into()).ok(),
         }
     }
@@ -45,7 +45,7 @@ impl UrlEncodeData {
     }
     /// Gets an Optional string slice to the raw data
     pub fn raw_string(&self) -> Option<&str> {
-        self.raw_string.as_ref().map(|x| x.as_str())
+        self.raw_string.as_deref()
     }
 }
 
-- 
GitLab


From 15a864bbfdd2d437315b0808da51fb9c6b941fb0 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sat, 15 Jul 2023 22:09:50 +0200
Subject: [PATCH 57/65] Add uri , work on FromStr of cookie

---
 TODO.md                                       |   7 +
 .../response/cookie_management/cookie.rs      |  10 +-
 core/http/src/utils/mod.rs                    |   1 +
 core/http/src/utils/url_utils/datatypes.rs    |  38 ++++
 core/http/src/utils/url_utils/mod.rs          |   7 +
 core/http/src/utils/url_utils/uri.rs          | 183 ++++++++++++++++++
 core/http/src/utils/urlencoded/datatypes.rs   |   8 +-
 core/http/src/utils/urlencoded/mod.rs         |   3 +-
 8 files changed, 245 insertions(+), 12 deletions(-)
 create mode 100644 core/http/src/utils/url_utils/datatypes.rs
 create mode 100644 core/http/src/utils/url_utils/mod.rs
 create mode 100644 core/http/src/utils/url_utils/uri.rs

diff --git a/TODO.md b/TODO.md
index c15fe15..7d14bdd 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,3 +1,5 @@
+GOOD HABITS
+
 1. If you collect an iterator which you don't index in, you don't need to collect it
 2. avoid temporary hashmaps
 3. rewrite POST request stuff TICK
@@ -6,4 +8,9 @@
 6. Remove unwraps
 7. Reusable allocations
 
+TODO:
+
+1. Uri structs everywhere
+2. Cookie From String fix
+
 API design 3. No decisions for the caller
diff --git a/core/http/src/handling/response/cookie_management/cookie.rs b/core/http/src/handling/response/cookie_management/cookie.rs
index 6de43e0..4bd4d2e 100644
--- a/core/http/src/handling/response/cookie_management/cookie.rs
+++ b/core/http/src/handling/response/cookie_management/cookie.rs
@@ -153,7 +153,7 @@ impl FromStr for Cookie {
 mod test {
     use std::time::Duration;
 
-    use crate::handling::response::{Cookie, CookieBuilder};
+    use crate::handling::response::CookieBuilder;
 
     use super::SameSite;
 
@@ -176,14 +176,12 @@ mod test {
             .expires("Monday")
             .finish();
         let test_cookie3_res = "Set-Cookie: ab=ss; HttpOnly; Partitioned; \
-            Max-Age=24; Domain=codecraft.com; Path=%2F; SameSite=None; Secure; Expires=Monday";
-
-        let test_cookie4_res = "ab=ss; HttpOnly; Partitioned; \
-            Max-Age=24; Domain=codecraft.com; Path=%2F; SameSite=None; Secure; Expires=Monday";
+            Max-Age=24; Domain=codecraft.com; Path=/; SameSite=None; Secure; Expires=Monday";
 
         assert_eq!(test_cookie1_res, test_cookie1);
         assert_eq!(test_cookie2_res, test_cookie2);
         assert_eq!(test_cookie3_res, test_cookie3.to_string());
-        assert_eq!(test_cookie4_res.parse::<Cookie>().unwrap(), test_cookie3);
     }
+    #[test]
+    fn cooki_from_string() {}
 }
diff --git a/core/http/src/utils/mod.rs b/core/http/src/utils/mod.rs
index 98498d0..6f54242 100644
--- a/core/http/src/utils/mod.rs
+++ b/core/http/src/utils/mod.rs
@@ -1,2 +1,3 @@
 pub mod mime;
+pub mod url_utils;
 pub mod urlencoded;
diff --git a/core/http/src/utils/url_utils/datatypes.rs b/core/http/src/utils/url_utils/datatypes.rs
new file mode 100644
index 0000000..3c40037
--- /dev/null
+++ b/core/http/src/utils/url_utils/datatypes.rs
@@ -0,0 +1,38 @@
+use std::error;
+
+use crate::utils::urlencoded::UrlEncodeData;
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
+pub struct Uri {
+    pub(super) parts: Vec<UrlEncodeData>,
+}
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct RawUri {
+    pub(super) raw_string: String,
+    pub(super) infinte_end: bool,
+    pub(super) parts: Vec<RawUriElement>,
+}
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub enum RawUriElement {
+    Variable,
+    Name(UrlEncodeData),
+}
+
+#[derive(Debug)]
+pub enum UriError {
+    InvalidUriEncoding,
+}
+
+#[derive(Debug)]
+pub struct ParseUriError {
+    error: UriError,
+}
+impl std::fmt::Display for ParseUriError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl error::Error for ParseUriError {}
diff --git a/core/http/src/utils/url_utils/mod.rs b/core/http/src/utils/url_utils/mod.rs
new file mode 100644
index 0000000..7a6061d
--- /dev/null
+++ b/core/http/src/utils/url_utils/mod.rs
@@ -0,0 +1,7 @@
+mod datatypes;
+mod uri;
+pub use datatypes::ParseUriError;
+pub use datatypes::RawUri;
+pub use datatypes::RawUriElement;
+pub use datatypes::Uri;
+pub use datatypes::UriError;
diff --git a/core/http/src/utils/url_utils/uri.rs b/core/http/src/utils/url_utils/uri.rs
new file mode 100644
index 0000000..b9e6939
--- /dev/null
+++ b/core/http/src/utils/url_utils/uri.rs
@@ -0,0 +1,183 @@
+use std::str::FromStr;
+
+use crate::utils::{url_utils::datatypes::RawUriElement, urlencoded::UrlEncodeData};
+
+use super::datatypes::{ParseUriError, RawUri, Uri, UriError};
+
+impl Uri {
+    pub fn new(parts: Vec<&str>) -> Self {
+        Self {
+            parts: parts
+                .into_iter()
+                .map(|part| UrlEncodeData::from_raw(part))
+                .collect(),
+        }
+    }
+}
+
+impl RawUri {
+    pub fn new(parts: Vec<&str>) -> Self {
+        let mut result = Self {
+            infinte_end: false,
+            parts: Vec::with_capacity(parts.len()),
+            raw_string: "/".to_owned() + &parts.join("/"),
+        };
+        for part in parts {
+            if part.starts_with("<") && part.ends_with("..>") {
+                result.infinte_end = true;
+                break;
+            }
+            if part.starts_with("<") && part.ends_with(">") {
+                result.parts.push(RawUriElement::Variable);
+                continue;
+            }
+            result
+                .parts
+                .push(RawUriElement::Name(UrlEncodeData::from_raw(part)))
+        }
+        result
+    }
+    pub fn compare_uri(self, uri: Uri) -> bool {
+        let mut iter_comp = uri.parts.iter();
+        let mut counter = 0;
+        for element in self.parts.iter() {
+            counter += 1;
+            let Some(compare_element) = iter_comp.next() else {
+                return false;
+            };
+
+            if *element == RawUriElement::Variable {
+                continue;
+            }
+            if let RawUriElement::Name(name) = element {
+                if name.encoded() != compare_element.encoded() {
+                    return false;
+                }
+            } else {
+                return false;
+            }
+        }
+        if counter > self.parts.len() && !self.infinte_end {
+            return false;
+        }
+        true
+    }
+}
+
+impl std::fmt::Display for RawUri {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", self.raw_string)
+    }
+}
+
+impl std::fmt::Display for Uri {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let url = self
+            .parts
+            .iter()
+            .map(|part| part.encoded())
+            .collect::<Vec<_>>();
+        write!(f, "/{}", url.join("/"))
+    }
+}
+
+impl FromStr for Uri {
+    type Err = ParseUriError;
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let split = s.split('/');
+        let mut result = Vec::new();
+        for sub in split {
+            if sub.is_empty() {
+                continue;
+            }
+            result.push(if let Ok(coded) = UrlEncodeData::from_encoded(sub) {
+                coded
+            } else {
+                UrlEncodeData::from_raw(sub)
+            });
+        }
+        Ok(Self { parts: result })
+    }
+}
+
+impl FromStr for RawUri {
+    type Err = UriError;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let parts = s.split('/').collect::<Vec<&str>>();
+        let mut result = Self {
+            infinte_end: false,
+            parts: Vec::new(),
+            raw_string: parts.join("/"),
+        };
+        for part in parts {
+            if part.is_empty() {
+                continue;
+            }
+            if part.starts_with("<") && part.ends_with("..>") {
+                result.infinte_end = true;
+                break;
+            }
+            if part.starts_with("<") && part.ends_with(">") {
+                result.parts.push(RawUriElement::Variable);
+                continue;
+            }
+            result
+                .parts
+                .push(RawUriElement::Name(UrlEncodeData::from_raw(part)))
+        }
+        Ok(result)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use crate::utils::{
+        url_utils::{
+            datatypes::{RawUri, RawUriElement},
+            Uri,
+        },
+        urlencoded::UrlEncodeData,
+    };
+
+    #[test]
+    fn uri_to_string() {
+        assert_eq!("/a/%20", Uri::new(vec!["a", " "]).to_string());
+    }
+
+    #[test]
+    fn uri_from_string() {
+        assert_eq!(Uri::new(vec!["a", " "]), "/a/%20".parse().unwrap())
+    }
+
+    #[test]
+    fn raw_uri_from_string() {
+        assert_eq!(
+            RawUri {
+                raw_string: "/<name>/a/<f..>".to_owned(),
+                infinte_end: true,
+                parts: vec![
+                    RawUriElement::Variable,
+                    RawUriElement::Name(UrlEncodeData::from_raw("a")),
+                ]
+            },
+            "/<name>/a/<f..>".parse().unwrap()
+        );
+    }
+
+    #[test]
+    fn raw_uri_to_string() {
+        assert_eq!(
+            "/<name>/a/<f..>",
+            RawUri {
+                raw_string: "/<name>/a/<f..>".to_owned(),
+                infinte_end: true,
+                parts: vec![
+                    RawUriElement::Variable,
+                    RawUriElement::Name(UrlEncodeData::from_raw("a")),
+                ]
+            }
+            .to_string()
+        )
+    }
+}
diff --git a/core/http/src/utils/urlencoded/datatypes.rs b/core/http/src/utils/urlencoded/datatypes.rs
index 2db1e18..d48e02b 100644
--- a/core/http/src/utils/urlencoded/datatypes.rs
+++ b/core/http/src/utils/urlencoded/datatypes.rs
@@ -2,15 +2,15 @@ use crate::utils::urlencoded::endecode::EnCodable;
 
 use super::endecode::DeCodable;
 
-#[derive(Clone)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
 /// A way to store UrlEncoded data
 pub struct UrlEncodeData {
     /// Encoded string
-    encoded: String,
+    pub(crate) encoded: String,
     /// raw data, unencoded
-    raw: Vec<u8>,
+    pub(crate) raw: Vec<u8>,
     /// raw string if it exists
-    raw_string: Option<String>,
+    pub(crate) raw_string: Option<String>,
 }
 
 impl UrlEncodeData {
diff --git a/core/http/src/utils/urlencoded/mod.rs b/core/http/src/utils/urlencoded/mod.rs
index 6511cfc..3145200 100644
--- a/core/http/src/utils/urlencoded/mod.rs
+++ b/core/http/src/utils/urlencoded/mod.rs
@@ -1,5 +1,4 @@
 mod datatypes;
 mod endecode;
 pub use datatypes::UrlEncodeData;
-pub use endecode::DeCodable;
-pub use endecode::EnCodable;
+pub use endecode::{DeCodable, EnCodable};
-- 
GitLab


From e748f9785a2566621ea520bb3fcc89214b22bd31 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Mon, 17 Jul 2023 23:13:23 +0200
Subject: [PATCH 58/65] FromStr for Cookie, Change Cookie Path to be Uri

- Finish implementing FromStr trait for Cookie
- Change the path variable of the Cookie struct to be a Uri
- Update docs of CookieBuilder to compile
---
 .../response/cookie_management/cookie.rs      | 176 +++++++++++++-----
 .../cookie_management/cookie_builder.rs       |  11 +-
 .../response/cookie_management/error_types.rs |  43 +++++
 .../response/cookie_management/mod.rs         |   5 +
 core/http/src/utils/url_utils/datatypes.rs    |   4 +-
 5 files changed, 188 insertions(+), 51 deletions(-)
 create mode 100644 core/http/src/handling/response/cookie_management/error_types.rs

diff --git a/core/http/src/handling/response/cookie_management/cookie.rs b/core/http/src/handling/response/cookie_management/cookie.rs
index 4bd4d2e..8234ab4 100644
--- a/core/http/src/handling/response/cookie_management/cookie.rs
+++ b/core/http/src/handling/response/cookie_management/cookie.rs
@@ -1,6 +1,17 @@
-use std::{error::Error, str::FromStr, time::Duration};
+use std::{collections::HashMap, str::FromStr, time::Duration};
 
-use crate::{handling::response::CookieBuilder, utils::urlencoded::DeCodable};
+use crate::{
+    handling::response::{cookie_management::error_types::CookieError, CookieBuilder},
+    utils::{url_utils::Uri, urlencoded::DeCodable},
+};
+
+macro_rules! update_map {
+    ($map:expr, $key:expr) => {
+        *$map.get_mut($key).unwrap() = true;
+    };
+}
+
+use super::error_types::{ParseCookieError, ParseSameSiteError, SameSiteError};
 
 /// Structure representing a Cookie
 /// # Creating a Cookie:
@@ -17,20 +28,20 @@ pub struct Cookie {
     pub(crate) cookie_string: Option<String>,
     pub(crate) name: String,
     pub(crate) value: String,
-    // expires: Option<Tm>,
-    pub(crate) max_age: Option<Duration>,
-    /// The cookie's domain, if any.
-    pub(crate) domain: Option<String>,
-    /// The cookie's path domain, if any.
-    pub(crate) path: Option<String>,
     /// Whether this cookie was marked Secure.
     pub(crate) secure: bool,
     /// Whether this cookie was marked HttpOnly.
     pub(crate) http_only: bool,
+    pub(crate) partitioned: bool,
+    // expires: Option<Tm>,
+    pub(crate) max_age: Option<Duration>,
     /// The draft `SameSite` attribute.
     pub(crate) same_site: Option<SameSite>,
+    /// The cookie's domain, if any.
+    pub(crate) domain: Option<String>,
+    /// The cookie's path domain, if any.
+    pub(crate) path: Option<Uri>,
     pub(crate) expires: Option<String>,
-    pub(crate) partitioned: bool,
 }
 
 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
@@ -52,6 +63,21 @@ impl std::fmt::Display for SameSite {
     }
 }
 
+impl FromStr for SameSite {
+    type Err = ParseSameSiteError;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "None" => Ok(SameSite::None),
+            "Lax" => Ok(SameSite::Lax),
+            "Strict" => Ok(SameSite::Strict),
+            _ => Err(Self::Err {
+                inner: SameSiteError::NotAValidVariant,
+            }),
+        }
+    }
+}
+
 impl std::fmt::Display for Cookie {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         let mut appendix = String::from("");
@@ -86,31 +112,24 @@ impl std::fmt::Display for Cookie {
     }
 }
 
-impl Error for ParseCookieError {}
-
-#[derive(Debug)]
-pub struct ParseCookieError {
-    inner: CookieError,
-}
-
-#[derive(Debug, PartialEq, PartialOrd, Eq, Ord)]
-pub enum CookieError {
-    MissingEqual,
-    InvalidAttribute,
-}
-
-impl std::fmt::Display for ParseCookieError {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "ParseCookieError {{ error: {:?} }}", self.inner)
-    }
-}
-
 impl FromStr for Cookie {
     type Err = ParseCookieError;
     fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let mut map = HashMap::with_capacity(8);
+        map.insert("Partitioned", false);
+        map.insert("HttpOnly", false);
+        map.insert("Secure", false);
+        map.insert("SameSite", false);
+        map.insert("Max-Age", false);
+        map.insert("Domain", false);
+        map.insert("Path", false);
+        map.insert("Expires", false);
         let mut final_result = CookieBuilder::build("", "");
         let mut first = true;
-        for part in s.split(';') {
+        let stripped = s.strip_prefix("Set-Cookie: ").ok_or(Self::Err {
+            inner: CookieError::NoSetCookieHeader,
+        })?;
+        for part in stripped.split(';') {
             let trimmed_part = part.trim();
             if first {
                 let Some(name_val) = part.split_once('=') else {
@@ -131,20 +150,74 @@ impl FromStr for Cookie {
                     );
                 }
                 first = false;
-                break;
+                continue;
             }
-            final_result = match trimmed_part {
-                "Secure" => final_result.secure(true),
-                "HttpOnly" => final_result.http_only(true),
-                "Partitioned" => final_result.partitioned(true),
-                _ => {
-                    return Err(Self::Err {
-                        inner: CookieError::InvalidAttribute,
-                    });
-                }
+            if !map.get("Max-Age").unwrap() && trimmed_part.starts_with("Max-Age=") {
+                final_result = final_result.max_age(Duration::from_secs(
+                    trimmed_part
+                        .strip_prefix("Max-Age=")
+                        .unwrap()
+                        .parse()
+                        .map_err(|_| Self::Err {
+                            inner: CookieError::InvalidMaxAge,
+                        })?,
+                ));
+                update_map!(map, "Max-Age");
+                continue;
+            }
+            if !map.get("Expires").unwrap() && trimmed_part.starts_with("Expires=") {
+                final_result = final_result.expires(trimmed_part.strip_prefix("Expires=").unwrap());
+                update_map!(map, "Expires");
+                continue;
+            }
+            if !map.get("HttpOnly").unwrap() && trimmed_part == "HttpOnly" {
+                final_result = final_result.http_only(true);
+                update_map!(map, "HttpOnly");
+                continue;
+            }
+            if !map.get("SameSite").unwrap() && trimmed_part.starts_with("SameSite=") {
+                final_result = final_result.same_site(
+                    trimmed_part
+                        .strip_prefix("SameSite=")
+                        .unwrap()
+                        .parse::<SameSite>()
+                        .map_err(|err| Self::Err {
+                            inner: CookieError::InvilidSameSite(err.inner),
+                        })?,
+                );
+                update_map!(map, "SameSite");
+                continue;
+            }
+            if !map.get("Path").unwrap() && trimmed_part.starts_with("Path=") {
+                final_result = final_result.path(
+                    trimmed_part
+                        .strip_prefix("Path=")
+                        .unwrap()
+                        .parse::<Uri>()
+                        .map_err(|err| Self::Err {
+                            inner: CookieError::PathError(err.error),
+                        })?,
+                );
+                update_map!(map, "Path");
+                continue;
+            }
+            if !map.get("Domain").unwrap() && trimmed_part.starts_with("Domain=") {
+                final_result = final_result.domain(trimmed_part.strip_prefix("Domain=").unwrap());
+                update_map!(map, "Domain");
+                continue;
+            }
+            if !map.get("Secure").unwrap() && trimmed_part == "Secure" {
+                final_result = final_result.secure(true);
+                update_map!(map, "Secure");
+                continue;
+            }
+
+            if !map.get("Partitioned").unwrap() && trimmed_part == "Partitioned" {
+                final_result = final_result.partitioned(true);
+                update_map!(map, "Partitioned");
+                continue;
             }
         }
-        println!("{:?}", final_result);
         Ok(final_result.finish())
     }
 }
@@ -153,7 +226,7 @@ impl FromStr for Cookie {
 mod test {
     use std::time::Duration;
 
-    use crate::handling::response::CookieBuilder;
+    use crate::handling::response::{Cookie, CookieBuilder};
 
     use super::SameSite;
 
@@ -169,19 +242,32 @@ mod test {
         let test_cookie3 = CookieBuilder::build("ab", "ss")
             .max_age(Duration::from_secs(24))
             .domain("codecraft.com")
-            .path("/")
+            .path("/".parse().unwrap())
             .same_site(SameSite::None)
             .http_only(true)
             .partitioned(true)
             .expires("Monday")
             .finish();
-        let test_cookie3_res = "Set-Cookie: ab=ss; HttpOnly; Partitioned; \
-            Max-Age=24; Domain=codecraft.com; Path=/; SameSite=None; Secure; Expires=Monday";
+        let test_cookie3_res = "Set-Cookie: ab=ss; Secure; HttpOnly; Partitioned; \
+            Max-Age=24; Domain=codecraft.com; Path=/; SameSite=None; Expires=Monday";
 
         assert_eq!(test_cookie1_res, test_cookie1);
         assert_eq!(test_cookie2_res, test_cookie2);
         assert_eq!(test_cookie3_res, test_cookie3.to_string());
     }
     #[test]
-    fn cooki_from_string() {}
+    fn cookie_from_string() {
+        let test_cookie3_res = "Set-Cookie: ab=ss; HttpOnly; Partitioned; \
+            Max-Age=24; Domain=codecraft.com; Path=/; SameSite=None; Secure; Expires=Monday";
+        let test_cookie3 = CookieBuilder::build("ab", "ss")
+            .max_age(Duration::from_secs(24))
+            .domain("codecraft.com")
+            .path("/".parse().unwrap())
+            .same_site(SameSite::None)
+            .http_only(true)
+            .partitioned(true)
+            .expires("Monday")
+            .finish();
+        assert_eq!(test_cookie3, test_cookie3_res.parse::<Cookie>().unwrap());
+    }
 }
diff --git a/core/http/src/handling/response/cookie_management/cookie_builder.rs b/core/http/src/handling/response/cookie_management/cookie_builder.rs
index 5a3dac3..2699257 100644
--- a/core/http/src/handling/response/cookie_management/cookie_builder.rs
+++ b/core/http/src/handling/response/cookie_management/cookie_builder.rs
@@ -1,6 +1,6 @@
 use std::time::Duration;
 
-use crate::utils::urlencoded::EnCodable;
+use crate::utils::{url_utils::Uri, urlencoded::EnCodable};
 
 use super::{Cookie, SameSite};
 
@@ -11,7 +11,7 @@ use super::{Cookie, SameSite};
 /// use http::handling::response::Cookie;
 /// use http::handling::response::CookieBuilder;
 ///
-/// let cookie = CookieBuilder::build("name", "value").path("/").finish();
+/// let cookie = CookieBuilder::build("name", "value").path("/".parse().unwrap()).finish();
 /// ```
 #[derive(Debug)]
 pub struct CookieBuilder {
@@ -49,8 +49,8 @@ impl CookieBuilder {
         self.inner.domain = Some(domain.encode());
         self
     }
-    pub fn path(mut self, path: &str) -> Self {
-        self.inner.path = Some(path.encode());
+    pub fn path(mut self, path: Uri) -> Self {
+        self.inner.path = Some(path);
         self
     }
     pub fn secure(mut self, secure: bool) -> Self {
@@ -62,6 +62,9 @@ impl CookieBuilder {
         self
     }
     pub fn same_site(mut self, same_site: SameSite) -> Self {
+        if same_site == SameSite::None {
+            self.inner.secure = true;
+        }
         self.inner.same_site = Some(same_site);
         self
     }
diff --git a/core/http/src/handling/response/cookie_management/error_types.rs b/core/http/src/handling/response/cookie_management/error_types.rs
new file mode 100644
index 0000000..12277c0
--- /dev/null
+++ b/core/http/src/handling/response/cookie_management/error_types.rs
@@ -0,0 +1,43 @@
+use std::error::Error;
+
+use crate::utils::url_utils::UriError;
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub enum SameSiteError {
+    NotAValidVariant,
+}
+
+#[derive(Debug)]
+pub struct ParseSameSiteError {
+    pub inner: SameSiteError,
+}
+
+impl Error for ParseSameSiteError {}
+
+impl std::fmt::Display for ParseSameSiteError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+impl Error for ParseCookieError {}
+
+#[derive(Debug)]
+pub struct ParseCookieError {
+    pub inner: CookieError,
+}
+
+#[derive(Debug, PartialEq, PartialOrd, Eq, Ord)]
+pub enum CookieError {
+    MissingEqual,
+    InvalidAttribute,
+    InvalidMaxAge,
+    NoSetCookieHeader,
+    InvilidSameSite(SameSiteError),
+    PathError(UriError),
+}
+
+impl std::fmt::Display for ParseCookieError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "ParseCookieError {{ error: {:?} }}", self.inner)
+    }
+}
diff --git a/core/http/src/handling/response/cookie_management/mod.rs b/core/http/src/handling/response/cookie_management/mod.rs
index 50f34ea..5681658 100644
--- a/core/http/src/handling/response/cookie_management/mod.rs
+++ b/core/http/src/handling/response/cookie_management/mod.rs
@@ -1,6 +1,11 @@
 mod cookie;
 mod cookie_builder;
+mod error_types;
 
 pub use cookie::Cookie;
 pub use cookie::SameSite;
 pub use cookie_builder::CookieBuilder;
+pub use error_types::CookieError;
+pub use error_types::ParseCookieError;
+pub use error_types::ParseSameSiteError;
+pub use error_types::SameSiteError;
diff --git a/core/http/src/utils/url_utils/datatypes.rs b/core/http/src/utils/url_utils/datatypes.rs
index 3c40037..6e36080 100644
--- a/core/http/src/utils/url_utils/datatypes.rs
+++ b/core/http/src/utils/url_utils/datatypes.rs
@@ -20,14 +20,14 @@ pub enum RawUriElement {
     Name(UrlEncodeData),
 }
 
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
 pub enum UriError {
     InvalidUriEncoding,
 }
 
 #[derive(Debug)]
 pub struct ParseUriError {
-    error: UriError,
+    pub error: UriError,
 }
 impl std::fmt::Display for ParseUriError {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-- 
GitLab


From 0d46a64806ca273261d40f2685110953d34c2a7e Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Wed, 19 Jul 2023 14:42:48 +0200
Subject: [PATCH 59/65] Implement HTTPS

---
 core/http/Cargo.lock                        | 269 ++++++++++++++++++-
 core/http/Cargo.toml                        |   1 +
 core/http/src/certificates/certificate.crt  |  29 +++
 core/http/src/certificates/identity.pfx     | Bin 0 -> 4179 bytes
 core/http/src/certificates/private.key      |  54 ++++
 core/http/src/handlers/handler.rs           |  25 +-
 core/http/src/handling/response/response.rs |   3 +-
 core/http/src/setup.rs                      |  10 +-
 site/Cargo.lock                             | 275 +++++++++++++++++++-
 9 files changed, 655 insertions(+), 11 deletions(-)
 create mode 100644 core/http/src/certificates/certificate.crt
 create mode 100644 core/http/src/certificates/identity.pfx
 create mode 100644 core/http/src/certificates/private.key

diff --git a/core/http/Cargo.lock b/core/http/Cargo.lock
index 8496ac6..9ac579c 100644
--- a/core/http/Cargo.lock
+++ b/core/http/Cargo.lock
@@ -20,12 +20,79 @@ version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
 
+[[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+
 [[package]]
 name = "cfg-if"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
+[[package]]
+name = "core-foundation"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
+
+[[package]]
+name = "errno"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "fastrand"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
+dependencies = [
+ "instant",
+]
+
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
 [[package]]
 name = "hermit-abi"
 version = "0.2.6"
@@ -35,20 +102,59 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "hermit-abi"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
+
 [[package]]
 name = "http"
 version = "0.1.0"
 dependencies = [
  "phf",
  "tokio",
+ "tokio-native-tls",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
 ]
 
+[[package]]
+name = "io-lifetimes"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
+dependencies = [
+ "hermit-abi 0.3.2",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
 [[package]]
 name = "libc"
 version = "0.2.144"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
 
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+
 [[package]]
 name = "lock_api"
 version = "0.4.9"
@@ -80,16 +186,84 @@ dependencies = [
  "windows-sys 0.45.0",
 ]
 
+[[package]]
+name = "native-tls"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
+dependencies = [
+ "lazy_static",
+ "libc",
+ "log",
+ "openssl",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "security-framework",
+ "security-framework-sys",
+ "tempfile",
+]
+
 [[package]]
 name = "num_cpus"
 version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.2.6",
  "libc",
 ]
 
+[[package]]
+name = "once_cell"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+
+[[package]]
+name = "openssl"
+version = "0.10.55"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "foreign-types",
+ "libc",
+ "once_cell",
+ "openssl-macros",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.90"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
 [[package]]
 name = "parking_lot"
 version = "0.12.1"
@@ -108,7 +282,7 @@ checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall",
+ "redox_syscall 0.2.16",
  "smallvec",
  "windows-sys 0.45.0",
 ]
@@ -161,6 +335,12 @@ version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
 
+[[package]]
+name = "pkg-config"
+version = "0.3.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
+
 [[package]]
 name = "proc-macro2"
 version = "1.0.56"
@@ -203,12 +383,67 @@ dependencies = [
  "bitflags",
 ]
 
+[[package]]
+name = "redox_syscall"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "rustix"
+version = "0.37.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "schannel"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
+dependencies = [
+ "windows-sys 0.48.0",
+]
+
 [[package]]
 name = "scopeguard"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
+[[package]]
+name = "security-framework"
+version = "2.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8"
+dependencies = [
+ "bitflags",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
 [[package]]
 name = "signal-hook-registry"
 version = "1.4.1"
@@ -262,6 +497,20 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "tempfile"
+version = "3.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "fastrand",
+ "redox_syscall 0.3.5",
+ "rustix",
+ "windows-sys 0.48.0",
+]
+
 [[package]]
 name = "tokio"
 version = "1.28.2"
@@ -292,12 +541,28 @@ dependencies = [
  "syn 2.0.15",
 ]
 
+[[package]]
+name = "tokio-native-tls"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
+dependencies = [
+ "native-tls",
+ "tokio",
+]
+
 [[package]]
 name = "unicode-ident"
 version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
 
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
 [[package]]
 name = "wasi"
 version = "0.11.0+wasi-snapshot-preview1"
diff --git a/core/http/Cargo.toml b/core/http/Cargo.toml
index 45da492..d2fc133 100644
--- a/core/http/Cargo.toml
+++ b/core/http/Cargo.toml
@@ -8,3 +8,4 @@ edition = "2021"
 [dependencies]
 tokio = { version = "1.28.2", features = ["full"] }
 phf = { version = "0.11", features = ["macros"] }
+tokio-native-tls = "0.3.0"
diff --git a/core/http/src/certificates/certificate.crt b/core/http/src/certificates/certificate.crt
new file mode 100644
index 0000000..fa80d20
--- /dev/null
+++ b/core/http/src/certificates/certificate.crt
@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIIE+zCCAuOgAwIBAgIUduzhfNiMYBDh6wuv3MjdxK2C6bYwDQYJKoZIhvcNAQEL
+BQAwDTELMAkGA1UEBhMCREUwHhcNMjMwNzE5MTEyNzE3WhcNMjQwNzE4MTEyNzE3
+WjANMQswCQYDVQQGEwJERTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+AKKTQ3sMq9yYNST56n9NbNkycJ1QQORl6DtqqFB3iVRrNOzs0o1RAqXtVCWIiyJ2
+cvC/nPz9V+QRM9ZwovYGt7I2IGm3Wu15wWJH71QakPTElsoM+twVHUU+E8yNaDpY
+vibP+6MIz7O1DD/uSqA5779n0/eZuC6Li1LYiaJNLHst9sqo1f5UccG66HdanT6+
+oCbvUyS8tiVnepM0rTku7k/7XVkKVa71VAojoVfNhSpF/tWQJC5PD8Sp9X5E31QK
+BMjMckdS/ev4qruPGBOF10eilt+nJAxUpbJ87UamG/VxI3DDNchZ+ssckgDRcd44
+Td3Z2SsOAcHebCtrgOL4hFZQ+DsBMIDCWuj/BcKmN+RsnE40X7I01qBjbUABU/kp
+cfJxd3YtkBysQ8VuMz00/jLzpUcTvbVjXq9ktCGBFbAUd+qqxNNA0Tqxw8TlE5pY
+is2DzVpZvtuDscZAevMFRmi0aYN/RPGhcggeAUDAE4pHDgUdyZx8DKPZeDrPHRg+
+q+ESDB1UI23D4xkg97dhMFCClUute5YItVv21uGlK8HVa9BpXNgEmqOWEbrAyaFk
+AKIsdibdo7G7DZxbC0NSP4MFrBxsdRl4MrCWKcipoWJ78LDQ5MXWtPEPotBQ+wsB
+zK56WUFkMKwyRXA8/tcS3DZ+GNugavMaSewJ2zgjgkLjAgMBAAGjUzBRMB0GA1Ud
+DgQWBBQpS4RUpA6uFkfMDlfH1AG8e8JyejAfBgNVHSMEGDAWgBQpS4RUpA6uFkfM
+DlfH1AG8e8JyejAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQAW
+9EW7neVsyntMqUWYHfg7hALxd800gF8t3jpBXOkg1j4Dg+XewsJsix8k96+zA0RF
+wXR2iyQGSaGE5wENdArbg0KJsTcm5R754jyPmOdUUxoC8e96+vJAcHRHPCZLb+7q
+meD/hqT22221bM517PUBYHzLvTEtUzRDOZkoG90QKBxyi934TWmr3hXVqp5YqLvu
+V50AOTy0p38q4oFCdocyq2LpLst8IrLZphAV5uAdNzk94hjxfACRSWdQjWefUEJl
+Qb/W5EdOIAZhXK+mMPskLxQcsqET70jWlVneuCocF11JzE5ouzefzUK9X/ofcaHI
+C0Vfien5Haq6xHEw1Lyq47dVcd0ztqVDaolA7TzTnVzTwLT7REyvOOlb1eaq6ZoC
+QpIiyLiJjytK1bof/H0HoJqHFEJtaPhL6no7HjhDMusKTXTOrWjG68Kwa6NgMzAa
+XjUluyXPlIGs/M4qFZYlwWEo9lK5txNFiAfvu5DnrqMK4jvlpDpktCcIBAxBaN+2
+c5X8prRGN+u6w0CgYrwV5+tzHaTho6FWQvA+XnuWlmFR2UJjkYXD5IQNDkbejWL4
+6XWC6X2fEGXfTKR4f6mkXOyg2YtaBLI6cxgxqYVhjMpiRu00ncRKohZjqDXVtOll
+u1HYrp5q7wYq/m9NVuZv8XYviTGSO/1oUR4n1Dng6g==
+-----END CERTIFICATE-----
diff --git a/core/http/src/certificates/identity.pfx b/core/http/src/certificates/identity.pfx
new file mode 100644
index 0000000000000000000000000000000000000000..23327800204e7b757f67586e636994a03c8fc84e
GIT binary patch
literal 4179
zcmai1Ra6v=)@6pFdk8^9x@$;jm9CNQF6j^jDHVq97#JFc5|Ebek`@qQXr$W#q?_wq
z|G&QP@jje&*4g`EzwNyb1V*X>1Ykm7q*&N^Tw%&#7eoLY01`%W4uX*!LtrEa5E$0l
zzZ5nShBf&Y8V3R}{;t7)834rKp96~sq6*>s_auZo0pYS6RcrtQYT-a2E(U}U8~6Xz
zfOuFK5ISr;%P?ht9VQ6C1tMi?%j@!b&u#f8D)F&@q)=QS49oIfT+DoUQR5<~q#n*!
z>Q>jAsB;KjDLh)b%E$%T#PR1F{%{30&d{gdC|*A3kC(>#8r;mf8vhY1yCXY`m5k_E
zLef`J?b_Wp74i0k<*99c=)mbQM!&#|v)kug6Nm;f;3yf9Xo|CK|A9|s@c6v{A(1j&
zv?JE6In!lcuSAn*tUk13Ep{}RC8?hr`{pWAB9hLR)Jk%WF`{rFmQg-u#~aX4tUnR1
znb9S`N1Pb9zq@>C-_C8Ie}>HF#28%-<wP@{o(;CFSj)C+)!EiDvlMt&C1^)@0<Squ
zZi4(TzNEl03VasI+rEDMedfOTRyXMi!c8Dj)lfGi%4KC4=Mo}Ny8>19WCN!+0u12>
zAw_4<*J${1V)54xD0UAb33FaiYY6`frO%u5*3>yP)a2&AI@$`jecbXpSbHInR<<vx
zm>5=+Z&Mo(;qhQmNqOfDRDUo}tDTu>5Zpv)k|vsW0Tyg2)coB5IY6|RIbjrN+5Ibf
z`^CBLqC+>xay--^Uy9On{{B{Igik}m9fy@DlH+952U131rV?86sixKK4c7FvazR7N
zO<m$UwEr-)ET?#0NH0I*E--2OwR1Fwlq|j)sy0Ve7R<5Jj;AU!<g!wIRv!E#Xq2b?
zQqt$*4AG8=%cZEghbj&g&ywJI@B0+xGiePGv1@RA^z-OlLqlt@;7eC~3@dGOToBjp
z+_5!+N^*mdfO{-Cx%6lq->XPf?h%R{Q^E&yrBsp+J3Wz;9@)&IQ2gx;*3V}KVC)XR
zkOS9jMA$Sx>s|gYS{r-GYmPV6Yq%@lMHY&&Zxr|+?^j66d`^$usK-=XD+Mq2&JNeM
zw4e!_eg|)1(#vyHUM_#nQunKP8BFf*1!YVvj3Hi?61}s4{U{}#xBBXvkNbQb24@28
z@*!RLE#l!lB%=S9>QK?Le!<>+UGCmQT8PQ7n&`ye-Vt9Wq(;BOs|o5<Fb+Pf?$hVs
zq#rqrZ<bN!y9~q~`sXnYH<l`qTmHc$|MqKv*Gb(8=y&j4P}jIXogq@4s9e?~_P~g#
z5j6_sEKvMvIENuC*n^3<X~i9Df1{<@B=FN970yjo>^Ry<wAuxDdu+knBiZIA3M%_X
z|K8!6v@<F5Agf4C!)&N}yhSdEVhUbjvnimCNg1SS&7LLtT10NEWLQ%|*YUR7Car7#
zKGu_+M7?JihwcwUOn*C&=y9%ptvHX>xviyz_I8+EAr4t?*reh_jSh-yFo-@)O_fnN
zI0!J?B*hS@9hD+pW@%ojkitt;EV3@VDm5_!hyeyTmryU8?pbC0%oxP}w5$=(Y4*rw
zgxOGW1gZM`=25t`IQI;LPtK;m+rHUr>w*i1rD7GkNlrCVj<urUZ?@Qs(040Cffte%
zH!LbYpqkrn8!!Wi659^eXVhf4f%fQgJ$>r7Nz0_52|igP@iz?jc%Rmh#a6?^9(}jc
z!%Ja{xKH66Q}m4)+I1E)D;o|R7ooYP9gc2-n6Ec98v29})QD}LQuQ7?M-a}JR$y=q
zic?(VWAdoC_8|9U6umi<k=F9n5sDAs$Xy+15vp!4&oP(hLk!eDrXP<yil`g#B97?D
z=!2)s#`#gDc}dLl@C#17OG|u`w_Z>s4g!RWQgCFZLQLGfIkP>+;ZE&x<AhF9q<`_B
zBkC2!wlVIn7Ji5#UkUcKfB;4vl2fPS9EB5aq%$dQN^{8dgf!MZ`N3>U)<6j8)aF%K
zf0o$E8=E%rU+RiYbJh2ElyVPR2d(MtbXzaSfqQDaa<f4Z6#VW@U%O1;^Nb>oFnWiw
zviQT@H4>9exNN5(FnrKIe*ND7z&iuM@cuwxc<8^gi%szV*+7U70RAOw{(=?%%kWXM
z${(jEZP5SI@J-TWK8sjiOw9^rRm3!lH2qc9#50bkceO7@`e3S1AH6^#kJoZIekZH;
zKNafMP+O+9(~i+$!-}-3@+}+|<4L?DHnQE3Y|Wr&Ldet-Ltcv8>gOh&QS|hTX~@QG
zmr8cXWiXBQW!B29RNJ=m&zohS6z*`;3!jG0gCsfkdAx2~sF?E25rn;e?l1}iUFye}
zZ@<A3ZWv?^I7Oyfg;y3fUgw`k`I4l(>W{^YHz(T6e8*iQcFCu|NVIF&3GN2hKIAlt
z?2~b2opsal?s)H+K#grbdN?(6zp7XMDP`zjn}~{7ICol2rLu~J&dff!AaIWzHA=9R
zA?7XEVc|e&q^~+iNlSB)l)Y~VWbvoo;yVeI!n4VY(i$H_FE;*ogkW*NUAybOJZneI
zBtKhY9-I>Nm?6+7%Sz6u)VyYk>Sr<0JO4PsyN0*-t{W@L3O@A*!C|p<2VxUrvA`N5
zKlxrq_myMJcid$u{euMDoKD3|*DjhC%&i(rBAV{JTINmK-u#i~sxNk-o}Fc^ewq7W
z1N|gl`B%~S>C!IJY?@(-Hch2hOpo9FSx;^-iXsIp&>NpMp+f4Fl*3oqkv^w$E#f+>
z*<I}j^L)N!=qzIzZGsYBE{*G%Yqsp)1xd_PAlg1ZJ#_pu&sA<pvL;8NKZEZ?Y?$pp
z{JTuQ>4r*cCsqgNQgPr?YzQr022$2rUNt5i;B`dg<r{Nf=RM?0(-!Q)XGKpOM_Q+0
z<$RHC!(yM%$H#!=aoQL2LLa>pZF-6=Pvn(_GouJ#wc|A?%;!V-no33q8rb$M(ArXe
zL@1njpEl~Cpqwt)T;-CK$%9vEbLILC!vIbU;~&rQohmA_Uc$g^{LuSqI~Y!q88Va-
z%*p(`U{Mc~T710@*HKm@SI3=J>)MgfUZHI3H{-htY}kp3@jKE$lk(6tOBOv6T~=8(
zWs}DkqB!&6>|x;u1V;Vdt3g%D=qrZY%RGF^8oOlQW_E3S(Jt)Q#P96Ka3`}BoMgf6
zy_DNOSf8RQX3vy;GBWm0k%I223`myq^vFqgk{0O3J9Czwi|xW!!k0#c-)-Mt8(lWy
zy&GqXajR_?K;akXDa5>3?Bw#$k;RxKwwllcS#w84v+j$n^SVk)WK`M+U+?0MYX@*q
z%{oS>q&_%M#I~I;7td8bzI^?GR-<U8v}WYXR&SemsWFvKW~sVcSA~W5_&vc>@3`{w
zw=`wxuyvEqEu@oc3g)2M<Go|>tIE*^t1svu)ly+iwX)yY7@V(PQDu*HcM57IZLGdr
zmp*t(yo?V?2ZjgUoDCC`D$|Ho{$$~#jV2_!`s~D@v_<dMI0ZrU+l+ltbHV1TX<1#j
zjRkC}J~n=-d~p#ktg6u+)b|$N7UDw6xx*6DF<llv9c)ICDVXPc2#tzrbRRb&-9H;k
zEYM_vTAFvWUs8}GBK*1!`P-Q>w%9lD&e?@*Jyw+6_+$fFbV_>fbwP>rAgd+{?ja*l
z-GW9_+WuKD>z60brdk+O+ag|LJu=LTP05*7H|cd$KMx3Jf&kSY!Vy+W8{(KbzG`~5
zZ2W214>K<kcpVHkg#pwBj8*oXk~cmn8L9AVmpf^|HH_hvGC~vkrv1>C|Mu#rl)olP
z^Fv|3M30JZ3+NQ<()EKzQH)mN1K!)>EP5ZuaHZZyoSj;~Bno-6$JTLnD*V6t5><IY
zz3DBs*vca3;-5cFNS<Ury?Mj2QaUBHsCu;DtnWfR7z|5N_H&G6jlmjNQt7mZA<XtD
zWm{I58?3i&VVU~QvA>mc*UF1X#)V%+yXw$<Sw_oocku=r4{NkOs~{CAj@J41p(cI#
zG8-^T9Pl$xR$(lR568(#U3`Dr^J#S%%|ICf>|>bbk=kS^MxXZ;ie`KEG*Wn!{ijm}
z!I*t+o*bRRj>aX|=k5Kd^pUo`hYYhfbLhsD%K$appc$?#b&u1-Dr^pIrwg2#NWqtu
zO(MyoeifRgPQWM`!uhD;bgYF9!>Q3vP>w(|4K7@Hwew{_Alc)KtMFZhQ#-x1qxX*U
z<vM8))gtk6uy8HP=E)|8yhXQF?^kGw7kucWr<|jt@cYkrp>%@iG6c_Ex1Y~QNv+^o
z!tO!)Ge}Z<^h-<jaFuO^`lca!=Si@G($<2Mc<qIKS#WBqUL;}CR6-O*laB->o^tdN
z6;J6z@44QgQ}2WRkLViG9sSnABRPHf#@*euZ%Z>wlr{V~^$lF|BPxETV&>84m9X2b
zsP6=>v%>7IXRC{(RBJb#lg{qtl)#>Qt6SV^D>iyQYPZkZtQoUud!^6SUh_7Vl!COj
zn6$I(<nZZTXCOn`*%`N`FRt+$d~iHFc4cwi6%xnIl==_ScCFp)(V?HPx@^d6<$;uM
zBo6n)TT7oO)$jC=pd=k#GZpR`=57~<L|-kLy(59r4BZ%-)0WPJNMzjKLYKOhg`3K+
zF<E|SV#*??e(qrx%P5+KC&W{B?DU3yOO#2SPC|KmMho<Qk6m((qkKrfD8CXH&ZTqL
zXDC4NhW!#6nu{T5CgV}d6hF*!M-7u>c6Q5P+ZZuQbSwiSbSlhGtBd=}It{7qCUkA9
z0>NwpJD{lA_+c<xQj3!0g1)EQ;)+1Uv&VrshUq?uPo6B*H>bP4MuXxEO->!KXDxJX
z`>O&KXiOR>Y|@gdx*GZ@(D3*~K%6SBE}<xIN_RA4mSLVLC$>pk-c&zWlFjC<?AuHX
zzr>~OI(9};LD%uoK7LK}km}ev5Da2wC8zwk-;HT&ckU^?grRg8fGdgQ*rYi~%g|h0
z-mp9GYtpx2f=jBACv1ib9h`=Ka@%CoVEt{ZyBHbK<s|L<eCH?`)7dka>KQWLyfM+*
z0`45doPVO7MVy9p0hQqkC`(Obo&3$=ZR(B~?lA)^da!T&k{Mi8=rM)Y%Nt)oRZUxz
z*GtcGdp;W^G?sLuuEe{!)~iu0f_hWPm<Heg=EcgWJ=y#1{@?AA=Jq|wVX`yhV3GY#
z$ES6Ns)#EadO7iq)H|K$W?O|X)ShHYrjaRS2PIO30Y<W{5r;nFmTcKM7~=f875nCo
z`93x<iw^E(w$&pCeyCWgJvkNfnpz}yXcm$4dU)nypJj|(gL4&>Y*<}K+dFr4>){Fh
zynoL~x-0CpJGEt@r2$WKS+0M@C%_6}{-@yKQ3_CjD4Ig7EYD$@n+IIwJFdD#UkXwU
zM<FjE0uZ8q-f<uR3j@TE!lNj`dVR=xddkL3Xi#M+jPh`BHOQDN_+;mCvc6*u!VO-D
N;o^^QT>5X-`wu`L;u-(|

literal 0
HcmV?d00001

diff --git a/core/http/src/certificates/private.key b/core/http/src/certificates/private.key
new file mode 100644
index 0000000..2bcad34
--- /dev/null
+++ b/core/http/src/certificates/private.key
@@ -0,0 +1,54 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+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
++C+hItN7Lj2S0FM6dEa+1g==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/core/http/src/handlers/handler.rs b/core/http/src/handlers/handler.rs
index 7ffa9e9..f1847b2 100644
--- a/core/http/src/handlers/handler.rs
+++ b/core/http/src/handlers/handler.rs
@@ -1,9 +1,10 @@
 use std::{io, path::PathBuf};
 
 use tokio::{
-    io::{AsyncBufReadExt, AsyncReadExt, BufReader},
-    net::TcpStream,
+    io::{AsyncBufReadExt, AsyncReadExt, BufReader, AsyncWriteExt},
+    net::TcpStream, stream,
 };
+use tokio_native_tls::{TlsStream, TlsAcceptor};
 
 use crate::{handling::{
     file_handlers::NamedFile,
@@ -28,7 +29,11 @@ static MAX_HTTP_MESSAGE_SIZE: u16 = 4196;
 ///
 /// # Panics
 /// No Panics
-pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint<'_>>) {
+pub async fn handle_connection(stream: TcpStream, mountpoints: Vec<MountPoint<'_>>, acceptor: TlsAcceptor) {
+    let Ok(mut stream) = acceptor.accept(stream).await else { 
+        eprintln!("\x1b[31mClient used http, not https\x1b[0m");
+        return;
+    };
     let mut buf_reader = BufReader::new(&mut stream);
     let mut http_request: Vec<String> = Vec::with_capacity(10);
     loop {
@@ -192,7 +197,7 @@ fn failure_handler(status: Status) -> Response {
 }
 
 /// Handler for len_not_defined errors. writes back directly
-async fn len_not_defined(stream: TcpStream, status: Status) -> io::Result<()> {
+async fn len_not_defined(stream: TlsStream<TcpStream>, status: Status) -> io::Result<()> {
     let page_411 = NamedFile::open(PathBuf::from("411.html")).unwrap();
     Response {
         cookies: None,
@@ -209,3 +214,15 @@ async fn len_not_defined(stream: TcpStream, status: Status) -> io::Result<()> {
 fn error_occured_when_writing(e: io::Error) {
     eprintln!("\x1b[31mError {e} occured when trying to write answer to TCP-Stream for Client, aborting\x1b[0m");
 }
+
+async fn redirect_to_secure(mut stream: TcpStream) {
+    let resp = Response {
+        cookies: None,
+        status: Some(Status::MovedPermanently),
+        headers: vec!["Location: https://127.0.0.1".to_string()],
+        body: Box::new("")
+    }.build(None);
+    if let Err(e) = stream.write_all(&resp).await {
+        error_occured_when_writing(e);
+    }
+}
diff --git a/core/http/src/handling/response/response.rs b/core/http/src/handling/response/response.rs
index 62de6e9..67f87bb 100644
--- a/core/http/src/handling/response/response.rs
+++ b/core/http/src/handling/response/response.rs
@@ -1,6 +1,7 @@
 use std::io::Result;
 
 use tokio::{io::AsyncWriteExt, net::TcpStream};
+use tokio_native_tls::TlsStream;
 
 use crate::handling::{methods::Method, request::Request, response::Status};
 
@@ -32,7 +33,7 @@ impl Response {
         compiled_out
     }
     /// Builds and writes The http-Response, consumes the  [tokio::net::TcpStream] [Request] and [Response]
-    pub async fn write(self, mut stream: TcpStream, request: Option<Request>) -> Result<()> {
+    pub async fn write(self, mut stream: TlsStream<TcpStream>, request: Option<Request>) -> Result<()> {
         let resp = self.build(request);
         stream.write_all(&resp).await?;
         Ok(())
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index 31669bb..c1b3ced 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -1,10 +1,11 @@
-use std::thread::available_parallelism;
+use std::{thread::available_parallelism};
 
 use tokio::{
     net::TcpListener,
     select,
     signal::unix::{signal, SignalKind},
 };
+use tokio_native_tls::{native_tls::{Identity, self}, TlsAcceptor};
 
 use crate::{
     handlers::handler::handle_connection,
@@ -28,6 +29,7 @@ pub struct Config {
     mountpoints: Option<Vec<MountPoint<'static>>>,
     /// Contains a [tokio::net::TcpListener] that is bound for the server
     address: TcpListener,
+    tls_acceptor: TlsAcceptor,
 }
 
 impl<'a> Config {
@@ -103,7 +105,8 @@ impl<'a> Config {
                 }
                 Ok((socket, _)) = self.address.accept() => {
                     let mountpoints = self.mountpoints.clone().unwrap();
-                    tokio::spawn(async move { handle_connection(socket, mountpoints).await; });
+                    let tls_acceptor = self.tls_acceptor.clone();
+                    tokio::spawn(async move { handle_connection(socket, mountpoints, tls_acceptor).await; });
                 }
             }
         }
@@ -135,6 +138,8 @@ pub async fn build(ip: &str) -> Config {
     if ip.len() != 2 {
         panic!("Invalid IP Address");
     }
+    let identity = Identity::from_pkcs12(include_bytes!("certificates/identity.pfx"), "1234").unwrap();
+
     let port = ip[1];
     let ip = ip[0];
     let workers = available_parallelism().unwrap().get();
@@ -148,5 +153,6 @@ pub async fn build(ip: &str) -> Config {
     Config {
         mountpoints: None,
         address: listener,
+        tls_acceptor: native_tls::TlsAcceptor::builder(identity).build().unwrap().into()
     }
 }
diff --git a/site/Cargo.lock b/site/Cargo.lock
index 84f675c..8373d43 100644
--- a/site/Cargo.lock
+++ b/site/Cargo.lock
@@ -20,12 +20,79 @@ version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
 
+[[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+
 [[package]]
 name = "cfg-if"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
+[[package]]
+name = "core-foundation"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
+
+[[package]]
+name = "errno"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "fastrand"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
+dependencies = [
+ "instant",
+]
+
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
 [[package]]
 name = "hermit-abi"
 version = "0.2.6"
@@ -35,20 +102,59 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "hermit-abi"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
+
 [[package]]
 name = "http"
 version = "0.1.0"
 dependencies = [
  "phf",
  "tokio",
+ "tokio-native-tls",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
 ]
 
+[[package]]
+name = "io-lifetimes"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
+dependencies = [
+ "hermit-abi 0.3.2",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
 [[package]]
 name = "libc"
 version = "0.2.144"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
 
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+
 [[package]]
 name = "lock_api"
 version = "0.4.9"
@@ -59,6 +165,12 @@ dependencies = [
  "scopeguard",
 ]
 
+[[package]]
+name = "log"
+version = "0.4.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
+
 [[package]]
 name = "mio"
 version = "0.8.7"
@@ -70,16 +182,84 @@ dependencies = [
  "windows-sys 0.48.0",
 ]
 
+[[package]]
+name = "native-tls"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
+dependencies = [
+ "lazy_static",
+ "libc",
+ "log",
+ "openssl",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "security-framework",
+ "security-framework-sys",
+ "tempfile",
+]
+
 [[package]]
 name = "num_cpus"
 version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.2.6",
  "libc",
 ]
 
+[[package]]
+name = "once_cell"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+
+[[package]]
+name = "openssl"
+version = "0.10.55"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "foreign-types",
+ "libc",
+ "once_cell",
+ "openssl-macros",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.18",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.90"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
 [[package]]
 name = "parking_lot"
 version = "0.12.1"
@@ -98,7 +278,7 @@ checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall",
+ "redox_syscall 0.2.16",
  "smallvec",
  "windows-sys 0.45.0",
 ]
@@ -151,6 +331,12 @@ version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
 
+[[package]]
+name = "pkg-config"
+version = "0.3.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
+
 [[package]]
 name = "proc-macro2"
 version = "1.0.59"
@@ -193,12 +379,67 @@ dependencies = [
  "bitflags",
 ]
 
+[[package]]
+name = "redox_syscall"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "rustix"
+version = "0.37.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "schannel"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
+dependencies = [
+ "windows-sys 0.48.0",
+]
+
 [[package]]
 name = "scopeguard"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
+[[package]]
+name = "security-framework"
+version = "2.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8"
+dependencies = [
+ "bitflags",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
 [[package]]
 name = "signal-hook-registry"
 version = "1.4.1"
@@ -260,6 +501,20 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "tempfile"
+version = "3.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "fastrand",
+ "redox_syscall 0.3.5",
+ "rustix",
+ "windows-sys 0.48.0",
+]
+
 [[package]]
 name = "tokio"
 version = "1.28.2"
@@ -290,12 +545,28 @@ dependencies = [
  "syn 2.0.18",
 ]
 
+[[package]]
+name = "tokio-native-tls"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
+dependencies = [
+ "native-tls",
+ "tokio",
+]
+
 [[package]]
 name = "unicode-ident"
 version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
 
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
 [[package]]
 name = "wasi"
 version = "0.11.0+wasi-snapshot-preview1"
-- 
GitLab


From 13596bfd4ec97638220a6fe5aee354d0ff1eec61 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Wed, 19 Jul 2023 16:14:23 +0200
Subject: [PATCH 60/65] fix cargo clippy warnings

---
 core/http/src/handlers/handler.rs             | 26 +++++++++----------
 core/http/src/handling/request/form_utils.rs  |  2 +-
 .../{response.rs => build_and_write.rs}       |  0
 .../response/cookie_management/cookie.rs      |  2 +-
 core/http/src/handling/response/mod.rs        |  2 +-
 core/http/src/utils/url_utils/uri.rs          | 13 ++++------
 core/http/src/utils/urlencoded/datatypes.rs   | 20 +++++++++++++-
 core/http/src/utils/urlencoded/endecode.rs    | 12 ++++++---
 core/http/src/utils/urlencoded/mod.rs         |  3 +++
 site/src/main.rs                              |  2 +-
 10 files changed, 52 insertions(+), 30 deletions(-)
 rename core/http/src/handling/response/{response.rs => build_and_write.rs} (100%)

diff --git a/core/http/src/handlers/handler.rs b/core/http/src/handlers/handler.rs
index f1847b2..fa5f75a 100644
--- a/core/http/src/handlers/handler.rs
+++ b/core/http/src/handlers/handler.rs
@@ -1,8 +1,8 @@
 use std::{io, path::PathBuf};
 
 use tokio::{
-    io::{AsyncBufReadExt, AsyncReadExt, BufReader, AsyncWriteExt},
-    net::TcpStream, stream,
+    io::{AsyncBufReadExt, AsyncReadExt, BufReader},
+    net::TcpStream,
 };
 use tokio_native_tls::{TlsStream, TlsAcceptor};
 
@@ -215,14 +215,14 @@ fn error_occured_when_writing(e: io::Error) {
     eprintln!("\x1b[31mError {e} occured when trying to write answer to TCP-Stream for Client, aborting\x1b[0m");
 }
 
-async fn redirect_to_secure(mut stream: TcpStream) {
-    let resp = Response {
-        cookies: None,
-        status: Some(Status::MovedPermanently),
-        headers: vec!["Location: https://127.0.0.1".to_string()],
-        body: Box::new("")
-    }.build(None);
-    if let Err(e) = stream.write_all(&resp).await {
-        error_occured_when_writing(e);
-    }
-}
+// async fn redirect_to_secure(mut stream: TcpStream) {
+//     let resp = Response {
+//         cookies: None,
+//         status: Some(Status::MovedPermanently),
+//         headers: vec!["Location: https://127.0.0.1".to_string()],
+//         body: Box::new("")
+//     }.build(None);
+//     if let Err(e) = stream.write_all(&resp).await {
+//         error_occured_when_writing(e);
+//     }
+// }
diff --git a/core/http/src/handling/request/form_utils.rs b/core/http/src/handling/request/form_utils.rs
index 67ada47..cc8999d 100644
--- a/core/http/src/handling/request/form_utils.rs
+++ b/core/http/src/handling/request/form_utils.rs
@@ -143,7 +143,7 @@ impl Request {
                     let Some(thing) = keymap.get_mut(&key) else {
                         continue;
                     };
-                    *thing = Ok(value.into());
+                    *thing = Ok(value);
                 }
             }
             Mime::MultipartFormData => {
diff --git a/core/http/src/handling/response/response.rs b/core/http/src/handling/response/build_and_write.rs
similarity index 100%
rename from core/http/src/handling/response/response.rs
rename to core/http/src/handling/response/build_and_write.rs
diff --git a/core/http/src/handling/response/cookie_management/cookie.rs b/core/http/src/handling/response/cookie_management/cookie.rs
index 8234ab4..6175266 100644
--- a/core/http/src/handling/response/cookie_management/cookie.rs
+++ b/core/http/src/handling/response/cookie_management/cookie.rs
@@ -102,7 +102,7 @@ impl std::fmt::Display for Cookie {
         if let Some(same_site) = &self.same_site {
             appendix += &format!("; {}", same_site);
             if !self.secure && *same_site == SameSite::None {
-                appendix += &format!("; Secure");
+                appendix += "; Secure";
             }
         }
         if let Some(expires) = &self.expires {
diff --git a/core/http/src/handling/response/mod.rs b/core/http/src/handling/response/mod.rs
index 535eaa8..9233b38 100644
--- a/core/http/src/handling/response/mod.rs
+++ b/core/http/src/handling/response/mod.rs
@@ -1,6 +1,6 @@
+mod build_and_write;
 mod cookie_management;
 mod datatypes;
-mod response;
 mod status;
 mod traits;
 
diff --git a/core/http/src/utils/url_utils/uri.rs b/core/http/src/utils/url_utils/uri.rs
index b9e6939..6b8146b 100644
--- a/core/http/src/utils/url_utils/uri.rs
+++ b/core/http/src/utils/url_utils/uri.rs
@@ -7,10 +7,7 @@ use super::datatypes::{ParseUriError, RawUri, Uri, UriError};
 impl Uri {
     pub fn new(parts: Vec<&str>) -> Self {
         Self {
-            parts: parts
-                .into_iter()
-                .map(|part| UrlEncodeData::from_raw(part))
-                .collect(),
+            parts: parts.into_iter().map(UrlEncodeData::from_raw).collect(),
         }
     }
 }
@@ -23,11 +20,11 @@ impl RawUri {
             raw_string: "/".to_owned() + &parts.join("/"),
         };
         for part in parts {
-            if part.starts_with("<") && part.ends_with("..>") {
+            if part.starts_with('<') && part.ends_with("..>") {
                 result.infinte_end = true;
                 break;
             }
-            if part.starts_with("<") && part.ends_with(">") {
+            if part.starts_with('<') && part.ends_with('>') {
                 result.parts.push(RawUriElement::Variable);
                 continue;
             }
@@ -114,11 +111,11 @@ impl FromStr for RawUri {
             if part.is_empty() {
                 continue;
             }
-            if part.starts_with("<") && part.ends_with("..>") {
+            if part.starts_with('<') && part.ends_with("..>") {
                 result.infinte_end = true;
                 break;
             }
-            if part.starts_with("<") && part.ends_with(">") {
+            if part.starts_with('<') && part.ends_with('>') {
                 result.parts.push(RawUriElement::Variable);
                 continue;
             }
diff --git a/core/http/src/utils/urlencoded/datatypes.rs b/core/http/src/utils/urlencoded/datatypes.rs
index d48e02b..3207955 100644
--- a/core/http/src/utils/urlencoded/datatypes.rs
+++ b/core/http/src/utils/urlencoded/datatypes.rs
@@ -13,6 +13,24 @@ pub struct UrlEncodeData {
     pub(crate) raw_string: Option<String>,
 }
 
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
+pub enum UrlEncodeError {
+    NonHexAfterPercent,
+}
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct ParseUrlEncodeError {
+    pub inner: UrlEncodeError,
+}
+
+impl std::fmt::Display for ParseUrlEncodeError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for ParseUrlEncodeError {}
+
 impl UrlEncodeData {
     /// Generates a [UrlEncodeData] from any raw data that can be a slice of [u8]
     pub fn from_raw<T: AsRef<[u8]>>(raw: T) -> Self {
@@ -27,7 +45,7 @@ impl UrlEncodeData {
     /// # Errors
     ///
     /// errors if the encoded data is wrongly encoded -> %<invalid_character>
-    pub fn from_encoded(encoded: &str) -> Result<Self, ()> {
+    pub fn from_encoded(encoded: &str) -> super::UriParseResult<Self> {
         Ok(Self {
             encoded: encoded.to_owned(),
             raw: encoded.decode()?,
diff --git a/core/http/src/utils/urlencoded/endecode.rs b/core/http/src/utils/urlencoded/endecode.rs
index 8dd45d6..8a77253 100644
--- a/core/http/src/utils/urlencoded/endecode.rs
+++ b/core/http/src/utils/urlencoded/endecode.rs
@@ -1,3 +1,5 @@
+use super::{datatypes::ParseUrlEncodeError, UriParseResult};
+
 /// Base of the HexaDecimal Number system
 static BASE16_HEXA_DECIMAL: u8 = 0x10;
 /// Highest possible Value per digit
@@ -15,7 +17,7 @@ pub trait DeCodable {
     ///
     /// # Errors
     /// Errors if the encoding isn't right
-    fn decode(&self) -> Result<Vec<u8>, ()>;
+    fn decode(&self) -> UriParseResult<Vec<u8>>;
 }
 
 impl<T: AsRef<[u8]>> EnCodable for T {
@@ -44,7 +46,7 @@ impl EnCodable for [u8] {
     }
 }
 impl DeCodable for &str {
-    fn decode(&self) -> Result<Vec<u8>, ()> {
+    fn decode(&self) -> UriParseResult<Vec<u8>> {
         let mut first = true;
         let mut result = Vec::with_capacity(self.len());
 
@@ -55,7 +57,7 @@ impl DeCodable for &str {
                 continue;
             }
             let Ok(char) = u8::from_str_radix(i[0..=1].as_ref(), BASE16_HEXA_DECIMAL.into()) else {
-                    return Err(());
+                    return Err(ParseUrlEncodeError { inner: super::datatypes::UrlEncodeError::NonHexAfterPercent });
             };
             result.push(char);
             result.extend_from_slice(i[2..].as_bytes());
@@ -97,7 +99,9 @@ mod test {
             .unwrap()
         );
         assert_eq!(
-            Err(()),
+            Err(crate::utils::urlencoded::datatypes::ParseUrlEncodeError {
+                inner: crate::utils::urlencoded::datatypes::UrlEncodeError::NonHexAfterPercent
+            }),
             "Darius%2iis%20the%20biggest%20genius%2FGenie%2FHuman%20extraordin%C3%A4ire".decode()
         );
         assert_eq!(
diff --git a/core/http/src/utils/urlencoded/mod.rs b/core/http/src/utils/urlencoded/mod.rs
index 3145200..bf5f292 100644
--- a/core/http/src/utils/urlencoded/mod.rs
+++ b/core/http/src/utils/urlencoded/mod.rs
@@ -1,4 +1,7 @@
 mod datatypes;
 mod endecode;
+use std::result;
+
+type UriParseResult<T> = result::Result<T, datatypes::ParseUrlEncodeError>;
 pub use datatypes::UrlEncodeData;
 pub use endecode::{DeCodable, EnCodable};
diff --git a/site/src/main.rs b/site/src/main.rs
index 22e7900..014d33a 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -105,7 +105,7 @@ async fn main() {
         rank: 0,
     };
 
-    http::build("127.0.0.1:8000")
+    http::build("127.0.0.1:8080")
         .await
         .mount("/", vec![fileserver, post_test, static_hi])
         .mount("/post/", vec![post_test])
-- 
GitLab


From 56a7d1fdde3ed6efb689d61423247dfd02ab582b Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Wed, 19 Jul 2023 17:37:45 +0200
Subject: [PATCH 61/65] Remove the println! statement that annoyed me half to
 death

---
 site/src/main.rs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/site/src/main.rs b/site/src/main.rs
index 014d33a..6938a3b 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -58,7 +58,6 @@ fn post_hi_handler(request: Request, data: Data) -> Outcome<Response, Status, Da
     if data.is_empty() {
         return Outcome::Forward(data);
     }
-    println!("{:?}", request.get_post_data(&["message"], &data));
     let dat = if let Ok(val) = request.get_post_data(&["message"], &data) {
         post_hi(String::from_utf8_lossy(val.get("message").unwrap().as_ref().unwrap()).to_string())
     } else {
-- 
GitLab


From 9191168be199f4175a27d43502b46aa8fa32e247 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Thu, 20 Jul 2023 17:19:46 +0200
Subject: [PATCH 62/65] Add HTTPS-REdirect from Port 8080 to 8443

---
 .../src/handling/response/build_and_write.rs  |  6 ++++
 core/http/src/setup.rs                        | 36 +++++++++++++------
 site/src/main.rs                              |  2 +-
 3 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/core/http/src/handling/response/build_and_write.rs b/core/http/src/handling/response/build_and_write.rs
index 67f87bb..3b6bd1b 100644
--- a/core/http/src/handling/response/build_and_write.rs
+++ b/core/http/src/handling/response/build_and_write.rs
@@ -38,4 +38,10 @@ impl Response {
         stream.write_all(&resp).await?;
         Ok(())
     }
+    
+    pub async fn write_unencrypted(self, mut stream: TcpStream) -> Result<()> {
+        let resp = self.build(None);
+        stream.write_all(&resp).await?;
+        Ok(())
+    }
 }
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index c1b3ced..4730fdb 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -9,7 +9,7 @@ use tokio_native_tls::{native_tls::{Identity, self}, TlsAcceptor};
 
 use crate::{
     handlers::handler::handle_connection,
-    handling::routes::{Route, Uri},
+    handling::{routes::{Route, Uri}, response::{Response, Status}},
 };
 
 #[derive(Clone)]
@@ -29,6 +29,7 @@ pub struct Config {
     mountpoints: Option<Vec<MountPoint<'static>>>,
     /// Contains a [tokio::net::TcpListener] that is bound for the server
     address: TcpListener,
+    to_secure_redirect: TcpListener,
     tls_acceptor: TlsAcceptor,
 }
 
@@ -93,10 +94,11 @@ impl<'a> Config {
     /// is no interrupt signal
     pub async fn launch(self) {
         println!(
-            "Server launched from http://{}",
-            self.address.local_addr().unwrap()
+            "Server launched from https://{} and http://{}",
+            self.address.local_addr().unwrap(), self.to_secure_redirect.local_addr().unwrap()
         );
         let mut sigint = signal(SignalKind::interrupt()).unwrap();
+        let location_string = format!("Location: https://{}", self.address.local_addr().unwrap());
         loop {
             select! {
                 _ = sigint.recv() => {
@@ -108,6 +110,15 @@ impl<'a> Config {
                     let tls_acceptor = self.tls_acceptor.clone();
                     tokio::spawn(async move { handle_connection(socket, mountpoints, tls_acceptor).await; });
                 }
+                Ok((socket, _)) = self.to_secure_redirect.accept() => {
+                    let redirect_response = Response {
+                        headers: vec![location_string.clone()],
+                        cookies: None,
+                        status: Some(Status::MovedPermanently),
+                        body: Box::new(""),
+                    };
+                    tokio::spawn(async move { let _ = redirect_response.write_unencrypted(socket).await; });
+                }
             }
         }
     }
@@ -122,22 +133,24 @@ impl<'a> Config {
 /// # Example
 /// ```
 /// async fn example() {
-///     let _ = http::build("127.0.0.1:8000");
+///     let _ = http::build("127.0.0.1:8080", "127.0.0.1:8443");
 /// }
 /// ```
 /// # Panics
 /// Panics if the IP is not bindable, or other forms of system errors or it's not a valid
 /// IP-Address
-pub async fn build(ip: &str) -> Config {
-    let listener = if let Ok(listener) = TcpListener::bind(ip).await {
-        listener
-    } else {
+pub async fn build(ip_http: &str, ip_secure: &str) -> Config {
+    let Ok(listener_secure) = TcpListener::bind(ip_secure).await  else {
         panic!("\x1b[31mCould't bind Listener to address\x1b[0m");
     };
-    let ip = ip.splitn(2, ':').collect::<Vec<&str>>();
+    let ip = ip_secure.splitn(2, ':').collect::<Vec<&str>>();
     if ip.len() != 2 {
         panic!("Invalid IP Address");
     }
+
+    let Ok(listener_http) = TcpListener::bind(ip_http).await  else {
+        panic!("\x1b[31mCould't bind Listener to address\x1b[0m");
+    };
     let identity = Identity::from_pkcs12(include_bytes!("certificates/identity.pfx"), "1234").unwrap();
 
     let port = ip[1];
@@ -148,11 +161,14 @@ pub async fn build(ip: &str) -> Config {
   >> \x1b[34mIp\x1b[0m: {ip}
   >> \x1b[34mPort\x1b[0m: {port}
   >> \x1b[34mWorkers\x1b[0m: {workers}
+\x1b[32m Security\x1b[0m
+  >> \x1b[32mHttp to Https Redirect: {ip_http} -> {ip_secure}\x1b[0m
 \x1b[35m🛪 Mountpoints\x1b[0m"
     );
     Config {
         mountpoints: None,
-        address: listener,
+        address: listener_secure,
+        to_secure_redirect: listener_http,
         tls_acceptor: native_tls::TlsAcceptor::builder(identity).build().unwrap().into()
     }
 }
diff --git a/site/src/main.rs b/site/src/main.rs
index 6938a3b..ffa61b1 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -104,7 +104,7 @@ async fn main() {
         rank: 0,
     };
 
-    http::build("127.0.0.1:8080")
+    http::build("127.0.0.1:8080", "127.0.0.1:8443")
         .await
         .mount("/", vec![fileserver, post_test, static_hi])
         .mount("/post/", vec![post_test])
-- 
GitLab


From 54277faade3c2f9b7610539714a1a0722ef0ee7d Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Fri, 21 Jul 2023 22:18:17 +0200
Subject: [PATCH 63/65] make https conditionally compiled with the secure
 feature Writing some examples Index page for lms

---
 core/http/Cargo.toml                          |   4 +
 core/http/src/handlers/handler.rs             |  25 +---
 .../src/handling/response/build_and_write.rs  |   5 +-
 core/http/src/setup.rs                        | 128 +++++++++++++-----
 examples/1.rs                                 | 113 ++++++++++++++++
 site/Cargo.toml                               |   3 +-
 site/src/main.rs                              | 109 ++-------------
 site/static/hello.css                         |   4 -
 site/static/hello.html                        |   4 +-
 site/static/style.css                         |  16 +++
 site/templates/index.html                     |  11 ++
 11 files changed, 259 insertions(+), 163 deletions(-)
 create mode 100644 examples/1.rs
 delete mode 100644 site/static/hello.css
 create mode 100644 site/static/style.css
 create mode 100644 site/templates/index.html

diff --git a/core/http/Cargo.toml b/core/http/Cargo.toml
index d2fc133..5d24dbd 100644
--- a/core/http/Cargo.toml
+++ b/core/http/Cargo.toml
@@ -3,8 +3,12 @@ name = "http"
 version = "0.1.0"
 edition = "2021"
 
+[features]
+secure = []
+
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
+
 [dependencies]
 tokio = { version = "1.28.2", features = ["full"] }
 phf = { version = "0.11", features = ["macros"] }
diff --git a/core/http/src/handlers/handler.rs b/core/http/src/handlers/handler.rs
index fa5f75a..38315a1 100644
--- a/core/http/src/handlers/handler.rs
+++ b/core/http/src/handlers/handler.rs
@@ -1,10 +1,6 @@
 use std::{io, path::PathBuf};
 
-use tokio::{
-    io::{AsyncBufReadExt, AsyncReadExt, BufReader},
-    net::TcpStream,
-};
-use tokio_native_tls::{TlsStream, TlsAcceptor};
+use tokio::io::{AsyncBufReadExt, AsyncReadExt, BufReader, AsyncWrite, AsyncRead};
 
 use crate::{handling::{
     file_handlers::NamedFile,
@@ -29,11 +25,7 @@ static MAX_HTTP_MESSAGE_SIZE: u16 = 4196;
 ///
 /// # Panics
 /// No Panics
-pub async fn handle_connection(stream: TcpStream, mountpoints: Vec<MountPoint<'_>>, acceptor: TlsAcceptor) {
-    let Ok(mut stream) = acceptor.accept(stream).await else { 
-        eprintln!("\x1b[31mClient used http, not https\x1b[0m");
-        return;
-    };
+pub async fn handle_connection<T: AsyncRead + AsyncWrite + std::marker::Unpin>(mut stream: T, mountpoints: Vec<MountPoint<'_>>) {
     let mut buf_reader = BufReader::new(&mut stream);
     let mut http_request: Vec<String> = Vec::with_capacity(10);
     loop {
@@ -197,7 +189,7 @@ fn failure_handler(status: Status) -> Response {
 }
 
 /// Handler for len_not_defined errors. writes back directly
-async fn len_not_defined(stream: TlsStream<TcpStream>, status: Status) -> io::Result<()> {
+async fn len_not_defined<T: AsyncRead + AsyncWrite + std::marker::Unpin>(stream: T, status: Status) -> io::Result<()> {
     let page_411 = NamedFile::open(PathBuf::from("411.html")).unwrap();
     Response {
         cookies: None,
@@ -215,14 +207,3 @@ fn error_occured_when_writing(e: io::Error) {
     eprintln!("\x1b[31mError {e} occured when trying to write answer to TCP-Stream for Client, aborting\x1b[0m");
 }
 
-// async fn redirect_to_secure(mut stream: TcpStream) {
-//     let resp = Response {
-//         cookies: None,
-//         status: Some(Status::MovedPermanently),
-//         headers: vec!["Location: https://127.0.0.1".to_string()],
-//         body: Box::new("")
-//     }.build(None);
-//     if let Err(e) = stream.write_all(&resp).await {
-//         error_occured_when_writing(e);
-//     }
-// }
diff --git a/core/http/src/handling/response/build_and_write.rs b/core/http/src/handling/response/build_and_write.rs
index 3b6bd1b..1d9e162 100644
--- a/core/http/src/handling/response/build_and_write.rs
+++ b/core/http/src/handling/response/build_and_write.rs
@@ -1,7 +1,6 @@
 use std::io::Result;
 
-use tokio::{io::AsyncWriteExt, net::TcpStream};
-use tokio_native_tls::TlsStream;
+use tokio::{io::{AsyncWriteExt, AsyncRead, AsyncWrite}, net::TcpStream};
 
 use crate::handling::{methods::Method, request::Request, response::Status};
 
@@ -33,7 +32,7 @@ impl Response {
         compiled_out
     }
     /// Builds and writes The http-Response, consumes the  [tokio::net::TcpStream] [Request] and [Response]
-    pub async fn write(self, mut stream: TlsStream<TcpStream>, request: Option<Request>) -> Result<()> {
+    pub async fn write<T: AsyncRead + AsyncWrite + std::marker::Unpin>(self, mut stream: T, request: Option<Request>) -> Result<()> {
         let resp = self.build(request);
         stream.write_all(&resp).await?;
         Ok(())
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index 4730fdb..f451ed4 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -3,8 +3,9 @@ use std::{thread::available_parallelism};
 use tokio::{
     net::TcpListener,
     select,
-    signal::unix::{signal, SignalKind},
+    signal::unix::{signal, SignalKind, Signal},
 };
+
 use tokio_native_tls::{native_tls::{Identity, self}, TlsAcceptor};
 
 use crate::{
@@ -29,7 +30,9 @@ pub struct Config {
     mountpoints: Option<Vec<MountPoint<'static>>>,
     /// Contains a [tokio::net::TcpListener] that is bound for the server
     address: TcpListener,
+    #[cfg(feature = "secure")]
     to_secure_redirect: TcpListener,
+    #[cfg(feature = "secure")]
     tls_acceptor: TlsAcceptor,
 }
 
@@ -93,36 +96,69 @@ impl<'a> Config {
     /// Panics if there are no Mountpoints in the Confiuration to lauch, as well as when the there
     /// is no interrupt signal
     pub async fn launch(self) {
-        println!(
-            "Server launched from https://{} and http://{}",
-            self.address.local_addr().unwrap(), self.to_secure_redirect.local_addr().unwrap()
-        );
+        {
+            #[cfg(feature = "secure")] {
+                println!(
+                    "Server launched from https://{} and http://{}",
+                    self.address.local_addr().unwrap(), self.to_secure_redirect.local_addr().unwrap()
+                );
+            }
+            #[cfg(not(feature = "secure"))] {
+                println!("Server launched from http://{}", self.address.local_addr().unwrap())
+            }
+        }
         let mut sigint = signal(SignalKind::interrupt()).unwrap();
         let location_string = format!("Location: https://{}", self.address.local_addr().unwrap());
         loop {
-            select! {
-                _ = sigint.recv() => {
-                    println!("Shutting down...");
-                    break;
-                }
-                Ok((socket, _)) = self.address.accept() => {
-                    let mountpoints = self.mountpoints.clone().unwrap();
-                    let tls_acceptor = self.tls_acceptor.clone();
-                    tokio::spawn(async move { handle_connection(socket, mountpoints, tls_acceptor).await; });
-                }
-                Ok((socket, _)) = self.to_secure_redirect.accept() => {
-                    let redirect_response = Response {
-                        headers: vec![location_string.clone()],
-                        cookies: None,
-                        status: Some(Status::MovedPermanently),
-                        body: Box::new(""),
-                    };
-                    tokio::spawn(async move { let _ = redirect_response.write_unencrypted(socket).await; });
-                }
+            if !self.selector(&mut sigint, &location_string).await {
+                break;
             }
         }
     }
+    #[cfg(feature = "secure")]
+    async fn selector(&self, sigint: &mut Signal, location_string: &str) -> bool{
+        select! {
+            _ = sigint.recv() => {
+                println!("Shutting down...");
+                return false;
+            }
+            Ok((socket, _)) = self.address.accept() => {
+                let mountpoints = self.mountpoints.clone().unwrap();
+                let Ok(socket) = self.tls_acceptor.accept(socket).await else { 
+                    eprintln!("\x1b[31mClient used http, not https\x1b[0m");
+                    return true;
+                };
+                tokio::spawn(async move { handle_connection(socket, mountpoints).await; });
+            }
+            Ok((socket, _)) = self.to_secure_redirect.accept() => {
+                let redirect_response = Response {
+                    headers: vec![location_string.to_string()],
+                    cookies: None,
+                    status: Some(Status::MovedPermanently),
+                    body: Box::new(""),
+                };
+                tokio::spawn(async move { let _ = redirect_response.write(socket, None).await; });
+            }
+        }
+        true
+    }
+    #[cfg(not(feature = "secure"))]
+    async fn selector(&self, sigint: &mut Signal, _location_string: &str) -> bool {
+        select! {
+            _ = sigint.recv() => {
+                println!("Shutting down...");
+                return false;
+            }
+            Ok((socket, _)) = self.address.accept() => {
+                let mountpoints = self.mountpoints.clone().unwrap();
+                tokio::spawn(async move { handle_connection(socket, mountpoints).await; });
+            }
+        }
+        true
+    }
+
 }
+
 /// # Creates a Webserver Config which can be launched with the launch function
 /// Takes the IP and Port as an argument
 ///
@@ -139,36 +175,60 @@ impl<'a> Config {
 /// # Panics
 /// Panics if the IP is not bindable, or other forms of system errors or it's not a valid
 /// IP-Address
-pub async fn build(ip_http: &str, ip_secure: &str) -> Config {
-    let Ok(listener_secure) = TcpListener::bind(ip_secure).await  else {
+#[cfg(feature = "secure")]
+pub async fn build(ip: &str, ip_http: &str) -> Config {
+    let Ok(listener) = TcpListener::bind(ip).await  else {
         panic!("\x1b[31mCould't bind Listener to address\x1b[0m");
     };
-    let ip = ip_secure.splitn(2, ':').collect::<Vec<&str>>();
-    if ip.len() != 2 {
+    let ip_vec = ip.splitn(2, ':').collect::<Vec<&str>>();
+    if ip_vec.len() != 2 {
         panic!("Invalid IP Address");
     }
-
     let Ok(listener_http) = TcpListener::bind(ip_http).await  else {
         panic!("\x1b[31mCould't bind Listener to address\x1b[0m");
     };
     let identity = Identity::from_pkcs12(include_bytes!("certificates/identity.pfx"), "1234").unwrap();
 
-    let port = ip[1];
-    let ip = ip[0];
+    let port = ip_vec[1];
+    let ip = ip_vec[0];
     let workers = available_parallelism().unwrap().get();
     println!(
-        "\x1b[34mâš™ Configuration\x1b[0m
+"\x1b[34mâš™ Configuration\x1b[0m
   >> \x1b[34mIp\x1b[0m: {ip}
   >> \x1b[34mPort\x1b[0m: {port}
   >> \x1b[34mWorkers\x1b[0m: {workers}
 \x1b[32m Security\x1b[0m
-  >> \x1b[32mHttp to Https Redirect: {ip_http} -> {ip_secure}\x1b[0m
+  >> \x1b[32mHttp to Https Redirect: http://{ip_http} -> https://{ip}:{port}\x1b[0m
 \x1b[35m🛪 Mountpoints\x1b[0m"
     );
     Config {
         mountpoints: None,
-        address: listener_secure,
+        address: listener,
         to_secure_redirect: listener_http,
         tls_acceptor: native_tls::TlsAcceptor::builder(identity).build().unwrap().into()
     }
 }
+#[cfg(not(feature = "secure"))]
+pub async fn build(ip: &str) -> Config {
+    let Ok(listener) = TcpListener::bind(ip).await  else {
+        panic!("\x1b[31mCould't bind Listener to address\x1b[0m");
+    };
+    let ip_vec = ip.splitn(2, ':').collect::<Vec<&str>>();
+    if ip_vec.len() != 2 {
+        panic!("Invalid IP Address");
+    }
+    let port = ip_vec[1];
+    let ip = ip_vec[0];
+    let workers = available_parallelism().unwrap().get();
+    println!(
+"\x1b[34mâš™ Configuration\x1b[0m
+  >> \x1b[34mIp\x1b[0m: {ip}
+  >> \x1b[34mPort\x1b[0m: {port}
+  >> \x1b[34mWorkers\x1b[0m: {workers}
+\x1b[35m🛪 Mountpoints\x1b[0m"
+    );
+    Config {
+        mountpoints: None,
+        address: listener,
+    }
+}
diff --git a/examples/1.rs b/examples/1.rs
new file mode 100644
index 0000000..8d64834
--- /dev/null
+++ b/examples/1.rs
@@ -0,0 +1,113 @@
+
+use std::{collections::HashMap, path::PathBuf};
+
+use http::handling::{
+    file_handlers::NamedFile,
+    methods::Method,
+    request::{Request, ParseFormError},
+    response::{Outcome, Response, Status},
+    routes::{Data, Route},
+};
+
+fn hashmap_to_string(map: &HashMap<&str, Result<&str, ParseFormError>>) -> String {
+    let mut result = String::new();
+    for (key, value) in map {
+        result.push_str(key);
+        result.push('=');
+        result.push_str(value.as_ref().unwrap());
+        result.push(';');
+    }
+    result.pop(); // Remove the trailing semicolon if desired
+    result
+}
+
+fn handle_static_hi(request: Request<>, data: Data) -> Outcome<Response, Status, Data> {
+    let keys = if let Ok(keys) = request.get_get_form_keys(&["asdf", "jkl"]) {
+        keys
+    } else {
+        return Outcome::Forward(data);
+    };
+    let response = hashmap_to_string(&keys);
+    Outcome::Success(Response {
+        headers: vec![],
+        cookies: None,
+        status: Some(Status::Ok),
+        body: Box::new(response),
+    })
+    // Outcome::Forward(data)
+}
+
+fn handler(request: Request<>, _data: Data) -> Outcome<Response, Status, Data> {
+    let response = fileserver(request.uri.raw_string().unwrap().strip_prefix("static/").unwrap());
+    let response = match response {
+        Ok(dat) => Response {
+            headers: vec![],
+            cookies: None,
+            status: Some(Status::Ok),
+            body: Box::new(dat),
+        },
+        Err(_) => return Outcome::Failure(Status::NotFound),
+    };
+    Outcome::Success(response)
+}
+
+fn fileserver(path: &str) -> Result<NamedFile, Status> {
+    NamedFile::open(PathBuf::from("static/".to_string() + path))
+}
+
+fn post_hi_handler(request: Request, data: Data) -> Outcome<Response, Status, Data> {
+    if data.is_empty() {
+        return Outcome::Forward(data);
+    }
+    let dat = if let Ok(val) = request.get_post_data(&["message"], &data) {
+        post_hi(String::from_utf8_lossy(val.get("message").unwrap().as_ref().unwrap()).to_string())
+    } else {
+        return Outcome::Failure(Status::BadRequest);
+    };
+    Outcome::Success(Response {
+        headers: vec![],
+        cookies: None,
+        status: Some(Status::Ok),
+        body: Box::new(dat),
+    })
+}
+
+fn post_hi(msg: String) -> String {
+    msg
+}
+
+#[tokio::main]
+async fn main() {
+    let fileserver = Route {
+        format: None,
+        handler,
+        name: Some("file_server"),
+        uri: "static/<path..>",
+        method: Method::Get,
+        rank: 1,
+    };
+
+    let post_test = Route {
+        format: None,
+        handler: post_hi_handler,
+        name: Some("post_test"),
+        uri: "post",
+        method: Method::Post,
+        rank: 0,
+    };
+
+    let static_hi = Route {
+        format: None,
+        handler: handle_static_hi,
+        name: Some("Handle_Static_hi"),
+        uri: "static/hi",
+        method: Method::Get,
+        rank: 0,
+    };
+    http::build("127.0.0.1:8080", "127.0.0.1:8443")
+        .await
+        .mount("/", vec![fileserver, post_test, static_hi])
+        .mount("/post/", vec![post_test])
+        .launch()
+        .await;
+}
diff --git a/site/Cargo.toml b/site/Cargo.toml
index 55ff9b1..1d8b400 100644
--- a/site/Cargo.toml
+++ b/site/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
+
 [dependencies]
-http = { path = "../core/http" }
+http = { path = "../core/http", features = ["secure"]}
 tokio = { version = "1.28.2", features = ["full"] }
diff --git a/site/src/main.rs b/site/src/main.rs
index ffa61b1..c4b515a 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -1,113 +1,28 @@
-use std::{collections::HashMap, path::PathBuf};
+use http::handling::{methods::Method, routes::{Route, Data}, request::Request, response::{Response, Outcome, Status}, file_handlers::NamedFile};
 
-use http::handling::{
-    file_handlers::NamedFile,
-    methods::Method,
-    request::{Request, ParseFormError},
-    response::{Outcome, Response, Status},
-    routes::{Data, Route},
-};
-
-fn hashmap_to_string(map: &HashMap<&str, Result<&str, ParseFormError>>) -> String {
-    let mut result = String::new();
-    for (key, value) in map {
-        result.push_str(key);
-        result.push('=');
-        result.push_str(value.as_ref().unwrap());
-        result.push(';');
-    }
-    result.pop(); // Remove the trailing semicolon if desired
-    result
-}
-
-fn handle_static_hi(request: Request<>, data: Data) -> Outcome<Response, Status, Data> {
-    let keys = if let Ok(keys) = request.get_get_form_keys(&["asdf", "jkl"]) {
-        keys
-    } else {
-        return Outcome::Forward(data);
-    };
-    let response = hashmap_to_string(&keys);
-    Outcome::Success(Response {
-        headers: vec![],
-        cookies: None,
-        status: Some(Status::Ok),
-        body: Box::new(response),
-    })
-    // Outcome::Forward(data)
-}
-
-fn handler(request: Request<>, _data: Data) -> Outcome<Response, Status, Data> {
-    let response = fileserver(request.uri.raw_string().unwrap().strip_prefix("static/").unwrap());
-    let response = match response {
-        Ok(dat) => Response {
-            headers: vec![],
-            cookies: None,
-            status: Some(Status::Ok),
-            body: Box::new(dat),
-        },
-        Err(_) => return Outcome::Failure(Status::NotFound),
-    };
-    Outcome::Success(response)
-}
-
-fn fileserver(path: &str) -> Result<NamedFile, Status> {
-    NamedFile::open(PathBuf::from("static/".to_string() + path))
-}
-
-fn post_hi_handler(request: Request, data: Data) -> Outcome<Response, Status, Data> {
-    if data.is_empty() {
-        return Outcome::Forward(data);
-    }
-    let dat = if let Ok(val) = request.get_post_data(&["message"], &data) {
-        post_hi(String::from_utf8_lossy(val.get("message").unwrap().as_ref().unwrap()).to_string())
-    } else {
-        return Outcome::Failure(Status::BadRequest);
-    };
-    Outcome::Success(Response {
-        headers: vec![],
-        cookies: None,
-        status: Some(Status::Ok),
-        body: Box::new(dat),
-    })
+fn index_handler(_request: Request, _data: Data) -> Outcome<Response, Status, Data> {
+    Outcome::Success(Response { headers: vec![], cookies: None, status: None, body: Box::new(index()) })
 }
 
-fn post_hi(msg: String) -> String {
-    msg
+fn index() -> NamedFile {
+    NamedFile::open("templates/index.html".into()).unwrap()
 }
 
 #[tokio::main]
 async fn main() {
-    let fileserver = Route {
-        format: None,
-        handler,
-        name: Some("file_server"),
-        uri: "static/<path..>",
-        method: Method::Get,
-        rank: 1,
-    };
-
-    let post_test = Route {
-        format: None,
-        handler: post_hi_handler,
-        name: Some("post_test"),
-        uri: "post",
-        method: Method::Post,
-        rank: 0,
-    };
-
-    let static_hi = Route {
+    let index_route = Route {
         format: None,
-        handler: handle_static_hi,
-        name: Some("Handle_Static_hi"),
-        uri: "static/hi",
+        handler: index_handler,
+        name: Some("Index"),
+        uri: "",
         method: Method::Get,
         rank: 0,
     };
 
-    http::build("127.0.0.1:8080", "127.0.0.1:8443")
+    // http::build("127.0.0.1:8000")
+    http::build("127.0.0.1:8443", "127.0.0.1:8080")
         .await
-        .mount("/", vec![fileserver, post_test, static_hi])
-        .mount("/post/", vec![post_test])
+        .mount("/", vec![index_route])
         .launch()
         .await;
 }
diff --git a/site/static/hello.css b/site/static/hello.css
deleted file mode 100644
index aba0df0..0000000
--- a/site/static/hello.css
+++ /dev/null
@@ -1,4 +0,0 @@
-body {
-  background-color: #212121;
-  color: #ffffff;
-}
diff --git a/site/static/hello.html b/site/static/hello.html
index ff042af..bf12019 100644
--- a/site/static/hello.html
+++ b/site/static/hello.html
@@ -1,9 +1,9 @@
-<!DOCTYPE html>
+<!doctype html>
 <html>
   <head>
     <meta charset="UTF-8" />
     <title>Hello</title>
-    <link rel="stylesheet" href="/static/hello.css" />
+    <link rel="stylesheet" href="/static/style.css" />
   </head>
   <body>
     <h1>Managed</h1>
diff --git a/site/static/style.css b/site/static/style.css
new file mode 100644
index 0000000..27589ec
--- /dev/null
+++ b/site/static/style.css
@@ -0,0 +1,16 @@
+body {
+  background-color: #212121;
+  color: #ffffff;
+  font-family:
+    system-ui,
+    -apple-system,
+    BlinkMacSystemFont,
+    "Segoe UI",
+    Roboto,
+    Oxygen,
+    Ubuntu,
+    Cantarell,
+    "Open Sans",
+    "Helvetica Neue",
+    sans-serif;
+}
diff --git a/site/templates/index.html b/site/templates/index.html
new file mode 100644
index 0000000..8645f34
--- /dev/null
+++ b/site/templates/index.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <title>LMS - The Library Management System</title>
+    <link rel="stylesheet" href="/static/style.css" />
+  </head>
+  <body>
+    <h1>Hello and Welcome</h1>
+  </body>
+</html>
-- 
GitLab


From 888a28d53b5c2c70e2956a9a8feada764cae4607 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Fri, 21 Jul 2023 22:22:20 +0200
Subject: [PATCH 64/65] Removing unnecessary function `write_unencrypted` due
 to replacement with generic write on response. Removing unnecessary imports

---
 core/http/src/handling/response/build_and_write.rs | 8 +-------
 core/http/src/setup.rs                             | 8 ++++++--
 2 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/core/http/src/handling/response/build_and_write.rs b/core/http/src/handling/response/build_and_write.rs
index 1d9e162..a8cdb09 100644
--- a/core/http/src/handling/response/build_and_write.rs
+++ b/core/http/src/handling/response/build_and_write.rs
@@ -1,6 +1,6 @@
 use std::io::Result;
 
-use tokio::{io::{AsyncWriteExt, AsyncRead, AsyncWrite}, net::TcpStream};
+use tokio::io::{AsyncWriteExt, AsyncRead, AsyncWrite};
 
 use crate::handling::{methods::Method, request::Request, response::Status};
 
@@ -37,10 +37,4 @@ impl Response {
         stream.write_all(&resp).await?;
         Ok(())
     }
-    
-    pub async fn write_unencrypted(self, mut stream: TcpStream) -> Result<()> {
-        let resp = self.build(None);
-        stream.write_all(&resp).await?;
-        Ok(())
-    }
 }
diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs
index f451ed4..9802f0e 100644
--- a/core/http/src/setup.rs
+++ b/core/http/src/setup.rs
@@ -1,4 +1,4 @@
-use std::{thread::available_parallelism};
+use std::thread::available_parallelism;
 
 use tokio::{
     net::TcpListener,
@@ -6,12 +6,16 @@ use tokio::{
     signal::unix::{signal, SignalKind, Signal},
 };
 
+#[cfg(feature = "secure")]
 use tokio_native_tls::{native_tls::{Identity, self}, TlsAcceptor};
 
 use crate::{
     handlers::handler::handle_connection,
-    handling::{routes::{Route, Uri}, response::{Response, Status}},
+    handling::routes::{Route, Uri},
 };
+#[cfg(feature = "secure")]
+use crate::handling::response::{Response, Status};
+
 
 #[derive(Clone)]
 /// Represnts a [MountPoint] that can be mounted in the config
-- 
GitLab


From 554dc92b91be13bb1e385b9c75d511b9d300a3d6 Mon Sep 17 00:00:00 2001
From: Darius Auding <Darius.auding@gmx.de>
Date: Sat, 22 Jul 2023 20:02:31 +0200
Subject: [PATCH 65/65] Add favicon, clean up

---
 core/http/src/handling/response/datatypes.rs |   1 +
 core/http/src/handling/response/traits.rs    |   4 +-
 core/http/src/utils/mime/mime_enum.rs        |   1 +
 site/assets/favicon.svg                      | 125 +++++++++++++++++++
 site/hello.css                               |   4 -
 site/img.jpg                                 | Bin 51549 -> 0 bytes
 site/src/main.rs                             |  51 +++++++-
 site/static/hello.html                       |  12 --
 site/static/hi                               |   1 -
 site/static/img.jpg                          | Bin 51549 -> 0 bytes
 site/templates/index.html                    |  12 +-
 11 files changed, 190 insertions(+), 21 deletions(-)
 create mode 100644 site/assets/favicon.svg
 delete mode 100644 site/hello.css
 delete mode 100644 site/img.jpg
 delete mode 100644 site/static/hello.html
 delete mode 100644 site/static/hi
 delete mode 100644 site/static/img.jpg

diff --git a/core/http/src/handling/response/datatypes.rs b/core/http/src/handling/response/datatypes.rs
index 9225ced..b8657ee 100644
--- a/core/http/src/handling/response/datatypes.rs
+++ b/core/http/src/handling/response/datatypes.rs
@@ -27,6 +27,7 @@ pub enum Outcome<S, E, F> {
 }
 
 /// Response is a wrapper for http responses.
+#[derive(Debug)]
 pub struct Response {
     /// the [`Vec<String>`] of headers unrelated to `Content-Type` and `Content-Length`
     pub headers: HeaderMap,
diff --git a/core/http/src/handling/response/traits.rs b/core/http/src/handling/response/traits.rs
index 6e96ddf..d3179a2 100644
--- a/core/http/src/handling/response/traits.rs
+++ b/core/http/src/handling/response/traits.rs
@@ -1,7 +1,9 @@
+use std::fmt::Debug;
+
 use crate::{handling::routes::Body, utils::mime::Mime};
 
 /// Trait for using datatypes as response bodies
-pub trait ResponseBody: Send {
+pub trait ResponseBody: Send + Debug {
     /// Get a cloned version of the data as a [`Vec<u8>`]
     /// # Ecamples
     /// ```
diff --git a/core/http/src/utils/mime/mime_enum.rs b/core/http/src/utils/mime/mime_enum.rs
index 12c63d6..1ad8181 100644
--- a/core/http/src/utils/mime/mime_enum.rs
+++ b/core/http/src/utils/mime/mime_enum.rs
@@ -4084,6 +4084,7 @@ impl Mime {
                 "json" => Mime::ApplicationJson,
                 "html" => Mime::TextHtml,
                 "css" => Mime::TextCss,
+                "svg" => Mime::ImageSvgXml,
                 &_ => Mime::TextPlain,
             },
             None => Mime::TextPlain,
diff --git a/site/assets/favicon.svg b/site/assets/favicon.svg
new file mode 100644
index 0000000..b4d9147
--- /dev/null
+++ b/site/assets/favicon.svg
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+
+<svg
+   fill="#000000"
+   height="800px"
+   width="800px"
+   version="1.1"
+   id="Capa_1"
+   viewBox="0 0 511 511"
+   xml:space="preserve"
+   sodipodi:docname="favicon.svg"
+   inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"><defs
+   id="defs290" /><sodipodi:namedview
+   id="namedview288"
+   pagecolor="#505050"
+   bordercolor="#eeeeee"
+   borderopacity="1"
+   inkscape:showpageshadow="0"
+   inkscape:pageopacity="0"
+   inkscape:pagecheckerboard="0"
+   inkscape:deskcolor="#505050"
+   showgrid="false"
+   inkscape:zoom="1.51125"
+   inkscape:cx="390.73615"
+   inkscape:cy="400"
+   inkscape:window-width="5120"
+   inkscape:window-height="1387"
+   inkscape:window-x="0"
+   inkscape:window-y="28"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="Capa_1" />
+<g
+   id="g285"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1">
+	<path
+   d="M487.5,128.106H479v-24.5c0-2.905-1.678-5.549-4.307-6.786C405.088,64.066,325.408,63.6,255.5,95.371   C185.592,63.6,105.912,64.067,36.307,96.82C33.678,98.057,32,100.701,32,103.606v24.5h-8.5c-12.958,0-23.5,10.542-23.5,23.5v264   c0,12.958,10.542,23.5,23.5,23.5h464c12.958,0,23.5-10.542,23.5-23.5v-264C511,138.648,500.458,128.106,487.5,128.106z    M263,239.583c0-0.009,0-0.019,0-0.028V108.416c64.137-28.707,136.861-28.707,201,0v27.161c0,0.01-0.001,0.02-0.001,0.029   s0.001,0.02,0.001,0.029v244.438c-32.237-13.461-66.371-20.193-100.5-20.193c-34.129,0-68.264,6.732-100.5,20.193V239.583z    M215,96.391c11.187,3.204,22.217,7.198,33,12.025v117.177l-12.34-8.227c-2.52-1.68-5.801-1.68-8.32,0L215,225.593V96.391z    M47,135.626c0-0.007,0.001-0.013,0.001-0.02S47,135.594,47,135.587v-27.171c48.563-21.736,102.046-26.999,153-15.82v32.856   c-26.767-5.505-54.078-6.777-81.328-3.75c-4.117,0.457-7.083,4.165-6.626,8.282c0.458,4.116,4.162,7.085,8.282,6.626   c26.708-2.967,53.479-1.562,79.671,4.165v48.686c-15.912-3.265-32.14-5.067-48.377-5.323c-4.145-0.078-7.552,3.239-7.618,7.38   c-0.065,4.142,3.239,7.552,7.38,7.618c16.331,0.258,32.654,2.164,48.614,5.647v16.66c-43.389-8.909-88.39-6.644-130.748,6.665   c-3.952,1.241-6.148,5.451-4.907,9.403c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347   c40.908-12.852,84.428-14.773,126.252-5.638v2.825c0,2.766,1.522,5.308,3.961,6.612c2.438,1.306,5.398,1.162,7.699-0.372   l19.84-13.227l16.5,11v136.454c-32.237-13.461-66.371-20.193-100.5-20.193c-34.129,0-68.264,6.732-100.5,20.193V135.626z    M224,424.106H23.5c-4.687,0-8.5-3.813-8.5-8.5v-264c0-4.687,3.813-8.5,8.5-8.5H32v248.5v8c0,4.142,3.358,7.5,7.5,7.5H224V424.106z    M57.29,392.106c58.099-22.934,122.32-22.935,180.42,0H57.29z M272,424.106h-33v-17h33V424.106z M453.71,392.106H273.29   C331.389,369.172,395.61,369.172,453.71,392.106z M496,415.606c0,4.687-3.813,8.5-8.5,8.5H287v-17h184.5c4.142,0,7.5-3.358,7.5-7.5   v-8v-248.5h8.5c4.687,0,8.5,3.813,8.5,8.5V415.606z"
+   id="path243"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M309.96,317.749c-8.302,1.74-16.615,3.911-24.708,6.454c-3.952,1.242-6.148,5.452-4.907,9.403   c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347c7.628-2.396,15.464-4.443,23.288-6.083   c4.054-0.85,6.652-4.825,5.802-8.879C317.989,319.497,314.011,316.9,309.96,317.749z"
+   id="path245"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M439.502,338.859c3.189,0,6.147-2.051,7.153-5.254c1.241-3.952-0.956-8.162-4.907-9.403   c-32.073-10.076-65.329-13.842-98.844-11.188c-4.129,0.326-7.211,3.938-6.885,8.068s3.935,7.213,8.068,6.885   c31.59-2.499,62.935,1.048,93.165,10.546C438,338.748,438.757,338.859,439.502,338.859z"
+   id="path247"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M287.498,306.767c0.745,0,1.502-0.112,2.25-0.347c48.249-15.159,99.256-15.159,147.504,0   c3.952,1.24,8.162-0.956,9.403-4.907c1.241-3.952-0.956-8.162-4.907-9.403c-51.191-16.083-105.306-16.083-156.496,0   c-3.952,1.241-6.149,5.451-4.907,9.403C281.352,304.716,284.309,306.767,287.498,306.767z"
+   id="path249"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M287.498,274.859c0.745,0,1.502-0.112,2.25-0.347c27.681-8.697,56.409-12.412,85.399-11.037   c4.147,0.192,7.651-2.999,7.847-7.137c0.196-4.138-2.999-7.65-7.137-7.847c-30.753-1.456-61.236,2.483-90.605,11.71   c-3.952,1.242-6.149,5.452-4.907,9.403C281.352,272.81,284.309,274.859,287.498,274.859z"
+   id="path251"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M441.748,260.202c-10.76-3.38-21.846-6.086-32.952-8.043c-4.08-0.719-7.968,2.006-8.688,6.085   c-0.719,4.079,2.005,7.969,6.085,8.688c10.467,1.844,20.917,4.395,31.058,7.581c0.749,0.235,1.505,0.347,2.25,0.347   c3.189,0,6.147-2.051,7.153-5.254C447.896,265.653,445.7,261.443,441.748,260.202z"
+   id="path253"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M287.498,242.767c0.745,0,1.502-0.112,2.25-0.347c48.249-15.159,99.256-15.159,147.504,0   c3.952,1.24,8.162-0.956,9.403-4.907c1.241-3.952-0.956-8.162-4.907-9.403c-51.191-16.083-105.306-16.083-156.496,0   c-3.952,1.241-6.149,5.451-4.907,9.403C281.352,240.716,284.309,242.767,287.498,242.767z"
+   id="path255"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M334.678,185.702c-16.732,1.858-33.362,5.36-49.426,10.407c-3.952,1.241-6.148,5.451-4.907,9.403   c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347c15.141-4.757,30.815-8.057,46.585-9.809   c4.117-0.457,7.083-4.165,6.626-8.282S338.79,185.244,334.678,185.702z"
+   id="path257"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M367.386,199.137c23.725,0.375,47.231,4.17,69.866,11.283c0.748,0.234,1.505,0.347,2.25,0.347   c3.189,0,6.146-2.051,7.153-5.254c1.241-3.952-0.956-8.162-4.907-9.403c-24.015-7.545-48.955-11.572-74.125-11.97   c-4.125-0.078-7.552,3.239-7.618,7.38S363.244,199.072,367.386,199.137z"
+   id="path259"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M390.671,168.704c4.116,0.46,7.825-2.509,8.282-6.626c0.458-4.117-2.509-7.825-6.626-8.282   c-36.252-4.027-72.278-0.526-107.075,10.406c-3.952,1.242-6.148,5.452-4.907,9.403c1.007,3.204,3.964,5.254,7.153,5.254   c0.745,0,1.502-0.112,2.25-0.347C322.545,168.208,356.5,164.909,390.671,168.704z"
+   id="path261"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M441.748,164.202c-5.418-1.702-10.96-3.246-16.472-4.588c-4.03-0.98-8.082,1.488-9.062,5.512   c-0.98,4.024,1.488,8.082,5.512,9.062c5.196,1.265,10.419,2.72,15.526,4.324c0.748,0.235,1.505,0.347,2.25,0.347   c3.189,0,6.147-2.051,7.153-5.254C447.896,169.653,445.7,165.443,441.748,164.202z"
+   id="path263"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M287.498,146.767c0.745,0,1.502-0.112,2.25-0.347c5.103-1.604,10.325-3.058,15.521-4.324   c4.024-0.98,6.492-5.037,5.512-9.062s-5.038-6.492-9.062-5.512c-5.513,1.342-11.053,2.886-16.468,4.587   c-3.951,1.242-6.148,5.452-4.907,9.403C281.352,144.716,284.309,146.767,287.498,146.767z"
+   id="path265"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M336.329,136.611c34.172-3.796,68.126-0.496,100.923,9.809c0.748,0.234,1.505,0.347,2.25,0.347   c3.189,0,6.146-2.051,7.153-5.254c1.241-3.952-0.956-8.162-4.907-9.403c-34.797-10.933-70.824-14.435-107.076-10.406   c-4.117,0.457-7.083,4.165-6.626,8.282C328.504,134.102,332.21,137.07,336.329,136.611z"
+   id="path267"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M93.96,317.749c-8.302,1.74-16.615,3.911-24.708,6.454c-3.952,1.242-6.148,5.452-4.907,9.403   c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347c7.628-2.396,15.464-4.443,23.288-6.083   c4.054-0.85,6.652-4.825,5.802-8.879S98.011,316.9,93.96,317.749z"
+   id="path269"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M223.502,338.859c3.189,0,6.147-2.051,7.153-5.254c1.241-3.952-0.956-8.162-4.907-9.403   c-32.073-10.076-65.331-13.842-98.844-11.188c-4.129,0.326-7.211,3.938-6.885,8.068s3.934,7.213,8.068,6.885   c31.591-2.499,62.935,1.048,93.165,10.546C222,338.748,222.757,338.859,223.502,338.859z"
+   id="path271"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M71.498,306.767c0.745,0,1.502-0.112,2.25-0.347c48.249-15.159,99.256-15.159,147.504,0   c3.952,1.24,8.162-0.956,9.403-4.907c1.241-3.952-0.956-8.162-4.907-9.403c-51.191-16.083-105.307-16.083-156.496,0   c-3.952,1.241-6.149,5.451-4.907,9.403C65.352,304.716,68.309,306.767,71.498,306.767z"
+   id="path273"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M71.498,274.859c0.745,0,1.502-0.112,2.25-0.347c27.681-8.697,56.411-12.412,85.399-11.037   c4.158,0.192,7.65-2.999,7.847-7.137c0.196-4.138-2.999-7.65-7.137-7.847c-30.756-1.456-61.236,2.483-90.605,11.71   c-3.952,1.242-6.149,5.452-4.907,9.403C65.352,272.81,68.309,274.859,71.498,274.859z"
+   id="path275"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M190.194,266.932c10.467,1.844,20.917,4.395,31.058,7.581c0.749,0.235,1.505,0.347,2.25,0.347   c3.189,0,6.147-2.051,7.153-5.254c1.241-3.952-0.956-8.162-4.907-9.403c-10.76-3.38-21.846-6.086-32.952-8.043   c-4.079-0.719-7.969,2.006-8.688,6.085C183.39,262.323,186.114,266.213,190.194,266.932z"
+   id="path277"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M118.678,185.702c-16.732,1.858-33.362,5.36-49.426,10.407c-3.952,1.241-6.148,5.451-4.907,9.403   c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347c15.141-4.757,30.815-8.057,46.585-9.809   c4.117-0.457,7.083-4.165,6.626-8.282C126.503,188.212,122.788,185.244,118.678,185.702z"
+   id="path279"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M64.345,173.605c1.007,3.204,3.964,5.254,7.153,5.254c0.745,0,1.502-0.112,2.25-0.347   c32.797-10.305,66.752-13.604,100.923-9.809c4.116,0.46,7.825-2.509,8.282-6.626c0.458-4.117-2.509-7.825-6.626-8.282   c-36.253-4.027-72.278-0.526-107.075,10.406C65.3,165.444,63.104,169.654,64.345,173.605z"
+   id="path281"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+	<path
+   d="M71.498,146.767c0.745,0,1.502-0.112,2.25-0.347c5.103-1.604,10.325-3.058,15.521-4.324   c4.024-0.98,6.492-5.037,5.512-9.062s-5.038-6.492-9.062-5.512c-5.513,1.342-11.053,2.886-16.468,4.587   c-3.951,1.242-6.148,5.452-4.907,9.403C65.352,144.716,68.309,146.767,71.498,146.767z"
+   id="path283"
+   style="stroke:#ffffff;stroke-opacity:1;fill:#ffffff;fill-opacity:1" />
+</g>
+</svg>
diff --git a/site/hello.css b/site/hello.css
deleted file mode 100644
index aba0df0..0000000
--- a/site/hello.css
+++ /dev/null
@@ -1,4 +0,0 @@
-body {
-  background-color: #212121;
-  color: #ffffff;
-}
diff --git a/site/img.jpg b/site/img.jpg
deleted file mode 100644
index 07eb7f85ac26c70344d552f56a81c44a0bf1b3db..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 51549
zcmeFYWmH?y*FG4mP@Ll47AO=g?pBHycW(<ti@OCYE-6qb9$LIeiUyY=!QF}ncM>#M
z7=AOeX4aZdGxK5o@65a>cdz^5-sGMqXWw(4z4vn-<{#Doq-sj4N&pND48VuS58z=D
zpa8(a#Qe|k*svcD96THxY-}8ST-+ykg!qJn1o#95M8wZXiHOOF2?$83NXf`4C@Cok
zNvLV4C}^HhP*VKoM=-D+zk`kQ6bI)i1rY%e#sB5@&<P;J!yL!z#KL$9z$C-KBExv-
z0Wbpq7&wo;{ZEJg*M@=l*vBWhcu(;O9&e~81z=)eVPRrp{ioNDcLzUS2Vj%oJbS?}
z|AbuUBkoIg3W2cXpLi^9tGg(5ClIWHpFF~!;!{!6(9*HJV&{0xDI_c+Dkd(W@J>-l
zSw&S%Pv5}M$k@cx+UB#ZoxOvjr<b>nub+QF#Mj8E=$P2Jl+^EO=|3_uvwjs678RG2
zmi?}&t*dW<Ha0c??e6LAgY^##PEJkF%+AgKTY#@`Y;JAu?C$L&PtVRTF0WA6H~+zf
z0l@lSVEu2%{tvjw9&uq}V`E|C{s$KZrthO+kzwP!;D7Q=UI+K1JNZk2Fg%L4$v>;R
zp0Wt)A}Bw3OyE<o3c=Zs|AF>DBl|xGEd2i#vi}X(|Bh<`K!}C$ICxlO09nAj-mf?g
zz<=9+{|Eo=1OM#<|Lp_+Klg#3>8C3=!>N4{_r;j`=!K~Vz|Q3=8jTNVQPh^W%xZHz
zg5B3!Axji1jWyvcZBQR+%znYUUCbj29XXu;uNtN1tpW6p)rySSZTUczktx!9s(4YD
ztW0c4T<8$@Gf$5;;lRuM2Y~&0*$~8Gd?$EQff49<M&Fn2PrH?F;!FMw7Ao5_`+mWs
zKIZOlqJ3L0H81bNJl`je8<n5s1f%*vx7@-&E$fSb@E~#Hg^x^1e5Q*dGi=^QW4SiS
zj!}+RWimD=qCPEs)Zdt@H)@(Pv5`~tD2K5yHBuaXkXl(^)oV|XmtG!n)7<e)3J4af
zX!6QVjBoJyW}U9g4hlFgt1~>^R1~KnG){<OZ@^WH+fgz3h5zY|N`cQ&Bhk%yF&C4v
z?@#mVul_Y#Dy*(j5mS5mVAbg_8LC8EJsuo`&HbJ^r%p3fbzh+w65l3|M&+!>N{V!w
z$2(>RHsRHs>;U)v&U{0$c-a_BiHXf{74Mc<$|pVpDJ0cZ#jBTD$jY43DS1~ZHJK08
zsp`CuoY!xbpMU6qe{%~49A*9VhR0;Rq~nR>&nryLL*<ibAjXdDimf!TB^t7Yqc-Zd
zE%gKE0!!`!5lTf~<H{9%Nd@AmTTj|8n-Fn|O$G+mT^|xO<&VWH%1>}%bfL&!9iQR{
zI!9IS_B`^ZZ$ZjP!(@nZht{<7G3;LO8~L?iiRs;4!vy5KOlm}8eSJA}fL~mjq|!^m
zwU>ku1^hI7Go12rEn{1<i{{wDBWY*J%c$Sf^+;obo;23q!P&oVE8FF%=~0mMt;M{#
z1x<Y}ueul#T_aV`Ylu5RVU)hxQTHRfJ^>3jo1lrC*LdetKN;kn@01PfE;k)D3oU<+
zji!ilnNX>q|K=fG<^a%9r1*ca*{(VcQEkR-JpkGkLV3+ClpP}rzZf$8tWrBPWcZcT
zUXNYLI{ZE|_C(v?FEu$L=bp0yN3~We5}Jy>vU1(g9&l>I(Cs)(Y&#oq5Qut9!Wj~m
zy_L2Az`mKn5;83m!%orn-F0NIx3#eaM2<d@qmj9&+<Hp!1g?D5Bm{E7`<sWi`I^xl
zi}YVbAdCJ$*XBLvtEpuD@Ce5Q@;$VtnT+M(mu{#+>gi5{hHxcz0_}j0X6|<&1;&`F
zU6Wc5ZRqoy9E_8xob^nRjI(}|%bJJ;jIgY|_CY*aX1}x4glT7ox^t$mfP11h;zreq
zJq~FE18&kS_~90U!wC^7G&V;^V+s}_|IA!8tr$i1iApxPh(*a$#D1;0ul@_+{;48|
z(a*BAk!<jJQcp^vUxj<PTN()pII_|rY-AxMF$Xr4J^*UpR;}_8bzr!E!?k?9M2xxd
zc78C7nk%>b9v&_T*32>Rmy&GINabwT(rx;9FEN)tP*Rei{xcP&j!{>s<RyI@S5C2|
zbR00@CRO9iu-wPQW-HA?!^|<}c`+ilLL!RO^QI}~4L^;x0$LVs`D?-4a5%ZqD7jG^
zMYt-zQeSzlp2`266mn|?*BhDlkuqie`U9$qIfVaOCsmX=3fD5&aT(HS{Pb0@qJH(J
zB5??J*5&*;h1ErhAhQeSbifz>JQm!gGp!XO655DMZ$wW7HTkO6LA1fxCYPrM3KuRd
zqnLtG_HJ!cz_R86z<Gh;Lh%70i!TM%Q|3D6!3z>B>4j&swm2NKfoK-pc^?3Cl;epO
z9nBrNpZv`y{iSav1_gt?_3l)!^^yCe9kj67rnaI0er5%&XJVb~X9eGtb!)i6-eDz1
zoUhU}^*Dp&OCA7!72Q8|k7)_Wn(LqbkqF?VS1&zro;A+)sMpZNP^8fQe~oFRC?=}&
zcNUKb$YtlO8B%VYS*Y&Otl@vq3Mmy@<qRrcT&Zn1RoM^7lJ*4mOhu8nPL^Vu^RXw7
zWAr{BBD}(Flf2PM{MQAm1keL@1Hb|AJ@^wo<q7sGvw{UV;e}Ymem7YFRoWK-@DC}#
z6aRC}%+0!7pw0t8s%u|*?7S@HO=VlVZ=b03Ia3-t5L^jRr1N+D4S*GkQQ&oTVlnor
zujVOopn3gow6WDm-2Bn{QT)?b-}onsVeU7RM@!;+a+I6#TiwVbo%$xWY;3{}hh4{c
zi|*+g-7u&aHc2Hw&%WE6nd7q9pPf*IDJ1@8W<5VoNz3tV0YvY7PmXrg7GLR{2b#Qh
zQOYN*TBwIt?`I9WnUC_jJg*Gl7S(JzQQb-@5gRy?W5Pm`!wG>e8`0y{?RnDj#G9$3
z&ilbl6%fK87o=!+{MRWd2M6Br;<AP2uTHnSuv@DYNP%r_+{Xr$bb0jTrXf{5;!0tz
zz`m*i<$5e5doztu00)!rF$qlRJ^++D;%@#$uOytd4@*Rtu2@z2)u2a9x=mr1;D|d7
z|DTq2+!bN))OiRk<z5z3S(V9xf51hd;9$X%6HQsJ+wWf}?*t7q=%aW&6DF_4$0|j&
zX1Fij8m@d8l_<chyryf~x;4Pi@1BcOp#Eae!40IKxi7_pq^WKJDP4!wL3|V#T0<u*
zKL&}q07=*7GFI>PT03;)$o5W&WVz_V=o!)&xh&}mGu+&Qi9W~N`xWVPotL@4C$h<8
z<tCen%ONchE1665i~rlsf^aG0i;-e?XFJziJg&>kW{cLfW`|5cihLdbBxtrhS<(uN
z!$N*bh0`TdHIV^&;{1pc6X6dM`y9W%{g>x@itcXd6F)q|)TM@8X?=FNvfA36%0!uR
z(=$j~+nq|dHK}WE^s%;=v>*ZY-NgQP97|$j8~Xg$14SECaUZ1H90mi&U##Tg>rBxU
zmz`+W3T+m;)?r1v-$l0pR3@pNlh>@HfZcm1y2^BYjh482#}3u`iEm5)hV_ck0o?8q
zb!Y2`_(=Y>%^bGta|-yBSzqICp*e%J$AJ_mE(4@&Oug878~uCGaAPL=j43WgHa24o
zAdza70jBR*`?Vs2s;f0dsR<)|qppoFIfsHJ&WHLvsAb~BE`*5{jqimK5EvgW3T7f<
znHwUyDBr0b?~}lPPUtt{`)`;30Wb?0fS}mHQNTAra;Sc9-&wxT2%O~A^5uQ?ZPqGr
zm7kwvXUP*b@<#)W4w%+d*=NffUtE{CXMv<S^ky@n&u;X>Zom*nyA701FF+#AL*n#x
zOPS~C`OP@i4{#B?bT4yYf^PYzP<l|dY?MP#^;kX0%f6z_@Y2l`zp6kzBw0|ey;|wo
z(9->D(T_!*%DOW@r_g%010g#ZM;FrNIgKqXGuvdpYsn`$V3fY9h~>W0za~$kmd@Im
zp_2{5m7d)X0AjBK&(bB>XX-C^lY_w&-mg+L6((PC`B5GF8GddubL!a=**RtPDy@3}
zFlrTAwP#j67gS7~?CY#a>izD`bg_{qegEqMMCzZO^-LuGgGalIeB-y^06zFwo4-N(
zPhVI6%f>2O^<N&gE9&IOfoS0=I+s4;Urkq$xxMW_F*RH{wFtbt#3^}~ydh~))X2C4
z)kZA|tr`_gIvd*92f(V;KG$jx7gADlE?w+6llzz<2-3nYJJA9Z<`Fx#FD$B_^B3~>
zmKhb>q!YP4({ulp0aMfBLzG>vhqq2PlKOi^Nr3I(O5K`k^0kw#Con5QyT+N+UQ6;c
zuQ7`5DDTmE*Xa=Kh<sP2yMxKgtNco8tXx#c#;%mzrvq-DkL8QZyvKiCnAjQp&Z}x#
z57tG)T<f2*AgQC+%w#D|2w|xWlGBWzQW3k$?YSZ{bf_CXW>k=c&@*GlH`P(6eUI}U
zD+8%~MHW`&uejI$WeKRBjXNEcbtFTUx2NfG<#xaGx@#H`$vE<cWk#6AR|E^V>%}}<
z_T(gInsYHq^R=O7f$WC9j@ZZ5S#aakp0>-T=SmKJ-ZTbZo1{<hKL3(!LCUA$mkDqb
zcSy6eJsC^CjVq6zdC*CY^?cxT=`Ue?03I$=8inIaxw5};z@sH?>`dAM-?QSf^`s?j
z!5!H}r%Q{u4o3)v1CVx7O5F}VU+GQRo>ukC_Zgh_?YB1f78dD)0rb-cKo?gK*IFte
zS^_COmr#_jb7+_xoHTvbX`ON?UBh*3*$CTESL??QAdV<TnJL##dO6E1s!#D4*-)h?
z$85+S;+~b?CJLTYG>wYqKNUQ*C(_vt`+MFCP|Z`;b@<oWxm`emg)B0Xz6sPLeGJsq
zTOL=}CnYY|o^sEk_C`6m%KH!3&)A#`pk<eomZvw89MGl#H07~V?gKz=_Joq`eTwL^
z{Dd+}U!3U0+`{*piXpnPe>tq`1MD|*s`)7CkBia>;`?{fKMwXCXOc2YP|8~A=o`O{
z(^N00Kn^E~tJZ;)bdVA1-hVwRTODybU|r||@ert4BDqfs(YrBtOZ+}l<J~#Q<GWJ#
z1Ps>`$<B|tkTw7+XIGFim)`aS5KB94=XzR92Wgb4hy1ow5A?dXRLBX$7$^Ct|JORf
z=mpXm=72cqf|`~P`D`kDNgTD2MlNBbTEubU?{KB2R{L5a1@=zqoxZ4g-f05&Lt?8O
z1Euv0dkS=OpjWzY3lP2jut?x5GskrMg&|n+O1}s8*U+_d*~8Rbr^?1T%c(Da`b9pF
z4*Ibin0u6NjyB3GGWtaPcBC`o7Cmj7X?JheGyz68LR?Y4YhyGAdFIV*UqK}UXS7vG
zLv~F0c^w82uonrPf?qc8+ckG9ci<os2i;D0)8mvRI!gDsD@j1pojh?+CiIv&Qf%76
zBu;;JcM6)?3nn^RclvH&^nQUbmYj-=Y3-Q+?)0Y?Fd=G49jR|po58*I`Dk-p@lF!t
zZgwkgPL@1H`PUB&w<s>+Z=Yn7&@3$RvyUaK4aU_fy(_a^^OX#in5Z-QF@N`NR*Kmx
zD<r;R>8F@FO39bRO6gAg5~4cgEvaES!~3O*r75gg%8q64NL`!#pK1+QT?Ow_o0_)l
z_3O})@J154T|qxP{nWlJ#@3Y8zPKNk?u}19@uZq?69)x6bG|h~-uBWkM^a-JgUZbg
zvMlQF%TL0+h)YUzR;r9%l+3UAS@r(lY}p>aAX$B4$Gm%%Iv938`6loz>tOG{=nNwt
z=#wroCKSD;b3OjVH%8dqn&f-*Rh2B~rqnvjeLr}g>qx$y0G5{I;djZD_H2-(n$hn!
zt-B3TD2YsN*=@|xwSnR{QGy};0d`xl#rL1<fqpQGEf*YvvnTH3U{l{57M$2ltXHAj
zs-o%n#1@S@`}X0oJZ@&5P~Q1l*lf9J`iIZooPBl+?<e*Qu`uMw%dJ;(TS@{V&Dz97
zB*q1_VKhRvnJtSHEp4Tk8q+Sty2p3B7`M%y%CeDyzCZH=wXs9NYUUdZQygQjzLBu|
z2Kf|?O76^N=0zpWiwWVm4SWPUMx7$L;VVnkx8<tBlMArc)4+f%SQ35WC!}=(RdOR%
z4G2-@(p}9UawV~hct^kGQc?r5D)RO<GF9$wdlIam-DvzV!B#c<MEvl#Bv_84qhk`t
zfbt2vz3$QO6F6mVWAQOy9603KJc(r{t7ne6nP_Snrh1dY^QCKD_(G;4Fss>XDWOD?
z3e6E@I^E8)l96;EO(!xe;t0Hy5X{>-XRdV1208*4ELx1D%bQr!lKYph=%EYkLHEDv
znU6^5cTL5$L<s1`T~}mAUW|?_1F704QDz8bZRAy2>1w9XGImZZe{7X<;fHgpOAy@h
z<E<fjL?W*YIo1tbp=qe8p2(kEhkpJJ74sKO@4SvBn$DS%HYqoupNen$w+1G-!_8lE
zxaq534|EV_6jiPXe!D)SUpuN##e$VOjy$gfGa2uK=h1Yt=LApB6D5tOCQqeBKF^Oo
z*~DzR)+A9oxsyeJdclNu`cP9B=ttke8h>4wC&3S!g9NOEB$#j}l0>}~N%hON*=@=#
z{*IG;oOr&<sY<U%vDlv{vAaUAn$<3Jb+*0#0TAwEwQQxhk$cj-z+Pvtd4H&)wUJ=d
zFR>MUDP8`0?a#hHq@=?J%&33}gd4!oBk5PBvk;<xD~l|~;W!}aQ#TmE_dt!`BLF)~
zUGKR0XPMK2OCoLH?X8nA7V8*i$(iu!k60NIKWI<FzBhS^8I(yQ=Cn_G@q~G_71nF{
zX7WzhWg)7qtm5g4YP`x3iZIoJ6XfF=s0o_~K1X$}(N-4LwN1aA{v;c~0e8S%bH7XU
zXM=(2LWmCteAn*P(6izsCp^bL?^nmq`fn0Irq|i;?tjTJIW43ZFZ!jg(3jEMIQf78
zKIevR7>~>bfScTZs2nh%2U21eXEyW`+>ptxsxVy08xgr^G+NGJl^I#w4Usti{GpT7
zgXH<#-`O823tQU9F{jq<X|iyXQ2~m2{jv<6%0SlCS~Dgh$}<SMvAu5x7k%b*{$g&M
zdBI3IjFMfa0&S=$&zGE5O#@FyL(&cYGr3v_f3T;}Q3NPUJ$1{r(e4(fWqf_`H%whs
zj^Mvye!wz#gU4?y$l2O;S-EQ=AZzc=1frbpAn+b`Re73!1z{0Y@{di1QeAhL+7rpX
zalvIJ&Usu(S4-Z{+KBSEf?6;lKFUi6^BcZwTztbG1G9QRLpW)o0z*yzdOI?OwKQw4
z8?~2Xb8%Hp@M3`?CvD$zZXqn|^_%5{h`nCXVZmYl`z1T5&-oqa*EyoZQsqqc!H&Zl
zDBO_6JJC=WM?ZM!;xUgfZn)IrTShsi1-#I(y^cLPb~N}Vg0VLn$`f^WrnQ<p`I{?Y
zI-cF-tG2*c=3@KnL6{gi&6uBEDl6GWY)lA4<V0&rJui*w*kN!r5}<lsH0J((St(!~
z>xz)h%1X`FLB0@kGa*2S^)Kb}xOZXycBzG$?T3Oi+^~H|vl>k5vwHfpce=wc{IsdM
ztdKA-`dnr0%ujI?t5UFYor5ueuh2cSM!Z5z`Xw@*9nWHUj4Yp4_CDY`VuPety#0mK
z69OaqIxfSPcxNE-j-3LMO-cOUZXULt;MYHpg6oP8fSyFBBl0KEDLAX?0@h!?tLzz&
zC(7tK^=T1B$re*dKENjD66R?cuFA!da<$~}!ic>nu%qh%5E}BuSa^(LG3_h-sIKe@
zL4Z{EHT%w<=>q_#9hZpj5d8wl)_$ZAUH2z7*?IR^vIB~^4+u>2m@b=qH4$wntgrOb
z;O*}O94vrQ&Yk__a$R|_t}v?^Gq1Ui;Vv)}?Y&1i>UYo^z#Qo%UO309;3|;OTTP!A
zlw@GkaY{MnwCfz`7*tl}*b+e~7?#4nbV<2G*OO8)uW!QYfS>-EtI=9qcEb$F(mwra
znzv};m&#$@+Yb$mKXw$y@Xct%D*CxEBn!}42)T@{kCKafdEW!Yk3QWOO6IWm>B`bL
zs^sZaW>u35Yy$GnnRbe~rr=O@KV6P#Zue3}opFp#ia(1mCwv(GSH<0eo13g}!CVbF
z;?$V~x<O-ak5h{piuiYI)UPr^IDLYs%bd<o!8=nf7a3CmCjDz82?4%WSVcCdgFXR2
z_IF8tM|}3lVcSBm!VgzWCD%rM5)Jh>tE3EC)VXdcu4W0zFQFD)(a$$8M&50e=_Ey)
z-F^a&rOS{_Z6fWWE5G_UE*>9t!etkk)pj2MHX(7Ie%amC_P$efM}(g%Sv}M_ld5;-
zJ!I*QFPzFD^mpW~5xTi2>emhMZShYnPcWp%q_u=k9{`6&9cXeMCU(Bf2Y@5Yl|9}4
zR49xA>mb~Tjn~A2YEGc~3MldEJ7mX7L-kh7&!D!(LP<u_98=byB75v#s^*t$4VQiL
zf3~saz>F%86FIXT%ikkm)ymDpp?<c6<D_*Fu9wWVCzjo7AkdG1AooR7m}Y^kj83Us
zW18&2FW(!`Y_%}>-)c{@N9{iir?Pz7g#>F)lqhqh|7B5uV;+6WDWu|9=o%(3Ksh#k
zE|g;}9aY3}9Q>o;z>w}f!8gl$+Sg}nQYD*ZH<+Zld<F@Q4l*c3IU+0^d@D=L?Y0Sq
z1#Tt0Al?XBSevLx3Kx;Tk@9qQ<o5>Wtt&$`^Uu43JZ*OoUETSMfY+1}rJrAXPY9Qw
zGadf<+TpeRe<@i>Au9(f;<ZyUDsw#&F&E9oIp5fLzd(3)Y>yR(0&U>cYsfo0Bam`x
z$9h9dsH(S;1%H#=Prh+wSZH}gdq%O|AA4w-wnBB?!|J?P^91({ag`Y-e<v>En5jqH
z1=A<@db+RjWlsOF6k`B-2hewM$CWkZMjZ!y(8iT#?EJ!z;y&v58BAlI*rvqwgrG3v
zvlW|?itHemZJe{(4!@gQu;2XbItyQvr*QdoPU@LkYX}KyrY_sX&2Nk{)zyuaurpK|
zSNyV^$z5ahjjNVr?k<+O21<nU-S-B(is>AQwH$KT(A~a%_SIL{4e(^BkfGKOVa|c1
z;#%t*m#!}f`e-2L+8wMCO9(sXqKxHJ58=)t<y&!4lJ9q`qwTEs)g6u|-t^fJfS;tc
zpEJ**OLe)aib0|K?24#m9LdTDe<|Ygr?tmNy=J%(nuZXX`|n<icHJFV=Xe)G2SfKt
z*QU4k0)}buq_>3b;XOGxfQ|bC^NyaeMYC>83{)C!#GzMU2f11*Pus=J*Zy)>K~iiL
zy!#DIC4Yd|<~Z)8S%-wh4CcUT0wQ27f$XA$D{2()g(f|&n9Mn0j;N{mv}DV98H*kZ
zgBPO%U?6)7rZ$5(2DL>_m!Cpz{se+e!@D&_=P<Nx>bJ(utL!$Sdx{V;q0P3r&ow?>
z;KQI5WaoSrhtk(adNfV^YUZVDA@+Q6;DsLoe%5N>dt$2I!~T$2u?Il<hZ|ya$(|+4
z0;p|(HFY{Q6>MrAU{pX;TFw%smARz!A<iUe2CMAI>h0ZAl<4J0*Y#lFd_4Ffok|yU
z!BSTx+a5^Vy;_XhDf_j%N0iJj+bCMXoFtpeAD5b#<mRvBue`iMyZoKKxScY+!vcHd
z@@MIBXUy@dG#?N=Ee;F*>WMxEa4jyE5>)o;c!=7L>cBrbsI$pWr0jZcboZhHK2Gbb
zjd`y<2?2WQhGcqfNaiJysbIZLS3_C9(JA}Kv7bKkvd(;<f#lFZqUNbtOVi5ww(TnG
zBttE;t|Q&?R|-uB)qZnr993s0o~<6k+3^8)PeJD-n(wtu=K!OYJIVW8d1J_(sV}&-
z*<9lkbhFzHxh(*BYU=7N>BJ{*=8+?qnl@tZ+FtgS#4t!tN87x<0Pf7&%r&5VFMTJy
z=*9WGhtg+xe<c>4QuBA>VV^S#0@)FekF_-sTJ=c_vouGQ8}zyy-#JUq0lF*lm*wK{
z2S8qO4bYl$h%-qE8Lqqo>f<9Gt8!9WcbJ5!K<l2Fo2$J2&B2-%=x#;h*Ep}S!8+}=
z*K^71W|Q!YngQ$DXt{%4hI9<6t`*+tIAtR5{917D{$&eSC$X{=)3UVFNGr>&j3Un_
z;y}Xg5}0W(=cY2eGl6$>@-Fp@eLv#3-qittt2<MadQUvTTlGHr_*>cHTr#NAA9_f#
zMv!Qxi)gK=Y(6oF@=Ojd7+wjHb27SYM_#mEni~DpBEnm5n_&`ZgF-va%!HoD^fMBW
z%3_>YS)l)dapx4GR`mlzI9K0C48Bz+lH?_pT{cI5stHVQkf}s&$TLTOPB}5iR;f*#
z*-2koHz8%R))mJ|!ezKIqJ`grC>%*0fD9nLK!Sc}qKk{8o=*-FmP)5Dy3jlY+w7Cg
ztF(Tvw5YU7G?*&gi&Z~u8@Fam%nh?(#C#lJY_A_fb#wt=MIG<xBSy>Uth5{`M41BM
zTlO{j5Sk&E=MgYr_xcKTZa-1j+)YIQPTCT`xg)i!A5>5wO)+WtpH!#pf^%zN)^4kO
zxu4gPV!?qZ6%Wt&HIGYN?zI>LGcXN?vh8!lMdhtXCNgV_Bz|@-`M310TmY70srOnh
z?UmBz1~ZT0xU&}@mGMFP!X~n+tisWVw8jO~Z<b1u(lh0!fvDZ8^lnXCkDcG*rGI_1
zDsQVO`#-yb%hwqhi~r1iqs5uk5cg)PtrL7~Qx}rT;h*7axdFEzB;|!x#09Kn;=+n_
z)j}x1yjCi`{KfUBh6HD#2LR^62r919-w6&*FqJ}5`lKu!tsrTtc;*wzx(U~kg7GR@
zbSl}ZdAYp&_`=&coX}6a;s*7~_N-4Fpspze=*$k+l07Rq6v=u+7!s4GL6k}H2DD;q
z9#jLV!bOs}TZ#K^bee)fFJx;i`Ldl~3{$Jfs4Aa-Trv{Vu}Km4WHlnoomlEzWJ^f;
zN@l?6XxgLZGpW2pQGXT^9%9d<*ZoOSi$ZCkFDswqNZtGXJmg{`B>rIT!14;dO5p(H
ztTt=oJ(X;vu@SP%Vb+-j3J<SuG*xX^Qs}6B{4WxhU>Xg}(n+~9HLb(y!!0gnBZhDS
z-yB$8AnALo|F#oNUoeCsd*0gJ!osYG1}ap&J<cSlvXodiFIcDKy#H9ZXczSX`rxL?
zjvA*?x+*)Rv=4v-BXZ(=AA~O-RM+vSp`^*92_}D{k82Ax%W(E+l5F5(3$9%<*yU?&
z5a7C-|GV>z>zjIKBd7bm=a{g^%B@$n>d93w2UZ2Nos7#4kN=GSyxj2Y7-une)0#z$
zv7@g^!H@NHon10XYuqp=AoM-aJgh9=PK#*b6s=bmLdsxUsqB4bCn+y=mbLx7oq?#6
zxI3$jaok{tIjw2)BA+<XMQKg)yt8cfV?RrhxbRrF_bGWw@cyPK_C{I%M%EJ-*qaS3
z+=WJPA~UVfV;sNoqzQ?$DeKr|OKM`m<?Iw21NWRKw8`r<QlOly1<><`L>B=Afpg4M
z9dMgF%~Y*g@bH8X(X7v{rlD%>?LS-yi~Xf3_R!7FQ4><VhfcHX!<?yYHsk4c6K-ex
zA;;+O>ZVT~%Jd+aw2gMMc(v4?8zIx-Bj*C)O{*^%n7toYMDxU@Y^&4C7CY#Ek+gQ$
zgBI!KC!`p%sJopliL{K`;|FiO^WFz|(JX#bc>owI1AO)ajlQCL9}9rENixDFmP>t;
zdpG!uYCa(uLiy`&RQJ_$R}pjw9gDfYki<v%5`VD2Cp^CK1@-T8Pn>B2ZjYnUN%>8(
z)bU9IZ~$<|s;<Hc=T1T>m(I8ZSye<UGQpf-(&r~iEPGBG0RCwCSgFFkMI1va{JMK(
z_&cUgs(5~a4o7y(B?+=KHLrZI*S-}XmaSf)vU?UF33m!1RR_M1QpdST|I{VbJ}o%_
z0}fUwF2HCdq<XbyEZUM8rB#6P;UhQxhl*TLk3UeKBb9uAG)~p|0igZHo~!KQZIdm)
zTN>w!*}sepec0$SuwJh_9qc6U+x=K@;{K<pz^v_5TnoK!?M4~8RtGxTIW25~!lZ<~
z%T^j*KrM!GSCT;(%1vUF$RDw-ivH^(K4%8)!E>S{EiQhFXiBC|cguL>0SvN1Lctqr
z{pv_m)1xrrbVyX`Q!w>6S-R67O0jW&x`~N=ra+u6;+*Q4u@_aVaK3I6Agf>eV1|Hw
zgN^k0P#=1oQl@fsJXq1=hB(@P-Pv(Wb!uw3ttB|N<yTV05qdBo^&C<sMZR{+jEQoY
zQ~6^KBVA^#kZ~xK^<P{9?@H?E2L0~WPQ0)ksjoBiLCRx05%P1qOMF79PYA#*Qdjg~
zCYO1!5F|BDx35uarSZMKVQke^58b~Xa&ys_>e9bE-;3%(e&WM$cmP<}ycTJ4>u6Ev
zj|};rqv5$hsFB{Pg}SFVmzFyhb&3hG$@~TDbaPd?ch$ZT_0^Pc?{fD^iqdhgbm$>x
zrSDsOj;-%a(T1={DfZufQ^ppes?f6%cwur4OJqpv&Y#QuKm!N{ia;L~SrHtq#iY-_
zwzSf`^<3|6{?cmC%FIu+E5Itu%WJBx(T9B{-F90Q+#-G)@<U!vw}dy|qk!1iBoVO+
zS4u@3&jl$QHP^+*Lbj|j9so5FD5H7rldPlN!YYx)nOu4Tjg)s$BL1{G6gIUC0O=9`
zIZ(TpeLJxO50BPmLuo6`3)d7u^rFuVvD3~f^_|+>oij^_y=BcpYFcf?YtlPOw0I?p
zMt`iv%O6Ltk=E}}3hQO{PCnVj<9w<q`x?^NWuIk{PsC{q_wiWmgipbb^f&)t;Y&Ib
z<`i`GJwDskA{Y0U0Ma;3t?Bi4P}<8B+@#OSk>AT%Ln&DrpCjYWwh(;XMC5u-rBc!b
z3PC&Uhv}Uuo^y^!@ZW|sQD<7t5-&f<Arhgbo2{4K3uJjrZTTF_b6-uJ<!yRSgI&@t
zM!}_)4(YMZPJy1Tm_dKVwm;KKYhvs>Nvc9;>N#}0K=_VVr02TndAdOQYO`cN_C62Z
z5csoZo!z-N5!Wuizgj=D+2W0im!);Od|yoDs+|DQfD(arEO=9q-Mu%~0B_1x`8!b^
zE?@!fMU@kpG=xH##-UZx4}46K`T&r()_18J8j)Jx9$lXYT_2HIZF3&clAW+D-HG3-
zF1{b2f))!m924~xxLWmU$tDZ0n9ifD`qFO_(TO}Ii>@E+*`|3YgU$*0N0sDn<_55E
zi!3I+<CmXY^9kLSaUbgyCX0}a-+-)5n$-`}i*LY62SmZ}4gynq%NJ%WKSz&B)Jx5d
z<taN-d?bnE7DKJnIuOmG4}h=l4{GJEOur-jd4z(5m$YjuxGB!L8)dGmJmDuWE-kVz
zlR@eXB6GSy@osXbug(ccmf25lj4Y4@w*fTg6NRcmbRWMf2Y8{<s*<(vt#K2G?`-h9
zN)WXM&J#SX>9XW?JnEV=UIRR=;jXnyro)3{<VS=R6=I{bn#z;yuE??Q6Dfi!RcjBz
zZw;m^YlKhr=JqAyE>u~wwHlL%sI{Bx8$kM0m;Zk71q(DfwZzWfZyFG`=LB=rAaRl+
zk@4N4K9{2IV{9$Slz+nsbvK@$3f6%-BMfLgWM8OBt&|L@^#VVrl+(%l41pi?v`+9Y
zYBcMm#A&6n-wrMA%W|q8$?T|4vsX9A{%V4HG9)LDC)E?rGW${9a}^cw43oP{cfjY4
z*h&s`6-!W&PqKql4Zt*U?-^{EOCgTX#<+dTbXqFojL#Ot@^?<#T9Kwcu^W2+YbRu;
zFn8?1xqzVSMIizA?cbt0|2p@&-A$o+w5TwIh_&y}rJ;2Qq4JsPmu|tH_Jbvi<q*#G
z?_UnRO1wRHe{+SS{E^w+tE82BhgYgj!4pTXoGVD&1ZP_o!o%Y@@-hF1+Ur!cKkrV(
z7h;MsZZKv;WvuTZK>^QGy1N@r@Ajpxr@eOah0pW@k{9U#Z|?o~4!IOIWD`2zyeLq`
zD%bV5>s}W2+x#^n7Dl)>amX07NSo2S@_HpZNq+6m1|zBxPgrh{CL!Fdx3P1?y?T{_
zAt!00$TaHCO?BYv;63q*^jnIrhl>e_L4T>4p}=c;hV)(jsqGPWcPngjM9J;n%KNqk
zxS5maAPu?>V{u^xUiiIz>`h|R#`BPi(-6AxhH3mi8|(~g-Wv=?l*Gl9ZenP%Yr_O;
znBOKbzZ_#lKy-Q~Q+Kqv-JhMNa<>)8)%|FI_n!F|(G9ofh_**PM1gDRDZP)f;}dU$
zC1W8qMm8&@6#jS=ikCm4PcX-h@c@)`%hmO$s<ec*A3&e)FlggS-oCxldjLdQBVgLo
z&O4_U*)z99Q7gZc89MH8JVH3{woOP3*)noc0#XkwdvA^J9%;wdp>@$qgSr*l?4LiO
zmL7DT!-*)jjxY$7$?IPx&X#$V22^TsHz?zOL$bQ%ry#wBOg0OrK9MZOzrEZZL;v#L
zylMY;Q7+*dFVv>0oaz$>LJXXOXIp=xPq)Q4)69=O(~0_BON)1riw9XbRP83USxQ?Q
zuBlk5U3+S4fgXQYo+A}FI|wmuX8a63#<IwNm7^f}s9QdTH7>&(<bk~Uduf1x#S8NY
zEHPwTi4KR}TL(e*tPD`1XnY;t5IB7zOK*V0f|JL)7xAW3(Z@g+f>!0UFE)3D373?J
zA$O*yT`sc3=OZw22ByX<DU!*g0-3$Z3nw0r5#ICLMu;;wnVXjeDDwa?op36=rRVPE
z%_+?6n^<Dji9^|SuW-&tvHS7XW$%62I@toJbsi3lZ{EyJ%3_7sj}cp;x>ca4#6&*L
zB<<5xvp!2&S~mk5os{320!qqE7ZXR+dc?}(x6n&}luMB4PcW$?ne&Xd&=Vo|VXAwB
z;CMF}g0Xy_OSF51WwO<%u&ZphIkBp&<h>x}NKQHH7wH(;A_pUS7tO<6wZXo};^=`a
z;qH}b+TAaDGq0850I;02suW3Okn;wJ&JuOfBe?(L>u=})Hf?_t|AcafM_|^GjMSal
z;}}CsC4|2=O?qA9+3NM25kI{m7ze&;EpFcHPP53+G@2kr8?>x}pX|#>&;6P_hu0;y
z2d2}i`<;curf-OMkQK|+%56xhN~dCnKli_Gwl0;K<&TF0IT%uptgM5?5ja1(JBVQ=
zX3P?BP^Pz+5}gBy-XX4>B)&KMU<H(dW!MT4{nhIPd)Lh&z{c!3DBWjk%X4P_>QzH&
z#Tc1iT=(DR_c!T9ZVi`z64IrOFCUAU=T*|9DYFG-rh8O+mX>3Tl@(mgsy1Q<lxHD5
zV<6G?mkwU{7=?eP#0?vnxu-z?kvy0~dmwQV(LEY+$IDJd?^YXYA7fFFY<URh8INZ#
zsr>_>S^hG67XDmQGtjpAr-rf#!)bN^%csDY%8w4V$)Ds0?8GXTd2fx7kyrCUJVolI
zLlafB?sS1Ee$0v9Xbco?8LC;uJA_V^ttd5U!XY`g=FL&dZN$Zm5!7VAodOX&Qxa8q
z;<e0qlo}*qI#|ZVr?Kdnr{y_YHui_ZSE{AEqt@E;un`$m&$F4Ukr@9aCXng`g`eGX
zCJ$#cM(M#<(uy4<68I~!lAzLmz=vwxoG~P;nbA@?99`o5lt)N-5g-W#0eSP$IXw%a
zLxSV$R5r7%T3cJwdCImWI&!RWnGZ|vFyn^jtn+8uU-{jxJ$jQ<)>X`69}|AozNCc#
zZ)M8sLn<Zw+CFW<(oX^;jyExHzEFPHS5hGU>H`V8NHj8^m9<{>LnTS3PhW6EMy6PW
zRAz1^KjZe@8l&BAKbWj6te*VBQ|vt1<w~LX56vb=vj6%ypNmimXMYi+0_4ir23R+_
zbS8JVAG+;57IpIq+7#I_Um|-tySTNp96<M&x2Fh_oW2um{?zfMhWQjpdfRbAygJx6
zCr#}CGiEU&9Ip%8O}R)n^<86e5bP?tbkA}K5wbzQS8KK_alUmpA9Lht<MK%wQyhKr
zA<#?8YX~{lEo76bJ@IRPV>^8$fLS*WJ+syG1V^QRSDtyavPj6Tg7(}OBt>70@*QkW
zTDe&tMIRQe#e0oV;Cdwzs>$r8%jMq(%xS@m>Hpp^{j59)m*i^MlbMowogf$Xwigd(
z@f&cHYHrtQ73*5Q_^50a{{4Q^%Iv3;YN5E`JBc#se<3>O!UO1OFwG0ZZ$^nHCdVJ&
z4!Gvg>B^ji)D&C@4^DM(i5M<3kQ`ya=^p@zM!rUGoJ1{Yl|Vy@UOV;+@9l_KB2wI8
z3|^2iX@x#8S%_^%T(W~{bj%6l$R?G*sr3Dn*%B<zy(P`nEtqQtNE_sZ6av1UuIIS8
zO_X;j;qxr9Vis5iX?^nsO>Nzkvs|9n$D1QuBG<j3x6;EN@?uyizjqwWul6}y)qgHF
zU06LvTrp289GXSry}n$3YhEhUxJsKl=>rycpoOnwQp>t39elDP%TF4bV{H@L3_@A1
z=eEFyKgv|uze2b(Qev!gF|KH2`;AsZYC~dVmf`embjric8ePV)keBb9fyx07fKJDf
z6GfGn+sd9MB>fsw<c34G?jKvk<AW)V&2EJ|AC<1fF=DO|+?7T~(e;x!8PWrieAJ}y
z%;C{xM44%d+G{|#JZ+z}({A5qMeZKXuoNu-{<Ya<Br0}o6{XJexdBO(aCWUkkW6qL
zmr#;8EFker;<94H_Hcx87B*=~jf_g(;F0F@il0A*e*}L&mHE}+1h;szw0ouF*iJL8
zneEvPdL0YR-hUMGK%7y5w;GEh{!ijJIG&`Hbv*TG?dJOup{ecuEXA&U;(gM)ETI$;
z;sh)%;;&5SH^ce=qqgf+k!(cA8+COM31=U5+1e-Yd){gE`lg++AC*BQb{CXlqU|$>
zNByP6_TG~uvZbinBoE-sA4}~(gu>r84)mI!M>$kwTaQi&ZGYPPy5L5Q1|S~*`@b<J
zmb`Y_Ormx-+-3O!Mn8YvOOi$v<Sw1FWC0e{*9u-hF&2xAlTg>N0&Gjcr3b)GIfmV}
zoU{bk(YvkdUy4W1aXxXgv`QI_meJSq+F)xMPaDf-2lo_R59{_5!`?L5bp<_VS{lc-
zd-Ai%_&U&iqK!*!Ra>JvorNc7XR6+9d><=;pEYm><*E!3!dU78QfmIi7;`;4Fn$1#
zN(JTNB4mmxt4Dh4*grw(i@#tqXWkQih5-%S_`yYfqDML#)^1*4qMjWBbfz1|$ppr|
z);b4PH(P7^vA<pJaO(SQRfY>&c2=|(cbbMx8I{^Ef^fBgS;zyxk7wEi@cH+KM!h;y
zsO@jlh3kaLegWg{P=1#><DG<lrKz~}dP#nqZtTNAqY_7VG(0@PeW5Yr5Y{-2`KEvD
zRpDo6`o65<n87?J^S2~7O;4o)>5l7MV@0SZImhVVF3+`jHb=#OnMgrGuu9ivxf~3U
z=OCHQ3AgGa(tT}5f_8BXb8CqFO38riNysCEn}v`~)oUndWvN!S4*XJDpic2Sut<+Z
z($V)B+vqXeOEuj1l(<Qbbb3yQL~G54onBpz?K>tWmE+uOi*%E~uV9!}HrCT2@^cr(
zEOjV5WJI4Vp0FzvrEbwQ$;M6Cu<yG#GV0E%yyYTYYxNQ3i^f-xQeXR57ecnj@)n7`
z|AMYQnaA-lZ>@jVKYx?tnH+~=XKR#3u^-GP+z@NYg4HC#t|AkU+KZeRM+%Y4X8i&+
zf4jb;UzXV66@lb;xz@D^P>Uvr&*NZ~_LO;Vd(~y~q)>r8qF}vSQQ)K{K`XK?B1rM`
z1l8&ev=QHOQnl-ECW$^)>8O(X80EwfWr9EBSOXgSj^~lR@F`0)6p_*$-Cz!OXWKW&
zz&d=cHtGY44F1F8Jhj4aHCw{bgWju@y>;O#%fSj*5r%AOFA_JC!<9m71sMRix=x8u
zb{{V`XZ)<$dOP?s?}qj?yIG(LwP#Dni+!!4pjaf|y1`YCh4o0P7u^@uc(eES6ZhK}
z);C_2vI(n{%&_LB+M47a3Uxv6B>a!X&Pbpo(Aie49*M2tEBD>zcdqVb=5Ih`9`e!@
zfsgxZ_P^>={!1v_JdC|?25zt4NYlTIJrNdP9Kw9j7#>IxvSqo40IgX-!e@k?zr6an
zPJLaoDq%+c&vT|@;qLcp7bK!#mFQ4oYfT+Oy2N*4yZ-_g^{6owT-~!wH{Q9K^k~va
zj8<h&PeSn;s5>9K30nO~r#7-;L`&8mh2KMaM5zU&PPxD0L_WPXkN6u3z?!4HiD+@b
zlbYj#Ln6`S2=9yK?b!VJy&u#bbyID1oQW*e1FT`G1EUg#9_D?qxm3}Y@y^Ve>IKcm
zVk{<FRyiDFk7CnhKWlT8Xq6MPyJ*QNk7C-ju%lY!X|tK(x8oEl%MEuinW*;oC19&|
zB~(mIteos@>?@iH1zP_B60#ygm8iRtpk(DTEccqFyPmAyATXafL?eFLq*<BM-Egr(
zc60>2M(F=YzsCFFyQL(zr*nKLG0_s2&$@iA(=u5=wB)ITJWzS+>pLdA%}n0<j6$aN
zBNMJ!={I*Yig~n+Yj{1mp}!&ls{oT$>v^2RyoUKTOueP?&kXl*C7V6(S|)3h!F~nF
zz9iWaxjF99b5~&yxnn?XcV$~mXU&o(%zo*gq*Cxmz+8N*<O2W?604&f^0R;4*!Y|v
z&**W{!asFgAYVJ~K(gqDBl$G8!yLmps*n2S9F$Gy!7J|LJ|%hvUhe`0H>_}417u_Q
zQb*tZ-Yjr|f4`#Kx2m5RTWBXic`OB;uBux*KjSkLBX&pe_~zl<=ba~74?a4A`1+Ld
z=KXSOoX)Y0-j&Ke1yg(d_A06HXVlcK++H5z6yQfUntbV%U+8Jx-X9v`c|{ChQ<dE>
zQPVuwt(2elxipoX_kt<jcXV-kHj2C|k$l~tm3Z;PjPqu_xRk5THv29EP<YFdY07%C
zZZnbE<?xwwb*L=oM!O`cdE;;UQ`bKhZBakH+0z(@m7l!}C4Y>c&44=S3$KOg!(qOY
z-2liD&h5K_jbO)v?q<pjMR>UnzlIP=L_p_S4rmQGRPsW2ePU09S{<FVTf*$i7=nKW
ziG0ju2l=jx9XZ#f0&1WM{;|QQg--tzHrRe|&0NfeRhc_nNmiaX7xAkzd4?0Y4er>O
zN(Xk<s{UFL$?2@DfN?aztro}WE<usNXX8Qc>*e><mNn}AE_G+DJd-MgN%Chb#QKi~
zOa`N&Eb63$fUVrR_{P@V@`K#J?fEG6;QL&pUU!8Vf#8T^_gs($XhzX%$~WTuUx(Ml
zpx<@z*pufiW@5{mDlBB>s#h^sSi&9!ku~*fHrkK7LPI%z#R2}GHm(h=1rHNptr#P$
zk(Gws>R%~9D|4fN-lru!iDbgA^j2!BPlXnrQ158E88e?H7`!9NtvZi#p!qU*{IM=c
z{s8T6;!EeUy`?~QEIR<vpFS5T_l{jz$3uuhR}{vW!KW1mAd<9jcW(Yz`D>+dVq9##
zAlnKOZYQ!=0vV5^R%>87(*R0!tln5W*t1xk{f0`m@tcDVF8i;cG5;J385w50(K)?e
zUk27y;PQE5@oGmAE_rob6%K3?HJy)q8FMtWSz!G7$Si1<bBH;=rqg^9@H@B6xG2Q=
z$SZlK3v*lY)ERJ5c(&NVi`T2P6o{tDC&H_0#1(_NnnH<xrY3xo1S2XmdX?YX6~7)}
z7r*DgDo#Qv75)4Bt7;wg2LcN6UROdIB?wz+fCGm3$!=dF3Qj3cWGSTHdog403$Qq6
zeZG|nx^f}e%es!FkF$T@P@~tAW?-4al*tzTO_0+LV%nHM$#492!+YWwm(ur0&NrW+
zhO=M%H}gl8O*^b@p{+K;F8PDW3h{-)yiiYFK@!6cE!x2vo>^b>-t#K+0u64m7TU6h
zlb7-YO&WZn^=E%YDi2VPuIf#O<>E%3ht!(%h*0qieDO5Rdo>Z+_T3ZDfU)rmGjZgQ
zSiCCxZvft`uoFFH@(U9NuHli$MBEkYLke<~KA4P`-fWuI%ZVMN8GohiAAgns!vOsh
z8-oZ%`TZRUE*{yIXW;{Ccx5T~C?|e3nh5FqQDnDICsIH_B0xRlIk+|rq(h|FZt#&A
z+ne%c$~=~P$?<q9j>c>Icc9QFDU1;TEu}xR6&D=ciUK*8V=@<k>`2++2f#)7!D`g%
zAFXb1m?=?SEizT#*|%qogVBpfLW#5|q~#P|$kOtx{G#H7IfxMDy-~&n?xHeUA#8#T
zVb{bSF@uhoGX?i)?qA1TYe~c4caiiRWN7C5fZZTF#FZ6-xT1lsKJTA}Z!b@ae{#RH
zJR|?En^Vq*32>%bNGslr9@c~m`CSlltV<Fu8!7y+k|*BfhgSAgL#lPv?ik=UfjQu&
z!4<_}0PX2`+LiAl5pwsk`TLIZ){-uDL#8sK?6&{uK5>9IB*GWSa`%|Zu~=!nc|1`i
z!6#u0XcnZtDG*FslP(!sg?pSOLfk0Z!#~>wS!4do50{n>lCMzguxzzJ7UpEzkD*7G
z?<I_OaKr9Gexq>BtEcOBk__v=zvppD9S-Xk-_kmVGy|WZmn_MV9m&?~-yivjp0VqX
z;pF&#{VS8+S}5urQ*lpnnp3d)ae=QXgs8{Y5IIIzCM3YSnIb}1Me-JJEe?26`7+j5
z*X63z*So-XM~>X3a22Jmc6ZT>bH9seas8-=6uq@O(0OvB>w55b_59Akm)SJhS54!#
z6w`Uy<&KkRHH{a2jv;b4$F%{8HMI&YXh_=Qy&zIMc(wR`YW>WG4XfN*OrP;z4CQ1w
zXkCm^^_=oC^iGoDHuYogYF_P$Uo;V>&s91!Tliauspp@BcXr1C;C5e1T?v(pLO}}d
z4AZZ=1@=s%qos`O$lB}w%#g`9#R9KmzkgfuW>oa=i0!Z^qKB(@JFUCc%R6&!FPt47
zB0GM&SZ<83O+Sh%<H&mx5ej`iZ-Rg5fO{_g^!@G{OXEmp2l;xxP`%@-KxMBji#Y4)
zP1JJ{1S_cLoKRhnMJp+7x&@2V{<b`==2Q0E1SPCCP(hIFA<;lO(=qHHA9_WgVi>>l
zy2v<2r^12OQ<LqX_fd};LfF)~an%LQdmkCQY)?r{jZy!<)eI?~DPoj+A+^efQ;2v~
z1iG?x5yi9+Y^2ee>SeYfw=0+OraFBwPlZ|S(u~op2ine6bLPCLRyS3}(>Z=bK|wXe
zRdvOZP{xRhS+nIkJ$YmAx0-nF4qv6-UkKox|C!rbf37fy{%Z8~&K{9eyWvV|e<=aX
zWm~Q@)Ki<{!%M+^OOcoP!hNnSSoK!kINpj*!As_7xu#lXUkyA(*=4#PHK*aH!YULB
z{*u&D<fL;OrEPf+qDBO7r~1Q3jJn&|<1HtTHd>(_R<$fW$K#D5>~831a{ar?0jI0v
z`&U3VWFMr;{CSLpxlkAGJH{Uf8i+sA;LL(Mrhg!%C#Wb%5_~Y?PZCo%pXDG`$eDOX
z#b84=m$k9&s!*QBA_~9LTIY*3<!L^x9=VKWsmUKZgY8&Z`RVQ)whJO=M%}me-5Bo8
zT+t(z)CjK5Zsn*0t6aRSy`b#i>;44h%%+RyK!bzivCU<Z_ry{yrL1>FdKO+A_6$>L
zo52H)i_ojCvi)@MtE=zCndS9gp~CnazY70HR2A@>bK%w1=^rpYGuX|xJ{I%2vm(!-
z<gm8lt*8~Xn_$_#Hi&-o5mm924U-mamEno%S;jAB{$@Kd0<huvqc*}Y8LQ_+O6-l&
zNGJnb8)IK~;KckM7VUSxq^9jb-!2`yY1Ck0ADI2=-Q;NgkAyYnuH(R+1jAQF@b6Z2
ztSw*vB=&xyN$e=yWJ>eF>V^afuq;Pv(`*uAgw0L<;jLpnk4+_HF6kHBwDFL*cUp37
z<+@$vl`D4T_t@+C5G*?u(A9|O@zrvJ60?zhj%DVZc+?wKk4l$ez<G*50`R<7qo=K&
zxdj*7HLgP7)<u=BPK`o_o4~n>eI|w`I`8rdUd9Nb{*GXUpo;m6i>r$4#Q%x7vwmyx
z58wU}6@w6@TR}k@q-!D{TDn^VB}NDcj2Z$GA}~P#X_U@M_vr2#l7mqagN+<)%xB-{
zIG%su`Tnru{_&38_wl~o=XIX1i>hZinR=zX+L|ZmBq4Gh@s-n3I`wrzCP*SYk%BxY
zrrlY~ktghqDUoB@d9j^(qo<}Tl)jI}@nfm;;HK|a3Li4A6epz1LR&KUWz!pFb!I03
zd(zQ_wi$VJ@=EOB&8)RsBvZ+mshREcgLcvl92C?iGi&03qK!aVHt*d%UB`xusk5%d
z4t`?b#OyTr4oRzB?82+36+Y|!mA-kEL$RAX-u6{0c)oukx-qDWxKfiWaXy(__maR!
zo&{U~gKDEIr5iXbW)Uk$T@=57y2YhE4QF_d$=;#iBAluwslJ-0q~mEy%BkCMDeGJJ
z51+Wur`UUTjtMk+UQ^=RZ~QTgdKS>~itf6guFOOf7SvH{;~vSf)l{N7*ACQ&nl#gD
z-+fV#Ons;DwOnxXC+}JrH5RGrHC>?^snNLqYB`WQm_D<4MZTaPv?v#ygwb~IjDrxM
z8&6%rgVH4=&yBC+OX^e86Fn09bPgsfq$Dl=ztRBUiyKfJgFlhwcYVhKT=GdX??z$Z
zL~NTbWe#J_G<PUm#r0U;i`R*0`gtAp`S|aNfF_b(DO9P1d>2f7xSP?-M)<zM&BJ$j
z?~3dE15SK>Vqu^w1J>I*!tWWP1&N;5QD^UCk?p=>;^F-V@bk78CdlG?Jj&es{RIWm
znp1f0XC3#_Ok`Z~oX6ry+&wDlmelP<wQG>{&WGu_cXHFXvc=>oeNIep2`CReFZ9jN
z8)3L~Q0+$)<NjuMaeR1Ukf>h$I*>tG(1r8P+~a8iNBQ1W;_pggdZ~>a<L4JdhF2cE
z#1u5TXcvh2sFF7Z#_;f4+VS-!i*NnGC+m7cxUVw^Y$&G_$!18Ow3yr&H#g26`|t&p
zF{c{DIHGuTQINLHd$m&;kj6zr;H#uMH_~_rB-EymKU4l8wP8q{uzP~>n8<VxYj31D
zj9i3A;B?m0>$0Vn3}=PI=ia?(n3TbU6P*0d&gnb1L_3_Wd5q#mN;JHFMYCw33!NPQ
zzH*|q^WC6XU^1FUZ|3%7Tvs)jI9V?LhnSI8cm@>Y>NTIU6T_NiV(_Y&7IU^$@BWsF
zIi+;8d_3j6E*I^zXHgW!N-Xy|`@C-Zy9mk4vB|}-V>VWF?fI)90k(@{#VfiVe)pG_
zU-rvAPSURVtr($Pe}Aw#|9NhTiZIRxv<F;VT32901ABv%@^vH!2Alue`@>=ss=1r{
z%6vFSXvU9&b9BJZ(c5dAoiSPBw*1*e=^yGZYe=*(R&ZUUo!*WE!Fr;VV>IoO@%6b?
zQcm3S9}_J}_CJyL!a$-l;5}yU`GakYf7Qk<k)_ar1Y&Pb_-P0$VV?A$PRjSGfH$8l
z!kZ4&LP?~B9y2t%_s|VZe`rb?%-y7DxccmPv{oI)CYTQ}{TgxS?52O=vLI7W%PVEB
zDPi~536Cu1pYSjn415b;%9uV8G}7t`&h1V(qexfPdhzh^OwlMXg)9U=%>uj!`0d2U
zT!5T-nui?7D?l!O6uQjjKatxvy@;RcSpCTNhS$vKeZ{?RXRwqHp+J>3jOj$UGPf#2
zVL#OGv81`Dqotv3ys`R9ml=8ww5Q7VlFD)4j$uksa|&KrXyr!3wG4`lq$MFI9$`9k
zzM#x|6CRpRyTki1CtZev8BRHti3<DYs+@n*+PojVW^0wH58~?=B>M-TyH?Rq>>N1b
zLbU26sJ_CWzuyQ%OO8lA=KqxVyI+YRh^Es_rdN~6028`Y#5S@dUy~J2zJ!t7Xez8u
z!prZCxo&tE>kIuCfDq)j!NU3aA+1i=f^h89Mwq?j{^E9KnMRR?D>YX2MmGzLH-7z7
ze9$u>|BW`Cb<dyInOKD$U&hYlKw+)(WNBiac_}za=tBpCRC|_uVyUmU|5IBj<j8NG
zBDP2c$7JtTuS%0fdVdzY>Pt__u^WV{f#s>1oTcy5Kvg@wN1|-pZ!)80sPk9bi&2S%
ze6eu4UDkrV&)&S%+Ix{vj!h4g%6nzzG)&*Us!JJH*OeK_Na;JU@`{E@jRgCffWF-6
zEkE(ei{E^B3RA(k;-7<|eHkh37x4%4|4sk;2S_u2KTikqTcm!#WqfI#PaKy~^P^$V
zSV%?aPpjB1?Ysx&E)<N-W?JQn6JAVvC;~UAH1vOm3%lp>f9+!K{^f2%X48I}>0$fD
z<DO}wsQUv@4X*PKE~+%wkOg?rSw&;vvG{iKAK>-8zG`Oag?|iRdfSd7xz$|wy7>wz
z!tEXQweo5sbw|@sje+}rf@1%_e`>su?_b_sR-l{{t&R<l0CZLhRd#Zp5nt8;zevWg
z=>-`#F@JOY!lRJA3W{u>|EQu!>EAC~vGnEcllbHjZcob$U|Xm>MyY+jeDV3fjWS)<
z!yUIxPS#2>S!*Z_Z(t)W1RWjtX5r|B-D!jGq{`O{vmEx;$>QP7TiqB6FZ;0Jc0G`Z
zN0sG!_1h9!SNHm6B~z6(1^inNpU~U{=p6)o*jTNg5rj{^5^tsIjf8%G&`Z`i9t24l
zw*x~|xEGrpPaeqL%&9*(ae0chBt^J>*HE6ylHxJ~o$b?V?E_zFtxRPD+`mfD+)<zg
zvI4NJM^xnv(>D_D`gBN#Dh(3rBSY7xTP@0C`@OpcCeO)N+u>eR6|0tPUu!Sl-uC9_
zN#V@3>YHtQ;+hqC(tu$okQJh)4?f*J((VK+okLk~L~gCDWO|0`I<306SDt7Hz+QCG
zI1YG*Wd}2z^HwnY?s#X?n;;?=isYBOxE4%r!Bj2>kZmqkGbjW!+)x%9?I8(*WNSc%
zgZ^C1g<W>qYiqN61Le*D+C4c~8vG&22JldnX=!PKCHTH6UTxy1;gtUDn)!0>Ln5mU
zc&0m}D#>lC>&di-<<j<p<2$!Bl&ZsRD7ugl7xq*k3ME~o0=lKh(feZ*&sZOICkCGV
zPdDRc$Ugx71=wB-vt3%)knYTpX{&zpxLYhC0>Eufv7UQ#Us=pLb=re!u(AIi;0OQE
z-`m0SWsq6Sby{DB(r+_ij#QL)LSJ@^c?m%rBMGO%*k!u^E&Z^8Hs>v!__4gUG5H$u
zf$W&7mu_KM>*myt?Swdau`SKLXU&!Nw1F+fU!-WBg)CHwau}L~ZVQJ)``ds1130fd
zsmlas1jkCz#|O@+2i%4bI2W!Acsei4E@I5xWgdpnKDy;+wbRK(yIY-3s#yiiBJtJP
z$xz(geH?37q;Bif8*7Dq*NVg0R2S!$@y{pM@CG;W)u&v8VP|{gs$1gVg`e&Y=?d}e
zSlleW;}N0Nh)Wem+C|@Vu(Pn|%6P_T)-PS%CC9>T&Q+p0wM^fn5n<PA9d}w}u+ppu
z3A=X7FLizIX7D{j>gxl|m8IXMzehVFuVyR=2AF)wOh?x5WS^B9<F4{Ih%j%O&-IM&
zgy<9ktBJ$E`7T*;L@&x!m!MBFi|z@0N&G4F*K4NHcg}Vg&JuRw>L%jl_0r3CXL^+L
z8c>4x+dN}>a+K|0xt+-w@)%t9#)?kQ)p>5|lJ*#V654d!WYdqNqDKQ=N=?7pc0CSj
zWI>gIGrJmVT<#XHbczU7zNNEX_3Y`*z9)MWkI~q$G$W~$kO|hdCvR;+XEbT@3AeCu
zO8)1FRfVtJW`J@(^7i0{n6hUxXTS&YERPz^;%;&+>$in55>2t95$GBHImcc*)8S_V
z-SFv257w|xNvaeQx^Mnmyc;6=75o>1#zOneA&(P@!D%ae$tY$MEc3t%!CnZ%ews(f
z)ZhV9+O&n?0%nQJFL8n2`i6gM{InKj{gD#{@>FYcE;=FbUitL}I!B%c|Mfequbr-X
zntcBHx7vf{1->F+<+}@(i~0Df%7c(6&H;X`6YOs!hL?AIHm>HGigtr!;-BJ$6AE%b
z@jtqwUj=;y->B_y)o1Tn`v;)Fg=wYgi(C;cX4Q-N?&JfjZuui=Bm;#$2nMTj>dy4m
zAT`^hE#5j_ZNLhx=l<w8<~HJ})<JC1-~XdKW&b_>n#}izAXhctb;X#Sx1ZW=S*$7J
z?6GW3eYhN<vfTvzV$Uf=WE=y%b#P!TRVLV|zdfFoBL00%GjT=$6=HyW`ZR=B)fVV<
z^kKHoxy%a+QbseWCsa+@gvq%%ZC{hODxf>y$h)ZSq4H(LrdX;M%I2;9W|($sB?!UE
zF<s@SWOOXZcHa*v)jP^y5USt7e3bFp?QlY`9n`PP2bo7w!WmbT5)PZMVdc-dW={Q>
zsAHynaFpXRj**GLhixhwc!dNRt(I?^lh#|}o%p9s%%lWTyxhI87Mgh}Y~vR=N2atW
zyMyM?%@2GtyOz!V0t1M&T#QjAhi63BT4rB8-wmDeIjXbnQm)FNqaLos{VpV3!vOWZ
z9OgcE%G;$ga!QJI`_xMI1_?>ysx7-u#O6{D^xOKDM7(Z>j`a^c+;&u)e6E3pT;XW<
z0NStpRA!PFaa=J4TuGu<Dg7_y5|0NG|71j`vAQZhxjx&p==}%yV8^}3{DF>)#Kmb*
zR6;3mF}U~#HKfZnSGUIN(0}<G6nRLk!uhLC4<&7-ErXx)lF6ase5Wu&>l_xu_zG|8
zC6RD>zWq^|;kv4RKQ}g)OQ?;(V_P@0sJ$&Hv`$ZjPLn)cOt~ZYH^VvCr&GZd!SyV8
z=>lIrDw6q=E39fY7#lZ5620uzY$3K@c!3H0I|~HgtYXSZ91P&q?;RO8`;IccJuV5_
zT_~vV9n2X6MnE1<R++5zlq|`tZ<hdnN*y5|911@{{DPVyc&E{o5hKo2>0_g{$tthm
zJzHEyte5a(ubNS24!G{96W1&4`qPehNpDo;8xGl}$1jGTwshQ6ocx*iXG2MaFYBD4
zu2CYf-x(T`ic>aP9Y=NFdG%5u_~&N^Q_OuD<9RIX_DbA^7pK+A?mxhNsrx!hh>ldc
z8_Tji5`mGgy^Kh4Qmoyr4vyUc2a;0<=$sylrHGBeTqiFR6;|6j#xG#Eu5;5n*155F
ziCi_E&yU*omlUtY4nZ8y8@P6EW#Fvl#uoG+-~~gE8=F&Y3iG-JAdHSAZ&gYkak)9q
zy!i*%h-j9)-s-CfgMibDf?DF{f5t2-Z(?E<ocjIC%AnmX+B<EWOO=N}WL0$2R`WEe
z%F+DaKzz|3R`p8o5Aw)zPf3mU>Bc;1KC23_pS=Yy8$tr0UP00G=1M<c_~J^p)Cl>y
z45cPY@-@^q?+2gyxA(Mm=MleAb1k<WC)%wOaW~iE!vy5iZI9a~gm!LeDN-f|KK_}c
zqjST1E6O3EnfF82Pmz@BtPe$Z)6nUBYzBbhA}uALfK~XzCE`}E>ad+}Bg^K=5Q%_i
z`pn%(bGC&i{{2DTZ$j|5(<5tkiNv*2x&6};JEe+%nEUab0^-v@*t54&leK{X9Ss&)
zG!8Qqt2I@1792XE>GvOoe*!on<*HENeA~RLW9l0pDc<;gTY|M4wnZy|&5R-}oPhj>
zzaxU2b~5r5PmCuS)u|e{2PpTOl8E364xJaKuZJ_ADCvkOoDQMU8E2p|uA%xsr^WH+
zQ8%#y$HtJ;YtX$D-K9dM>7MOZ)Xx#Xs?{81l$c@;UUm7G^reQLIzTz=yebH<lAvWs
zt@^O>jwXTn4lp~|c0OiVD4IkD;=lD|@vhv!*csZUs&M_%sm<rVpR~{%V5BTF^X@eg
zQ9yGO8_=Ci(L4Xu#_h_qaue}M(MPxE=bjR_-+N5@q{m3J=2Lt*S}6a$8Q@eg_XKS>
zqnvrGO<Xc^`xW8Ovcb0;jZzXh#^<UyD)QX)%@|)gk9U0w|Hb)50R_nkL`l54pW)Rz
z@&)-|L8`F*TivAemV;!4-f}3#XxP2;%TsAHUh?;q#~}rPu|zP;vIX-u!GM{tW!9Av
zJ3>jx(H=^QO8R+l;g!dA;<skG*1Nfi;V$G6lc(kgzcHZBCq_{D5A;0oW~cc~M?JC!
zc?V=q^I>0DRjn?~Kw<y{3Myel@lORVt~oOUeE03_@$$F;yftb(ji<`7+EQd`uRQA7
z!aNvn2#VhCV>SCxnNr^%@%taZbpppvAmt1CjQ<OHg!%_qKpM?7F1whM8-DaX4}@51
z{5}8;`Ee+d;9(%pexUF>yL;M&x}hDdlk=vS;`PKxtZ_f`HI^~Ot86zFVKgD+%Xc&D
zamb4LT|P|Z)-6!}ouS5e5dW-`oQ{oG?@sq;!?f`;s0+eF|GRDb{{S&o6AMeJ#GyGh
zpKCh1eB!Ok`Tnp65C&Z1I-~$$$3Izhn(iBwY%;2USfy+PWZjXL<0IPdTp~WC!gZ%@
zUmRQ8^r~o~mkYkcpE^t!n=dUDd+i!FUJ`&;ryuv~auZg0r%qeHP+1{p9$G89M`%^E
zZ*1=HQpzajOGT|se2yP&xL~4qmBoI?Gjr>ltQ8UX0<8EyosXZTF8)_>Nsr@m+8~l-
zhb^AX-t1p(#@wGK=!N{HUQfIh-0z5hJZ{ADMU4M=dyW3>bg9SOA9&Mzn=#V60?cF-
zy`kUMlsshns=>~6aX;t9#7nhM2aGi;^>Zm`c#*pH95m0q+qkLnp5|9>E8n^)Bjsrr
zEo4k4<K{(6V#GfH=BuvXb6xSa*Ns9JJ23TY!RZi+wNTM@&nS_`ijkW^5#4sE-Rg#0
zdxrWaO8d|Ikj!UZ<bOe7B`(90={J?%%aTD~c5;%P!E)eF30hd1-j#CS507WQA6oNM
zKgcyZE1Pl`er0RjM}u8DPn|wns{aZO&~SWGSnfp59wx>c)cTredUo_#3WU6iqke{Z
z-FWee)e>szeCspkMjk8~&RP;<Z36D~XeJk99zKLsK?JOKPry2(vqwffx{VHsGjg4G
z%3L+dZ-<y-Th2jfX*tJt0%<IPG;+LQ2|*MG<pI1oB2&r6O{iC4$XXlV7lKMK_8!XR
zLjsGtq5@Q8c^Qh-?m+V3eCHW<ku^xtNA^G!HRxyk1&o@iJM)tfPTH0;YBdSy_tAGt
zX`1*=kY2S#l=6saeoXix-pOp7tUukM&;dd&zT4U0`z)fUw7!&TPvJ_Jok^{{BG38G
z%k*YQKK96N2mda_Epz>-n-s`Sdp`-X6L3a8W>=KfIj-i6BK|!WwkLP>&vQKvKaRHX
z>tZS9tNe(MK&Y0u`lm@8J2fUWIs=j;8xhTDFBR5^jW@LiBew_m_HDOdF|RmTW(>7x
zI11e2*S7SgmM|5eFDKl-s@|m!-NLs~=PXDu@?%7qzzj?x`6)2jrkS1TcbDp0oNd>F
zyX|_tT5J!Q&2}3Jcylrol&WBF$<YYFCB_jn8@_dpx{t1)N%M)}@iJHeq5lE?zy^Hk
zvv;Da3We#*Jkj5C7*%>pl%Q0X^S$Pa?291@Le3O&e87a@j)Sx+J-A4mer9OGs3&pv
zscG4-GukVTZ9lZuc95y#6Tb9aL<4W*HpvCg_k+q*g7Z)Q=vm(Vr+Sekg_iO`ruq_T
z<8l;=XL&TaiYg~sL3v>#{eXXfhKTkHl+>?1dBoRLZ(Zfm6G7oR^g|(Qz3EZe`yE_K
zFtXOCN2Yg*Z(GkAyqK_53-0LUP`3q|REv`&5RjkbdwC7kqvH#XX(lDW1j~k$&vNWR
zAGWV@9EvI1o<2X<!52P*qg0c%LN@-&(-eX&zJ6fXvlD7-B3&o&?Rj%y4l3|_`cwB-
zssj~ZwBV48sfL4&F9Hq_XIkY=`)%#CPrQUVoOE2xZE}$jbwzD5nUVfUhXc0NP$K_)
zNgz`C`D#sY#(-m|@*|tOZ5|ae*D_0&06{+WcstOQ;>~!iP{7XOi?Bisl)^+kIL0`$
z3ZG76f1Y56p?rBXU`5CNpz*d5a7A6J7Way&H?(#wg=?Wkc5j;XZ#hMmckC&%CKvdd
z^<3|T{L480g8vP4FU5Bp-bfnG<2SBs0D6qHn!q}rmI0YztRwvt;O;tYldE|?>gMKf
zs+mI12HM?*tNCGSEjtnjMSI?yj$QC8#mz>m69rq4U|oaC{*jg0Rj1Hh?ocW*rN>II
zFT<ZFWwBrER9e-~&Y&Nr@*L(3aRg&+Zo#W3J+FMth0Z>{%iQ7JB%dIUyB)+b%P`nA
zILI^WP1p;73v*7knq(yp<mh=rPo|ri{5;d$A#&xv_kQ#PN!^eFe+`4)->(DvmE?_|
z8u~FOBylou39!dQq*AEP4?g;?7UO+lyM*hUS-QH$0M_6X-)JAevW$;RC{X*SaFy7?
zBGX6ujl`x!ANjeGL&fb&X1S{k&K;%F5w_ujGRG&HW>26LECg^KrR(XRMzSrqhTsVu
zMU@1&Vx&^aRyv`Z`z~!VnB~Bi=xfXV$D%h0<#aQ~@jDOakA2*%;Q+^`Z;B{a>Rzt+
zN-H;e*2VS@cK1c)KTAj6lVn-%st@Zz6qsJoY4H>>HGn3cR9n(}#@l$krj}RBxyxm5
zHwP_oE!0VX8!|s&zN(&3yg+^B^b7q}2Youzl-nY4ci^mw0>$uo=2V7FI`BAZQIDo{
zkRZ4sD%sjTb7Ng)Ai3;?LD(0rM9?5nQb2_>>20k$QgK`#C`zUt8btJ?TS)M9fsDw@
zCgSa87XnQZ7ieY=NuJ|u!fS+HJ(kZVi@m@%G+TUPIMVCnc6-m7REtXo&AYbuOyfD0
ze@F?$k2HTl+f*;lU`K~lKemcfw)n2M`K}OkX3<g>V{=FLHHYa9^Sv3h)J_?Kl3q?m
zV^<x!c4RH^yz5-|uv#Lc>vYPWi&|ZOB-+!5p2Qp#s4vv`Nq?cFRB$Q_dvsmQTicHF
zX?c4}YpW6ZA=WXSoT}_TdyqfO*tIsx{3CJtsxiIPB_k+@Cu+yxu$S!W-mpT(*a8<D
zuIJou=BRPvr%mQv=;KxU42e*vp`9?wiwp#RnEuURX3K=*X}ni_IPx)kaK-KmhDkHh
z0z0?R9HEd2@{qgeleldrA!cw#xvOl80hG@_v^uaI!xeK$tV3K7!YU!(LNu<w5IG1I
z*4L^%oX$~xnuomMn{`m>34z=n%oFYxHs<}g%)qxub^^<aZ<$3U5!&{6&z~>E>6}u&
zR2lWVx_Xn69MeM}X>#&M>T&z70%R22iFb~=&{o00Tmx5=O!I`RY4V>jsF*K~m`q&I
zkyTsAv?lpTQ<zjl;>*pG`Qy?LKo%>jUzMB5FY|dOVh`=)w?NtUCqzg}LWQQSwz_y5
z8el*%smwC_-;73}qc7EUE9LWUq_mPI3>G5p_bbE-Ln$p^Unl=bjX^}X@Ni@*1~P}S
z4?n&1I6xyF82l&eCo6TjbMOyP01Dc!SIV%tP9-I}j(ke-eSA^mNwXxCvt*D}!MbB%
zdv@Op=3J)57|-_HvgX~3e4OFH8BBMkQh58nX~{Vq5BUZE3EmK1P5C_FDll(IvVnNN
z`73(19zQbJu@nEufl}!%d+zveqC7ZRlw>!!8DbpfRO;qX4Hiz3y`iP72DHxvM%l$`
z?8u;>V3`R<xcbVyLCXp{uj)VCe^ar9&(Ny-VV&iIUGmRn&nh2x9zSi4m)J<i+k$Qi
zCPy>2v?Yq^j|{;~ac_$c5u4famVNyiY?;sruJLOAD;x-M;Zz{n>vCtphAjSsv?m#R
ziIS6%pnWu86vzRFJ%!pg$9Re6w)Fh2ydTD_wa1|9xJ}>xAt)KLx#RYmc`+|?vH8nB
zt=Lzw5z(>4e2$J3doSAm_EY^;lGAzk63@&~Sl(BUE(2cQQo=*%Kd#lI8Ko_iP03*^
zXH{wEzVUzI(z9B&<xlc%e%P|1CG2si4rXSz77Q5`d~mP^-t!3QV9>ArtQ+@nhdb39
zN!k-1YBly(D0~dlHs*s-)Em>?0yyXO@u&GZ%E?s@Dh8bAUKb08Idh2i%nKJL_#BzE
zif4+;q>gw-N@!BkaHo(fIw9t}kc+;ZK(<O_JcXHcr~#BT5JQ}5IQPZfo@<i~!tr&j
z@{`=pB;TLZy9j$3?Wr)7xpUo?=F5<NF7uVkdsu~)a~Z~@B~6Tt74c;3b6m?{;2_Ue
z4RTD$_N?=vwPwI;tl@<BmI}`fnIY*<I0-%vyRL(CgWWVwJ7`;Qt!hy~gl%?X68{<*
zKOTwUhSZ-sM-!F6Iw;ZTqg?G-Gb%NYCI4Li|9ne%*s0^?_L|G}P-2S8q_?9lh}Sk`
z>?NbzA^9P2xIN8!R%CllYM^#n65oV2HAA7UjK^oG=|$uzBhO$@aL!)mFfLc__*liI
zNOb)ju5$A-P^x@r#YIbeOH_}FLcV@+mjF6LKjn7tl{eZ{cqp-7zt6)+2X^bPu7r@W
zP0cViue<d4B>Z$NkmQiH3&+;ruN8FaIe0#2g)i}v5z5D`Z1Wm|e9bvxQ+HYjEXEWO
zZOe`mtr;qZWcPrltY}Zsn~W!#%Xg--h~!ekxEnMFq^K6g(G@R0Xb!jD296hFQwz^U
z@9!n=+<Y-CcL*ldLybuc?rHrU&12^$e;VzLZNs`X+m6_H3!JPM2RHEz^kL6!_`mWq
z{3XHFJVxyH=AC>SWGPTOT)Wmfj?9OlKi9LuUN1Nj1LI~ZCMc^`?hS^`h+Fyfe<0}|
zn*SRP5t=NZs{*nH_p2xC9nHR-rB_8(=n<k_=DgvqSKu!_ChEaq>sj*&j2n1hY|O2J
z_AlaUqVyW1hqSyH3#?;p9GgF`<d<^iWUCib5}3D?>klkPST!sZDZo#tebIK_UKI=g
z#+9RebN70K<e`%tUUmq5e^3G(mNep+^_o+;KA*FKTw>?&0Y%e*989VnAtv4mYj*-~
zpp3yXIti!*=hpPN-kQ)}^5ik}3#b>=SY%}OD_AM!a=ZQ!Lem{KHXrd`4)#fzhKS5C
zPf!*BMoI;%+^RSZWMthGaE#UpA4nb6>g0>^vTOIXx9utSjrenwA@ZE$ExIrBqt7C#
zu4K(oZr}Wyk=#?I>eNSxft!?J0_%_FRQjzsS`eSCa{S{719?Yrul=dse-nrX0DSAU
z?w={woxEq?ME3`pvZ)NP0Am<NdrF<4HXGXvZc3UG>-r&d>T;)fRKIvA{{ckI)CSmT
z`qLXd%^T#lYv&Ekk{mC;JWTw<W%YYTqLgoh+p(DCX7~%*A-7CTZs+T+$murn4X0>*
zW+9eK?gll$2Nsg0!O;HY%a9=_^Vcs)om>o9b{qa4_iMy&1MN8SB;_q_e6HG!n$l{+
z<x}5Bn4Qk%^cQp@sp$BN_hGoQOG}6;z<ef*r3zR>q#g0BZ1h=L+ECu$Ifea@37*$g
zN_5No>?<C<>dc;^&Vyk%*AI7(PFM@0`4hFY`R8S!zJdRZFeA{0dK8RP@a?|hXObsB
zT+Dvo-XofpUyYr6QTgMW6qOmFy7v7olGUySx&(i`D&ix&p2+2JOlrExUzv{!dGFiv
z5Y*xL0I1Y%?N`qgjY;q8XR6+_f4Y!%^LVMHgP7h%+>q<fMlKA!P?$NxdS8e91x;i?
zLLPw^QEx&%#>8Y?b@=I5l>PPXs$g2Gu?ZT2{O1GTvb{x8{=<*AR>#>RwAwIzXkDX0
zknj9swmU)a*RI2&iNwh^M_<HKGTt*q1n)7<_S9CcLR9Z3YPZVcZE(HFabUEXh|CAT
z4Rv`V$dq~1na5+YgmQZ5<!`R(pPnv6Mp8(^w{uackNBe@6$A<le2Q?nE#vf2c6W9b
zNC$MxWyL+Q+t*gZs%Pc<vPt#+mCv5a(I-$y&EX=RmxUN(LSuLQMioQf-XuoAr<31Q
zXs+$Zl_t*`{vpJ{6RjDOpKXAhjqCGChKZa@ibB=(>t|<`4zy&CB_zaibRoF}b=>nc
zWSsw&qDsE1()b;nzd*nDIqL)VKgUS@I+BFt0SrI8>shC(Qs2t>rd#g2#`{Pm8t1Ec
zF1NA1)I{ShWy%}OGsEK)N|(fxGibLLC0`UljJ;^-OaBRb()d(2bR@UGZNC%#a3zqV
zAW2f>(_J2iXhWpjPGN9F&9AbO?vhR}6+M3U+U?*IdnqE)YQq(Ivl30efnF@&Up_Z|
zM|^EQW#>F%F9JcD)wprq#{A+JrrS%j4Gr@fI4cXjgUeM57e?Fdy%i2m_9ppvMAzpd
zG-3!M(b$kye8b5WwRa;=6oJAk2n8XrE=Ur4rr8&RmM`+0IrtQd2O>{7=!446q>jwT
zDEl_~w#n1(4-#mC2J>UvW`@fjmpQZaYb_C_ppsm06Z^B=9^&nm{RSf&*<1Mr<68Zp
zq++PA>3E5XE!Av@N0#`#b0_s(J@4&)WiJCcv<_z}@2jy0vWc6H^!U;@?zdhqCEkPK
z5N~_GJkF{XBu+4Qk?h;4vkX64vy!?d4CKv!5*Qkphyt}qK7;f3n>G@v33Hnh;zG10
zgBEDDezv5KO8fgjGJ+!ME@*US)JV1ryqGJ+`=gPtC_vCRP`>xkgxfkqHpG^T3eK>9
zHS5eYLe^MIfh+#D^(ypvE2h$0mU$a)LW=yqk<xY6#h|o^F~vVyTMWPwzb{p;M1dFq
zxP!$d^~$R>VZ{R{+HF_Mmg@1qt1MIIjpy3O%_Gf1ka{nh*(71h*Ie)n-D!ZVDF+kb
z$}BXs^r0k3R=kv((GFZfyUY2Y8vitNJ1HjXkkoxj%$-H-X*>FTcoSdz==&P<XBn%1
zp>ycH>txdp1^~lZfcSLPy9$jO0@rmxy?yl6m91MU8fF!Ed$}CGkZ;tPT)B*)kUEPA
z4{^m@pavE^LlnF{yh{7tr;%E{A|pwW$<p6WoGw@xE@yDF4UN8*HX2H8HP#a>%gO3}
zmii?;#clzwLocx!MtHCIsx+X`y=sUmA1Ob23sj`Zq)_O<Owi;)z=JRo1C?+3Jz5q#
z-aQ3M9!o#HIwXqrw;!!@eUbFy0GDg&u+^s^RG(W99S^qNKGc|JfJs#63O1i^!Ixa#
zM1d`)3_<||r&SuLh5`?Qh{J@;LxGJyK4B>zbY((vgGfNUjN){^;)Td0R>|T$J&NO!
z#O<0tD8&h@i;jhPQWUc0Bu&uo!}NpT@Q=WhkW(ifU}2~)UKwm8$6ZHPde_-A0eU`8
zb5fQ$IZiPd_mf^Ao~-jmYMkKrKmWh;6#wsh7}3QOUDr0QVmp5O<z<g|hhz-LFKsxf
zLdWpxF1btg_x*%Kb{czoF#Gm*87g^xf5EPb9hv={y>n!-AbI9PWA&4RS3b#jp22^~
zM385_W#iKPY2&Tn+3J;)ALj}hCk4-28t1SC)AWr5A88Wr&3%Y{M%P)Q_nznLzB|kn
zV80vfSX*e1t)n)yFSWd)k8NSt|1K{JZS`OM1~AY{-=T71WQ>#fLw&+zpl{KgH-Tmx
zq$cDQ6cdc1&ymD|*2g?8eZ75M;NE9R5HsLsdjwqIx&i2fWFb5uIch-g2a{fY6F2s1
z>gU>8Lf#p_Iq;brEFUz`5?B!nRSQNQv~rwBVHCR07r*O!1x;x^?-5;veu#fD;0etB
zPs9XTEPVFXbZw_m${%TF8>KO<<0O6xlWCl5@tv-#Jd51VnEf`LkB||2P4a#!eklL#
z*0k3dze7Sb`gxT*vm;XAu%lNrFQ5iy0+&5uVAfW~ynM>Q3&)H#^cnQLxg4{X%dgPF
z>C(heC!^i^LNM#>A3zDzDJ6>gf$QID`Ro<@4={kWt7a^%_X#|dgFTxvu>qHjZXDT?
zD(Zn+OOwAQdb#IcTaF1VZ*RXi5jBTim?ng5wX{#1e{cQ=_-q%$2{}D(P>!QGBQ^YN
z-~ZXn*=~&HX37zs<W}OH^*F(4vR#?~N!HEExr8M_*kRdNwjRNGreQ)b59?KZk>Uwd
zJ1#TB_)qQjMiw^f#GVZlpuTT2`^0f%d2oPuC3QAB&uJqeV?>_?VZhd%1b)+A-pYn5
z1xoHlsVubwZIeE}@j{9i;+>unT|m=k$DH+_8*~o^DY;7fLasZK?5@|cIYLx1*4opH
zs-9`mO(OZc5KPtvrdTOTztr)+IYpI9w-{|aLt=6&)7>Z6a~Xufd*u~^#HsPSr&Vkl
zb5q~?5T6%>nL5g)J|J2k*~Pfw#qs+q8g_`bt)^B-<v)1_03<j2!+3ylN?(Z2w}6C)
z#CAvGyCUF&EliGhvFIYuMf46I#Y1(Cb&~3+jlVOr7bcI}QFn(-5@{y@gSl7t=jU^r
zZ8+tPf~yDK_<!|Wn_+$R`m}_y>B^WAUKg!7)jfa1mo9Ml-skr+WV^ZAzB*&(uFrD3
zU?jZ0WDKG$@;n0*qAZQk%e>XsW8LLdQc%<8xWjK6ZmRTo?OnV1SXBV(b~KS6V+Skh
z^!Amc^jIo-VxJB)pxDrgzdT+&A5pJvsIH5(wpt4LCEE`^C2v&Pm-cWG5^o!?9-L@o
zYi1|07UD;+0&m}0>Zb@K$J3a;em?>=@HKshOZ^8BrzEddEJa&>4@x<^NayJ;@G@Pd
z7h|S~$Hxt{A>xHfDopiM9}SFk%5lzZS8l`>G;1v&N9_`}{muux4eh`?ql*}h{HA^r
zBK=2n4o<5(RpQyEa}(E2#(49rVL?ACv-2jYbCOJ2)H1a4sq-n9v)Hj#5C)PjgbSQ8
zqBiAG&^lX%97z<P^d6DP<IpOgXeSPbkxJinM}iJ(Hm*M^&!fG?AD_5!Z4>rmIW%px
z{h|*d1hts2Iy9`l>ro9or_jd|ToH>LX<cE_jBv_nCptTA_`70oK9%IBkOAypink0~
ztVK<TW3Ej4PISHgLzP0;Mwv!x#{1w!bKY}uDGWs~EH?J4{;)KR&1Th2qOF`(k!(r1
z^EHIw(4G~}t*FdqEAmV;^%6r0%8W?K0n<BS(6+bW`PIjn?-h7%NK#DFVDtVnT($wt
zQ{EtJ!X^s7)W5r;%KX-L%@lffiALO-O~cq;4>Fp2`wea#tD%9}?8~1C2rV{90SkKm
z5F$IUj^eTc=r8b{v&=z6EIJYh4iMr4%&pQVUd$dD7wj@AIX9>?Cm;Z+L%8B~7K9Fz
z>gu|t<u}H8wc`I}zgZC{a_8_bQtYZqIpq+@s^~#oSYm+#_DEyY3M@nyDm>^t8r9+*
zir&lrIwfzunjeMB;?hZemb)M>hei+MUgBfpbWg`Nuw(2_GOe-!MUlWKFf@_KfP=0d
zmQ$q`I=y3Jk)CHvPnPT4ZzSi&(`IaW3h&g0rac%U{|E3l5eT!wt9C1k)nofA=$1!^
ze7UaR?;Vwq8>@|HN{kamjpA;L9#xf|%S<le?nX@qAxup{v*!WxtR$Q>W9^WKH_P(3
zms|g{niqzeml219fbjtn>oDoQ+LLl=9_XHRxD8D_&<RKn4nkPgwOearANIFqj87ZY
zZcM3Cil5&uQHS=}FWtApT%<Uoe$d1UQE<5$(d|++lXlaIH0?oD^Sx*$lv%ZRXo215
z{O+<I?gasWLg@|yE|)A5VV-E}vXu~5BikcL9&zWumry!sqvau?O9`bM^r<108IVs9
z`VB$4xrus3pqrnr=kTA+^5JGus{0t$M!dV*@fI_(LL1%mjpwi6vHiL^njvuQ+U>3s
z-X9^9qRsNFdpw;esy?6`-C?c_AedvqdSSN~xbE*&+x>XM`GL#dVj^@nkiO_pwwyCx
zjowTx>VIi4EeogcjJXAAC3fl*%UGGGm}fWNc~|(x{irw!e(E{weE>Qw{4Vh|h*NM4
z`DK+gjE3-Ht}^ppg1FyCEjzTkE;fB<m4w$p{FwZ0oT&F6k`g34bUAmQj#>kyCY9GU
zuBUIDLuLEP=&j<}Rd@#UaIigycFfM@#u-c5iCTR=4}N)P_3Is8DS>6j(jsOo`qd(&
zj`Bd5$On!V=E95OwKi+W-6}pl7r43+*yp4MF^3DX=qfo0YEs8>=oCvqI1H-fP|XZk
zrF&|YiI}VH@a#%>Wlq~Y5{e!`$r(I<moYCCT>f?MzkocN7m;SmCWrmET$c7$3G+Fs
zWt?(jE-GcG+aHyvq#_0(?o{mwufc`^;7q+8qP6oS!bZOFRjwNX1LJ&LtqjebMEI;Q
z(50cDNIOkFR4S7F2Y`e6WHQc>i_$OW7b&iNGcPN_+lROOH5^lev%R{1^Wsw053)Qm
z)Cs@buEGmosc=SVW!}FOB+QHcHT~RakM4jHNbb;;DrWT+WJLVt!>tA&k3DByR>L8+
zUYPt93T5Q64S3ri#+4EhvH6*q-IG#<uvZ#a{PG1-DwJ%^!n0og6RTQf`-a8xkc*+G
zfz!ZABM%0a6A&hUksBQinuwDBAZE*^g^=U1jwk>9nJp*SI9J7ZC4Pz^Qvw#XscChd
zVMVAhQV+r9cvsgOvvz!wl|b>h^<!Mi?cJ8CFm*R%9aelc#Jbi(AI(;&SZ38%^e7qW
zjh_)e(D=D)k;~!OUtKsVuSl7GMMBuw{oi%;FF5Rnu(AwTU<<yRBL%#eA{FDU$*-!f
z=KFJGf4CAKW8lS;)~h1=QzZ3S8-D{-pt)-Hy84!gMGm0f_tGeJBeAz%uem5)-0n#c
zacZoT@ZYx=oSZ*g$NDOdhgk{%gi-Tf@xF<=!E9Q%*`l02M#b@T$sWFTb60gGxgyE*
zp`yn<TDg^c8NNxTZNm;<Hz_A6`t0kGop>lUF2|n5C3RXETB?j6TxYko;VkAzxw`h<
zx0lf39{;a$cm5{pwM$2R<7~xteQTV;7uW9vNtzNBN_SwnZGL!GoN6Bvo$i|pR+Dkx
zZR_8Ia)&fjS6o5kh6kn-Q4GYtCwC3ae#VS$>Sj@=!^%Cv)-u!NzqkIxr8#)e7&Mv*
zv4_6LjRn}zlGv+YFh%#VhBpevjs&NwZB?9ZGET`T-My7bu_qwZACiQ*SWk;pegYaQ
z0J{zA;2U^GotP6Dh^Glt8i)=R_&oyMREIN~s@JEe9JSQc**2@WPC+<{54#5`F0E>P
z*)Z8gmH!mF&cV9$a>g9z@Pg&~&l%rxvYSj+EhC>VXW+hB{<675h??ho++lC4jF7$&
zXrRrwV7R8q@Y1|Vvs+I-?idEW+G-3}W(CQ235cAB=FEk)3lhqq#eA4D7meNy+BV(m
zYE<w7?M06#()mjc^~?}K4>ZxH>e<M2aO}YH{?5@fY+=h{=#fwoxuA112k?1Ze_LY?
zHok1b*QcvBV=TNquTHG&bz-|98u@3!?n~$DE$n<8?Z>txqhS_>lKbDFxQC)!_PNgJ
zAXimMuR9JYo@1v{XSoL_m6@cyDEv{4<#TV2iyu9TNuPKwSzTy!uzY>A1z_i1`5HOA
zN#!}ewPG1}*TCEt))Qouyj1E>FOkCciX*Lvp@985&fL*?QB*5v<mleMw0I;hVmdSX
z%lO}=uNr&6dtW+P&koZZ-J|Y&HuO%M{V|a*xgx6n`}GjMh*{1~ume*$ao)b^?<yAB
zBeXK7VQk0bjCxe^0^kE(Y*$@tZyh+_<qbVq`K>}66(pIo;6I?l$#d~%*}lDIthXZ-
z=jkdFzr2fD&LJn8BfX6&eK@`irkJ+(;XE|OqZXf{5BRAS7+!nh-h)WlW0&ioBeTh~
zPyzPXp9v`>Ko&3-Ppa|=%x!OL8=`$vPE6I0E}}qV&Q5Ao!TSBsg@%m*PW~oD8!&(*
zL%k0#s>|JaD7&{F<0GCs4)?_Zdq^v*a=;gpsYC81f=lb{^&MC<!B(oJK6&(r{l`=3
z__f58Dc7J^{#Qo14?GZ@DlKes25-&hCQg4ID#vX5ABfw<%L*==|J5hZ?X0hC`ha8l
zA2R7k8@k@xiBZxTSU18=tWQKMdcQkg%#HpK`?YE|c^o;I1AJK{DtEPMK1Z4-EE-iu
zLhnAFmJEFW*;~*aJrFzM^Y;o$cM0dLBrS?>|2OP?|M#3B?RX2YE&410XdT0xtysjo
zM{=fA+8fO0galxkNDnVti{bvVH7u9b@Z^R(s!U{*CN?fvOI%Wo=n)_EP<?VicA})L
zT+ED{0L==!8q@oB1He!Xn0h!9{wiaot@hZl$#K#YDo!8LSAD%Yuy53FKH~8Y;L8Jy
z&ATVDbm`={O)25_G(3hPQGYD4K1gxs&dO{^6G!!*4E@@y4}=nO$!>W^%>FBv>vG-7
z!GYVqTp;c=?Yr7N&j~gB+m&_7%K;=7hvU+kbJq6PLB^NG3<ArviLTL{#q}}{^wGA7
z2T}WGZ{YoM6^UwcPTX;Tzi2<6ZBbya;8dG5Wzg0)N8CTaPZ(R=TKTgJnEMp!_^6T>
z{WVPcvuE7rVd9h?<s$9T=NMw7om5ME+Ib{f#Rp5JCrM#a6j$bPhgD4nJ`=u$IA56*
zEKN^wF79e+phXN;w5SJUz0~QJ;c~`CM~XnUPAv&~z{*e+-VSlJ<%F-MyFPDbjRNbX
z04~scUVMY?t>3^@EUYX;x4<{?jFij%vJTQ`aKj`ekVagb$r0;z<BIw{kETf(_0yzP
z+zpTxmRHc%o2@^%RH6D(3hcRe1`TidC@sH|&($igJ74>B<{uz$PXCQVvp<Kwt{$6*
zykM{{g<4zu%Kcay9une9qA_25U`<yATWPefG41un16xt3N*!hC15BY>UkU{pM0c~f
zDyoIvNHc8>O+_TtGLk3mOy{EZ3rX)p@R#qA2glY8R<x1T`5qM%jaE@DqWK!*xetXG
zH+n<`uJM6pFG3Z<tgfi4st9i}AK^cS{iswmdlfPPgO2@o(Sv>9s!F$()J#9O<<E{z
z1n<6pj#|$)KhYSF!?UseG@tW>;u50((Gy^bN#oPo&Rt#~<zX?~9=-z+fAl749UUG0
zwk18iPX=GCImVkeNM_5GHOeF{E{!No3yJj?u4>&eH6>5h&#QWTf~qsHu0LyxsUJZ<
zQQs(012st79hUVz7lq4JBpXV4?u1M`w~H54WHa?La`H}l)GJA^dsb92h4?(%Smt`E
zB(RfyJa;E+=tx%rZyF|3DLHiX;$dC3E8O{K8S$OTH{5pS_7$hgjiImi9JML93SUg;
z+E;39`)z*|uB)4PzFKyfjVq8K<vU!9VDTLuFs?8+aK1Jsr7b;17m5xLpt<dOo1W{}
zKfqtpbEXVAx$R~e&JZC?ac`z0XL~^pN%zzl{09h-4`uhovB$ll87nV3c6W?_Kf|$e
zJ=J;bdui<Mp*uHf0Ns$iqTYtb;nMJIApeIWVe5jMh)M=^Ay3V?bpQwbHR75IjL2PY
zS5=u6$)6MQBy}I5-yNFb^U0Bs2DkRVScq^RJAJkjdM!weB$mzMyir3$CZt_x&a9if
zE$U{@P{E%biZYp3$3X~d*6>ow3sQv<*_|WV_WAT$x9(b-;gY+x_u(zYl$|Z_z1wPU
zZ9YMb+pQU*&k=Ikm#OjhO7|NRKRFkI3(m32KP`>l9|S|+hY2{xh)8*nt&I5Pt;9|{
zrh62y{rY;9^amdYxZsykx$jd+3JtrMw-YDkBaRgYgi}e&<@w53NIOaTr`piL7On0!
zoXaN}jo{}@z9$Y_v*XR1L%7;z+k{bb5qrZRu;&9<>Yhms!5OCQy}CB)6))dkj5=aK
z?q;xS=uM+VSUf#9x!Rh4y#I5mvV^FCFcSC>q+PW2(&BPp(A&0hskt7Jmku=yp;`m_
z{qSTgU-+pgt99*Y&a0imx$3*z%EXQYA3F(bLndaRhffuAX<4t-N-o0Oueq(Ew6s{Z
zVnJ(x8&dSczu03nh3`x&3cFSMKF&?miB?pnfq4G|gk=1MOA=mXcETUb9#zJTR0KZR
zSQ&&iphz?APoN9M8oJ6Jrk@fdFN`uvH^bUSWm%Li-?+t~Im#?{PnIq1b>YEhj|FAb
zccmTK1`nRkD1UFUp*)J@Vv;JZ*N{oJ(-2BezF#aNq0jqp_zc|#iHD3ePB)$xR=f8^
zy@yA4@F_F9k?XYlu3mb)JmkxIliz2-dxqg^1~0uU%8^(I>5THHg%#7o$A8YA5A*-3
z<^O*I>i_SffI=+Y-rYw@0UD1}9QLTR)Bupc5If8WjtzCYxLD%*r$IX|KgCF!Ec2Xy
zfLy6F8g%*^u)!r2!dL$(z0!K9=`B}h&_jD}jnEul>*5buv%;PHyYY0&P31{8bWHxL
zWL*^XJ{V-k!nnY)`7(J{#v6J5g3BM&8-BV??7r~<V-8O)j%aHqRL%3@$|S{1=`Xpa
zx@AN7N%g?E>=k~-Fk~+M{T;(j@?zN%G%UsPi_BnwBev9Z!{K<R%14i%g=t~b%{Q8I
zfkLvs@qB`1-`rG#nH)p!K~I)}*xZSWS|flge^M=N54a`jcr%Ys;-BSFMt{0`^UG!M
z{0h;VdQfv<m=u{2Vg24z#p{P3*L1-<Yf*|sL1f(rI*Wx@^2}2mDt7GW#CGwx3;jF4
zn=tUy6+)CT&fD<uFK>I!{F4xw;?dh7nQae=$4Pc99dQ>&@dnrVo%7D@JwiUvuIg*h
z&e+)uRbt?wzSjp~PjoTg4VL_G#LM?#g`q4YGj%Mh*C&VDTLgUi?Z4<>+^samf0f2U
zQZ{lKde(t7V}T;9>X(mS233=WMb~Gp!Q$qXrB3X7k5!#Z9R7Pg+(o%R>EsU_uPqm3
z(sx|-<N5-5I!ixP{3N@^Id=4&I$@}a^}?iWUdnZ6?oHzAvCrM6ScaE>21eU9NXTrD
zO1vvlqCur{1XNDtPs@gmgXAEswvCemG&BU<Mz^-jBQz4#{`~c?$u(ST)sJjR`$Mpl
zY6c3=l~Xz=464#hX6z{Hzd<~IF*fv8z<S<G^^*3|6iB^C8YB65M)dRI?`4sHfD5)Q
zugQ6j%lr>M)~RMn4ck=qTC?@8r#Q4z9IgWC((=6|JR(YtdDA<i)iJ*hL;_76Z180z
z_oK9Eu(g}D5Z>*YHXAQ9)VPiXFFaZ;6#+7J7o@OHflemE&(f%d!CbmJm0kwT?M-pZ
z|23Rr({Gd<l*#8PV=EG%ye&}&p6?nVoJ{;k18>8S$8!`>5CMDFWa$wlPc8|e(-ZTo
zu)i;xJD5Vi7_)p7K5HU0|8kU^LwhV=g-<p4c^#Lx#^;Uiiwk>;A#wAm)Q$cpFS{a3
zb|T~>1a(Sz*ko(}a`=v5nLby1V3{AQN#sJ`FVSE59=${-Q+9YO_NdNGIR=}rkEQ5E
z>vWx;8%5U+ht_BNYwk7s-Jd5fg4Cz{0#_+O*<B$|7JD@3C1cm{>Jq6Jw5=TR!Oq@<
zQmNPwHcZ^U0hTHy500h6%PhG6bP$?(we!T0!{j-q*4n+%N&Cn+$rTVvB*iPd$YTGX
zp`^o4rZ;g<DN-D!=?WA;5t+g7_PZfW7H4vdwr)g}t%e~f`qcFO@Ga-CSpKf9wbs((
zPZEyYyNLAdkd^lWx4-3lpOB&NwQvpG*L6mlj>4}?bKU|hBsdk~9MX^s6hEHNC!Qj{
zhFz812z$Ptp|6nBp$*$UJbHCfJCgyZ-6lgM6>KD4mo=s%C6QuSq9hq;{GtL%i*we%
zk~&`X3Ce6Z>_;d2bV$N1gu!?0Q1Ckz78jj+-(pGT>Q&^<YX~ZL&*gt`6|wfW-7BSZ
za&hWab~-LseeXNJ21j{r?Aw`^{bjmR?g@02y!-etq2MJs><wvXjV(^0=QD)$>Wti)
zCRH}eNjv!40WjNNz9`M1(&9StYM8Cn-Q&3Eg$d>VOn9`iCF26fT>b+9cM5qpI`mJj
zf!U!fScP-Q6dG-XS8oQfr2lU4;TRnFbH=bPkBstDx^2`beUPsx%R+%I{XGsrA=oND
z)9QsyTwamdwF<Ze6f~w)I2m2v&P>Vi+^F{_#r1Rln?Kou&2KewX#CHa#&gO^hujmK
z5zATjKyL?Ch|!b>TaWUi**bKvtIi6Ifm3uK%|#y1R>+6NV&%D=#k45T4@;#tkh&b>
zK3LluHO|X2QYbqs&D&?o6x<gu4NS}c4ITI$^MMp^JvKVJL-gFgDcb1EE`7&74}n^#
zbotw|GGPDqfL%`i?(CSPJ41~6CM}^{2Sw3sjlkY6MzLAHML4yEk|KNuZntmnE4?6Z
z+%h4u;J&TvCrXve)$QY<H$eE0te(|;nV@G%W^x1i?kDzkB%!qS==0I`$HM>9-dTP{
z)xK|k6cq(2m5>^xLqMc+1f*jK>6Y$p7(fK11*Bu>p+~yAq?PU(8i^qX7{+JrKj2xv
zH_!V1zUx`{i~VNLi@n#Hb6xwo&ht1v$LRM3^I``5zC=%n^8vjI4olo1e=-zbi&pg%
zQ<c`t5kTklBD99}_|F`=>|C}BLK)Q!p{bqB$8onyqwq4Dnjz|m3l$CwGPM!FZ<D}W
z^blrux0H^ye=YdOrPckvNXUQM@f-zN?9+RAndBL~)*O*9MDtD%lm+?ZecOGNjf3>e
z&o|7cUmO`Kh<;>nVs|0lZhcpUA?}E%r9i6{^)z4hxi}XKdEW)%HCFL#G#)=ji201_
z$DTR9bve+nqi0XrB$-G#)KLY$5$v;-$4WGl==oe%)t8!nKDemVbd22Lh}+TV38?$Z
z(Y2|HYw_@M<-!-+>F9&H+C@jH3iZ2b=T2b}uc#ctekv@eRBOVyQBeF=g}_yH-{=Ce
zs@6quPJf<5_<aOBrR?f@<xY*bpGl&{tNqfPg8nZ6t^=;%$ZAoh_b(MveFv_yv<W1s
zy*&tVVpFyq?mBz42~-!xI$P!`hCM*WzGf1q(UA^q3rfKV4|DosF1m7=+iC#E-g{EY
zSuX%2X|Elp8B3&cq!_%;^E7}6Vd^>`M%kvg4h`TqJ(!hWx9hSZ7@^<N3{1{bl#GWV
zq5=<z@a^~!2{T8sFE^jYZ5h9F8VWI1f2p-kt})ce5^&0G%xT<h@5E_h8WtuaDgGsL
zCcEE*hz@yoW+%?iAL_ptz_~a|^7dL!YZtts)eL`#O(<TT4fhBL>?e0{$h9H4zDgMQ
zwzL19`GoqMbZ-TC_uYfW&j9>vuyV1d$d>;$d#PI~Lx&Joa4q;+3myg`M?pIqgh#{5
z(^Wdw7i$NS_ZJHmCtZmp#+~i528Bd2SlSH<L4A~tS?kv4zw-?g#pAuKQ?ypx$V{nR
z^O-ZvXne}`33RK+Dq`~ae)&t*v`_Ql@P_0aeuxG{=9sXY-*2?Z$Bb5+$e$4zM2;Tk
z=5=Vmorv4(in<v<yed6s_e%yN=q<({n9LY`E_B~=_2T`~vA$6E#{sI^_IUx+!5d7D
z<Xa@5ixoPcUlyf@2ike-b#G-nyOtD^UwZ`p4xQv1(?y${WX*o%<P9mVXxnu7K^3}?
z0KL>l+p!Pmt^IbN{(T5?alm`L+)Rcj^iSF_1EJsSB;nj+nlYB-#_%O3)$^^ot#sHP
ze<3qsJ7GNjT3ehSu2lsVDhQQ${_5b53Om*xYZXWy&>)p47r(q7UDH`j)EF26`QjF*
zc5JNTZJK~sTRwN=-}Ht_Qf2ec4g}U%lvfRVu|2Z>avTzy&!9eE6jB%m6DQyQZ7tl2
zp=`yw(JI*1SH62@yaBeqyn<^~os1<Gu4FX6q0=8RQR#6D-hHx%(hfD!uh^t|8Tn0$
z9=;+&LxE*<x8fprHmHErM#SkArNJz_Ohyx2vmLn=l=TJDOMmoKit@QsYqQULUZdF*
znBT>sH7J$miz$`P7AI0C9IlEUjB<&&+Eg(6!nbL~Sc_D8H!Z(CKOQ_svx<)U!ra`G
zf64P!KBJhbsrrM<R2<mNRpK2vwPdt^mCiQO^m(Y4uGZG~rNL)Kth6bJCsr9?mqtXI
zu>mI0Lm5jqO&#OczUADAuQZIaP+LmhM)Q@~`pQOLa6LKD4qPDTuix{t^8d&VcI>UB
zAllHPC<jF^a7BnpJLT)4e5W0IRJxtd-k81vXfYszM->+k!mAIwZ+ZsO6^!TJ{J!7h
zT_lM|omuJoOsp*TtobZn*Ox2UUYvT@*E9a%)n!;g75S7!M9t&0ScQRoT%}tr*@#wC
zve=l1Rk}_@8}wJ=n5pRn++4RlaW-W_oEQ2=rxK^|E8MFX7YOio5t8vdVdU`AdeNh|
z_f#H3auldir!76<h}JBTzg;dC_lqhK(wUvQNu1Np(;s*knyHmsY*rt4R3e(VoO;Dn
z=I}&s-{_2tS2N~=%PYKiI5r#?&(7eD?Z{}|$7j9gI5VX_J(WI{BK<~mXFR4jC!m??
ztG@utLb}Cjo>u9~`Z|cg^G(^)-u9J_7>f*-VuuFnWYgCRBq^_^XszsL&DQRyrSSHj
z$7L&hRlPJmhKQA}d>!-~+4P8;pOv5Hz5BH!mYgU5X^4ls8u5d+4gujr$!-8~ll`JJ
zT&z1z&z#Pf#O^?pH|s^{gEVCF53Qv+8JRt8_Z;Z@IoeLd;1}x3Mk9<u{QSak`jB!b
z*uBk!j3mk?4w-{Etu)$MbBbK#D%x|~XK|HWtlU|6<mGS>Ys331QLv4v+fZM<t}1*x
zc|$V-Qn1nCDSqFZ(l{LS7|oY6?#4LX*H)Uw5Fa6uY98zNbfbd{OJ-U9EPx%a9@@B+
z>{WAS<XLWPSw)8~3A2v3K{`r9RRNvU05)AYJuKJle?1ycbwy7)(2lQm7Yq7j*<XH4
z|EMT02qX|_Lli;|#6uf1e3R{vZFOU8O<i|GGqncj90JxV1xF!8XnmBG8B(L`N>6M~
zGbwDBi9U6;3XW|}Q=_<4Psk(S?lB59iSPR!N!$zn#BSY^U~=@Px9q7)G%`^(BMc{(
zHY|Tj)+p0`Pg$MH#d7oM`R4TF2AcU!k!q3Y;$tGW;DzeIh{Og1ci5X8cLuJ>LV#lr
z#QP}Vp<&2JhKuc{!bXcOBiWfE{k)MJSC=!c3V{2pUU-^QbjUd0K9m4Wm4||Nd(IBq
zm-*q;^2h_#C4T<AAu)R9*!ojfLQHs8;$*y+vM6oiL4Cs%P=#F9+I|Z^HX}TDPeEU&
z!1t)+q^-i-#(i(IF0mu!3Oo&d)U;S!7XW1UvDsm}$X*m0z<wJ;J%6Cz&$xG_=uafy
zU?E9do}$na(i+$Sh8C%g-7`ijW4+kS*VKM)y8Gezq6gp^j-&6qjOG?Q4-lqTG<HV)
zSPElr%JAEMm$->Kw8Y8G3^F<o$Y$?f^TG4S4T(X_c1XE(OuMKpG3%B-{;M0>@bl7b
zW!=abkpQN@fUz?T(P&B}S41*B7@2f}vkA4w+H3DqV{&F|QN|KJ`M3H;GWfEXLLqw4
z$~j*z+VTXFD==4wuP@t7QYOtB>P6fpL0>66tzpBhY)Av^<{}*^MiEXdwL99oIUZ!Y
zWR{@g_O$A<)LxFK>syXDQwI^584IJ_dav3^rzrij`q!&<^n-eS-B2DOP)#--go~+o
zP??wIr5aw%oTQ}XKQFd!6^eEn43rzI<C=s0$e1%d&~{^qU0z0<NNTd=+nHZy96y0<
zFt>|yxNiMFEhWY&?ynU^FXi6}(GZc=746k8NH>N}^GBOBxS^(GxJn$d6_Ggaqk0x5
z7;7PhnN_SYvJ%0cK}s0j)o^b7IC4F6bD2u)F+=aDoxujUfC2i@8_tr!MwLA1QQ=$T
z>qZW10eWK0y)%hJi=XWKM|UaA_~x?18IlTY(Uvp3$B*M0mRYCy6zk_<d))l^Kd4)7
zSdIemt})v^y}p<Eq<2fsjAO?M6rTo+*J(xrq!HlIW~=DBd!-e<GtD{SLyDmyla6jz
z;PcY<dnn6ne7g#L<Bo<#KmS@cU;>31u;0rIqZuVryxHmy;B!)TX*2D_SE%S9pXVO7
ztj|1}vK1rVx_QSw4zlbBtFT%td+l05odP)WH;?5>AHz~xY_Rt2<H&T!@H|JS2i9&*
zXF9}OR=eg{!UZAu8N9GIfN51?GN(3(C6;3Pk>E{w%u1-cXo}Y4&hKOMx+cTQ@K=|n
zb8)t14@c@7)C?Afej7--CUB`?USWaTkXIA-XiXTD&3Xj+j6R(o7xxxMQ#N#gPZh(t
zS8-%^x@G(`PVLZ;b*Zm^pw!#ApV<2|X{_N7TY&%Xop9`n1+=wj9mo$D6}6HwS<eY`
zYioQPa+YoL)Wg!@BGhS=mGX14a7R(G7aRmUztCNoR@+6ji@_JAWWIHkFxp$iuR9v^
zVEU5-4bgCz!sm$AmA`<Y)KkX++n~V)iXz^&mS2yoA}@$)q>B3IPLJxSyn!xjCC+kp
z4=vC#lW5a2e_1SY{8At_{R3;Wu0T?>kW*F$jhq@*SF3F>!GV^5)nyHugeFTT@Px~%
z<NXlNi7bPoLV8{Hie@JE`}?)12n$`Naj&|q9(E`^QWH?DMBC0B9gf`^(kn$N*^uXE
zEe#z&H4U-y88yBM{oV<M18TcL%Qfxnz2@ztwYJyphm7X!0iz5J8nl*4u|_gtI*B^M
zMNK|s^3B_Z!`bxIENIq(!DivCz=5#$zigVMMftj@<1s%EFUkW6QLYEQZgT6b8FJ&t
zl?A&*IhZpbcnoeW{=`SLrNV5auHLkXLp!37rsl3s90rvzv`@hqmdlIaILzB%p<5^R
z^SjMf7Fje=xJ`WjLubA)DHEbxZuJV-dbpf<<+LTg?Y~4>I<e_HqtdqV_&md(b=AFR
z6AX4cR5$9)W<tK2Sbr<&=J5(Un8bz8G?IPWOdJ&5oYGj9cVm}lPl+Fs=d+TZw3>nE
z*VO|>T*rLrV#@=9D)`@d*-xL0#q#;}FwB!VXAa3CX@821pH}`Eodf^`0WKfcV^^^e
z$`g}b^Le}DU7lhFx6qTE(TN)0bVhTK>Qw%Zx`Yj>?pWNCKkQ?boMXA(6H7w0W?QLG
z5hs^r5T=>GfLhMh;>9~!`rz2;mAZJmL6>*Z&t5Xde=g-xmtWH?Q1lY;7bvPMDdrJk
znpxd;T?Rsv-XB82@9mC(^T72)oxMpER5b{<k=C&E$8OuGKjK7S-M*b0sT>yUh$Dgj
z1YSf#@fSe8CQO8BgGBG?S+qwLEzT{-&^0tjP_o4aX{lQjei9RSKk076oY399Fs2x`
z$}aIN*KOZfsO(%#H~K%_<^8`sj~)9xv4#ip{{@ht#jR@O)@L0gtj!lk@^8P)R;wuy
z{cH=AXg@hBbAjy>i`7jL)aAQ;CbZ-DzIGOOSv3lY!C<j+HEnTy4xHE+jTnwrsrv~D
zES(v5$yf04j%VK3Na>;yCTQt`qKzBLs{uL$l6Jb<i=jWBDCM)O@6my>*6}y)DUv>g
zIibVzVqLrh3500efs&*nf<95PbuC+p7IPk*??Mj@mC+6b`As$;-aji3kIn?;9Hh&%
zCahR*$t=?GZ<$~vLE7<Y;@CLoy#!0S!9fa)`_mi69wRzKzYjH2boRU@;efkY>bK}U
z4+74fkM>K8tSK1Zfm1=Wv=3J|@I^qlT8excl3;e64AJ?G5c(CPd7#W?`#Egh=wJo-
z7x2xf;xZLiQCTWm3`eUL^!&}$V}FT4<sv!nvkj^Zz6gdSDg&BAo+hv+{VU9idy5ig
zrsZ4<wSK4_$J`u$K{V^?LVA1R>B#3p+^hcCftl8R2hQJ?&li1~J;v2I@=4Lyp!X^y
zJc2j$33o^@SqRE_GnME-V~D44x)w`TXp7v}QnYjLxicf;=(;rRLfeHRi8@8TP8a<;
zp4b=9ql!!FctlOP@8EB<p5@aT1?Q1%5v8b1!G~7Z1e&et6hjqTnP@wjO?G7)bLD$e
zUW`$7k~LR`*m>pKCc7@Qa&7mT8z&_-2l+Y&X1O1}+GSS&Q5r1pkE#s&hJ-NCH#Dc$
zm*k>?LTrQwM4o=psOvaR1gDaP3!V~6yu^+6osIDBk#-_FNRUa>p}zhhkTVYMoNYJu
z{&e}YR<KFpZiNCu+KpQ5Ijpd$AOUlpK5ysf!4;cDmPOaSNcxRfXu!H;QT$}5?!ykB
zhEYr(osqY~B|G~MeZr$er4d+SZMJf9p}+g+6Jz(}A7$?|ePb)IyB4^DCtIH!+mN%w
zJ^^=zCu^f|37(bdiAGm5Fr+rk;e3*M_A#mXr`G5|;&C{<&I7~H{(k1tRqnT}OH+Yq
zW|Ha?i6hsCJ~A0);QUot564AABKjJ_wb{~L$m<aOI&xx~YOYnOt8X`0aGQ^hCx>F{
zV7Ph)IQG)c@8h$YH`V=XK|G;yVW2qd_qbGd4?`EG=)?aL$-g`V@m{ELtXP!~dwImE
zuF9z!fB&06i>dDT53x43-LP)*L{)789*66r)F8arE?EG?Y9*DLwrQPe`E}Y<K+#g*
zu-pLsK0A&xCTXwA`z!D70a1wL=#y+#9LI;a2FR|RLhaUH?pZeeYf;HBu_)~aSP_)h
z5tz$tEWt9Or+*|`_+2LDbUiW|ZVMofVT+vzn$GuHBR9yf>vOuaGyslh*|+0OBW|mt
znQs$01NFQ<%;(+s%S@$&MK1pZtT6=Y*+WVA$f%_qVen<FkJ}1OM>#ltLjt_~4eE!5
zcQ)64apM0Ga(CSy_&S}JK#{EZ>Z`xBcYS>V7ThVB`<}Mok~9waTp9@ub+4cLH2J8$
zn1?+eXG`pcmi-4(;A=SsAH@NSWoVhAfT!vp7_wpQxbN9DIs;$u{sqwJ_GEZAB)io1
zuf7wYj=l-7)o1102}TQ}BFqq@ro0(R#zd=C3zVnIzd*OKkK8bWFZqscjN*#CT|yRK
zx3=PB3>N@dFJgqbrm(xB&DF>ipz#BLNb<z5)N**rco^Spac?F92`@qml!zCu-?DBw
zoTheqUYK@)V!%A}DdtY{t`jw)(T0PAZ(QZC_+F;0rdOI@g9R(?^pLI+&G<a+Mqw(Y
z9bi2Z+k<SnD8=YJ(uB>pBoQJv1KwFzL#2tKtxdCp{!)1!xj$olS+Ur}4V8v4{U$_1
z7=OAA)hC${#)v=cAIhbs>a3i^?xs91k-U>bi)!R0e7nh%{^GP%{LVjXz{~>L_&+^q
zNWfRJ`#$HT%_=G6p$<m89x0kho=XPw<{w0Qu^T8!$2(z-5ooBC7b`ni>$nEgwiC(U
zbg9!m{QQ$H?wITe9F?A-J)@!6z%^sJ{(N?I&*050k!T!4wC>!|8^2%Q-WjeWEuer>
z9<gE)`CM+UN?P1k2Vsf895mQ=N0bXoM08wfN{aR*>y&rnx)u8#SUV8>PjFH-2)l#)
z;;?b&hIuxsKChuz)2%1bu*Kk<<9F{vYF=~p-Yq|x!8i;<qFB~AaM^Yf!SqQ;dY`N<
zED?qitf)iwpJt5yPtPOW4txoDup3BT+kg8}a#b_t@n__t$6_JAk>^7!IHw&OPTe44
ze~#(Rn&}D(>C6G=pwuPL?MBO=OdSTI8tXL7{pkkH5V!@+R&5A{$5uesp)n2G=q}=d
zhWSu9C1mH;<Hv9YD<Om0u9%%B=Y}|VU`xr_XH4#nUBl?)sBpanUSpfAp))>f{_|t{
z@Yo7Zyp~+wYrl(KZlzBu_tE*H+Xdnwu!+=80r4!B`}uO0Uh=#gRlghPxjqq*9%0Cl
z3=oFjrY#SixKx`1yAf~{hHpKQCEg`SaGVsj7WYCR^dedbJh$_j$@u67i=;1AkZs~^
zr3@}QP_6AkJS`yhdEic$=Yy*!#b6`6b5=~Na$UTlDm?X0Ie0c5;4u~9Mmzj<!hNq^
z0y>ma;}=6~%p*Tl$vb<nmCQwgCg3Z$*v|10zRV#^2S$*`vlzO`$KG)NbHEjY6xzwm
zfC;_xaaE?wViCAkuIPmOe%d%Yq$WeXK-)6U<SU1?9Br2g&1-519n4uwMKO*T<@s)C
z)Ps`nb?OoB?y|H>yWph9Lt;BJWeeu=s3u`g(@~$~tc@5aDZ_f<w5AZ)JUnduoIqa@
z`CPH%W4OVj`NX!trwx*J9xNgiym1_&WyIW=sCI(Med_S)LHB?w_r+6T?L-uIF*^=j
zZeN8BRmEL9P+(m?(!Lj!aRd|iqxkAn^Nn^k{Pn^?vc7d#-Ftgg;Wl<C$d$LNe<VU=
z;LfMu@N6UP410F;pN;`(HcdDtZ!9P$5a!nqNwP0p5a4vS^MBIeOoU*)>cFE2(9M%d
zu3qT9x-34W1@qtg&LrPDT$KWZDSu;+u6hi={WWahQd@!_8!;>lT?9uwQ<`l?c3};c
z^)cq(8ke5~a5y0*xGG6o!eLOq{H1Gw<TKqdn25PL?4+WNc|e=2<x`uK8}aVi`T*+p
z@HBy9)0|DR>u&uO$%v<9rFjHCE;kcT?KeoB-q4g-nZg8L!val_NBEZL`OCxLkYnk}
zHq)}#Iz_VME0HQsE?->~>I;g`Gn}S<b$|S;ze_V{FEKj!yyOkcso03~GiSQ_I~fWn
zH_tXeWwHxFmmyve09;^HwBBwACM|H7W1Aahxj4Adj9PSYdFsOYF~U%%Qjm?%Gj5`E
zVJ}hMF7WA@6t%kC1nzQ*^T1K*&22UdiM`R1(yvsG2_5tIfBKauW~ZVdv=?Rh@HE#6
z&j@_CgM}XsWcw6FD<=%%Uc;1`Ei4p9B4(>I4YeW#H8pKb-bR}rT1L2|YlH54#<@*=
zyP?%Y=B+4O^;~89M^U!ikK=J59C8c(h`||2ZlE-`T})d&737P8cVl>F8K*_1xnmDI
zruGnQ$yJxq#@oJ$MoA|F>uup-=7G;`)iV^aU3Lp?hmvOiMY+{*1w%*NZ)nFKnB}{?
z+9>N;x5d2;`M2+6t_1HM`qpQ7Ijt{~u~afFbXGkUG8->+0X{)Eea(J{^y+Py(_2+Z
z*W&*y-KFo{KQ|TdejK6F)NB_OVQDs8<rpwZVlcLL&hO#$+`v{pKl+*&xNZd7w|n)>
zTUF=gUV2r5&432<=^~xR87(%4+$aX-t*_kDAh$-h@WH5K<z`yJmQKx8bbA2YGR>7&
zQ`?Z>mqtj&M-2@$-3Kci*NzG=cGn-1wnn&>D6}xQ8fo4;pq8DSZn;F1kFPH-6UvVk
zOz2-D%v%W6KaM#EfbeqZeeAJ>*nKvi>&UIGH`l?=!gscXM}=fid}VfLK|JBaJ=GOk
zlKI6n3wt(9`*h#FUP1Hs6|+p1b&cD+6841U@KxJqw&Vn&;fb9zLFX`=dI8G5bAHdN
z>%^fs%|BxDVnNt=+mH0Cyb;v4V}H6dKblvG0>qSkSA)>_ejb4i>xZ16TJI1wIuV%B
z2X^Si`&$pQg8|#3KMGTSAOvXEW>hGA-rGw)2CCTbP2SHN_n81v=<-kg<biPk<mJg$
z+?R6^WiD{2X<ftn$Wm^odcdeF=pp3UoIm49CfQpVm}<O~;SyoxO4>Q;u4ag3u=ERc
zKwc!vf8&Ldgly>k3n1{9Y~Vid{V3q{BX2~TFzuZ0)T)nb&gd@ytb6QF?{kT&*8k&n
zvgV7k(!QLR?r`t=-UfE$AWqz3=U@zOtV;5Y_!c))l@?CVcXPHeet%b7pvuqCPN|_i
z=6mHHv7^Ba<uz~v_J@X-WN8&8d^Ii-#qni{xIO5q;zdLia#B2?v|_^tD!8Bjz<1^<
zvh_I}#d)KMwOlq;Sun~cJ$`w~H<l5UgUodKi0gN9+^?Un%ybG)b#bDn&A)}N8&1mE
zb!v9_^Jl)@B=(yv_SWvh)oLKSa)_Fuz^a^+LuL;S)OlbwVg%X=_E$x<*>y&`Je}L$
z1{o5{YL}(o$>TcO;wBa!$l(q$S4c4A!@>ReHXzC{dEe-rYt;vFueypcQ$HUspCXd>
ziPkk2)P)XITQi-l@2hS0u_Qldj7C8Dr|U6U?6$)LdZX!wnGzL}zSkl4jg=Og*Htq)
zK5Z;GO<-b_m%-ggVQpD5g?W<_>*c8RT$a~|Mb4}e9zBzFSBB{99^8hB)*;1wx<5%;
z<^#*$EVHbN!9{WmlgCU|79i&YB-CF02W>foUdL7|Y_*S)*DYs#D;C5pTQZ=Aq8w>M
zNv+3`eV7%enud%r2|SixfhxncNe5*S8POpnHopyE8ZI`oNK%gIbpC?%^R^HA<70Dk
zsmnw~fx>)}Z(HTDV#aLphg;QlWiCInCwC~WaN-RPJHFQ8GcD4LggBjmMsFxDv$zJt
z>3-owFc>N<5vBmW;VKkv*V~1yttZCVKfA6dhVzVq$E0Mu@&c1r0d5j)ivz|DX#WHx
z2wI@=raDft6+<$lL9%@F*gi49;%(h{_=S#B4n6ye5gedNPl%COrMH{r$x=UuLcgEX
z+)tPd+E=qui$kq~ITq%qHN$uHM%f-EFfdGm{=NTB!VagH?a$(SlK^F(MNsajEM0k3
zwQ#r=1)Gcn%$!_o*tq=!Hs7CHzHFmN&~)~2bflOck+~xTl1N8#z4VuCzsuvJUnhFZ
z*w^tTKE#$X<8=(YvuiG-INCWt*@YbX^iL&Mx<yNx!y>f$$J3mfkeQZca`hDHNe#sb
zIx_2hdZuM8irM}GUB+K9)GQ1qF}A^wos7c1xJy#9NM;O9nTQa66?0i>Y+}+evvRBZ
zXg;d}^A~GfNVFq=lBXa4Es@}g5H$bQRlFitFFg!;Z&D?3ee`9eMYH!tg3m8yH@YLL
zI3*delrxwIsX2$a&j2=<uOU&Vy>;@i58eB~&-1CK-xpQkA2i?+xNOxFAHH;~-LMev
zLAgc6_Tl*@%v*Up$X|jp+}*soBfdbLIXb$EAq;mlvcf+-v@)Y`&Q=e0IaUa8sx^M|
z3B;Wi0btn$bfVeGk}7R$Jw@)w`-qoy3$(Gr@<%G{8OXZn`ow_kvN+an?@TruCYr<)
z)$G_cmFHe<H<cYK7%Hrdvez_7Bu;#lRU6&aovM@fV2%3eoPU(F3%a?`7`Z6MjzG_e
z@KK(|L`!<hV5gmf3F4V#F4|*ykf*HC@v?S<h9P-X*mn3Ae-5|&QF}5Rmks?+vXyxm
z<-7(NdW<izH?W(~cXk*2r|%ZjchVzasG-#$izN89q}%ki<nW>rd}(->1`cb5lA}s_
zIBNusO&SuRT%t!#zBkELj@#I^_+t<@ArSCie%*`Oh<mi#&NI1LJyW~rhoUx#`1VXZ
zycnJc;f8cx&e|~LuIWSR5R5S~!~U>&<$yG4kzmws#BrE7Gs?k#ruj0_!~6hk@kHu4
zJ*4|4(<|`};f6?|knEU%ZvX+L&l`Ia99eE&Gkty#AUWSZk=Rca=cI5AM&P2KAH1Kf
zsO0h|_h5=IF>hY@IUf;cfU{7Rz9DW~m#+Kzk)}w{Rtc>{tWX83KNSKPdh=b6E2dWe
z3*q9c>DQ9T!EC@MP?q6zD^T=(Tl3p*0lQS6A>W^F8!4Gj5iy(CFfG4`j>UT`$hIu4
zWkUq11;Cj*W^xmxX42>{g!-fyz616c4>VUKg*9kZcCa#Sj~DmY<>TBm7r?$T1;q?0
zFE4VQq=PdO4^>;kVS1rke|$APQ+<CujH@LT(g?dOy?WQ@5yGo*2yO3RkL&&TY_zV8
ztsupKns&)Dh~L5E4y^d}&Be1_-yY9*MD@oC6CoRn$%oBt-;<SkXx*jU12Lr=Ma{V4
zD;H4yf{$+>Mg|feq9Wh>Sw@vVhK~Q{Q~naYy`u6MEA`H;EM47TTo|}?FjEd!uQv^2
z%i$h(g@vF#wd>!SG<;WdJhpo)w2X6z*fS)HM}o8_r_}?}3+O|(oi{C$f-V<3?xUXf
zpPH#O3Df4?y#~D+FX~5NuK9+HG2;-1`Znv_^cg=Be4nkz%)qATojrZf)AKzHpAij6
zc7l_s8RtzL2@5x7I)MFT^->Wz8Z*V=Q;r>Y@3k4tSe~KIUv32oS6YUe`}>O$73|i$
zm?~^<Yc%@75NHYRt=GXuVN_grOdzb!%k%>nbxi82F&E*jG0Et!@Fr2aTkfSn$8DCi
zncRLQ*JzN+^cg&=9T4!@<{7AVPvbJygA2Gbr8XMSJrFs_?Pd8%H>1QX(GZ&)zAW(u
z?by|gxtx*4X88g43}!m8^AN)m%ue<wtbzJ2Z*d0<r;h7yvI9{OJ=veRnyF-HZV2e+
z6Q%8azAH@?XSN5TG}K>GwpX98v@mP%?7MzK9i6z+8e%xPreCsoMm*T~xh3plg5W`)
zJHIiddjMpKw}SfFyUl^uJ*-FAWoFpBrC%Hvwz7q26nF3Ck-9g`L*z0kc0k3WUop;$
zRP|`YJ4^!g+_961O$g_)i&Wv2<}*g@0*<v4*jLF9KCh}&+c1BJa<0%ya+NUW(99u?
z!q<U>{E5ZVFq9|gu;az}Db*agtNu=D*8s->^WE8j{=l*f(TasJk+&6wL})F+JNdTv
z)a++9j_+L6?ieW2SbDeZdZT^kE~Uc)D@1)5)raAVI@BB48T-5vm^zT{RqtD83mFAf
zSHuOmqdZohFBTquwd{?e&UX&!fK(VOOx3^5i)54epE?fzZNE!-SULFzbDG4i-}|Yn
z`WAOKeGTn%Vl0LHPKfMICco3N)&@Xbj6$UW{ya#5HO<Qi`WTtfWxzF8#lRUhylpn@
zV1=k-LO{^CPX8}pTrN!RCh|_bxi;)(dA%{hGNS(_wK?S}m>M!BEbvuyIEGEC$dFbt
zRuwxH7YV-ZW5{Z`(ewdU1aKqSFD+->br$4#yF951w^G!w(o4PLp4&UdA*>p%iS4`7
zOjhR>L*h2W)H8XF6<tF;A$b!IkP;TYGwOqP;w;9age%XYB|7y?K~Shz&oNchD#5m(
z0qAGChFy3fEb)3>m-ovIqSxxlg?8$+8XI5Bt;^v+^<a!Y`=20a#`oTnZ8tydeEyNC
zg-XYwW@(xg&L1<d1wd>Ij%r7bm&sMlOEXR;#&IsZ`xD3psAAkP$SRaontoD=BNynC
zxOg*L<&AqOjVeU42{Kom{FxzpZW2}T{#ro{X{>|Bs_s79S?f_J&te3ofx6AcY2_8|
zI&QmQb=G?)z!33&qMT`N{yEY#PZgQPE#;bs!*bxYkVk(3T>@4KIu~4Dy-ZEnUb-Jx
zUY}up9~!%Qi>zZA*%08~f!X>Y-K;_b4wVA}4?K0j_iLh&dNmkBgYsJ+izmxizvCnj
zU*KE3t)t3V&M2u&h-3w5a>&Y7P3Ku3bI>))P>6rRxtU&I!5Q*bycM@@&h_EFrUJ)@
zJq`3BsuyG5#u7kQs{-nJUB_;~DX(@8eT`l~J&nRo;Y}qhILN<%eo&3T*YhXTdlQ^6
z%FSy|(UPDWTB0?(un7#cZH>HWbGbv#-pqKlU)j%}*Uf)od|S+ZAf_Vk(vajq?x5%W
z(idOs?+VoF!VyLem5`AIm4cyoLtr&6E&i7kyem@w5iQxBl+XTL#oiM~Abb?FLfWgW
zBu-AEQLzD#uN4jXU2x~sfpH!X&|%p|w6>B#FxlVG{@S}UeJ{+DcHOQH<#7_%1H^Z*
z2=BSE_l)6QW(e{h3Cy{y94bO!LleLKulWW4ADH(azc>B-jy)5}+yf`{u78(al<4FJ
z-IxzU_ql&p#r<*+She%Hj^C@^uI#1Gj_VH-v9e)No7;yqHfMu*cI=|a=stp86S9F%
z0d{}Vu?<h04eVfy94#`{K3HL0v)Bq1h3Fk=(OlycI(yO5&N7V+3w^VSTWUaQAI5B_
zSd{=cD@>afCr6|CLBeI&VDI`EY*<4X==P*zUDL%D!Z^APBpE6Dy7l#{uLZbg`~fod
z7w`j8hg9!9Fk+rQI?sAtT_qF$C&Ad6{k#T4;y@8N!ZwaUbD^}NRSQVUUGfGfqaUgT
zf$%sfq3=-om?!HeDLwmPr~SwJN!m7cgRw;I5B<O)kf$i-^}AAuTyHyY)yLi8$Cl`E
zz6CXPZc@o&fC*uc`tSdIyw!i(LjUjk{96P6*1*3t@NW(LTLb^r!2e%05cqfg{{Z@I
B#&7@t

diff --git a/site/src/main.rs b/site/src/main.rs
index c4b515a..3520b3b 100644
--- a/site/src/main.rs
+++ b/site/src/main.rs
@@ -1,5 +1,23 @@
 use http::handling::{methods::Method, routes::{Route, Data}, request::Request, response::{Response, Outcome, Status}, file_handlers::NamedFile};
 
+fn static_files_handler(request: Request<>, _data: Data) -> Outcome<Response, Status, Data> {
+    let response = static_files(request.uri.raw_string().unwrap());
+    let response = match response {
+        Ok(dat) => Response {
+            headers: vec![],
+            cookies: None,
+            status: Some(Status::Ok),
+            body: Box::new(dat),
+        },
+        Err(_) => return Outcome::Failure(Status::NotFound),
+    };
+    Outcome::Success(response)
+}
+
+fn static_files(path: &str) -> Result<NamedFile, Status> {
+    NamedFile::open(("static/".to_string() + path).into())
+}
+
 fn index_handler(_request: Request, _data: Data) -> Outcome<Response, Status, Data> {
     Outcome::Success(Response { headers: vec![], cookies: None, status: None, body: Box::new(index()) })
 }
@@ -8,21 +26,50 @@ fn index() -> NamedFile {
     NamedFile::open("templates/index.html".into()).unwrap()
 }
 
+fn favicon_handler(_request: Request, _data: Data) -> Outcome<Response, Status, Data> {
+    let response = Response {
+        headers: vec![],
+        cookies: None, 
+        status: None,
+        body: Box::new(NamedFile::open("/assets/favicon.svg".into()).unwrap())
+    };
+    Outcome::Success(response)
+}
+
 #[tokio::main]
 async fn main() {
     let index_route = Route {
         format: None,
         handler: index_handler,
-        name: Some("Index"),
+        name: Some("index"),
         uri: "",
         method: Method::Get,
         rank: 0,
     };
 
+    let static_route = Route { 
+        format: None,
+        handler: static_files_handler,
+        name: Some("static files"),
+        uri: "",
+        method: Method::Get,
+        rank: 0
+    };
+
+    let favicon = Route {
+        format: None, 
+        handler: favicon_handler,
+        name: Some("favicon"),
+        uri: "favicon.ico",
+        method: Method::Get,
+        rank: 0
+    };
+
     // http::build("127.0.0.1:8000")
     http::build("127.0.0.1:8443", "127.0.0.1:8080")
         .await
-        .mount("/", vec![index_route])
+        .mount("/", vec![index_route, favicon])
+        .mount("/static", vec![static_route])
         .launch()
         .await;
 }
diff --git a/site/static/hello.html b/site/static/hello.html
deleted file mode 100644
index bf12019..0000000
--- a/site/static/hello.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!doctype html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <title>Hello</title>
-    <link rel="stylesheet" href="/static/style.css" />
-  </head>
-  <body>
-    <h1>Managed</h1>
-    <img src="/static/img.jpg" alt="" />
-  </body>
-</html>
diff --git a/site/static/hi b/site/static/hi
deleted file mode 100644
index 8bd6648..0000000
--- a/site/static/hi
+++ /dev/null
@@ -1 +0,0 @@
-asdf
diff --git a/site/static/img.jpg b/site/static/img.jpg
deleted file mode 100644
index 07eb7f85ac26c70344d552f56a81c44a0bf1b3db..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 51549
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
B#&7@t

diff --git a/site/templates/index.html b/site/templates/index.html
index 8645f34..7dc2842 100644
--- a/site/templates/index.html
+++ b/site/templates/index.html
@@ -6,6 +6,16 @@
     <link rel="stylesheet" href="/static/style.css" />
   </head>
   <body>
-    <h1>Hello and Welcome</h1>
+    <header>
+      <nav>
+        <div>LOGO</div>
+        <div>
+          <div>Dashboard</div>
+          <div>Books</div>
+          <div>Magazines</div>
+          <div>Newspapers</div>
+        </div>
+      </nav>
+    </header>
   </body>
 </html>
-- 
GitLab