Url

URLs

type alias Url =
{ protocol : Protocol
, host : String
, port_ : Maybe Int
, path : String
, query : Maybe String
, fragment : Maybe String
}

In the URI spec, Tim Berners-Lee says a URL looks like this:

  https://example.com:8042/over/there?name=ferret#nose
  \___/   \______________/\_________/ \_________/ \__/
    |            |            |            |        |
  scheme     authority       path        query   fragment

When you are creating a single-page app with Browser.application, you use the Url.Parser module to turn a Url into even nicer data.

If you want to create your own URLs, check out the Url.Builder module as well!

Note: This is a subset of all the full possibilities listed in the URI spec. Specifically, it does not accept the userinfo segment you see in email addresses like tom@example.com.

type Protocol
= Http
| Https

Is the URL served over a secure connection or not?

toString : Url -> String

Turn a Url into a String.

fromString : String -> Maybe Url

Attempt to break a URL up into Url. This is useful in single-page apps when you want to parse certain chunks of a URL to figure out what to show on screen.

fromString "https://example.com:443"
-- Just
--   { protocol = Https
--   , host = "example.com"
--   , port_ = Just 443
--   , path = "/"
--   , query = Nothing
--   , fragment = Nothing
--   }

fromString "https://example.com/hats?q=top%20hat"
-- Just
--   { protocol = Https
--   , host = "example.com"
--   , port_ = Nothing
--   , path = "/hats"
--   , query = Just "q=top%20hat"
--   , fragment = Nothing
--   }

fromString "http://example.com/core/List/#map"
-- Just
--   { protocol = Http
--   , host = "example.com"
--   , port_ = Nothing
--   , path = "/core/List/"
--   , query = Nothing
--   , fragment = Just "map"
--   }

The conversion to segments can fail in some cases as well:

fromString "example.com:443"        == Nothing  -- no protocol
fromString "http://tom@example.com" == Nothing  -- userinfo disallowed
fromString "http://#cats"           == Nothing  -- no host

Note: This function does not use percentDecode anything. It just splits things up. Url.Parser actually needs the raw query string to parse it properly. Otherwise it could get confused about = and & characters!

Percent-Encoding

percentEncode : String -> String

Use Url.Builder instead! Functions like absolute, relative, and crossOrigin already do this automatically! percentEncode is only available so that extremely custom cases are possible, if needed.

Percent-encoding is how the official URI spec “escapes” special characters. You can still represent a ? even though it is reserved for queries.

This function exists in case you want to do something extra custom. Here are some examples:

-- standard ASCII encoding
percentEncode "hat"   == "hat"
percentEncode "to be" == "to%20be"
percentEncode "99%"   == "99%25"

-- non-standard, but widely accepted, UTF-8 encoding
percentEncode "$" == "%24"
percentEncode "¢" == "%C2%A2"
percentEncode "€" == "%E2%82%AC"

This is the same behavior as JavaScript's encodeURIComponent function, and the rules are described in more detail officially here and with some notes about Unicode here.

percentDecode : String -> Maybe String

Use Url.Parser instead! It will decode query parameters appropriately already! percentDecode is only available so that extremely custom cases are possible, if needed.

Check out the percentEncode function to learn about percent-encoding. This function does the opposite! Here are the reverse examples:

-- ASCII
percentDecode "hat"       == Just "hat"
percentDecode "to%20be"   == Just "to be"
percentDecode "99%25"     == Just "99%"

-- UTF-8
percentDecode "%24"       == Just "$"
percentDecode "%C2%A2"    == Just "¢"
percentDecode "%E2%82%AC" == Just "€"

Why is it a Maybe though? Well, these strings come from strangers on the internet as a bunch of bits and may have encoding problems. For example:

percentDecode "%"   == Nothing  -- not followed by two hex digits
percentDecode "%XY" == Nothing  -- not followed by two HEX digits
percentDecode "%C2" == Nothing  -- half of the "¢" encoding "%C2%A2"

This is the same behavior as JavaScript's decodeURIComponent function.