Fuzzyurl
Fuzzyurl provides two related functions: non-strict parsing of URLs or URL-like strings into their component pieces (protocol, username, password, hostname, port, path, query, and fragment), and fuzzy matching of URLs and URL patterns.
Specifically, URLs that look like this:
[protocol ://] [username [: password] @] [hostname] [: port] [/ path] [? query] [# fragment]
Fuzzyurls can be constructed using some or all of the above
fields, optionally replacing some or all of those fields with a *
wildcard if you wish to use the Fuzzyurl as a URL mask.
Parsing URLs
iex> f = Fuzzyurl.from_string("https://api.example.com/users/123?full=true")
%Fuzzyurl{fragment: nil, hostname: "api.example.com", password: nil, path: "/users/123", port: nil, protocol: "https", query: "full=true", username: nil}
iex> f.protocol
"https"
iex> f.hostname
"api.example.com"
iex> f.query
"full=true"
Constructing URLs
iex> f = Fuzzyurl.new(hostname: "example.com", protocol: "http", port: "8080")
%Fuzzyurl{fragment: nil, hostname: "example.com", password: nil, path: nil, port: "8080", protocol: "http", query: nil, username: nil}
iex> Fuzzyurl.to_string(f)
"http://example.com:8080"
Matching URLs
Fuzzyurl supports wildcard matching:
*matches anything, includingnil.foo*matchesfoo,foobar,foo/bar, etc.*barmatchesbar,foobar,foo/bar, etc.
Path and hostname matching allows the use of a greedier wildcard ** in
addition to the naive wildcard *:
*.example.commatchesfilsrv-01.corp.example.combut notexample.com.**.example.commatchesfilsrv-01.corp.example.comandexample.com./some/path/*matches/some/path/foo/barand/some/path/but not/some/path/some/path/**matches/some/path/foo/barand/some/path/and/some/path
The Fuzzyurl.mask/0 and Fuzzyurl.mask/1 functions aid in the
creation of URL masks.
iex> m = Fuzzyurl.mask
%Fuzzyurl{fragment: "*", hostname: "*", password: "*", path: "*", port: "*", protocol: "*", query: "*", username: "*"}
iex> Fuzzyurl.matches?(m, "http://example.com/a/b/c")
true
iex> m2 = Fuzzyurl.mask(path: "/a/b/**")
%Fuzzyurl{fragment: "*", hostname: "*", password: "*", path: "/a/b/**", port: "*", protocol: "*", query: "*", username: "*"}
iex> Fuzzyurl.matches?(m2, "https://example.com/a/b/")
true
iex> Fuzzyurl.matches?(m2, "git+ssh://jen@example.com/a/b")
true
iex> Fuzzyurl.matches?(m2, "https://example.com/a/bar")
false
Fuzzyurl.best_match, given a list of URL masks and a URL, will return
the mask which most closely matches the URL:
iex> masks = ["/foo/*", "/foo/bar", Fuzzyurl.mask]
iex> Fuzzyurl.best_match(masks, "http://example.com/foo/bar")
%Fuzzyurl{fragment: "*", hostname: "*", password: "*", path: "/foo/bar", port: "*", protocol: "*", query: "*", username: "*"}
Summary
Functions
From a list of Fuzzyurl masks, returns the one which best matches url.
Returns nil if none of masks match
Creates a new Fuzzyurl from the given URL string. Provide mask: true
when creating a URL mask
Returns a Fuzzyurl containing all wildcard matches, that will match any Fuzzyurl
Returns a Fuzzyurl mask with the given parameters set.
params may be a map or a keyword list
Returns an integer representing how closely mask (which may have
wildcards) resembles url (which may not), or :no_match in the
case of a conflict
Returns a Fuzzyurl struct containing values indicating match quality: 0 for a wildcard match, 1 for exact match, and :no_match otherwise
Returns true if mask matches url, false otherwise
Creates an empty Fuzzyurl
Creates a new Fuzzyurl with the given parameters
Creates a new Fuzzyurl with the given parameters
Returns a String representation of fuzzy_url
Returns a new Fuzzyurl based on fuzzy_url, with the given arguments
changed
Types
t :: %Fuzzyurl{fragment: term, hostname: term, password: term, path: term, port: term, protocol: term, query: term, username: term}
Functions
Specs
best_match([string_or_fuzzyurl], string_or_fuzzyurl) ::
Fuzzyurl.t |
nil
From a list of Fuzzyurl masks, returns the one which best matches url.
Returns nil if none of masks match.
url and each mask may be a Fuzzyurl or a string.
iex> masks = ["/foo/*", "/foo/bar", Fuzzyurl.mask]
iex> Fuzzyurl.best_match(masks, "http://example.com/foo/bar")
%Fuzzyurl{fragment: "*", hostname: "*", password: "*", path: "/foo/bar", port: "*", protocol: "*", query: "*", username: "*"}
Specs
from_string(String.t, [tuple]) :: Fuzzyurl.t
Creates a new Fuzzyurl from the given URL string. Provide mask: true
when creating a URL mask.
iex> Fuzzyurl.from_string("http://example.com")
%Fuzzyurl{fragment: nil, hostname: "example.com", password: nil, path: nil, port: nil, protocol: "http", query: nil, username: nil}
iex> Fuzzyurl.from_string("*.example.com:443", mask: true)
%Fuzzyurl{fragment: "*", hostname: "*.example.com", password: "*", path: "*", port: "443", protocol: "*", query: "*", username: "*"}
Specs
mask :: Fuzzyurl.t
Returns a Fuzzyurl containing all wildcard matches, that will match any Fuzzyurl.
iex> Fuzzyurl.mask()
%Fuzzyurl{fragment: "*", hostname: "*", password: "*", path: "*", port: "*", protocol: "*", query: "*", username: "*"}
Specs
mask(map | [tuple]) :: Fuzzyurl.t
Returns a Fuzzyurl mask with the given parameters set.
params may be a map or a keyword list.
iex> Fuzzyurl.mask(hostname: "example.com")
%Fuzzyurl{fragment: "*", hostname: "example.com", password: "*", path: "*", port: "*", protocol: "*", query: "*", username: "*"}
Specs
match(string_or_fuzzyurl, string_or_fuzzyurl) ::
non_neg_integer |
:no_match
Returns an integer representing how closely mask (which may have
wildcards) resembles url (which may not), or :no_match in the
case of a conflict.
mask and url may each be a Fuzzyurl or a string.
iex> Fuzzyurl.match("http://example.com", "http://example.com")
2
iex> Fuzzyurl.match("example.com", "http://example.com")
1
iex> Fuzzyurl.match("**.example.com", "http://example.com")
0
iex> Fuzzyurl.match("*.example.com", "http://example.com")
:no_match
Specs
match_scores(string_or_fuzzyurl, string_or_fuzzyurl) :: Fuzzyurl.t
Returns a Fuzzyurl struct containing values indicating match quality: 0 for a wildcard match, 1 for exact match, and :no_match otherwise.
mask and url may each be a Fuzzyurl or a string.
iex> mask = Fuzzyurl.mask(hostname: "example.com")
iex> Fuzzyurl.match_scores(mask, "http://example.com")
%Fuzzyurl{fragment: 0, hostname: 1, password: 0, path: 0, port: 0, protocol: 0, query: 0, username: 0}
Specs
matches?(string_or_fuzzyurl, string_or_fuzzyurl) ::
false |
true
Returns true if mask matches url, false otherwise.
mask and url may each be a Fuzzyurl or a string.
iex> mask = Fuzzyurl.mask(hostname: "example.com")
iex> Fuzzyurl.matches?(mask, "http://example.com")
true
iex> Fuzzyurl.matches?(mask, "http://nope.example.com")
false
Specs
new :: Fuzzyurl.t
Creates an empty Fuzzyurl.
iex> Fuzzyurl.new()
%Fuzzyurl{fragment: nil, hostname: nil, password: nil, path: nil, port: nil, protocol: nil, query: nil, username: nil}
Specs
new([tuple]) :: Fuzzyurl.t
Creates a new Fuzzyurl with the given parameters.
params may be a map or a keyword list.
iex> Fuzzyurl.new(hostname: "example.com", protocol: "http")
%Fuzzyurl{fragment: nil, hostname: "example.com", password: nil, path: nil, port: nil, protocol: "http", query: nil, username: nil}
Specs
Creates a new Fuzzyurl with the given parameters.
iex> Fuzzyurl.new("http", "user", "pass", "example.com", "80", "/", "query=true", "123")
%Fuzzyurl{fragment: "123", hostname: "example.com", password: "pass", path: "/", port: "80", protocol: "http", query: "query=true", username: "user"}
Specs
to_string(Fuzzyurl.t) :: String.t
Returns a String representation of fuzzy_url.
iex> fuzzy_url = Fuzzyurl.new(hostname: "example.com", protocol: "http")
iex> Fuzzyurl.to_string(fuzzy_url)
"http://example.com"
Specs
with(Fuzzyurl.t, [tuple]) :: Fuzzyurl.t
with(Fuzzyurl.t, map) :: Fuzzyurl.t
Returns a new Fuzzyurl based on fuzzy_url, with the given arguments
changed.
params may be a map or a keyword list.
iex> fuzzy_url = Fuzzyurl.new(hostname: "example.com", protocol: "http")
iex> fuzzy_url |> Fuzzyurl.with(protocol: "https", path: "/index.html")
%Fuzzyurl{fragment: nil, hostname: "example.com", password: nil, path: "/index.html", port: nil, protocol: "https", query: nil, username: nil}