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) {
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) {
Ok(Some(req)) => {
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("/")
|| req.uri.contains("/./")
|| req.uri.contains("/../")
@ -43,8 +42,8 @@ fn request_handler(client: &mut super::HttpStream) {
} else if req.uri.eq("/") {
res.status(200);
} else if req.uri.starts_with("/_usimp/") {
res.add_header("Cache-Control", "no-store");
res.add_header("Access-Control-Allow-Origin", "*");
res.header.add_field("Cache-Control", "no-store");
res.header.add_field("Access-Control-Allow-Origin", "*");
if req.uri.eq("/_usimp/websocket") {
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),
_ => {
res.status(405);
res.add_header("Allow", "POST");
res.header.add_field("Allow", "POST");
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 length = buf.as_bytes().len();
res.add_header("Content-Length", length.to_string().as_str());
res.add_header("Content-Type", "application/json; charset=utf-8");
res.header
.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) {
println!("Unable to send: {}", e);
@ -136,7 +137,7 @@ fn endpoint_handler(
mut res: super::Response,
endpoint: &str,
) {
let length = req.find_header("Content-Length");
let length = req.header.find_field("Content-Length");
let length: usize = match match length {
Some(length) => length,
None => {
@ -178,8 +179,10 @@ fn endpoint_handler(
// TODO compress
let length = buf.as_bytes().len();
res.add_header("Content-Length", length.to_string().as_str());
res.add_header("Content-Type", "application/json; charset=utf-8");
res.header
.add_field("Content-Length", length.to_string().as_str());
res.header
.add_field("Content-Type", "application/json; charset=utf-8");
res.status(200);
client.respond(&mut res).unwrap();

View File

@ -66,13 +66,13 @@ pub struct Request {
version: String,
pub method: Method,
pub uri: String,
header: Header,
pub header: Header,
}
pub struct Response {
version: String,
status: Status,
header: Header,
pub header: Header,
}
impl Method {
@ -200,15 +200,17 @@ impl Header {
value: String::from(value),
})
}
}
impl Request {
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 field_has_value(&self, field_name: &str, value: &str) -> bool {
if let Some(field) = self.find_field(field_name) {
let value = value.to_lowercase();
field
.to_lowercase()
.split(",")
.any(|mut s| s.trim().eq(value.as_str()))
} else {
false
}
}
}
@ -219,8 +221,8 @@ impl Response {
status: Status::from_code(200).unwrap(),
header: Header::new(),
};
res.add_header("Server", "Locutus");
res.add_header(
res.header.add_field("Server", "Locutus");
res.header.add_field(
"Date",
chrono::Utc::now()
.format("%a, %d %b %Y %H:%M:%S GMT")
@ -230,14 +232,6 @@ impl Response {
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) {
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> {
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();
self.add_header(
self.header.add_field(
"Content-Length",
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);
}
@ -324,8 +319,8 @@ impl HttpStream {
fn keep_alive(&mut self, res: &mut Response) {
if self.client_keep_alive && self.server_keep_alive {
res.add_header("Connection", "keep-alive");
res.add_header("Keep-Alive", "timeout=3600, max=200");
res.header.add_field("Connection", "keep-alive");
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 {
} else {
res.status(405);
res.add_header("Allow", "GET");
res.header.add_field("Allow", "GET");
return http::error_handler(
client,
res,
@ -23,8 +23,8 @@ pub fn connection_handler(
);
}
if let Some(connection) = req.find_header("Connection") {
if !connection.eq_ignore_ascii_case("upgrade") {
if let Some(_) = req.header.find_field("Connection") {
if !req.header.field_has_value("Connection", "upgrade") {
return http::error_handler(
client,
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") {
return http::error_handler(
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") {
return http::error_handler(
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();
hasher.input_str(key);
hasher.input_str("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
@ -85,7 +85,7 @@ pub fn connection_handler(
let mut result = [0u8; 160 / 8];
hasher.result(&mut 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 {
return http::error_handler(
client,
@ -96,8 +96,8 @@ pub fn connection_handler(
}
client.server_keep_alive = false;
res.add_header("Connection", "Upgrade");
res.add_header("Upgrade", "websocket");
res.header.add_field("Connection", "Upgrade");
res.header.add_field("Upgrade", "websocket");
res.status(101);
res.send(&mut client.stream).unwrap();