WebSocket Firefox

This commit is contained in:
2021-05-22 14:24:42 +02:00
parent 3aef8956dd
commit 3867435a2d
3 changed files with 44 additions and 46 deletions

View File

@ -24,14 +24,13 @@ pub fn connection_handler(client: super::Stream) {
fn request_handler(client: &mut super::HttpStream) { fn request_handler(client: &mut super::HttpStream) {
let mut res = super::Response::new(); let mut res = super::Response::new();
if let Some(conn) = res.find_header("Connection") {
client.client_keep_alive = client.client_keep_alive && conn.eq_ignore_ascii_case("keep-alive");
}
match super::parser::parse_request(&mut client.stream) { match super::parser::parse_request(&mut client.stream) {
Ok(Some(req)) => { Ok(Some(req)) => {
println!("{} {}", req.method, req.uri); println!("{} {}", req.method, req.uri);
client.client_keep_alive =
client.client_keep_alive && req.header.field_has_value("Connection", "keep-alive");
if !req.uri.starts_with("/") if !req.uri.starts_with("/")
|| req.uri.contains("/./") || req.uri.contains("/./")
|| req.uri.contains("/../") || req.uri.contains("/../")
@ -43,8 +42,8 @@ fn request_handler(client: &mut super::HttpStream) {
} else if req.uri.eq("/") { } else if req.uri.eq("/") {
res.status(200); res.status(200);
} else if req.uri.starts_with("/_usimp/") { } else if req.uri.starts_with("/_usimp/") {
res.add_header("Cache-Control", "no-store"); res.header.add_field("Cache-Control", "no-store");
res.add_header("Access-Control-Allow-Origin", "*"); res.header.add_field("Access-Control-Allow-Origin", "*");
if req.uri.eq("/_usimp/websocket") { if req.uri.eq("/_usimp/websocket") {
return websocket::connection_handler(client, &req, res); return websocket::connection_handler(client, &req, res);
@ -62,7 +61,7 @@ fn request_handler(client: &mut super::HttpStream) {
Method::POST => return endpoint_handler(client, &req, res, endpoint), Method::POST => return endpoint_handler(client, &req, res, endpoint),
_ => { _ => {
res.status(405); res.status(405);
res.add_header("Allow", "POST"); res.header.add_field("Allow", "POST");
error = Some(Error::new(Kind::UsimpProtocolError, Class::ClientError)) error = Some(Error::new(Kind::UsimpProtocolError, Class::ClientError))
} }
}, },
@ -119,8 +118,10 @@ pub fn error_handler(client: &mut super::HttpStream, mut res: super::Response, e
let buf = obj.to_string() + "\r\n"; let buf = obj.to_string() + "\r\n";
let length = buf.as_bytes().len(); let length = buf.as_bytes().len();
res.add_header("Content-Length", length.to_string().as_str()); res.header
res.add_header("Content-Type", "application/json; charset=utf-8"); .add_field("Content-Length", length.to_string().as_str());
res.header
.add_field("Content-Type", "application/json; charset=utf-8");
if let Err(e) = client.respond(&mut res) { if let Err(e) = client.respond(&mut res) {
println!("Unable to send: {}", e); println!("Unable to send: {}", e);
@ -136,7 +137,7 @@ fn endpoint_handler(
mut res: super::Response, mut res: super::Response,
endpoint: &str, endpoint: &str,
) { ) {
let length = req.find_header("Content-Length"); let length = req.header.find_field("Content-Length");
let length: usize = match match length { let length: usize = match match length {
Some(length) => length, Some(length) => length,
None => { None => {
@ -178,8 +179,10 @@ fn endpoint_handler(
// TODO compress // TODO compress
let length = buf.as_bytes().len(); let length = buf.as_bytes().len();
res.add_header("Content-Length", length.to_string().as_str()); res.header
res.add_header("Content-Type", "application/json; charset=utf-8"); .add_field("Content-Length", length.to_string().as_str());
res.header
.add_field("Content-Type", "application/json; charset=utf-8");
res.status(200); res.status(200);
client.respond(&mut res).unwrap(); client.respond(&mut res).unwrap();

View File

@ -66,13 +66,13 @@ pub struct Request {
version: String, version: String,
pub method: Method, pub method: Method,
pub uri: String, pub uri: String,
header: Header, pub header: Header,
} }
pub struct Response { pub struct Response {
version: String, version: String,
status: Status, status: Status,
header: Header, pub header: Header,
} }
impl Method { impl Method {
@ -200,15 +200,17 @@ impl Header {
value: String::from(value), value: String::from(value),
}) })
} }
}
impl Request { pub fn field_has_value(&self, field_name: &str, value: &str) -> bool {
pub fn find_header(&self, name: &str) -> Option<&str> { if let Some(field) = self.find_field(field_name) {
self.header.find_field(name) let value = value.to_lowercase();
} field
.to_lowercase()
pub fn add_header(&mut self, name: &str, value: &str) { .split(",")
self.header.add_field(name, value) .any(|mut s| s.trim().eq(value.as_str()))
} else {
false
}
} }
} }
@ -219,8 +221,8 @@ impl Response {
status: Status::from_code(200).unwrap(), status: Status::from_code(200).unwrap(),
header: Header::new(), header: Header::new(),
}; };
res.add_header("Server", "Locutus"); res.header.add_field("Server", "Locutus");
res.add_header( res.header.add_field(
"Date", "Date",
chrono::Utc::now() chrono::Utc::now()
.format("%a, %d %b %Y %H:%M:%S GMT") .format("%a, %d %b %Y %H:%M:%S GMT")
@ -230,14 +232,6 @@ impl Response {
res res
} }
pub fn find_header(&self, name: &str) -> Option<&str> {
self.header.find_field(name)
}
pub fn add_header(&mut self, name: &str, value: &str) {
self.header.add_field(name, value)
}
pub fn status(&mut self, status_code: u16) { pub fn status(&mut self, status_code: u16) {
self.status = Status::from_code(status_code).unwrap() self.status = Status::from_code(status_code).unwrap()
} }
@ -261,13 +255,14 @@ impl Response {
pub fn send_default(&mut self, stream: &mut Stream) -> Result<(), std::io::Error> { pub fn send_default(&mut self, stream: &mut Stream) -> Result<(), std::io::Error> {
let mut buf = None; let mut buf = None;
if let None = self.find_header("Content-Length") { if let None = self.header.find_field("Content-Length") {
let new_buf = self.format_default_response(); let new_buf = self.format_default_response();
self.add_header( self.header.add_field(
"Content-Length", "Content-Length",
new_buf.as_bytes().len().to_string().as_str(), new_buf.as_bytes().len().to_string().as_str(),
); );
self.add_header("Content-Type", "text/html; charset=utf-8"); self.header
.add_field("Content-Type", "text/html; charset=utf-8");
buf = Some(new_buf); buf = Some(new_buf);
} }
@ -324,8 +319,8 @@ impl HttpStream {
fn keep_alive(&mut self, res: &mut Response) { fn keep_alive(&mut self, res: &mut Response) {
if self.client_keep_alive && self.server_keep_alive { if self.client_keep_alive && self.server_keep_alive {
res.add_header("Connection", "keep-alive"); res.header.add_field("Connection", "keep-alive");
res.add_header("Keep-Alive", "timeout=3600, max=200"); res.header.add_field("Keep-Alive", "timeout=3600, max=200");
} }
} }
} }

View File

@ -14,7 +14,7 @@ pub fn connection_handler(
if let http::Method::GET = req.method { if let http::Method::GET = req.method {
} else { } else {
res.status(405); res.status(405);
res.add_header("Allow", "GET"); res.header.add_field("Allow", "GET");
return http::error_handler( return http::error_handler(
client, client,
res, res,
@ -23,8 +23,8 @@ pub fn connection_handler(
); );
} }
if let Some(connection) = req.find_header("Connection") { if let Some(_) = req.header.find_field("Connection") {
if !connection.eq_ignore_ascii_case("upgrade") { if !req.header.field_has_value("Connection", "upgrade") {
return http::error_handler( return http::error_handler(
client, client,
res, res,
@ -41,7 +41,7 @@ pub fn connection_handler(
); );
} }
if let Some(upgrade) = req.find_header("Upgrade") { if let Some(upgrade) = req.header.find_field("Upgrade") {
if !upgrade.eq_ignore_ascii_case("websocket") { if !upgrade.eq_ignore_ascii_case("websocket") {
return http::error_handler( return http::error_handler(
client, client,
@ -59,7 +59,7 @@ pub fn connection_handler(
); );
} }
if let Some(version) = req.find_header("Sec-WebSocket-Version") { if let Some(version) = req.header.find_field("Sec-WebSocket-Version") {
if !version.eq("13") { if !version.eq("13") {
return http::error_handler( return http::error_handler(
client, client,
@ -77,7 +77,7 @@ pub fn connection_handler(
); );
} }
if let Some(key) = req.find_header("Sec-WebSocket-Key") { if let Some(key) = req.header.find_field("Sec-WebSocket-Key") {
let mut hasher = crypto::sha1::Sha1::new(); let mut hasher = crypto::sha1::Sha1::new();
hasher.input_str(key); hasher.input_str(key);
hasher.input_str("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); hasher.input_str("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
@ -85,7 +85,7 @@ pub fn connection_handler(
let mut result = [0u8; 160 / 8]; let mut result = [0u8; 160 / 8];
hasher.result(&mut result); hasher.result(&mut result);
let key = base64::encode(result); let key = base64::encode(result);
res.add_header("Sec-WebSocket-Accept", key.as_str()); res.header.add_field("Sec-WebSocket-Accept", key.as_str());
} else { } else {
return http::error_handler( return http::error_handler(
client, client,
@ -96,8 +96,8 @@ pub fn connection_handler(
} }
client.server_keep_alive = false; client.server_keep_alive = false;
res.add_header("Connection", "Upgrade"); res.header.add_field("Connection", "Upgrade");
res.add_header("Upgrade", "websocket"); res.header.add_field("Upgrade", "websocket");
res.status(101); res.status(101);
res.send(&mut client.stream).unwrap(); res.send(&mut client.stream).unwrap();