1 // Copyright 2016 The rust-url developers.
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
9 //! Getters and setters for URL components implemented per https://url.spec.whatwg.org/#api
11 //! Unless you need to be interoperable with web browsers,
12 //! you probably want to use `Url` method instead.
14 use {Url, Position, Host, ParseError, idna}
;
15 use parser
::{Parser, SchemeType, default_port, Context, Input}
;
17 /// https://url.spec.whatwg.org/#dom-url-domaintoascii
18 pub fn domain_to_ascii(domain
: &str) -> String
{
19 match Host
::parse(domain
) {
20 Ok(Host
::Domain(domain
)) => domain
,
25 /// https://url.spec.whatwg.org/#dom-url-domaintounicode
26 pub fn domain_to_unicode(domain
: &str) -> String
{
27 match Host
::parse(domain
) {
28 Ok(Host
::Domain(ref domain
)) => {
29 let (unicode
, _errors
) = idna
::domain_to_unicode(domain
);
36 /// Getter for https://url.spec.whatwg.org/#dom-url-href
37 pub fn href(url
: &Url
) -> &str {
41 /// Setter for https://url.spec.whatwg.org/#dom-url-href
42 pub fn set_href(url
: &mut Url
, value
: &str) -> Result
<(), ParseError
> {
43 *url
= Url
::parse(value
)?
;
47 /// Getter for https://url.spec.whatwg.org/#dom-url-origin
48 pub fn origin(url
: &Url
) -> String
{
49 url
.origin().ascii_serialization()
52 /// Getter for https://url.spec.whatwg.org/#dom-url-protocol
54 pub fn protocol(url
: &Url
) -> &str {
55 &url
.as_str()[..url
.scheme().len() + ":".len()]
58 /// Setter for https://url.spec.whatwg.org/#dom-url-protocol
59 pub fn set_protocol(url
: &mut Url
, mut new_protocol
: &str) -> Result
<(), ()> {
60 // The scheme state in the spec ignores everything after the first `:`,
61 // but `set_scheme` errors if there is more.
62 if let Some(position
) = new_protocol
.find('
:'
) {
63 new_protocol
= &new_protocol
[..position
];
65 url
.set_scheme(new_protocol
)
68 /// Getter for https://url.spec.whatwg.org/#dom-url-username
70 pub fn username(url
: &Url
) -> &str {
74 /// Setter for https://url.spec.whatwg.org/#dom-url-username
75 pub fn set_username(url
: &mut Url
, new_username
: &str) -> Result
<(), ()> {
76 url
.set_username(new_username
)
79 /// Getter for https://url.spec.whatwg.org/#dom-url-password
81 pub fn password(url
: &Url
) -> &str {
82 url
.password().unwrap_or("")
85 /// Setter for https://url.spec.whatwg.org/#dom-url-password
86 pub fn set_password(url
: &mut Url
, new_password
: &str) -> Result
<(), ()> {
87 url
.set_password(if new_password
.is_empty() { None }
else { Some(new_password) }
)
90 /// Getter for https://url.spec.whatwg.org/#dom-url-host
92 pub fn host(url
: &Url
) -> &str {
93 &url
[Position
::BeforeHost
..Position
::AfterPort
]
96 /// Setter for https://url.spec.whatwg.org/#dom-url-host
97 pub fn set_host(url
: &mut Url
, new_host
: &str) -> Result
<(), ()> {
98 if url
.cannot_be_a_base() {
104 let scheme
= url
.scheme();
105 let result
= Parser
::parse_host(Input
::new(new_host
), SchemeType
::from(scheme
));
107 Ok((h
, remaining
)) => {
109 opt_port
= if let Some(remaining
) = remaining
.split_prefix('
:'
) {
110 Parser
::parse_port(remaining
, || default_port(scheme
), Context
::Setter
)
111 .ok().map(|(port
, _remaining
)| port
)
116 Err(_
) => return Err(())
119 url
.set_host_internal(host
, opt_port
);
123 /// Getter for https://url.spec.whatwg.org/#dom-url-hostname
125 pub fn hostname(url
: &Url
) -> &str {
126 url
.host_str().unwrap_or("")
129 /// Setter for https://url.spec.whatwg.org/#dom-url-hostname
130 pub fn set_hostname(url
: &mut Url
, new_hostname
: &str) -> Result
<(), ()> {
131 if url
.cannot_be_a_base() {
134 let result
= Parser
::parse_host(Input
::new(new_hostname
), SchemeType
::from(url
.scheme()));
135 if let Ok((host
, _remaining
)) = result
{
136 url
.set_host_internal(host
, None
);
143 /// Getter for https://url.spec.whatwg.org/#dom-url-port
145 pub fn port(url
: &Url
) -> &str {
146 &url
[Position
::BeforePort
..Position
::AfterPort
]
149 /// Setter for https://url.spec.whatwg.org/#dom-url-port
150 pub fn set_port(url
: &mut Url
, new_port
: &str) -> Result
<(), ()> {
153 // has_host implies !cannot_be_a_base
154 let scheme
= url
.scheme();
155 if !url
.has_host() || scheme
== "file" {
158 result
= Parser
::parse_port(Input
::new(new_port
), || default_port(scheme
), Context
::Setter
)
160 if let Ok((new_port
, _remaining
)) = result
{
161 url
.set_port_internal(new_port
);
168 /// Getter for https://url.spec.whatwg.org/#dom-url-pathname
170 pub fn pathname(url
: &Url
) -> &str {
174 /// Setter for https://url.spec.whatwg.org/#dom-url-pathname
175 pub fn set_pathname(url
: &mut Url
, new_pathname
: &str) {
176 if !url
.cannot_be_a_base() {
177 url
.set_path(new_pathname
)
181 /// Getter for https://url.spec.whatwg.org/#dom-url-search
182 pub fn search(url
: &Url
) -> &str {
183 trim(&url
[Position
::AfterPath
..Position
::AfterQuery
])
186 /// Setter for https://url.spec.whatwg.org/#dom-url-search
187 pub fn set_search(url
: &mut Url
, new_search
: &str) {
188 url
.set_query(match new_search
{
190 _
if new_search
.starts_with('?'
) => Some(&new_search
[1..]),
191 _
=> Some(new_search
),
195 /// Getter for https://url.spec.whatwg.org/#dom-url-hash
196 pub fn hash(url
: &Url
) -> &str {
197 trim(&url
[Position
::AfterQuery
..])
200 /// Setter for https://url.spec.whatwg.org/#dom-url-hash
201 pub fn set_hash(url
: &mut Url
, new_hash
: &str) {
202 if url
.scheme() != "javascript" {
203 url
.set_fragment(match new_hash
{
205 _
if new_hash
.starts_with('
#') => Some(&new_hash[1..]),
211 fn trim(s
: &str) -> &str {