A Gleam package for parsing domain names into their component parts using the Public Suffix List.
Add psl to your Gleam project:
gleam add psl@2
import gleam/option.{None} import psl pub fn main() { // Load the public suffix list (include private domains) let list = psl.load_suffix_list(True, None) // Parse a simple domain let assert Ok(parts) = psl.parse("https://gleam.run", list) // parts.transit_routing_domain -> "" // parts.second_level_domain -> "gleam" // parts.top_level_domain -> "run" // parts.subdomain_parts -> [] // Parse a domain with a subdomain let assert Ok(parts) = psl.parse("https://packages.gleam.run", list) // parts.transit_routing_domain -> "packages" // parts.second_level_domain -> "gleam" // parts.top_level_domain -> "run" // parts.subdomain_parts -> ["packages"] let assert Ok(parts) = psl.parse("https://fun.packages.gleam.run", list) // parts.transit_routing_domain -> "fun.packages" // parts.second_level_domain -> "gleam" // parts.top_level_domain -> "run" // parts.subdomain_parts -> ["fun", "packages"] // Parse UTF-8 let assert Ok(parts) = psl.parse("https://gleam.مليسيا", list) // parts.transit_routing_domain -> "" // parts.second_level_domain -> "gleam" // parts.top_level_domain -> "مليسيا" (decoded from punycode) // parts.subdomain_parts -> [] // Parse punycode domains // Punycode domains (xn--) are decoded to UTF-8 let assert Ok(parts) = psl.parse("https://gleam.xn--mgbx4cd0ab", list) // parts.transit_routing_domain -> "" // parts.second_level_domain -> "gleam" // parts.top_level_domain -> "مليسيا" (decoded from punycode) // parts.subdomain_parts -> [] }
You can provide your own public suffix list file instead of using the bundled one:
import gleam/option.{Some} import psl pub fn main() { // Load a custom suffix list let list = psl.load_suffix_list(True, Some("path/to/list.dat")) let assert Ok(parts) = psl.parse("https://gleam.run", list) }
You can add your own rules for private DNS domains that are not on the Public Suffix List:
import gleam/option.{None} import psl pub fn main() { // Load the standard list let list = psl.load_suffix_list(True, None) // Add a custom rule for your private domain // Normal domains: mysuffix" // Wildcards: "*mysuffix" // Exceptions: "!www.mysuffix" let list = psl.add_rule(list, "mysuffix", False) let assert Ok(parts) = psl.parse("https://neat.gleam.mysuffix", list) // parts.second_level_domain -> "gleam" // parts.top_level_domain -> "mysuffix" }
- Inspired by publicsuffix-ruby by Simone Carletti
- Uses the Public Suffix List maintained by Mozilla
Apache-2.0