#hostname #validation #punycode #idna #publicsuffix

adbyss_psl

A minimal Public Suffix List hostname validator

60 releases (12 breaking)

0.15.2 Jan 9, 2025
0.15.1 Nov 28, 2024
0.14.0 Oct 22, 2024
0.11.1 Jul 25, 2024
0.4.2 Jul 29, 2021

#314 in Web programming

Download history 5/week @ 2024-10-02 313/week @ 2024-10-16 53/week @ 2024-10-23 23/week @ 2024-10-30 122/week @ 2024-11-06 37/week @ 2024-11-13 19/week @ 2024-11-20 149/week @ 2024-11-27 5/week @ 2024-12-04 3/week @ 2024-12-11 143/week @ 2025-01-08 11/week @ 2025-01-15

154 downloads per month

WTFPL license

110KB
1K SLoC

Adbyss: Public Suffix

docs.rs changelog
crates.io ci deps.rs
license contributions welcome

This library contains a single public-facing struct — adbyss_psl::Domain — used for validating and normalizing Internet hostnames, like "www.domain.com".

It will:

  • Validate, normalize, and Puny-encode internationalized/Unicode labels (RFC 3492);
  • Validate and normalize the public suffix;
  • Ensure conformance with RFC 1123;
  • And locate the boundaries of the subdomain (if any), root (required), and suffix (required);

Examples

New instances of Domain can be initialized using either Domain::new or TryFrom<&str>.

use adbyss_psl::Domain;

// These are equivalent and fine:
assert!(Domain::new("www.MyDomain.com").is_some());
assert!(Domain::try_from("www.MyDomain.com").is_ok());

// The following is valid DNS, but invalid as an Internet hostname:
assert!(Domain::new("_acme-challenge.mydomain.com").is_none());

Valid Internet hostnames must be no longer than 253 characters, and contain both root and (valid) suffix components.

Their labels — the bits between the dots — must additionally:

  • Be no longer than 63 characters;
  • (Ultimately) contain only ASCII letters, digits, and -;
  • Start and end with an alphanumeric character;

Unicode/internationalized labels are allowed, but must be Puny-encodable and not contain any conflicting bidirectionality constraints. Domain will encode such labels using Punycode when it finds them, ensuring the resulting hostname will always be ASCII-only.

Post-parsing, Domain gives you access to each individual component, or the whole thing:

use adbyss_psl::Domain;

let dom = Domain::new("www.MyDomain.com").unwrap();

// Pull out the pieces if you're into that sort of thing.
assert_eq!(dom.host(), "www.mydomain.com");
assert_eq!(dom.subdomain(), Some("www"));
assert_eq!(dom.root(), "mydomain");
assert_eq!(dom.suffix(), "com");
assert_eq!(dom.tld(), "mydomain.com");

// If you just want the sanitized host back as an owned value, use
// `Domain::take` or `String::from`:
let owned = dom.take(); // "www.mydomain.com"

Optional Crate Features

  • serde: Enables serialization/deserialization support.

Dependencies

~1.9–3MB
~52K SLoC