diff --git a/Cargo.lock b/Cargo.lock
index 7c1bdbfaf..a1fd76643 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -109,14 +109,6 @@ dependencies = [
"unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
-[[package]]
-name = "conduit-mime-types"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "cookie"
version = "0.1.21"
@@ -195,15 +187,6 @@ dependencies = [
"regex 0.1.65 (registry+https://github.com/rust-lang/crates.io-index)",
]
-[[package]]
-name = "error"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "traitobject 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "eth-secp256k1"
version = "0.5.4"
@@ -318,13 +301,13 @@ dependencies = [
"ethcore-rpc 1.1.0",
"ethcore-util 1.1.0",
"hyper 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "iron 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-http-server 4.0.0 (git+https://github.com/tomusdrw/jsonrpc-http-server.git?branch=old-hyper)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-status 0.1.6 (git+https://github.com/tomusdrw/parity-status.git)",
"parity-wallet 0.1.1 (git+https://github.com/tomusdrw/parity-wallet.git)",
"parity-webapp 0.1.0 (git+https://github.com/tomusdrw/parity-webapp.git)",
+ "url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -484,23 +467,6 @@ dependencies = [
"xmltree 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
-[[package]]
-name = "iron"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "conduit-mime-types 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "error 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "hyper 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "itertools"
version = "0.4.12"
@@ -654,11 +620,6 @@ dependencies = [
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
-[[package]]
-name = "modifier"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
[[package]]
name = "net2"
version = "0.2.23"
@@ -744,14 +705,6 @@ name = "parity-webapp"
version = "0.1.0"
source = "git+https://github.com/tomusdrw/parity-webapp.git#a24297256bae0ae0712c6478cd1ad681828b3800"
-[[package]]
-name = "plugin"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "primal"
version = "0.2.3"
@@ -1057,11 +1010,6 @@ name = "traitobject"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "traitobject"
-version = "0.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
[[package]]
name = "transient-hashmap"
version = "0.1.0"
@@ -1075,14 +1023,6 @@ name = "typeable"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "typemap"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "unsafe-any 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "unicase"
version = "1.4.0"
@@ -1109,14 +1049,6 @@ name = "unicode-xid"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "unsafe-any"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "traitobject 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "url"
version = "0.2.38"
diff --git a/webapp/Cargo.toml b/webapp/Cargo.toml
index eb3e9c042..157d9e506 100644
--- a/webapp/Cargo.toml
+++ b/webapp/Cargo.toml
@@ -12,7 +12,7 @@ log = "0.3"
jsonrpc-core = "2.0"
jsonrpc-http-server = { git = "https://github.com/tomusdrw/jsonrpc-http-server.git", branch="old-hyper" }
hyper = { version = "0.8", default-features = false }
-iron = { version = "0.3" }
+url = "0.5"
ethcore-rpc = { path = "../rpc" }
ethcore-util = { path = "../util" }
parity-webapp = { git = "https://github.com/tomusdrw/parity-webapp.git" }
diff --git a/webapp/src/lib.rs b/webapp/src/lib.rs
index ed9a13967..8452f6453 100644
--- a/webapp/src/lib.rs
+++ b/webapp/src/lib.rs
@@ -20,8 +20,8 @@
#[macro_use]
extern crate log;
+extern crate url;
extern crate hyper;
-extern crate iron;
extern crate jsonrpc_core;
extern crate jsonrpc_http_server;
extern crate ethcore_rpc as rpc;
diff --git a/webapp/src/router/mod.rs b/webapp/src/router/mod.rs
index 070f94a34..f91e837a3 100644
--- a/webapp/src/router/mod.rs
+++ b/webapp/src/router/mod.rs
@@ -18,6 +18,7 @@
//! Processes request handling authorization and dispatching it to proper application.
mod api;
+mod url;
pub mod auth;
use std::sync::Arc;
@@ -25,7 +26,7 @@ use hyper;
use hyper::{server, uri, header};
use page::Page;
use apps::Pages;
-use iron::request::Url;
+use self::url::Url;
use jsonrpc_http_server::ServerHandler;
use self::auth::{Authorization, Authorized};
diff --git a/webapp/src/router/url.rs b/webapp/src/router/url.rs
new file mode 100644
index 000000000..108de740d
--- /dev/null
+++ b/webapp/src/router/url.rs
@@ -0,0 +1,177 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+//! HTTP/HTTPS URL type. Based on URL type from Iron library.
+
+use url::Host;
+use url::{whatwg_scheme_type_mapper};
+use url::{self, SchemeData, SchemeType};
+
+/// HTTP/HTTPS URL type for Iron.
+#[derive(PartialEq, Eq, Clone, Debug)]
+pub struct Url {
+ /// The lower-cased scheme of the URL, typically "http" or "https".
+ pub scheme: String,
+
+ /// The host field of the URL, probably a domain.
+ pub host: Host,
+
+ /// The connection port.
+ pub port: u16,
+
+ /// The URL path, the resource to be accessed.
+ ///
+ /// A *non-empty* vector encoding the parts of the URL path.
+ /// Empty entries of `""` correspond to trailing slashes.
+ pub path: Vec,
+
+ /// The URL username field, from the userinfo section of the URL.
+ ///
+ /// `None` if the `@` character was not part of the input OR
+ /// if a blank username was provided.
+ /// Otherwise, a non-empty string.
+ pub username: Option,
+
+ /// The URL password field, from the userinfo section of the URL.
+ ///
+ /// `None` if the `@` character was not part of the input OR
+ /// if a blank password was provided.
+ /// Otherwise, a non-empty string.
+ pub password: Option,
+
+ /// The URL query string.
+ ///
+ /// `None` if the `?` character was not part of the input.
+ /// Otherwise, a possibly empty, percent encoded string.
+ pub query: Option,
+
+ /// The URL fragment.
+ ///
+ /// `None` if the `#` character was not part of the input.
+ /// Otherwise, a possibly empty, percent encoded string.
+ pub fragment: Option
+}
+
+impl Url {
+ /// Create a URL from a string.
+ ///
+ /// The input must be a valid URL with a special scheme for this to succeed.
+ ///
+ /// HTTP and HTTPS are special schemes.
+ ///
+ /// See: http://url.spec.whatwg.org/#special-scheme
+ pub fn parse(input: &str) -> Result {
+ // Parse the string using rust-url, then convert.
+ match url::Url::parse(input) {
+ Ok(raw_url) => Url::from_generic_url(raw_url),
+ Err(e) => Err(format!("{}", e))
+ }
+ }
+
+ /// Create a `Url` from a `rust-url` `Url`.
+ pub fn from_generic_url(raw_url: url::Url) -> Result {
+ // Create an Iron URL by extracting the special scheme data.
+ match raw_url.scheme_data {
+ SchemeData::Relative(data) => {
+ // Extract the port as a 16-bit unsigned integer.
+ let port: u16 = match data.port {
+ // If explicitly defined, unwrap it.
+ Some(port) => port,
+
+ // Otherwise, use the scheme's default port.
+ None => {
+ match whatwg_scheme_type_mapper(&raw_url.scheme) {
+ SchemeType::Relative(port) => port,
+ _ => return Err(format!("Invalid special scheme: `{}`",
+ raw_url.scheme))
+ }
+ }
+ };
+
+ // Map empty usernames to None.
+ let username = match &*data.username {
+ "" => None,
+ _ => Some(data.username)
+ };
+
+ // Map empty passwords to None.
+ let password = match data.password {
+ None => None,
+ Some(ref x) if x.is_empty() => None,
+ Some(password) => Some(password)
+ };
+
+ Ok(Url {
+ scheme: raw_url.scheme,
+ host: data.host,
+ port: port,
+ path: data.path,
+ username: username,
+ password: password,
+ query: raw_url.query,
+ fragment: raw_url.fragment
+ })
+ },
+ _ => Err(format!("Not a special scheme: `{}`", raw_url.scheme))
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::Url;
+
+ #[test]
+ fn test_default_port() {
+ assert_eq!(Url::parse("http://example.com/wow").unwrap().port, 80u16);
+ assert_eq!(Url::parse("https://example.com/wow").unwrap().port, 443u16);
+ }
+
+ #[test]
+ fn test_explicit_port() {
+ assert_eq!(Url::parse("http://localhost:3097").unwrap().port, 3097u16);
+ }
+
+ #[test]
+ fn test_empty_username() {
+ assert!(Url::parse("http://@example.com").unwrap().username.is_none());
+ assert!(Url::parse("http://:password@example.com").unwrap().username.is_none());
+ }
+
+ #[test]
+ fn test_not_empty_username() {
+ let user = Url::parse("http://john:pass@example.com").unwrap().username;
+ assert_eq!(user.unwrap(), "john");
+
+ let user = Url::parse("http://john:@example.com").unwrap().username;
+ assert_eq!(user.unwrap(), "john");
+ }
+
+ #[test]
+ fn test_empty_password() {
+ assert!(Url::parse("http://michael@example.com").unwrap().password.is_none());
+ assert!(Url::parse("http://:@example.com").unwrap().password.is_none());
+ }
+
+ #[test]
+ fn test_not_empty_password() {
+ let pass = Url::parse("http://michael:pass@example.com").unwrap().password;
+ assert_eq!(pass.unwrap(), "pass");
+
+ let pass = Url::parse("http://:pass@example.com").unwrap().password;
+ assert_eq!(pass.unwrap(), "pass");
+ }
+}