Introduced ClientProtocolError
This commit is contained in:
@ -17,6 +17,7 @@ pub enum Kind {
|
|||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum Class {
|
pub enum Class {
|
||||||
|
ClientProtocolError,
|
||||||
ClientError,
|
ClientError,
|
||||||
ServerError,
|
ServerError,
|
||||||
}
|
}
|
||||||
@ -110,7 +111,7 @@ impl From<std::io::Error> for Error {
|
|||||||
kind: Kind::IoError,
|
kind: Kind::IoError,
|
||||||
msg: Some(error.to_string()),
|
msg: Some(error.to_string()),
|
||||||
desc: 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,
|
kind: Kind::JsonParseError,
|
||||||
msg: Some("Unable to parse JSON data".to_string()),
|
msg: Some("Unable to parse JSON data".to_string()),
|
||||||
desc: Some(error.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,
|
kind: Kind::Utf8DecodeError,
|
||||||
msg: Some("Unable to decode UTF-8 data".to_string()),
|
msg: Some("Unable to decode UTF-8 data".to_string()),
|
||||||
desc: Some(error.to_string()),
|
desc: Some(error.to_string()),
|
||||||
class: Class::ClientError,
|
class: Class::ClientProtocolError,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,10 +75,10 @@ fn request_handler(client: &mut super::HttpStream) {
|
|||||||
_ => {
|
_ => {
|
||||||
res.status(405);
|
res.status(405);
|
||||||
res.header.add_field("Allow", "POST");
|
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 {
|
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) {
|
pub fn error_handler(client: &mut super::HttpStream, mut res: super::Response, error: Error) {
|
||||||
println!("{}", error.to_string());
|
println!("{}", error.to_string());
|
||||||
match &error.class() {
|
match &error.class() {
|
||||||
Class::ClientError => {
|
Class::ClientProtocolError => {
|
||||||
if res.status.code < 400 || res.status.code >= 499 {
|
if res.status.code < 400 || res.status.code >= 499 {
|
||||||
res.status(400)
|
res.status(400)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
Class::ClientError => {
|
||||||
|
if res.status.code < 200 || res.status.code >= 299 {
|
||||||
|
res.status(200)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Class::ServerError => {
|
Class::ServerError => {
|
||||||
if res.status.code < 500 || res.status.code > 599 {
|
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());
|
let mut obj = serde_json::Value::Object(serde_json::Map::new());
|
||||||
obj["status"] = serde_json::Value::String("error".to_string());
|
obj["status"] = serde_json::Value::String("error".to_string());
|
||||||
obj["message"] = 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 buf = obj.to_string() + "\r\n";
|
||||||
|
|
||||||
let length = buf.as_bytes().len();
|
let length = buf.as_bytes().len();
|
||||||
@ -157,7 +163,7 @@ fn endpoint_handler(
|
|||||||
return error_handler(
|
return error_handler(
|
||||||
client,
|
client,
|
||||||
res,
|
res,
|
||||||
Error::new(Kind::HttpRequestParseError, Class::ClientError)
|
Error::new(Kind::HttpRequestParseError, Class::ClientProtocolError)
|
||||||
.set_desc("field 'Content-Length' missing".to_string()),
|
.set_desc("field 'Content-Length' missing".to_string()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -169,7 +175,7 @@ fn endpoint_handler(
|
|||||||
return error_handler(
|
return error_handler(
|
||||||
client,
|
client,
|
||||||
res,
|
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(),
|
format!("unable to parse field 'Content-Length': {}", &e).to_string(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -198,7 +204,7 @@ fn endpoint_handler(
|
|||||||
return error_handler(
|
return error_handler(
|
||||||
client,
|
client,
|
||||||
res,
|
res,
|
||||||
Error::new(Kind::UsimpProtocolError, Class::ClientError)
|
Error::new(Kind::UsimpProtocolError, Class::ClientProtocolError)
|
||||||
.set_desc("Unable to find field 'From-Domain'".to_string())
|
.set_desc("Unable to find field 'From-Domain'".to_string())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -210,7 +216,7 @@ fn endpoint_handler(
|
|||||||
return error_handler(
|
return error_handler(
|
||||||
client,
|
client,
|
||||||
res,
|
res,
|
||||||
Error::new(Kind::UsimpProtocolError, Class::ClientError)
|
Error::new(Kind::UsimpProtocolError, Class::ClientProtocolError)
|
||||||
.set_desc("Unable to find field 'To-Domain'".to_string())
|
.set_desc("Unable to find field 'To-Domain'".to_string())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ pub fn parse_response(stream: &mut http::Stream) -> Result<http::Response, Error
|
|||||||
let status_code = match status_code.parse::<u16>() {
|
let status_code = match status_code.parse::<u16>() {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
return Err(Error::new(Kind::HttpRequestParseError, Class::ClientError)
|
return Err(Error::new(Kind::HttpRequestParseError, Class::ClientProtocolError)
|
||||||
.set_desc(error.to_string()))
|
.set_desc(error.to_string()))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -132,7 +132,7 @@ impl Parser<'_> {
|
|||||||
match self.state {
|
match self.state {
|
||||||
State::Finish => return Ok(self.header_size),
|
State::Finish => return Ok(self.header_size),
|
||||||
State::Error => {
|
State::Error => {
|
||||||
return Err(Error::new(Kind::HttpRequestParseError, Class::ClientError)
|
return Err(Error::new(Kind::HttpRequestParseError, Class::ClientProtocolError)
|
||||||
.set_desc(format!(
|
.set_desc(format!(
|
||||||
"invalid character at position {}",
|
"invalid character at position {}",
|
||||||
self.header_size - 1
|
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()));
|
.set_desc("input too short".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,14 +16,21 @@ pub struct Envelope {
|
|||||||
|
|
||||||
pub fn endpoint(envelope: Envelope) -> Result<serde_json::Value, Error> {
|
pub fn endpoint(envelope: Envelope) -> Result<serde_json::Value, Error> {
|
||||||
// TODO check authorization
|
// TODO check authorization
|
||||||
// TODO domain_check
|
// TODO check from/to domain
|
||||||
match envelope.endpoint.as_str() {
|
let out = match envelope.endpoint.as_str() {
|
||||||
"echo" => Ok(serde_json::to_value(echo(serde_json::from_value(envelope.data)?)?)?),
|
"echo" => serde_json::to_value(echo(serde_json::from_value(envelope.data)?)?)?,
|
||||||
"authenticate" => Ok(serde_json::to_value(authenticate(serde_json::from_value(envelope.data)?)?)?),
|
"authenticate" => serde_json::to_value(authenticate(serde_json::from_value(envelope.data)?)?)?,
|
||||||
"subscribe" => Ok(serde_json::to_value(subscribe(serde_json::from_value(envelope.data)?)?)?),
|
"subscribe" => 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)?)?)?),
|
"send_event" => serde_json::to_value(send_event(serde_json::from_value(envelope.data)?)?)?,
|
||||||
_ => return Err(Error::new(Kind::InvalidEndpointError, Class::ClientError)),
|
_ => 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 {
|
pub fn get_id(input: &str) -> String {
|
||||||
|
@ -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
|
// FIXME control frames may show up in a fragmented stream
|
||||||
if msg_type != 0 && header.opcode != 0 {
|
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()));
|
.set_desc("continuation frame expected".to_string()));
|
||||||
} else if header.opcode >= 8 && (!header.fin || header.payload_len >= 126) {
|
} 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()));
|
.set_desc("invalid control frame".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,12 +26,12 @@ pub fn recv_message(client: &mut http::HttpStream) -> Result<Message, Error> {
|
|||||||
0 => {}, // cont
|
0 => {}, // cont
|
||||||
1 => {}, // text
|
1 => {}, // text
|
||||||
2 => // binary
|
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())),
|
.set_desc("binary frames must not be sent on a usimp connection".to_string())),
|
||||||
8 => {}, // close
|
8 => {}, // close
|
||||||
9 => {}, // ping
|
9 => {}, // ping
|
||||||
10 => {}, // pong
|
10 => {}, // pong
|
||||||
_ => return Err(Error::new(Kind::WebSocketError, Class::ClientError)
|
_ => return Err(Error::new(Kind::WebSocketError, Class::ClientProtocolError)
|
||||||
.set_desc("invalid opcode".to_string())),
|
.set_desc("invalid opcode".to_string())),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,37 +101,37 @@ pub fn handshake(
|
|||||||
} else {
|
} else {
|
||||||
res.status(405);
|
res.status(405);
|
||||||
res.header.add_field("Allow", "GET");
|
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()));
|
.set_desc("method not allowed".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(_) = req.header.find_field("Connection") {
|
if let Some(_) = req.header.find_field("Connection") {
|
||||||
if !req.header.field_has_value("Connection", "upgrade") {
|
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()));
|
.set_desc("invalid value for header field 'Connection'".to_string()));
|
||||||
}
|
}
|
||||||
} else {
|
} 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()));
|
.set_desc("unable to find header field 'Connection'".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(upgrade) = req.header.find_field("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 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()));
|
.set_desc("invalid value for header field 'Upgrade'".to_string()));
|
||||||
}
|
}
|
||||||
} else {
|
} 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()));
|
.set_desc("unable to find header field 'Upgrade'".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(version) = req.header.find_field("Sec-WebSocket-Version") {
|
if let Some(version) = req.header.find_field("Sec-WebSocket-Version") {
|
||||||
if !version.eq("13") {
|
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()));
|
.set_desc("invalid value for header field 'Sec-WebSocket-Key'".to_string()));
|
||||||
}
|
}
|
||||||
} else {
|
} 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()));
|
.set_desc("unable to find header field 'Sec-WebSocket-Version'".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ pub fn handshake(
|
|||||||
let key = base64::encode(result);
|
let key = base64::encode(result);
|
||||||
res.header.add_field("Sec-WebSocket-Accept", key.as_str());
|
res.header.add_field("Sec-WebSocket-Accept", key.as_str());
|
||||||
} else {
|
} 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()));
|
.set_desc("unable to find header field 'Sec-WebSocket-Key'".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user