Merge pull request #1124 from aaxdev/fix/support-mobile-signalr-msgpack
Fixing MsgPack headers type and support mobile SignalR
This commit is contained in:
commit
d7b0d6f9f5
|
@ -20,10 +20,12 @@ static SHOW_WEBSOCKETS_MSG: AtomicBool = AtomicBool::new(true);
|
||||||
#[get("/hub")]
|
#[get("/hub")]
|
||||||
fn websockets_err() -> EmptyResult {
|
fn websockets_err() -> EmptyResult {
|
||||||
if CONFIG.websocket_enabled() && SHOW_WEBSOCKETS_MSG.compare_and_swap(true, false, Ordering::Relaxed) {
|
if CONFIG.websocket_enabled() && SHOW_WEBSOCKETS_MSG.compare_and_swap(true, false, Ordering::Relaxed) {
|
||||||
err!("###########################################################
|
err!(
|
||||||
|
"###########################################################
|
||||||
'/notifications/hub' should be proxied to the websocket server or notifications won't work.
|
'/notifications/hub' should be proxied to the websocket server or notifications won't work.
|
||||||
Go to the Wiki for more info, or disable WebSockets setting WEBSOCKET_ENABLED=false.
|
Go to the Wiki for more info, or disable WebSockets setting WEBSOCKET_ENABLED=false.
|
||||||
###########################################################################################")
|
###########################################################################################"
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::empty())
|
Err(Error::empty())
|
||||||
}
|
}
|
||||||
|
@ -137,7 +139,6 @@ struct InitialMessage {
|
||||||
const PING_MS: u64 = 15_000;
|
const PING_MS: u64 = 15_000;
|
||||||
const PING: Token = Token(1);
|
const PING: Token = Token(1);
|
||||||
|
|
||||||
const ID_KEY: &str = "id=";
|
|
||||||
const ACCESS_TOKEN_KEY: &str = "access_token=";
|
const ACCESS_TOKEN_KEY: &str = "access_token=";
|
||||||
|
|
||||||
impl WSHandler {
|
impl WSHandler {
|
||||||
|
@ -148,6 +149,32 @@ impl WSHandler {
|
||||||
let io_error = io::Error::from(io::ErrorKind::InvalidData);
|
let io_error = io::Error::from(io::ErrorKind::InvalidData);
|
||||||
Err(ws::Error::new(ws::ErrorKind::Io(io_error), msg))
|
Err(ws::Error::new(ws::ErrorKind::Io(io_error), msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_request_token(&self, hs: Handshake) -> Option<String> {
|
||||||
|
use std::str::from_utf8;
|
||||||
|
|
||||||
|
// Verify we have a token header
|
||||||
|
if let Some(header_value) = hs.request.header("Authorization") {
|
||||||
|
if let Ok(converted) = from_utf8(header_value) {
|
||||||
|
if let Some(token_part) = converted.split("Bearer ").nth(1) {
|
||||||
|
return Some(token_part.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Otherwise verify the query parameter value
|
||||||
|
let path = hs.request.resource();
|
||||||
|
if let Some(params) = path.split('?').nth(1) {
|
||||||
|
let params_iter = params.split('&').take(1);
|
||||||
|
for val in params_iter {
|
||||||
|
if val.starts_with(ACCESS_TOKEN_KEY) {
|
||||||
|
return Some(val[ACCESS_TOKEN_KEY.len()..].into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Handler for WSHandler {
|
impl Handler for WSHandler {
|
||||||
|
@ -156,35 +183,16 @@ impl Handler for WSHandler {
|
||||||
//
|
//
|
||||||
// We don't use `id`, and as of around 2020-03-25, the official clients
|
// We don't use `id`, and as of around 2020-03-25, the official clients
|
||||||
// no longer seem to pass `id` (only `access_token`).
|
// no longer seem to pass `id` (only `access_token`).
|
||||||
let path = hs.request.resource();
|
|
||||||
|
|
||||||
let (_id, access_token) = match path.split('?').nth(1) {
|
// Get user token from header or query parameter
|
||||||
Some(params) => {
|
let access_token = match self.get_request_token(hs) {
|
||||||
let params_iter = params.split('&').take(2);
|
Some(token) => token,
|
||||||
|
|
||||||
let mut id = None;
|
|
||||||
let mut access_token = None;
|
|
||||||
|
|
||||||
for val in params_iter {
|
|
||||||
if val.starts_with(ID_KEY) {
|
|
||||||
id = Some(&val[ID_KEY.len()..]);
|
|
||||||
} else if val.starts_with(ACCESS_TOKEN_KEY) {
|
|
||||||
access_token = Some(&val[ACCESS_TOKEN_KEY.len()..]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match (id, access_token) {
|
|
||||||
(Some(a), Some(b)) => (a, b),
|
|
||||||
(None, Some(b)) => ("", b), // Ignore missing `id`.
|
|
||||||
_ => return self.err("Missing access token"),
|
_ => return self.err("Missing access token"),
|
||||||
}
|
|
||||||
}
|
|
||||||
None => return self.err("Missing query parameters"),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Validate the user
|
// Validate the user
|
||||||
use crate::auth;
|
use crate::auth;
|
||||||
let claims = match auth::decode_login(access_token) {
|
let claims = match auth::decode_login(access_token.as_str()) {
|
||||||
Ok(claims) => claims,
|
Ok(claims) => claims,
|
||||||
Err(_) => return self.err("Invalid access token provided"),
|
Err(_) => return self.err("Invalid access token provided"),
|
||||||
};
|
};
|
||||||
|
@ -335,7 +343,7 @@ impl WebSocketUsers {
|
||||||
/* Message Structure
|
/* Message Structure
|
||||||
[
|
[
|
||||||
1, // MessageType.Invocation
|
1, // MessageType.Invocation
|
||||||
{}, // Headers
|
{}, // Headers (map)
|
||||||
null, // InvocationId
|
null, // InvocationId
|
||||||
"ReceiveMessage", // Target
|
"ReceiveMessage", // Target
|
||||||
[ // Arguments
|
[ // Arguments
|
||||||
|
@ -352,7 +360,7 @@ fn create_update(payload: Vec<(Value, Value)>, ut: UpdateType) -> Vec<u8> {
|
||||||
|
|
||||||
let value = V::Array(vec![
|
let value = V::Array(vec![
|
||||||
1.into(),
|
1.into(),
|
||||||
V::Array(vec![]),
|
V::Map(vec![]),
|
||||||
V::Nil,
|
V::Nil,
|
||||||
"ReceiveMessage".into(),
|
"ReceiveMessage".into(),
|
||||||
V::Array(vec![V::Map(vec![
|
V::Array(vec![V::Map(vec![
|
||||||
|
|
Loading…
Reference in New Issue