Introduced ClientProtocolError

This commit is contained in:
2021-05-24 13:33:10 +02:00
parent e12f39aee9
commit 3314144ee1
5 changed files with 47 additions and 33 deletions

View File

@ -17,6 +17,7 @@ pub enum Kind {
#[derive(Copy, Clone, Debug)]
pub enum Class {
ClientProtocolError,
ClientError,
ServerError,
}
@ -110,7 +111,7 @@ impl From<std::io::Error> for Error {
kind: Kind::IoError,
msg: Some(error.to_string()),
desc: Some(error.to_string()),
class: Class::ClientError,
class: Class::ClientProtocolError,
}
}
}
@ -121,7 +122,7 @@ impl From<serde_json::Error> for Error {
kind: Kind::JsonParseError,
msg: Some("Unable to parse JSON data".to_string()),
desc: Some(error.to_string()),
class: Class::ClientError,
class: Class::ClientProtocolError,
}
}
}
@ -156,7 +157,7 @@ impl From<std::string::FromUtf8Error> for Error {
kind: Kind::Utf8DecodeError,
msg: Some("Unable to decode UTF-8 data".to_string()),
desc: Some(error.to_string()),
class: Class::ClientError,
class: Class::ClientProtocolError,
}
}
}

View File

@ -75,10 +75,10 @@ fn request_handler(client: &mut super::HttpStream) {
_ => {
res.status(405);
res.header.add_field("Allow", "POST");
error = Some(Error::new(Kind::UsimpProtocolError, Class::ClientError))
error = Some(Error::new(Kind::UsimpProtocolError, Class::ClientProtocolError))
}
},
_ => error = Some(Error::new(Kind::InvalidEndpointError, Class::ClientError)),
_ => error = Some(Error::new(Kind::InvalidEndpointError, Class::ClientProtocolError)),
}
if let Some(error) = error {
@ -112,10 +112,15 @@ fn request_handler(client: &mut super::HttpStream) {
pub fn error_handler(client: &mut super::HttpStream, mut res: super::Response, error: Error) {
println!("{}", error.to_string());
match &error.class() {
Class::ClientError => {
Class::ClientProtocolError => {
if res.status.code < 400 || res.status.code >= 499 {
res.status(400)
}
},
Class::ClientError => {
if res.status.code < 200 || res.status.code >= 299 {
res.status(200)
}
}
Class::ServerError => {
if res.status.code < 500 || res.status.code > 599 {
@ -128,6 +133,7 @@ pub fn error_handler(client: &mut super::HttpStream, mut res: super::Response, e
let mut obj = serde_json::Value::Object(serde_json::Map::new());
obj["status"] = serde_json::Value::String("error".to_string());
obj["message"] = serde_json::Value::String(error.to_string());
obj["data"] = serde_json::Value::Null;
let buf = obj.to_string() + "\r\n";
let length = buf.as_bytes().len();
@ -157,7 +163,7 @@ fn endpoint_handler(
return error_handler(
client,
res,
Error::new(Kind::HttpRequestParseError, Class::ClientError)
Error::new(Kind::HttpRequestParseError, Class::ClientProtocolError)
.set_desc("field 'Content-Length' missing".to_string()),
)
}
@ -169,7 +175,7 @@ fn endpoint_handler(
return error_handler(
client,
res,
Error::new(Kind::HttpRequestParseError, Class::ClientError).set_desc(
Error::new(Kind::HttpRequestParseError, Class::ClientProtocolError).set_desc(
format!("unable to parse field 'Content-Length': {}", &e).to_string(),
),
)
@ -198,7 +204,7 @@ fn endpoint_handler(
return error_handler(
client,
res,
Error::new(Kind::UsimpProtocolError, Class::ClientError)
Error::new(Kind::UsimpProtocolError, Class::ClientProtocolError)
.set_desc("Unable to find field 'From-Domain'".to_string())
);
}
@ -210,7 +216,7 @@ fn endpoint_handler(
return error_handler(
client,
res,
Error::new(Kind::UsimpProtocolError, Class::ClientError)
Error::new(Kind::UsimpProtocolError, Class::ClientProtocolError)
.set_desc("Unable to find field 'To-Domain'".to_string())
);
}

View File

@ -43,7 +43,7 @@ pub fn parse_response(stream: &mut http::Stream) -> Result<http::Response, Error
let status_code = match status_code.parse::<u16>() {
Ok(v) => v,
Err(error) => {
return Err(Error::new(Kind::HttpRequestParseError, Class::ClientError)
return Err(Error::new(Kind::HttpRequestParseError, Class::ClientProtocolError)
.set_desc(error.to_string()))
}
};
@ -132,7 +132,7 @@ impl Parser<'_> {
match self.state {
State::Finish => return Ok(self.header_size),
State::Error => {
return Err(Error::new(Kind::HttpRequestParseError, Class::ClientError)
return Err(Error::new(Kind::HttpRequestParseError, Class::ClientProtocolError)
.set_desc(format!(
"invalid character at position {}",
self.header_size - 1
@ -141,7 +141,7 @@ impl Parser<'_> {
_ => {}
}
}
return Err(Error::new(Kind::HttpRequestParseError, Class::ClientError)
return Err(Error::new(Kind::HttpRequestParseError, Class::ClientProtocolError)
.set_desc("input too short".to_string()));
}

View File

@ -16,14 +16,21 @@ pub struct Envelope {
pub fn endpoint(envelope: Envelope) -> Result<serde_json::Value, Error> {
// TODO check authorization
// TODO domain_check
match envelope.endpoint.as_str() {
"echo" => Ok(serde_json::to_value(echo(serde_json::from_value(envelope.data)?)?)?),
"authenticate" => Ok(serde_json::to_value(authenticate(serde_json::from_value(envelope.data)?)?)?),
"subscribe" => Ok(serde_json::to_value(subscribe(serde_json::from_value(envelope.data)?)?)?),
"send_event" => Ok(serde_json::to_value(send_event(serde_json::from_value(envelope.data)?)?)?),
_ => return Err(Error::new(Kind::InvalidEndpointError, Class::ClientError)),
}
// TODO check from/to domain
let out = match envelope.endpoint.as_str() {
"echo" => serde_json::to_value(echo(serde_json::from_value(envelope.data)?)?)?,
"authenticate" => serde_json::to_value(authenticate(serde_json::from_value(envelope.data)?)?)?,
"subscribe" => serde_json::to_value(subscribe(serde_json::from_value(envelope.data)?)?)?,
"send_event" => serde_json::to_value(send_event(serde_json::from_value(envelope.data)?)?)?,
_ => return Err(Error::new(Kind::InvalidEndpointError, Class::ClientProtocolError)),
};
let mut envelope = serde_json::Value::Object(serde_json::Map::new());
envelope["status"] = serde_json::Value::String("success".to_string());
envelope["message"] = serde_json::Value::Null;
envelope["data"] = out;
Ok(envelope)
}
pub fn get_id(input: &str) -> String {

View File

@ -15,10 +15,10 @@ pub fn recv_message(client: &mut http::HttpStream) -> Result<Message, Error> {
// FIXME control frames may show up in a fragmented stream
if msg_type != 0 && header.opcode != 0 {
return Err(Error::new(Kind::WebSocketError, Class::ClientError)
return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError)
.set_desc("continuation frame expected".to_string()));
} else if header.opcode >= 8 && (!header.fin || header.payload_len >= 126) {
return Err(Error::new(Kind::WebSocketError, Class::ClientError)
return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError)
.set_desc("invalid control frame".to_string()));
}
@ -26,12 +26,12 @@ pub fn recv_message(client: &mut http::HttpStream) -> Result<Message, Error> {
0 => {}, // cont
1 => {}, // text
2 => // binary
return Err(Error::new(Kind::UsimpProtocolError, Class::ClientError)
return Err(Error::new(Kind::UsimpProtocolError, Class::ClientProtocolError)
.set_desc("binary frames must not be sent on a usimp connection".to_string())),
8 => {}, // close
9 => {}, // ping
10 => {}, // pong
_ => return Err(Error::new(Kind::WebSocketError, Class::ClientError)
_ => return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError)
.set_desc("invalid opcode".to_string())),
}
@ -101,37 +101,37 @@ pub fn handshake(
} else {
res.status(405);
res.header.add_field("Allow", "GET");
return Err(Error::new(Kind::WebSocketError, Class::ClientError)
return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError)
.set_desc("method not allowed".to_string()));
}
if let Some(_) = req.header.find_field("Connection") {
if !req.header.field_has_value("Connection", "upgrade") {
return Err(Error::new(Kind::WebSocketError, Class::ClientError)
return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError)
.set_desc("invalid value for header field 'Connection'".to_string()));
}
} else {
return Err(Error::new(Kind::WebSocketError, Class::ClientError)
return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError)
.set_desc("unable to find header field 'Connection'".to_string()));
}
if let Some(upgrade) = req.header.find_field("Upgrade") {
if !upgrade.eq_ignore_ascii_case("websocket") {
return Err(Error::new(Kind::WebSocketError, Class::ClientError)
return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError)
.set_desc("invalid value for header field 'Upgrade'".to_string()));
}
} else {
return Err(Error::new(Kind::WebSocketError, Class::ClientError)
return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError)
.set_desc("unable to find header field 'Upgrade'".to_string()));
}
if let Some(version) = req.header.find_field("Sec-WebSocket-Version") {
if !version.eq("13") {
return Err(Error::new(Kind::WebSocketError, Class::ClientError)
return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError)
.set_desc("invalid value for header field 'Sec-WebSocket-Key'".to_string()));
}
} else {
return Err(Error::new(Kind::WebSocketError, Class::ClientError)
return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError)
.set_desc("unable to find header field 'Sec-WebSocket-Version'".to_string()));
}
@ -145,7 +145,7 @@ pub fn handshake(
let key = base64::encode(result);
res.header.add_field("Sec-WebSocket-Accept", key.as_str());
} else {
return Err(Error::new(Kind::WebSocketError, Class::ClientError)
return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError)
.set_desc("unable to find header field 'Sec-WebSocket-Key'".to_string()));
}