Skip to content

Commit

Permalink
Auto merge of #535 - servo:socket_addrs, r=nox
Browse files Browse the repository at this point in the history
Restore DNS resolution functionality from url 1.x

This is an alternative to #533.

I feel that an inherent method is more appropriate than an impl of the `ToSocketAddrs` trait: it is not the URL as a whole that is converted, only parts of it.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-url/535)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo authored Aug 5, 2019
2 parents f491cb4 + 2f199ff commit a93e8cb
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 7 deletions.
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

0 comments on commit a93e8cb

Please sign in to comment.