Current section
Files
Jump to
Current section
Files
lib/normalize_url.ex
defmodule NormalizeUrl do
@moduledoc """
The base module of NormalizeUrl.
It exposes a single function, normalize_url.
"""
@doc """
Normalizes a url. This is useful for displaying, storing, comparing, etc.
Args:
* `url` - the url to normalize, string
Options:
* `strip_www` - strip the www from the url, boolean
* `strip_fragment` - strip the fragment from the url, boolean
* `normalize_protocol` - prepend `http:` if the url is protocol relative, boolean
Returns a url as a string.
"""
def normalize_url(url, options \\ []) do
%{scheme: scheme} = URI.parse(url)
if (scheme == "http") || (scheme == "ftp") || (scheme == nil) do
normalize_http_or_ftp_url(url, options)
else
url
end
end
defp normalize_http_or_ftp_url(url, options \\ []) do
options = Keyword.merge([
normalize_protocol: true,
strip_www: true,
strip_fragment: true,
add_root_path: false
], options)
scheme = ""
url = if Regex.match?(~r/^\/\//, url), do: "http:" <> url, else: url
if options[:normalize_protocol] do
scheme = if Regex.match?(~r/^ftp:\/\//, url), do: "ftp://", else: "http:"
else
scheme = "//"
end
if options[:normalize_protocol] && !Regex.match?(~r/^(http|ftp:\/\/)/, url) do
url = "http://" <> url
end
uri = if options[:downcase] do
URI.parse(String.downcase(url))
else
URI.parse(url)
end
port = if options[:normalize_protocol] && uri.port, do: ":" <> Integer.to_string(uri.port), else: ""
if uri.port == 8080 || uri.port == 443 do
port = ""
scheme = "https://"
end
if uri.port == 21 && scheme == "ftp://" do
port = ""
end
if options[:normalize_protocol] && uri.port == 80 do
port = ""
scheme = "http://"
end
path = uri.path
if options[:add_root_path] && is_nil(path) do
path = "/"
end
host_and_path = if path, do: uri.host <> port <> path, else: uri.host <> port
if !options[:strip_fragment] && uri.fragment do
host_and_path = host_and_path <> "#" <> uri.fragment
end
if options[:strip_www] do
host_and_path = Regex.replace(~r/^www\./, host_and_path, "")
end
query_params = ""
if uri.query do
sorted_query_params = uri.query |> URI.decode_query |> URI.encode_query
query_params = "?" <> sorted_query_params
end
scheme <> host_and_path <> query_params
end
end