1# Guide to upgrading from url 0.x to 1.x 2 3* The fields of `Url` are now private because the `Url` constructor, parser, 4 and setters maintain invariants that could be violated if you were to set the fields directly. 5 Instead of accessing, for example, `url.scheme`, use the getter method, such as `url.scheme()`. 6 Instead of assigning directly to a field, for example `url.scheme = "https".to_string()`, 7 use the setter method, such as `url.set_scheme("https").unwrap()`. 8 (Some setters validate the new value and return a `Result` that must be used). 9 10* The methods of `Url` now return `&str` instead of `String`, 11 thus reducing allocations and making serialization cheap. 12 13* The `path()` method on `url::Url` instances used to return `Option<&[String]>`; 14 now it returns `&str`. 15 If you would like functionality more similar to the old behavior of `path()`, 16 use `path_segments()` that returns `Option<str::Split<char>>`. 17 18 Before upgrading: 19 20 ```rust 21 let issue_list_url = Url::parse( 22 "https://github.com/rust-lang/rust/issues?labels=E-easy&state=open" 23 ).unwrap(); 24 assert_eq!(issue_list_url.path(), Some(&["rust-lang".to_string(), 25 "rust".to_string(), 26 "issues".to_string()][..])); 27 ``` 28 29 After upgrading: 30 31 ```rust 32 let issue_list_url = Url::parse( 33 "https://github.com/rust-lang/rust/issues?labels=E-easy&state=open" 34 ).unwrap(); 35 assert_eq!(issue_list_url.path(), "/rust-lang/rust/issues"); 36 assert_eq!(issue_list_url.path_segments().map(|c| c.collect::<Vec<_>>()), 37 Some(vec!["rust-lang", "rust", "issues"])); 38 ``` 39 40* The `path_mut()` method on `url::Url` instances that allowed modification of a URL's path 41 has been replaced by `path_segments_mut()`. 42 43 Before upgrading: 44 45 ```rust 46 let mut url = Url::parse("https://github.com/rust-lang/rust").unwrap(); 47 url.path_mut().unwrap().push("issues"); 48 ``` 49 50 After upgrading: 51 52 ```rust 53 let mut url = Url::parse("https://github.com/rust-lang/rust").unwrap(); 54 url.path_segments_mut().unwrap().push("issues"); 55 ``` 56 57* The `domain_mut()` method on `url::Url` instances that allowed modification of a URL's domain 58 has been replaced by `set_host()` and `set_ip_host()`. 59 60* The `host()` method on `url::Url` instances used to return `Option<&Host>`; 61 now it returns `Option<Host<&str>>`. 62 The `serialize_host()` method that returned `Option<String>` 63 has been replaced by the `host_str()` method that returns `Option<&str>`. 64 65* The `serialize()` method on `url::Url` instances that returned `String` 66 has been replaced by an `as_str()` method that returns `&str`. 67 68 Before upgrading: 69 70 ```rust 71 let this_document = Url::parse("http://servo.github.io/rust-url/url/index.html").unwrap(); 72 assert_eq!(this_document.serialize(), "http://servo.github.io/rust-url/url/index.html".to_string()); 73 ``` 74 75 After upgrading: 76 77 ```rust 78 let this_document = Url::parse("http://servo.github.io/rust-url/url/index.html").unwrap(); 79 assert_eq!(this_document.as_str(), "http://servo.github.io/rust-url/url/index.html"); 80 ``` 81 82* `url::UrlParser` has been replaced by `url::Url::parse()` and `url::Url::join()`. 83 84 Before upgrading: 85 86 ```rust 87 let this_document = Url::parse("http://servo.github.io/rust-url/url/index.html").unwrap(); 88 let css_url = UrlParser::new().base_url(&this_document).parse("../main.css").unwrap(); 89 assert_eq!(css_url.serialize(), "http://servo.github.io/rust-url/main.css".to_string()); 90 ``` 91 92 After upgrading: 93 94 ```rust 95 let this_document = Url::parse("http://servo.github.io/rust-url/url/index.html").unwrap(); 96 let css_url = this_document.join("../main.css").unwrap(); 97 assert_eq!(css_url.as_str(), "http://servo.github.io/rust-url/main.css"); 98 ``` 99 100* `url::parse_path()` and `url::UrlParser::parse_path()` have been removed without replacement. 101 As a workaround, you can give a base URL that you then ignore too `url::Url::parse()`. 102 103 Before upgrading: 104 105 ```rust 106 let (path, query, fragment) = url::parse_path("/foo/bar/../baz?q=42").unwrap(); 107 assert_eq!(path, vec!["foo".to_string(), "baz".to_string()]); 108 assert_eq!(query, Some("q=42".to_string())); 109 assert_eq!(fragment, None); 110 ``` 111 112 After upgrading: 113 114 ```rust 115 let base = Url::parse("http://example.com").unwrap(); 116 let with_path = base.join("/foo/bar/../baz?q=42").unwrap(); 117 assert_eq!(with_path.path(), "/foo/baz"); 118 assert_eq!(with_path.query(), Some("q=42")); 119 assert_eq!(with_path.fragment(), None); 120 ``` 121 122* The `url::form_urlencoded::serialize()` method 123 has been replaced with the `url::form_urlencoded::Serializer` struct. 124 Instead of calling `serialize()` with key/value pairs, 125 create a new `Serializer` with a new string, 126 call the `extend_pairs()` method on the `Serializer` instance with the key/value pairs as the argument, 127 then call `finish()`. 128 129 Before upgrading: 130 131 ```rust 132 let form = url::form_urlencoded::serialize(form.iter().map(|(k, v)| { 133 (&k[..], &v[..]) 134 })); 135 ``` 136 137 After upgrading: 138 139 ```rust 140 let form = url::form_urlencoded::Serializer::new(String::new()).extend_pairs( 141 form.iter().map(|(k, v)| { (&k[..], &v[..]) }) 142 ).finish(); 143 ``` 144 145* The `set_query_from_pairs()` method on `url::Url` instances that took key/value pairs 146 has been replaced with `query_pairs_mut()`, which allows you to modify the `url::Url`'s query pairs. 147 148 Before upgrading: 149 150 ```rust 151 let mut url = Url::parse("https://duckduckgo.com/").unwrap(); 152 let pairs = vec![ 153 ("q", "test"), 154 ("ia", "images"), 155 ]; 156 url.set_query_from_pairs(pairs.iter().map(|&(k, v)| { 157 (&k[..], &v[..]) 158 })); 159 ``` 160 161 After upgrading: 162 163 ```rust 164 let mut url = Url::parse("https://duckduckgo.com/").unwrap(); 165 let pairs = vec![ 166 ("q", "test"), 167 ("ia", "images"), 168 ]; 169 url.query_pairs_mut().clear().extend_pairs( 170 pairs.iter().map(|&(k, v)| { (&k[..], &v[..]) }) 171 ); 172 ``` 173 174* `url::SchemeData`, its variants `Relative` and `NonRelative`, 175 and the struct `url::RelativeSchemeData` have been removed. 176 Instead of matching on these variants 177 to determine if you have a URL in a relative scheme such as HTTP 178 versus a URL in a non-relative scheme as data, 179 use the `cannot_be_a_base()` method to determine which kind you have. 180 181 Before upgrading: 182 183 ```rust 184 match url.scheme_data { 185 url::SchemeData::Relative(..) => {} 186 url::SchemeData::NonRelative(..) => { 187 return Err(human(format!("`{}` must have relative scheme \ 188 data: {}", field, url))) 189 } 190 } 191 ``` 192 193 After upgrading: 194 195 ```rust 196 if url.cannot_be_a_base() { 197 return Err(human(format!("`{}` must have relative scheme \ 198 data: {}", field, url))) 199 } 200 ``` 201 202* The functions `url::whatwg_scheme_type_mapper()`, the `SchemeType` enum, 203 and the `scheme_type_mapper()` method on `url::UrlParser` instances have been removed. 204 `SchemeType` had a method for getting the `default_port()`; 205 to replicate this functionality, use the method `port_or_known_default()` on `url::Url` instances. 206 The `port_or_default()` method on `url::Url` instances has been removed; 207 use `port_or_known_default()` instead. 208 209 Before upgrading: 210 211 ```rust 212 let port = match whatwg_scheme_type_mapper(&url.scheme) { 213 SchemeType::Relative(port) => port, 214 _ => return Err(format!("Invalid special scheme: `{}`", 215 raw_url.scheme)), 216 }; 217 ``` 218 219 After upgrading: 220 221 ```rust 222 let port = match url.port_or_known_default() { 223 Some(port) => port, 224 _ => return Err(format!("Invalid special scheme: `{}`", 225 url.scheme())), 226 }; 227 ``` 228 229* The following formatting utilities have been removed without replacement; 230 look at their linked previous implementations 231 if you would like to replicate the functionality in your code: 232 * [`url::format::PathFormatter`](https://github.com/servo/rust-url/pull/176/commits/9e759f18726c8e1343162922b87163d4dd08fe3c#diff-0bb16ac13b75e9b568fa4aff61b0e71dL24) 233 * [`url::format::UserInfoFormatter`](https://github.com/servo/rust-url/pull/176/commits/9e759f18726c8e1343162922b87163d4dd08fe3c#diff-0bb16ac13b75e9b568fa4aff61b0e71dL50) 234 * [`url::format::UrlNoFragmentFormatter`](https://github.com/servo/rust-url/pull/176/commits/9e759f18726c8e1343162922b87163d4dd08fe3c#diff-0bb16ac13b75e9b568fa4aff61b0e71dL70) 235 236* `url::percent_encoding::percent_decode()` used to have a return type of `Vec<u8>`; 237 now it returns an iterator of decoded `u8` bytes that also implements `Into<Cow<u8>>`. 238 Use `.into().to_owned()` to obtain a `Vec<u8>`. 239 (`.collect()` also works but might not be as efficient.) 240 241* The `url::percent_encoding::EncodeSet` struct and constant instances 242 used with `url::percent_encoding::percent_encode()` 243 have been changed to structs that implement the trait `url::percent_encoding::EncodeSet`. 244 * `SIMPLE_ENCODE_SET`, `QUERY_ENCODE_SET`, `DEFAULT_ENCODE_SET`, 245 and `USERINFO_ENCODE_SET` have the same behavior. 246 * `USERNAME_ENCODE_SET` and `PASSWORD_ENCODE_SET` have been removed; 247 use `USERINFO_ENCODE_SET` instead. 248 * `HTTP_VALUE_ENCODE_SET` has been removed; 249 an implementation of it in the new types can be found [in hyper's source]( 250 https://github.com/hyperium/hyper/blob/67436c5bf615cf5a55a71e32b788afef5985570e/src/header/parsing.rs#L131-L138) 251 if you need to replicate this functionality in your code. 252 * `FORM_URLENCODED_ENCODE_SET` has been removed; 253 instead, use the functionality in `url::form_urlencoded`. 254 * `PATH_SEGMENT_ENCODE_SET` has been added for use on '/'-separated path segments. 255 256* `url::percent_encoding::percent_decode_to()` has been removed. 257 Use `url::percent_encoding::percent_decode()` which returns an iterator. 258 You can then use the iterator’s `collect()` method 259 or give it to some data structure’s `extend()` method. 260* A number of `ParseError` variants have changed. 261 [See the documentation for the current set](http://servo.github.io/rust-url/url/enum.ParseError.html). 262* `url::OpaqueOrigin::new()` and `url::Origin::UID(OpaqueOrigin)` 263 have been replaced by `url::Origin::new_opaque()` and `url::Origin::Opaque(OpaqueOrigin)`, respectively. 264