Url Parsing in Erlang

Our URL parsing program demonstrates how to parse and extract information from URLs in Erlang.

-module(url_parsing).
-export([main/0]).

main() ->
    % We'll parse this example URL, which includes a
    % scheme, authentication info, host, port, path,
    % query params, and query fragment.
    S = "postgres://user:pass@host.com:5432/path?k=v#f",

    % Parse the URL and ensure there are no errors.
    {ok, U} = uri_string:parse(S),

    % Accessing the scheme is straightforward.
    io:format("~p~n", [maps:get(scheme, U)]),

    % UserInfo contains all authentication info; we need to parse it further
    % to get individual username and password values.
    UserInfo = maps:get(userinfo, U),
    [Username, Password] = string:split(UserInfo, ":"),
    io:format("~p~n", [UserInfo]),
    io:format("~p~n", [Username]),
    io:format("~p~n", [Password]),

    % The Host contains both the hostname and the port,
    % if present. We can extract them separately.
    Host = maps:get(host, U),
    Port = maps:get(port, U),
    io:format("~p:~p~n", [Host, Port]),
    io:format("~p~n", [Host]),
    io:format("~p~n", [Port]),

    % Here we extract the path and the fragment after the #.
    io:format("~p~n", [maps:get(path, U)]),
    io:format("~p~n", [maps:get(fragment, U)]),

    % To get query params in a string of k=v format,
    % use the query field. You can also parse query params
    % into a map using uri_string:dissect_query/1.
    Query = maps:get(query, U),
    io:format("~p~n", [Query]),
    QueryMap = uri_string:dissect_query(Query),
    io:format("~p~n", [QueryMap]),
    io:format("~p~n", [proplists:get_value("k", QueryMap)]).

Running our URL parsing program shows all the different pieces that we extracted.

$ erl -noshell -s url_parsing main -s init stop
"postgres"
"user:pass"
"user"
"pass"
"host.com":5432
"host.com"
5432
"/path"
"f"
"k=v"
[{"k","v"}]
"v"

In this Erlang version:

  1. We use the uri_string module to parse the URL, which returns a map.
  2. We extract various parts of the URL using maps:get/2.
  3. For the user info, we manually split the string to get username and password.
  4. The host and port are already separated in the parsed map.
  5. For query parameters, we use uri_string:dissect_query/1 to parse them into a list of key-value tuples.
  6. We use io:format/2 for printing, which is similar to fmt.Println in Go.

Note that Erlang’s approach to URL parsing is slightly different from Go’s, but it provides similar functionality.