mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-28 12:45:27 +00:00
servo: Merge #6127 - Throw a SyntaxError if the WebSocket URL can't be parsed. Fix #6061 (from Nashenas88:websockets-invalid-urls); r=Ms2ger
Fix #6061. Source-Repo: https://github.com/servo/servo Source-Revision: d869a3c7a8378a77a9a5e86c118115f969ade193
This commit is contained in:
parent
175f0c39b1
commit
8af3f9a70e
@ -9,8 +9,7 @@ use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
||||
use dom::bindings::codegen::InheritTypes::EventTargetCast;
|
||||
use dom::bindings::codegen::InheritTypes::EventCast;
|
||||
use dom::bindings::error::{Error, Fallible};
|
||||
use dom::bindings::error::Error::InvalidAccess;
|
||||
use dom::bindings::error::Error::Syntax;
|
||||
use dom::bindings::error::Error::{InvalidAccess, Syntax};
|
||||
use dom::bindings::global::{GlobalField, GlobalRef};
|
||||
use dom::bindings::js::{Temporary, JSRef, Rootable};
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
@ -34,7 +33,6 @@ use websocket::stream::WebSocketStream;
|
||||
use websocket::client::request::Url;
|
||||
use websocket::Client;
|
||||
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
#[jstraceable]
|
||||
enum WebSocketRequestState {
|
||||
@ -64,6 +62,45 @@ pub struct WebSocket {
|
||||
sendCloseFrame: Cell<bool>
|
||||
}
|
||||
|
||||
fn parse_web_socket_url(url_str: &str) -> Fallible<(Url, String, u16, String, bool)> {
|
||||
// https://html.spec.whatwg.org/multipage/#parse-a-websocket-url's-components
|
||||
// Steps 1 and 2
|
||||
let parsed_url = Url::parse(url_str);
|
||||
let parsed_url = match parsed_url {
|
||||
Ok(parsed_url) => parsed_url,
|
||||
Err(_) => return Err(Error::Syntax),
|
||||
};
|
||||
|
||||
// Step 4
|
||||
if parsed_url.fragment != None {
|
||||
return Err(Error::Syntax);
|
||||
}
|
||||
|
||||
// Steps 3 and 5
|
||||
let secure = match parsed_url.scheme.as_ref() {
|
||||
"ws" => false,
|
||||
"wss" => true,
|
||||
_ => return Err(Error::Syntax), // step 3
|
||||
};
|
||||
|
||||
let host = parsed_url.host().unwrap().serialize(); // Step 6
|
||||
let port = parsed_url.port_or_default().unwrap(); // Step 7
|
||||
let mut resource = parsed_url.path().unwrap().connect("/"); // Step 9
|
||||
if resource.is_empty() {
|
||||
resource = "/".to_owned(); // Step 10
|
||||
}
|
||||
|
||||
// Step 11
|
||||
if let Some(ref query) = parsed_url.query {
|
||||
resource.push('?');
|
||||
resource.push_str(query);
|
||||
}
|
||||
|
||||
// Step 12
|
||||
// FIXME remove parsed_url once it's no longer used in WebSocket::new
|
||||
Ok((parsed_url, host, port, resource, secure))
|
||||
}
|
||||
|
||||
impl WebSocket {
|
||||
pub fn new_inherited(global: GlobalRef, url: DOMString) -> WebSocket {
|
||||
WebSocket {
|
||||
@ -84,11 +121,12 @@ impl WebSocket {
|
||||
|
||||
}
|
||||
|
||||
pub fn new(global: GlobalRef, url: DOMString) -> Temporary<WebSocket> {
|
||||
pub fn new(global: GlobalRef, url: DOMString) -> Fallible<Temporary<WebSocket>> {
|
||||
/*TODO: This constructor is only a prototype, it does not accomplish the specs
|
||||
defined here:
|
||||
http://html.spec.whatwg.org
|
||||
All 9 items must be satisfied.
|
||||
Item 1 is already satisfied.
|
||||
The remaining 8 items must be satisfied.
|
||||
TODO: This constructor should be responsible for spawning a thread for the
|
||||
receive loop after ws_root.r().Open() - See comment
|
||||
*/
|
||||
@ -96,7 +134,13 @@ impl WebSocket {
|
||||
global,
|
||||
WebSocketBinding::Wrap).root();
|
||||
let ws_root = ws_root.r();
|
||||
let parsed_url = Url::parse(&ws_root.url).unwrap();
|
||||
|
||||
// FIXME extract the right variables once Client::connect implementation is
|
||||
// fixed to follow the RFC 6455 properly
|
||||
let (parsed_url, _, _, _, _) = try!(parse_web_socket_url(&ws_root.url));
|
||||
|
||||
// TODO Client::connect does not conform to RFC 6455
|
||||
// see https://github.com/cyderize/rust-websocket/issues/38
|
||||
let request = Client::connect(parsed_url).unwrap();
|
||||
let response = request.send().unwrap();
|
||||
response.validate().unwrap();
|
||||
@ -107,8 +151,9 @@ impl WebSocket {
|
||||
let failed = ws_root.failed.get();
|
||||
if failed && (ready_state == WebSocketRequestState::Closed || ready_state == WebSocketRequestState::Closing) {
|
||||
//Do nothing else. Let the close finish.
|
||||
return Temporary::from_rooted(ws_root);
|
||||
return Ok(Temporary::from_rooted(ws_root));
|
||||
}
|
||||
|
||||
let (temp_sender, temp_receiver) = response.begin().split();
|
||||
let mut other_sender = ws_root.sender.borrow_mut();
|
||||
let mut other_receiver = ws_root.receiver.borrow_mut();
|
||||
@ -133,11 +178,11 @@ impl WebSocket {
|
||||
it confirms the websocket is now closed. This requires the close event
|
||||
to be fired (dispatch_close fires the close event - see implementation below)
|
||||
*/
|
||||
Temporary::from_rooted(ws_root)
|
||||
Ok(Temporary::from_rooted(ws_root))
|
||||
}
|
||||
|
||||
pub fn Constructor(global: GlobalRef, url: DOMString) -> Fallible<Temporary<WebSocket>> {
|
||||
Ok(WebSocket::new(global, url))
|
||||
WebSocket::new(global, url)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user