reorganize module
This commit is contained in:
2
components/calendar/.cargo/config.toml
Normal file
2
components/calendar/.cargo/config.toml
Normal file
@@ -0,0 +1,2 @@
|
||||
[alias]
|
||||
dev = "watch -w src -w examples -w src/templates -w src/scripts -x 'run --example server'"
|
1546
components/calendar/Cargo.lock
generated
Normal file
1546
components/calendar/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
17
components/calendar/Cargo.toml
Normal file
17
components/calendar/Cargo.toml
Normal file
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "calendar"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
http = "0.2"
|
||||
hyper = { version = "0.14", features = ["full"] }
|
||||
httparse = "1"
|
||||
rhai = { version = "1.21", features = ["serde"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
tera = "1.0"
|
||||
once_cell = "1"
|
||||
rhai_tera = { path = "../../rhai_tera" }
|
||||
utils = { path = "../../utils" }
|
51
components/calendar/README.md
Normal file
51
components/calendar/README.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Calendar Server Example
|
||||
|
||||
A simple Rust web server using Hyper that exposes an `/all_calendars` endpoint.
|
||||
|
||||
## Running the server
|
||||
|
||||
```bash
|
||||
# Navigate to the examples directory
|
||||
cd /path/to/examples
|
||||
|
||||
# Build and run the server
|
||||
cargo run
|
||||
```
|
||||
|
||||
Once the server is running, you can access the endpoint at:
|
||||
- http://127.0.0.1:8080/all_calendars
|
||||
|
||||
## Features
|
||||
- Simple HTTP server using Hyper
|
||||
- Single endpoint that returns "Hello World"
|
||||
|
||||
|
||||
Sure thing! Here’s the Markdown version you can copy-paste directly into your README.md:
|
||||
|
||||
## 🔁 Live Reload (Hot Reload for Development)
|
||||
|
||||
To automatically recompile and restart your example server on file changes (e.g. Rust code, templates, Rhai scripts), you can use [`cargo-watch`](https://github.com/watchexec/cargo-watch):
|
||||
|
||||
### ✅ Step 1: Install `cargo-watch`
|
||||
|
||||
```bash
|
||||
cargo install cargo-watch
|
||||
```
|
||||
|
||||
### ✅ Step 2: Run the server with live reload
|
||||
|
||||
cargo watch -x 'run --example server'
|
||||
|
||||
This will:
|
||||
• Watch for file changes in your project
|
||||
• Rebuild and re-run examples/server.rs whenever you make a change
|
||||
|
||||
### 🧠 Bonus: Watch additional folders
|
||||
|
||||
To also reload when .tera templates or .rhai scripts change:
|
||||
|
||||
cargo watch -w src -w examples -w src/templates -w src/scripts -x 'run --example server'
|
||||
|
||||
### 💡 Optional: Clear terminal on each reload
|
||||
|
||||
cargo watch -c -x 'run --example server'
|
11
components/calendar/develop.sh
Executable file
11
components/calendar/develop.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# 🚀 Start dev server with file watching and browser reload
|
||||
reloadd \
|
||||
--watch src \
|
||||
--watch src/templates \
|
||||
--watch examples \
|
||||
--port 8080 \
|
||||
--run "cargo build" \
|
||||
--run "cargo run --example server"
|
119
components/calendar/examples/server.rs
Normal file
119
components/calendar/examples/server.rs
Normal file
@@ -0,0 +1,119 @@
|
||||
use hyper::{Body, Request, Response, Server};
|
||||
use hyper::service::{make_service_fn, service_fn};
|
||||
use hyper::{Method, StatusCode};
|
||||
use std::convert::Infallible;
|
||||
use std::net::SocketAddr;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::process::Command;
|
||||
use httparse;
|
||||
|
||||
async fn handle_request(req: Request<Body>) -> Result<Response<Body>, Infallible> {
|
||||
// Serialize request into raw HTTP format
|
||||
let raw_request = build_raw_http_request(req).await;
|
||||
|
||||
// Spawn the binary
|
||||
let mut child = Command::new("./target/debug/calendar")
|
||||
.stdin(std::process::Stdio::piped())
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.spawn()
|
||||
.expect("failed to spawn binary");
|
||||
|
||||
// Feed raw HTTP request to binary's stdin
|
||||
if let Some(mut stdin) = child.stdin.take() {
|
||||
let _ = stdin.write_all(&raw_request).await;
|
||||
}
|
||||
|
||||
// Read response from binary's stdout
|
||||
let mut stdout = child.stdout.take().expect("no stdout");
|
||||
let mut output = Vec::new();
|
||||
let _ = stdout.read_to_end(&mut output).await;
|
||||
|
||||
let _ = child.wait().await;
|
||||
|
||||
// Parse raw HTTP response
|
||||
match parse_raw_http_response(&output) {
|
||||
Ok(res) => Ok(res),
|
||||
Err(e) => {
|
||||
let mut resp = Response::new(Body::from(format!("Failed to parse response: {}", e)));
|
||||
*resp.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
Ok(resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build raw HTTP request string
|
||||
async fn build_raw_http_request(req: Request<Body>) -> Vec<u8> {
|
||||
let mut raw = String::new();
|
||||
|
||||
let method = req.method();
|
||||
let path = req.uri().path();
|
||||
let version = match req.version() {
|
||||
hyper::Version::HTTP_11 => "HTTP/1.1",
|
||||
_ => "HTTP/1.1",
|
||||
};
|
||||
|
||||
raw.push_str(&format!("{method} {path} {version}\r\n"));
|
||||
|
||||
for (key, value) in req.headers() {
|
||||
if let Ok(val_str) = value.to_str() {
|
||||
raw.push_str(&format!("{}: {}\r\n", key, val_str));
|
||||
}
|
||||
}
|
||||
|
||||
raw.push_str("\r\n");
|
||||
|
||||
let body_bytes = hyper::body::to_bytes(req.into_body()).await.unwrap_or_default();
|
||||
let mut full = raw.into_bytes();
|
||||
full.extend_from_slice(&body_bytes);
|
||||
|
||||
full
|
||||
}
|
||||
|
||||
// Parse raw HTTP response into hyper::Response<Body>
|
||||
fn parse_raw_http_response(bytes: &[u8]) -> Result<Response<Body>, Box<dyn std::error::Error>> {
|
||||
let mut headers = [httparse::EMPTY_HEADER; 64];
|
||||
let mut res = httparse::Response::new(&mut headers);
|
||||
let parsed_len = res.parse(bytes)?.unwrap(); // returns offset
|
||||
|
||||
let status = res.code.unwrap_or(200);
|
||||
let mut builder = Response::builder().status(status);
|
||||
|
||||
for h in res.headers.iter() {
|
||||
builder = builder.header(h.name, std::str::from_utf8(h.value)?);
|
||||
}
|
||||
|
||||
// Get body and append LiveReload script
|
||||
let mut body = bytes[parsed_len..].to_vec();
|
||||
let livereload_snippet = br#"<script>
|
||||
const ws = new WebSocket("ws://localhost:35729");
|
||||
ws.onmessage = (msg) => {
|
||||
if (msg.data === "reload") location.reload();
|
||||
};
|
||||
</script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
|
||||
>
|
||||
"#;
|
||||
body.extend_from_slice(b"\n");
|
||||
body.extend_from_slice(livereload_snippet);
|
||||
|
||||
Ok(builder.body(Body::from(body))?)
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
|
||||
|
||||
let make_svc = make_service_fn(|_conn| async {
|
||||
Ok::<_, Infallible>(service_fn(handle_request))
|
||||
});
|
||||
|
||||
println!("Proxy server running at http://{}", addr);
|
||||
|
||||
if let Err(e) = Server::bind(&addr).serve(make_svc).await {
|
||||
eprintln!("server error: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
33
components/calendar/src/controller/calendar.rs
Normal file
33
components/calendar/src/controller/calendar.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
use hyper::{Request, Body, Response, StatusCode};
|
||||
use std::path::PathBuf;
|
||||
|
||||
// Import the rhai_tera module
|
||||
extern crate rhai_tera;
|
||||
|
||||
pub fn get_calendars(_req: Request<Body>) -> Response<Body> {
|
||||
let tera = setup_tera_with_rhai();
|
||||
let context = tera::Context::new(); // no need to pass data — we're calling the Rhai function inside
|
||||
|
||||
let rendered = match tera.render("get_calendars.html.tera", &context) {
|
||||
Ok(html) => Response::new(Body::from(html)),
|
||||
Err(err) => {
|
||||
// 🔍 Print the full error with source
|
||||
eprintln!("Template render error: {:?}", err); // or use err.to_string() for cleaner message
|
||||
|
||||
let mut res = Response::new(Body::from(format!("Template error: {}", err)));
|
||||
*res.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
res
|
||||
}
|
||||
};
|
||||
|
||||
rendered
|
||||
}
|
||||
|
||||
fn setup_tera_with_rhai() -> tera::Tera {
|
||||
rhai_tera::setup_tera_with_rhai(
|
||||
"src/templates/**/*",
|
||||
"get_calendars",
|
||||
PathBuf::from("../../database/scripts/calendars.rhai"),
|
||||
"get_calendars"
|
||||
)
|
||||
}
|
19
components/calendar/src/lib.rs
Normal file
19
components/calendar/src/lib.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
use hyper::{Body, Method, Request, Response, StatusCode};
|
||||
use std::convert::Infallible;
|
||||
|
||||
mod controller {
|
||||
pub mod calendar;
|
||||
}
|
||||
|
||||
use controller::calendar;
|
||||
|
||||
pub async fn handle_request(req: Request<Body>) -> Result<Response<Body>, Infallible> {
|
||||
match (req.method(), req.uri().path()) {
|
||||
(&Method::GET, "/calendars") => Ok(calendar::get_calendars(req)),
|
||||
_ => {
|
||||
let mut res = Response::new(Body::from("Not Found"));
|
||||
*res.status_mut() = StatusCode::NOT_FOUND;
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
}
|
14
components/calendar/src/main.rs
Normal file
14
components/calendar/src/main.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
// Import the rhai_tera module from the root of the repo
|
||||
extern crate rhai_tera;
|
||||
extern crate utils;
|
||||
|
||||
use calendar::handle_request;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let input = utils::read_request_from_stdin()?;
|
||||
let request = utils::parse_http_request(&input)?;
|
||||
let response = handle_request(request).await?;
|
||||
utils::print_http_response(response).await;
|
||||
Ok(())
|
||||
}
|
17
components/calendar/src/templates/get_calendars.html.tera
Normal file
17
components/calendar/src/templates/get_calendars.html.tera
Normal file
@@ -0,0 +1,17 @@
|
||||
<h2>Calendars</h2>
|
||||
<ul>
|
||||
{% for cal in get_calendars() %}
|
||||
<li>
|
||||
<article>
|
||||
<header>
|
||||
<h3>{{ cal.name }}</h3>
|
||||
<p>{{ cal.description }}</p>
|
||||
</header>
|
||||
<footer>
|
||||
<p>{{ cal.id }}</p>
|
||||
<p>{{ cal.owner_id }}</p>
|
||||
</footer>
|
||||
</article>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
2
components/website/.cargo/config.toml
Normal file
2
components/website/.cargo/config.toml
Normal file
@@ -0,0 +1,2 @@
|
||||
[alias]
|
||||
dev = "watch -w src -w examples -w src/templates -w src/scripts -x 'run --example server'"
|
1534
components/website/Cargo.lock
generated
Normal file
1534
components/website/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
16
components/website/Cargo.toml
Normal file
16
components/website/Cargo.toml
Normal file
@@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "calendar"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
hyper = { version = "0.14", features = ["full"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
http = "0.2"
|
||||
httparse = "1"
|
||||
rhai = { version = "1.21", features = ["serde"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
tera = "1.0"
|
||||
once_cell = "1"
|
||||
rhai_tera = { path = "../../rhai_tera" }
|
51
components/website/README.md
Normal file
51
components/website/README.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Calendar Server Example
|
||||
|
||||
A simple Rust web server using Hyper that exposes an `/all_calendars` endpoint.
|
||||
|
||||
## Running the server
|
||||
|
||||
```bash
|
||||
# Navigate to the examples directory
|
||||
cd /path/to/examples
|
||||
|
||||
# Build and run the server
|
||||
cargo run
|
||||
```
|
||||
|
||||
Once the server is running, you can access the endpoint at:
|
||||
- http://127.0.0.1:8080/all_calendars
|
||||
|
||||
## Features
|
||||
- Simple HTTP server using Hyper
|
||||
- Single endpoint that returns "Hello World"
|
||||
|
||||
|
||||
Sure thing! Here’s the Markdown version you can copy-paste directly into your README.md:
|
||||
|
||||
## 🔁 Live Reload (Hot Reload for Development)
|
||||
|
||||
To automatically recompile and restart your example server on file changes (e.g. Rust code, templates, Rhai scripts), you can use [`cargo-watch`](https://github.com/watchexec/cargo-watch):
|
||||
|
||||
### ✅ Step 1: Install `cargo-watch`
|
||||
|
||||
```bash
|
||||
cargo install cargo-watch
|
||||
```
|
||||
|
||||
### ✅ Step 2: Run the server with live reload
|
||||
|
||||
cargo watch -x 'run --example server'
|
||||
|
||||
This will:
|
||||
• Watch for file changes in your project
|
||||
• Rebuild and re-run examples/server.rs whenever you make a change
|
||||
|
||||
### 🧠 Bonus: Watch additional folders
|
||||
|
||||
To also reload when .tera templates or .rhai scripts change:
|
||||
|
||||
cargo watch -w src -w examples -w src/templates -w src/scripts -x 'run --example server'
|
||||
|
||||
### 💡 Optional: Clear terminal on each reload
|
||||
|
||||
cargo watch -c -x 'run --example server'
|
11
components/website/develop.sh
Executable file
11
components/website/develop.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# 🚀 Start dev server with file watching and browser reload
|
||||
reloadd \
|
||||
--watch src \
|
||||
--watch src/templates \
|
||||
--watch examples \
|
||||
--port 8080 \
|
||||
--run "cargo build" \
|
||||
--run "cargo run --example server"
|
119
components/website/examples/server.rs
Normal file
119
components/website/examples/server.rs
Normal file
@@ -0,0 +1,119 @@
|
||||
use hyper::{Body, Request, Response, Server};
|
||||
use hyper::service::{make_service_fn, service_fn};
|
||||
use hyper::{Method, StatusCode};
|
||||
use std::convert::Infallible;
|
||||
use std::net::SocketAddr;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::process::Command;
|
||||
use httparse;
|
||||
|
||||
async fn handle_request(req: Request<Body>) -> Result<Response<Body>, Infallible> {
|
||||
// Serialize request into raw HTTP format
|
||||
let raw_request = build_raw_http_request(req).await;
|
||||
|
||||
// Spawn the binary
|
||||
let mut child = Command::new("./target/debug/calendar")
|
||||
.stdin(std::process::Stdio::piped())
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.spawn()
|
||||
.expect("failed to spawn binary");
|
||||
|
||||
// Feed raw HTTP request to binary's stdin
|
||||
if let Some(mut stdin) = child.stdin.take() {
|
||||
let _ = stdin.write_all(&raw_request).await;
|
||||
}
|
||||
|
||||
// Read response from binary's stdout
|
||||
let mut stdout = child.stdout.take().expect("no stdout");
|
||||
let mut output = Vec::new();
|
||||
let _ = stdout.read_to_end(&mut output).await;
|
||||
|
||||
let _ = child.wait().await;
|
||||
|
||||
// Parse raw HTTP response
|
||||
match parse_raw_http_response(&output) {
|
||||
Ok(res) => Ok(res),
|
||||
Err(e) => {
|
||||
let mut resp = Response::new(Body::from(format!("Failed to parse response: {}", e)));
|
||||
*resp.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
Ok(resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build raw HTTP request string
|
||||
async fn build_raw_http_request(req: Request<Body>) -> Vec<u8> {
|
||||
let mut raw = String::new();
|
||||
|
||||
let method = req.method();
|
||||
let path = req.uri().path();
|
||||
let version = match req.version() {
|
||||
hyper::Version::HTTP_11 => "HTTP/1.1",
|
||||
_ => "HTTP/1.1",
|
||||
};
|
||||
|
||||
raw.push_str(&format!("{method} {path} {version}\r\n"));
|
||||
|
||||
for (key, value) in req.headers() {
|
||||
if let Ok(val_str) = value.to_str() {
|
||||
raw.push_str(&format!("{}: {}\r\n", key, val_str));
|
||||
}
|
||||
}
|
||||
|
||||
raw.push_str("\r\n");
|
||||
|
||||
let body_bytes = hyper::body::to_bytes(req.into_body()).await.unwrap_or_default();
|
||||
let mut full = raw.into_bytes();
|
||||
full.extend_from_slice(&body_bytes);
|
||||
|
||||
full
|
||||
}
|
||||
|
||||
// Parse raw HTTP response into hyper::Response<Body>
|
||||
fn parse_raw_http_response(bytes: &[u8]) -> Result<Response<Body>, Box<dyn std::error::Error>> {
|
||||
let mut headers = [httparse::EMPTY_HEADER; 64];
|
||||
let mut res = httparse::Response::new(&mut headers);
|
||||
let parsed_len = res.parse(bytes)?.unwrap(); // returns offset
|
||||
|
||||
let status = res.code.unwrap_or(200);
|
||||
let mut builder = Response::builder().status(status);
|
||||
|
||||
for h in res.headers.iter() {
|
||||
builder = builder.header(h.name, std::str::from_utf8(h.value)?);
|
||||
}
|
||||
|
||||
// Get body and append LiveReload script
|
||||
let mut body = bytes[parsed_len..].to_vec();
|
||||
let livereload_snippet = br#"<script>
|
||||
const ws = new WebSocket("ws://localhost:35729");
|
||||
ws.onmessage = (msg) => {
|
||||
if (msg.data === "reload") location.reload();
|
||||
};
|
||||
</script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
|
||||
>
|
||||
"#;
|
||||
body.extend_from_slice(b"\n");
|
||||
body.extend_from_slice(livereload_snippet);
|
||||
|
||||
Ok(builder.body(Body::from(body))?)
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
|
||||
|
||||
let make_svc = make_service_fn(|_conn| async {
|
||||
Ok::<_, Infallible>(service_fn(handle_request))
|
||||
});
|
||||
|
||||
println!("Proxy server running at http://{}", addr);
|
||||
|
||||
if let Err(e) = Server::bind(&addr).serve(make_svc).await {
|
||||
eprintln!("server error: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
33
components/website/src/controller/calendar.rs
Normal file
33
components/website/src/controller/calendar.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
use hyper::{Request, Body, Response, StatusCode};
|
||||
use std::path::PathBuf;
|
||||
|
||||
// Import the rhai_tera module
|
||||
extern crate rhai_tera;
|
||||
|
||||
pub fn get_calendars(_req: Request<Body>) -> Response<Body> {
|
||||
let tera = setup_tera_with_rhai();
|
||||
let context = tera::Context::new(); // no need to pass data — we're calling the Rhai function inside
|
||||
|
||||
let rendered = match tera.render("get_calendars.html.tera", &context) {
|
||||
Ok(html) => Response::new(Body::from(html)),
|
||||
Err(err) => {
|
||||
// 🔍 Print the full error with source
|
||||
eprintln!("Template render error: {:?}", err); // or use err.to_string() for cleaner message
|
||||
|
||||
let mut res = Response::new(Body::from(format!("Template error: {}", err)));
|
||||
*res.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
res
|
||||
}
|
||||
};
|
||||
|
||||
rendered
|
||||
}
|
||||
|
||||
fn setup_tera_with_rhai() -> tera::Tera {
|
||||
rhai_tera::setup_tera_with_rhai(
|
||||
"src/templates/**/*",
|
||||
"get_calendars",
|
||||
PathBuf::from("../../database/scripts/calendars.rhai"),
|
||||
"get_calendars"
|
||||
)
|
||||
}
|
72
components/website/src/main.rs
Normal file
72
components/website/src/main.rs
Normal file
@@ -0,0 +1,72 @@
|
||||
// Import the rhai_tera module from the root of the repo
|
||||
extern crate rhai_tera;
|
||||
|
||||
mod controller {
|
||||
pub mod calendar;
|
||||
}
|
||||
|
||||
use controller::calendar;
|
||||
|
||||
use hyper::{Body, Method, Request, Response, StatusCode};
|
||||
use std::convert::Infallible;
|
||||
use std::io::{self, Read};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let input = read_request_from_stdin()?;
|
||||
let request = parse_http_request(&input)?;
|
||||
let response = handle_request(request).await?;
|
||||
print_http_response(response).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_request_from_stdin() -> io::Result<String> {
|
||||
let mut buffer = String::new();
|
||||
io::stdin().read_to_string(&mut buffer)?;
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
fn parse_http_request(input: &str) -> Result<Request<Body>, Box<dyn std::error::Error>> {
|
||||
let mut headers = [httparse::EMPTY_HEADER; 32];
|
||||
let mut req = httparse::Request::new(&mut headers);
|
||||
|
||||
let bytes = input.as_bytes();
|
||||
let parsed_len = req.parse(bytes)?.unwrap();
|
||||
|
||||
let method = req.method.ok_or("missing method")?.parse::<Method>()?;
|
||||
let path = req.path.ok_or("missing path")?;
|
||||
let uri = path.parse::<hyper::Uri>()?;
|
||||
|
||||
let body = &bytes[parsed_len..];
|
||||
let request = Request::builder()
|
||||
.method(method)
|
||||
.uri(uri)
|
||||
.body(Body::from(body.to_vec()))?;
|
||||
|
||||
Ok(request)
|
||||
}
|
||||
|
||||
async fn handle_request(req: Request<Body>) -> Result<Response<Body>, Infallible> {
|
||||
match (req.method(), req.uri().path()) {
|
||||
(&Method::GET, "/calendars") => Ok(calendar::get_calendars(req)),
|
||||
_ => {
|
||||
let mut res = Response::new(Body::from("Not Found"));
|
||||
*res.status_mut() = StatusCode::NOT_FOUND;
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn print_http_response(res: Response<Body>) {
|
||||
println!("HTTP/1.1 {}", res.status());
|
||||
|
||||
for (key, value) in res.headers() {
|
||||
println!("{}: {}", key, value.to_str().unwrap_or_default());
|
||||
}
|
||||
|
||||
println!(); // blank line before body
|
||||
|
||||
let body_bytes = hyper::body::to_bytes(res.into_body()).await.unwrap();
|
||||
let body = String::from_utf8_lossy(&body_bytes);
|
||||
println!("{}", body);
|
||||
}
|
17
components/website/src/templates/get_calendars.html.tera
Normal file
17
components/website/src/templates/get_calendars.html.tera
Normal file
@@ -0,0 +1,17 @@
|
||||
<h2>Calendars</h2>
|
||||
<ul>
|
||||
{% for cal in get_calendars() %}
|
||||
<li>
|
||||
<article>
|
||||
<header>
|
||||
<h3>{{ cal.name }}</h3>
|
||||
<p>{{ cal.description }}</p>
|
||||
</header>
|
||||
<footer>
|
||||
<p>{{ cal.id }}</p>
|
||||
<p>{{ cal.owner_id }}</p>
|
||||
</footer>
|
||||
</article>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
Reference in New Issue
Block a user