Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore DNS resolution functionality from url 1.x #535

Merged
merged 2 commits into from
Aug 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

name = "url"
# When updating version, also modify html_root_url in the lib.rs
version = "2.0.0"
version = "2.1.0"
authors = ["The rust-url developers"]

description = "URL library for Rust, based on the WHATWG URL Standard"
Expand Down
2 changes: 1 addition & 1 deletion idna/tests/punycode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
// except according to those terms.

use idna::punycode::{decode, encode_str};
use serde_json::Value;
use serde_json::map::Map;
use serde_json::Value;
use std::str::FromStr;
use test::TestFn;

Expand Down
2 changes: 1 addition & 1 deletion idna/tests/tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
extern crate idna;
extern crate serde_json;
extern crate rustc_test as test;
extern crate serde_json;

mod punycode;
mod uts46;
Expand Down
63 changes: 59 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,9 @@ use std::cmp;
use std::error::Error;
use std::fmt::{self, Write};
use std::hash;
use std::io;
use std::mem;
use std::net::IpAddr;
use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
use std::ops::{Range, RangeFrom, RangeTo};
use std::path::{Path, PathBuf};
use std::str;
Expand Down Expand Up @@ -945,6 +946,61 @@ impl Url {
self.port.or_else(|| parser::default_port(self.scheme()))
}

/// Resolve a URL’s host and port number to `SocketAddr`.
///
/// If the URL has the default port number of a scheme that is unknown to this library,
/// `default_port_number` provides an opportunity to provide the actual port number.
/// In non-example code this should be implemented either simply as `|| None`,
/// or by matching on the URL’s `.scheme()`.
///
/// If the host is a domain, it is resolved using the standard library’s DNS support.
///
/// # Examples
///
/// ```no_run
/// let url = url::Url::parse("https://example.net/").unwrap();
/// let addrs = url.socket_addrs(|| None).unwrap();
/// std::net::TcpStream::connect(&*addrs)
/// # ;
/// ```
///
/// ```
/// /// With application-specific known default port numbers
/// fn socket_addrs(url: url::Url) -> std::io::Result<Vec<std::net::SocketAddr>> {
/// url.socket_addrs(|| match url.scheme() {
/// "socks5" | "socks5h" => Some(1080),
/// _ => None,
/// })
/// }
/// ```
pub fn socket_addrs(
&self,
default_port_number: impl Fn() -> Option<u16>,
) -> io::Result<Vec<SocketAddr>> {
// Note: trying to avoid the Vec allocation by returning `impl AsRef<[SocketAddr]>`
// causes borrowck issues because the return value borrows `default_port_number`:
//
// https://github.com/rust-lang/rfcs/blob/master/text/1951-expand-impl-trait.md#scoping-for-type-and-lifetime-parameters
//
// > This RFC proposes that *all* type parameters are considered in scope
// > for `impl Trait` in return position

fn io_result<T>(opt: Option<T>, message: &str) -> io::Result<T> {
opt.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, message))
}

let host = io_result(self.host(), "No host name in the URL")?;
let port = io_result(
self.port_or_known_default().or_else(default_port_number),
"No port number in the URL",
)?;
Ok(match host {
Host::Domain(domain) => (domain, port).to_socket_addrs()?.collect(),
Host::Ipv4(ip) => vec![(ip, port).into()],
Host::Ipv6(ip) => vec![(ip, port).into()],
})
}

/// Return the path for this URL, as a percent-encoded ASCII string.
/// For cannot-be-a-base URLs, this is an arbitrary string that doesn’t start with '/'.
/// For other URLs, this starts with a '/' slash
Expand Down Expand Up @@ -2296,9 +2352,8 @@ impl<'de> serde::Deserialize<'de> for Url {
where
E: Error,
{
Url::parse(s).map_err(|err| {
Error::invalid_value(Unexpected::Str(s), &err.description())
})
Url::parse(s)
.map_err(|err| Error::invalid_value(Unexpected::Str(s), &err.description()))
}
}

Expand Down