psl ๐๐ถ๏ธโ
A Gleam package for parsing domain names into their component parts using the Public Suffix List.
Installation
Add psl
to your Gleam project:
gleam add psl@2
Usage
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 -> []
}
Using Your Own List
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)
}
Adding Custom Rules
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"
}
Credits
- Inspired by publicsuffix-ruby by Simone Carletti
- Uses the Public Suffix List maintained by Mozilla
Licence
Apache-2.0