This commit is contained in:
Arkitu 2025-05-02 00:37:11 +02:00
parent b90c978a38
commit e6bc8561d4
6 changed files with 62 additions and 62 deletions

View File

@ -33,19 +33,14 @@
<form id="login-page"> <form id="login-page">
Enter your name : Enter your name :
<input <input
id="username" name="username"
type="text" type="text"
autocomplete="username" autocomplete="username"
minlength="3" minlength="3"
maxlength="16" maxlength="16"
required required
/> />
<button <button hx-post="/chat" hx-target="#login-page" hx-swap="outerHTML">
hx-get="/chat/connect"
hx-include="#username"
hx-target="#login-page"
hx-swap="outerHTML"
>
Connect Connect
</button> </button>
</form> </form>

View File

@ -1,10 +1,10 @@
use core::fmt::Write; use core::{fmt::Write, str::from_utf8};
use heapless::{String, Vec}; use heapless::{String, Vec};
use log::info; use log::info;
use pico_website::unwrap; use pico_website::unwrap;
use ringbuffer::{ConstGenericRingBuffer, RingBuffer}; use ringbuffer::{ConstGenericRingBuffer, RingBuffer};
use crate::socket::HttpResCode; use crate::socket::{HttpRequestType, HttpResCode};
use super::App; use super::App;
@ -47,16 +47,21 @@ impl App for ChatApp {
fn socket_name(&self) -> &'static str { fn socket_name(&self) -> &'static str {
"chat" "chat"
} }
async fn handle_request<'a>(&'a mut self, path: &str) -> (HttpResCode, &'static str, &'a [u8]) { async fn handle_request<'a>(
match path { &'a mut self,
"/" | "/index" | "/index.html" | "/chat" | "/chat.html" => { path: &str,
req_type: HttpRequestType,
content: &str,
) -> (HttpResCode, &'static str, &'a [u8]) {
match (req_type, path) {
(HttpRequestType::Get, "/" | "/index" | "/index.html" | "/chat" | "/chat.html") => {
(HttpResCode::Ok, "html", include_bytes!("./chat.html")) (HttpResCode::Ok, "html", include_bytes!("./chat.html"))
} }
path => { (req_type, path) => {
let (path, args) = path.split_once('?').unwrap_or((path, "")); let (path, args) = path.split_once('?').unwrap_or((path, ""));
let mut load = None; let mut load = None;
let mut username = None; let mut username = None;
for arg in args.split('&') { for arg in args.split('&').chain(content.split('&')) {
match arg.split_once('=') { match arg.split_once('=') {
Some(("load", n)) => { Some(("load", n)) => {
let n: u16 = match n.parse() { let n: u16 = match n.parse() {
@ -76,18 +81,22 @@ impl App for ChatApp {
_ => {} _ => {}
} }
} }
if path == "/chat" && username.is_some() { if path == "/chat" && username.is_some() {
return ( self.res_buf.clear();
HttpResCode::Ok, unwrap(write!(
"html", &mut self.res_buf,
"<div \ "<div \
class=\"message\" \ class=\"message\" \
hx-get=\"/chat/message/abs/0?load=\" \ hx-get=\"/chat/message/abs/0?load={}\" \
hx-target=\"this\" \ hx-target=\"this\" \
hx-swap=\"outerHTML\" \ hx-swap=\"outerHTML\" \
hx-trigger=\"load\" \ hx-trigger=\"load\" \
></div>", ></div>",
); MEMORY_SIZE
))
.await;
return (HttpResCode::Ok, "html", &self.res_buf);
} else if path.starts_with("/chat/message/abs/") && path.len() > 18 { } else if path.starts_with("/chat/message/abs/") && path.len() > 18 {
let msg_id: u16 = match path[18..].parse() { let msg_id: u16 = match path[18..].parse() {
Ok(n) => n, Ok(n) => n,

View File

@ -1,4 +1,4 @@
use crate::socket::HttpResCode; use crate::socket::{HttpRequestType, HttpResCode};
use super::App; use super::App;
@ -7,7 +7,12 @@ impl App for IndexApp {
fn socket_name(&self) -> &'static str { fn socket_name(&self) -> &'static str {
"index" "index"
} }
async fn handle_request<'a>(&'a mut self, path: &str) -> (HttpResCode, &'static str, &'a [u8]) { async fn handle_request<'a>(
&'a mut self,
path: &str,
_req_type: HttpRequestType,
_content: &str,
) -> (HttpResCode, &'static str, &'a [u8]) {
match path { match path {
"/" | "/index" | "/index.html" => { "/" | "/index" | "/index.html" => {
(HttpResCode::Ok, "html", include_bytes!("./index.html")) (HttpResCode::Ok, "html", include_bytes!("./index.html"))

View File

@ -1,4 +1,4 @@
use crate::socket::HttpResCode; use crate::socket::{HttpRequestType, HttpResCode};
pub mod chat; pub mod chat;
pub mod index; pub mod index;
@ -6,5 +6,10 @@ pub mod ttt;
pub trait App { pub trait App {
fn socket_name(&self) -> &'static str; fn socket_name(&self) -> &'static str;
async fn handle_request<'a>(&'a mut self, path: &str) -> (HttpResCode, &'static str, &'a [u8]); async fn handle_request<'a>(
&'a mut self,
path: &str,
req_type: HttpRequestType,
content: &str,
) -> (HttpResCode, &'static str, &'a [u8]);
} }

View File

@ -5,7 +5,7 @@ use heapless::Vec;
use pico_website::unwrap; use pico_website::unwrap;
use portable_atomic::{AtomicBool, AtomicU32}; use portable_atomic::{AtomicBool, AtomicU32};
use crate::socket::HttpResCode; use crate::socket::{HttpRequestType, HttpResCode};
use super::App; use super::App;
@ -154,7 +154,12 @@ impl App for TttApp {
fn socket_name(&self) -> &'static str { fn socket_name(&self) -> &'static str {
self.team.name() self.team.name()
} }
async fn handle_request<'a>(&'a mut self, path: &str) -> (HttpResCode, &'static str, &'a [u8]) { async fn handle_request<'a>(
&'a mut self,
path: &str,
_req_type: HttpRequestType,
_content: &str,
) -> (HttpResCode, &'static str, &'a [u8]) {
match path { match path {
"/" | "/index" | "/index.html" | "/ttt" | "/ttt.html" => { "/" | "/index" | "/index.html" | "/ttt" | "/ttt.html" => {
(HttpResCode::Ok, "html", include_bytes!("./ttt.html")) (HttpResCode::Ok, "html", include_bytes!("./ttt.html"))

View File

@ -64,41 +64,31 @@ pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl App,
} }
}; };
let mut headers: &[u8] = &buf[..n]; let (headers, content) = match from_utf8(&buf[..n]) {
let mut _content: &[u8] = &[]; Ok(b) => match b.split_once("\r\n\r\n") {
for i in 0..(n - 1) { Some(t) => t,
if &buf[i..i + 1] == b"\r\n" { None => (b, ""),
headers = &buf[0..i]; },
if i + 2 < n { Err(_) => {
_content = &buf[i + 2..n]; warn!("Non utf8 http request");
} break;
} }
} };
let mut headers = headers.split(|x| *x == b'\n'); // let mut headers = headers.split(|x| *x == b'\n');
let (request_type, path) = match headers.next() { let (request_type, path) = match headers.lines().next() {
None => { None => {
warn!("Empty request"); warn!("Empty request");
break; break;
} }
Some(l1) => { Some(l1) => {
let mut l1 = l1.split(|x| *x == b' '); let mut l1 = l1.split(' ');
( (
match l1.next() { match l1.next() {
Some(b"GET") => HttpRequestType::Get, Some("GET") => HttpRequestType::Get,
Some(b"POST") => HttpRequestType::Post, Some("POST") => HttpRequestType::Post,
Some(t) => { Some(t) => {
match from_utf8(t) { warn!("Unknown request type : {}", t);
Ok(t) => {
warn!("Unknown request type : {}", t);
}
Err(e) => {
warn!(
"Error while parsing request type : {}\nRaw type : {:?}",
e, t
);
}
}
break; break;
} }
None => { None => {
@ -107,16 +97,7 @@ pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl App,
} }
}, },
match l1.next() { match l1.next() {
Some(path) => match from_utf8(path) { Some(path) => path,
Ok(p) => p,
Err(e) => {
warn!(
"Error while parsing requested path : {}\nRaw path : {:?}",
e, path
);
break;
}
},
None => { None => {
warn!("No path"); warn!("No path");
break; break;
@ -143,7 +124,7 @@ pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl App,
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
include_bytes!("../static/htmx.min.js"), include_bytes!("../static/htmx.min.js"),
), ),
p => app.handle_request(p).await, p => app.handle_request(p, request_type, content).await,
}; };
res_head_buf.clear(); res_head_buf.clear();
@ -179,7 +160,7 @@ pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl App,
} }
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
enum HttpRequestType { pub enum HttpRequestType {
Get, Get,
Post, Post,
} }