37

I'm trying to use URLComponents to compose a URL as that appears to be what it's for.

However, when I then access the url property of the components it is nil.

Example...

var urlComponents = URLComponents(string: "http://google.com")!
urlComponents.path = "auth/login"

Then I do ...

print(urlComponents)

Output...

scheme: http host: google.com path: auth/login
  - scheme : "http"
  - host : "google.com"
  - path : "auth/login"

But then...

print(urlComponents.url)

outputs nil.

Am I doing something wrong with this? How do I get the fully formed URL from all this? Thanks

Fogmeister
  • 70,181
  • 37
  • 189
  • 274

2 Answers2

107

It looks like path parameter's string must start with /.

So change "auth/login" to "/auth/login" will do.

user28434'mstep
  • 5,401
  • 1
  • 16
  • 31
  • 3
    I was just about to come and answer this myself after a bit more digging in the docs. (Who'd have thought that the docs would explain what's going wrong, haha!) Thanks – Fogmeister Oct 04 '16 at 13:00
  • 13
    I wonder what is the point in having a dedicated type that constructs an URL for you (as opposed to just building the string manually from scheme, host, etc.) if you still have to look out for these things? sheesh... – Nicolas Miari May 23 '17 at 06:47
  • 3
    @NicolasMiari it's actually really useful for embedding query parameters and different schemes and hosts into the url etc... Maybe switching between a test and a production host etc... – Fogmeister Oct 05 '17 at 14:59
  • 1
    Tanks, this really helped me! Same issue and scratching my head for hours. Was missing the front "/" from the path. – Jim Burke May 28 '20 at 14:21
20

TL;DR

If you're creating a web URL (e.g. http://example.com/path), include the / because it uses the following template:

{scheme}://{user}:{password}@{host}:{port}{path}?{query}#{fragment}

If you're creating a non web URL (e.g. mailto:user@example.com), don't include the / because it uses the following template:

{scheme}:{path}?{query}%23{fragment}

To clarify why this is happening, the actual template of URLComponents is as follows:

{scheme}://{user}:{password}@{host}:{port}{path}?{query}#{fragment}

Notice how there is punctuation (://, :, @, :, ?, #) between every two components, except for {port} and {path}.

Therefore, {path} must be prefixed with the punctuation (/), otherwise it'll produce an invalid URL.

In your case you must use :

urlComponents.path = "/auth/login"

Note that even if you omit URLComponents's uncommon fields, you still run into the same problem:

{scheme}://{host}{path}?{query}#{fragment}

Notice how {host} and {path} are adjacent in this case as well, with no punctuation separating the two.

You may be wondering why, then, Apple didn't include the punctuation before {port}. My guess is because URLComponents can be used to produce any type of URL in the RFC 3986 spec, not only Web URLs. E.g. it could easily produce http://www.example.com/foo, but it should just as easily produce a URL of the form mailto:user@example.com.

URLComponents makes this possible by changing the delimiter between {scheme} and {path} when {host} is omitted:

{scheme}:{path}?{query}%23{fragment}

Thus when we want to produce a mailto link, we would actually not include the / in path:

urlComponents.scheme = "mailto"
urlComponents.path = "user@example.com"
// urlComponents.url!.absoluteString == "mailto:user@example.com"

Comparing the properties of URLComponents to URL's properties provides a bit more insight (and reveals a bit of inconsistency):

let string = "scheme://user:password@host:123/path/path/path/?query#fragment"
let urlComponents = URLComponents(string: string)!
let url = URL(string: string)!

// these are expected
url.absoluteString == urlComponents.url!.absoluteString
url.scheme == urlComponents.scheme
url.user == urlComponents.user
url.password == urlComponents.password
url.host == urlComponents.host
url.port == urlComponents.port
url.query == urlComponents.query
url.fragment == urlComponents.fragment

// this is unexpected. They should have been equal to each other
url.path != urlComponents.path

url.path == "/path/path/path"
urlComponents.path == "/path/path/path/"

url.pathComponents == ["/", "path", "path", "path"]
url.lastPathComponent == "path"

Two things to note:

  • url.path doesn't have / in the suffix.
  • url.pathComponents[0] is the first / in the URL.

For an exhaustive list of templates, you can use this code:

let componentsCount = Double(8)
let iterations = Int(pow(2, componentsCount))

for i in 0..<iterations {
  var urlComponents = URLComponents()
  var key = ""
  if i & 0b10000000 > 0 { urlComponents.scheme = "scheme"; key += "s" } else { key += " " }
  if i & 0b01000000 > 0 { urlComponents.user = "user"; key += "u" } else { key += " " }
  if i & 0b00100000 > 0 { urlComponents.password = "password"; key += "w" } else { key += " " }
  if i & 0b00010000 > 0 { urlComponents.host = "host"; key += "h" } else { key += " " }
  if i & 0b00001000 > 0 { urlComponents.port = 123; key += "r" } else { key += " " }
  if i & 0b00000100 > 0 { urlComponents.path = "/path"; key += "p" } else { key += " " }
  if i & 0b00000010 > 0 { urlComponents.query = "query"; key += "q" } else { key += " " }
  if i & 0b00000001 > 0 { urlComponents.fragment = "fragment"; key += "f" } else { key += " " }

  if let url = urlComponents.url?.absoluteString {
    print("[\(key)] \(url)")
  } else {
    print("[\(key)] ------- nil --------")
  }
}

Which produces the following output:

[        ] 
[       f] #fragment
[      q ] ?query
[      qf] ?query#fragment
[     p  ] /path
[     p f] /path#fragment
[     pq ] /path?query
[     pqf] /path?query#fragment
[    r   ] //:123
[    r  f] //:123#fragment
[    r q ] //:123?query
[    r qf] //:123?query#fragment
[    rp  ] //:123/path
[    rp f] //:123/path#fragment
[    rpq ] //:123/path?query
[    rpqf] //:123/path?query#fragment
[   h    ] //host
[   h   f] //host#fragment
[   h  q ] //host?query
[   h  qf] //host?query#fragment
[   h p  ] //host/path
[   h p f] //host/path#fragment
[   h pq ] //host/path?query
[   h pqf] //host/path?query#fragment
[   hr   ] //host:123
[   hr  f] //host:123#fragment
[   hr q ] //host:123?query
[   hr qf] //host:123?query#fragment
[   hrp  ] //host:123/path
[   hrp f] //host:123/path#fragment
[   hrpq ] //host:123/path?query
[   hrpqf] //host:123/path?query#fragment
[  w     ] //:password@
[  w    f] //:password@#fragment
[  w   q ] //:password@?query
[  w   qf] //:password@?query#fragment
[  w  p  ] //:password@/path
[  w  p f] //:password@/path#fragment
[  w  pq ] //:password@/path?query
[  w  pqf] //:password@/path?query#fragment
[  w r   ] //:password@:123
[  w r  f] //:password@:123#fragment
[  w r q ] //:password@:123?query
[  w r qf] //:password@:123?query#fragment
[  w rp  ] //:password@:123/path
[  w rp f] //:password@:123/path#fragment
[  w rpq ] //:password@:123/path?query
[  w rpqf] //:password@:123/path?query#fragment
[  wh    ] //:password@host
[  wh   f] //:password@host#fragment
[  wh  q ] //:password@host?query
[  wh  qf] //:password@host?query#fragment
[  wh p  ] //:password@host/path
[  wh p f] //:password@host/path#fragment
[  wh pq ] //:password@host/path?query
[  wh pqf] //:password@host/path?query#fragment
[  whr   ] //:password@host:123
[  whr  f] //:password@host:123#fragment
[  whr q ] //:password@host:123?query
[  whr qf] //:password@host:123?query#fragment
[  whrp  ] //:password@host:123/path
[  whrp f] //:password@host:123/path#fragment
[  whrpq ] //:password@host:123/path?query
[  whrpqf] //:password@host:123/path?query#fragment
[ u      ] //user@
[ u     f] //user@#fragment
[ u    q ] //user@?query
[ u    qf] //user@?query#fragment
[ u   p  ] //user@/path
[ u   p f] //user@/path#fragment
[ u   pq ] //user@/path?query
[ u   pqf] //user@/path?query#fragment
[ u  r   ] //user@:123
[ u  r  f] //user@:123#fragment
[ u  r q ] //user@:123?query
[ u  r qf] //user@:123?query#fragment
[ u  rp  ] //user@:123/path
[ u  rp f] //user@:123/path#fragment
[ u  rpq ] //user@:123/path?query
[ u  rpqf] //user@:123/path?query#fragment
[ u h    ] //user@host
[ u h   f] //user@host#fragment
[ u h  q ] //user@host?query
[ u h  qf] //user@host?query#fragment
[ u h p  ] //user@host/path
[ u h p f] //user@host/path#fragment
[ u h pq ] //user@host/path?query
[ u h pqf] //user@host/path?query#fragment
[ u hr   ] //user@host:123
[ u hr  f] //user@host:123#fragment
[ u hr q ] //user@host:123?query
[ u hr qf] //user@host:123?query#fragment
[ u hrp  ] //user@host:123/path
[ u hrp f] //user@host:123/path#fragment
[ u hrpq ] //user@host:123/path?query
[ u hrpqf] //user@host:123/path?query#fragment
[ uw     ] //user:password@
[ uw    f] //user:password@#fragment
[ uw   q ] //user:password@?query
[ uw   qf] //user:password@?query#fragment
[ uw  p  ] //user:password@/path
[ uw  p f] //user:password@/path#fragment
[ uw  pq ] //user:password@/path?query
[ uw  pqf] //user:password@/path?query#fragment
[ uw r   ] //user:password@:123
[ uw r  f] //user:password@:123#fragment
[ uw r q ] //user:password@:123?query
[ uw r qf] //user:password@:123?query#fragment
[ uw rp  ] //user:password@:123/path
[ uw rp f] //user:password@:123/path#fragment
[ uw rpq ] //user:password@:123/path?query
[ uw rpqf] //user:password@:123/path?query#fragment
[ uwh    ] //user:password@host
[ uwh   f] //user:password@host#fragment
[ uwh  q ] //user:password@host?query
[ uwh  qf] //user:password@host?query#fragment
[ uwh p  ] //user:password@host/path
[ uwh p f] //user:password@host/path#fragment
[ uwh pq ] //user:password@host/path?query
[ uwh pqf] //user:password@host/path?query#fragment
[ uwhr   ] //user:password@host:123
[ uwhr  f] //user:password@host:123#fragment
[ uwhr q ] //user:password@host:123?query
[ uwhr qf] //user:password@host:123?query#fragment
[ uwhrp  ] //user:password@host:123/path
[ uwhrp f] //user:password@host:123/path#fragment
[ uwhrpq ] //user:password@host:123/path?query
[ uwhrpqf] //user:password@host:123/path?query#fragment
[s       ] scheme:
[s      f] scheme:%23fragment
[s     q ] scheme:?query
[s     qf] scheme:?query%23fragment
[s    p  ] scheme:/path
[s    p f] scheme:/path#fragment
[s    pq ] scheme:/path?query
[s    pqf] scheme:/path?query#fragment
[s   r   ] scheme://:123
[s   r  f] scheme://:123#fragment
[s   r q ] scheme://:123?query
[s   r qf] scheme://:123?query#fragment
[s   rp  ] scheme://:123/path
[s   rp f] scheme://:123/path#fragment
[s   rpq ] scheme://:123/path?query
[s   rpqf] scheme://:123/path?query#fragment
[s  h    ] scheme://host
[s  h   f] scheme://host#fragment
[s  h  q ] scheme://host?query
[s  h  qf] scheme://host?query#fragment
[s  h p  ] scheme://host/path
[s  h p f] scheme://host/path#fragment
[s  h pq ] scheme://host/path?query
[s  h pqf] scheme://host/path?query#fragment
[s  hr   ] scheme://host:123
[s  hr  f] scheme://host:123#fragment
[s  hr q ] scheme://host:123?query
[s  hr qf] scheme://host:123?query#fragment
[s  hrp  ] scheme://host:123/path
[s  hrp f] scheme://host:123/path#fragment
[s  hrpq ] scheme://host:123/path?query
[s  hrpqf] scheme://host:123/path?query#fragment
[s w     ] scheme://:password@
[s w    f] scheme://:password@#fragment
[s w   q ] scheme://:password@?query
[s w   qf] scheme://:password@?query#fragment
[s w  p  ] scheme://:password@/path
[s w  p f] scheme://:password@/path#fragment
[s w  pq ] scheme://:password@/path?query
[s w  pqf] scheme://:password@/path?query#fragment
[s w r   ] scheme://:password@:123
[s w r  f] scheme://:password@:123#fragment
[s w r q ] scheme://:password@:123?query
[s w r qf] scheme://:password@:123?query#fragment
[s w rp  ] scheme://:password@:123/path
[s w rp f] scheme://:password@:123/path#fragment
[s w rpq ] scheme://:password@:123/path?query
[s w rpqf] scheme://:password@:123/path?query#fragment
[s wh    ] scheme://:password@host
[s wh   f] scheme://:password@host#fragment
[s wh  q ] scheme://:password@host?query
[s wh  qf] scheme://:password@host?query#fragment
[s wh p  ] scheme://:password@host/path
[s wh p f] scheme://:password@host/path#fragment
[s wh pq ] scheme://:password@host/path?query
[s wh pqf] scheme://:password@host/path?query#fragment
[s whr   ] scheme://:password@host:123
[s whr  f] scheme://:password@host:123#fragment
[s whr q ] scheme://:password@host:123?query
[s whr qf] scheme://:password@host:123?query#fragment
[s whrp  ] scheme://:password@host:123/path
[s whrp f] scheme://:password@host:123/path#fragment
[s whrpq ] scheme://:password@host:123/path?query
[s whrpqf] scheme://:password@host:123/path?query#fragment
[su      ] scheme://user@
[su     f] scheme://user@#fragment
[su    q ] scheme://user@?query
[su    qf] scheme://user@?query#fragment
[su   p  ] scheme://user@/path
[su   p f] scheme://user@/path#fragment
[su   pq ] scheme://user@/path?query
[su   pqf] scheme://user@/path?query#fragment
[su  r   ] scheme://user@:123
[su  r  f] scheme://user@:123#fragment
[su  r q ] scheme://user@:123?query
[su  r qf] scheme://user@:123?query#fragment
[su  rp  ] scheme://user@:123/path
[su  rp f] scheme://user@:123/path#fragment
[su  rpq ] scheme://user@:123/path?query
[su  rpqf] scheme://user@:123/path?query#fragment
[su h    ] scheme://user@host
[su h   f] scheme://user@host#fragment
[su h  q ] scheme://user@host?query
[su h  qf] scheme://user@host?query#fragment
[su h p  ] scheme://user@host/path
[su h p f] scheme://user@host/path#fragment
[su h pq ] scheme://user@host/path?query
[su h pqf] scheme://user@host/path?query#fragment
[su hr   ] scheme://user@host:123
[su hr  f] scheme://user@host:123#fragment
[su hr q ] scheme://user@host:123?query
[su hr qf] scheme://user@host:123?query#fragment
[su hrp  ] scheme://user@host:123/path
[su hrp f] scheme://user@host:123/path#fragment
[su hrpq ] scheme://user@host:123/path?query
[su hrpqf] scheme://user@host:123/path?query#fragment
[suw     ] scheme://user:password@
[suw    f] scheme://user:password@#fragment
[suw   q ] scheme://user:password@?query
[suw   qf] scheme://user:password@?query#fragment
[suw  p  ] scheme://user:password@/path
[suw  p f] scheme://user:password@/path#fragment
[suw  pq ] scheme://user:password@/path?query
[suw  pqf] scheme://user:password@/path?query#fragment
[suw r   ] scheme://user:password@:123
[suw r  f] scheme://user:password@:123#fragment
[suw r q ] scheme://user:password@:123?query
[suw r qf] scheme://user:password@:123?query#fragment
[suw rp  ] scheme://user:password@:123/path
[suw rp f] scheme://user:password@:123/path#fragment
[suw rpq ] scheme://user:password@:123/path?query
[suw rpqf] scheme://user:password@:123/path?query#fragment
[suwh    ] scheme://user:password@host
[suwh   f] scheme://user:password@host#fragment
[suwh  q ] scheme://user:password@host?query
[suwh  qf] scheme://user:password@host?query#fragment
[suwh p  ] scheme://user:password@host/path
[suwh p f] scheme://user:password@host/path#fragment
[suwh pq ] scheme://user:password@host/path?query
[suwh pqf] scheme://user:password@host/path?query#fragment
[suwhr   ] scheme://user:password@host:123
[suwhr  f] scheme://user:password@host:123#fragment
[suwhr q ] scheme://user:password@host:123?query
[suwhr qf] scheme://user:password@host:123?query#fragment
[suwhrp  ] scheme://user:password@host:123/path
[suwhrp f] scheme://user:password@host:123/path#fragment
[suwhrpq ] scheme://user:password@host:123/path?query
[suwhrpqf] scheme://user:password@host:123/path?query#fragment

Notice how none of these are nil. If you change urlComponents.path = "/path" to urlComponents.path = "path", however, you get a completely different set of templates:

[        ] 
[       f] #fragment
[      q ] ?query
[      qf] ?query#fragment
[     p  ] path
[     p f] path#fragment
[     pq ] path?query
[     pqf] path?query#fragment
[    r   ] //:123
[    r  f] //:123#fragment
[    r q ] //:123?query
[    r qf] //:123?query#fragment
[    rp  ] ------- nil --------
[    rp f] ------- nil --------
[    rpq ] ------- nil --------
[    rpqf] ------- nil --------
[   h    ] //host
[   h   f] //host#fragment
[   h  q ] //host?query
[   h  qf] //host?query#fragment
[   h p  ] ------- nil --------
[   h p f] ------- nil --------
[   h pq ] ------- nil --------
[   h pqf] ------- nil --------
[   hr   ] //host:123
[   hr  f] //host:123#fragment
[   hr q ] //host:123?query
[   hr qf] //host:123?query#fragment
[   hrp  ] ------- nil --------
[   hrp f] ------- nil --------
[   hrpq ] ------- nil --------
[   hrpqf] ------- nil --------
[  w     ] //:password@
[  w    f] //:password@#fragment
[  w   q ] //:password@?query
[  w   qf] //:password@?query#fragment
[  w  p  ] ------- nil --------
[  w  p f] ------- nil --------
[  w  pq ] ------- nil --------
[  w  pqf] ------- nil --------
[  w r   ] //:password@:123
[  w r  f] //:password@:123#fragment
[  w r q ] //:password@:123?query
[  w r qf] //:password@:123?query#fragment
[  w rp  ] ------- nil --------
[  w rp f] ------- nil --------
[  w rpq ] ------- nil --------
[  w rpqf] ------- nil --------
[  wh    ] //:password@host
[  wh   f] //:password@host#fragment
[  wh  q ] //:password@host?query
[  wh  qf] //:password@host?query#fragment
[  wh p  ] ------- nil --------
[  wh p f] ------- nil --------
[  wh pq ] ------- nil --------
[  wh pqf] ------- nil --------
[  whr   ] //:password@host:123
[  whr  f] //:password@host:123#fragment
[  whr q ] //:password@host:123?query
[  whr qf] //:password@host:123?query#fragment
[  whrp  ] ------- nil --------
[  whrp f] ------- nil --------
[  whrpq ] ------- nil --------
[  whrpqf] ------- nil --------
[ u      ] //user@
[ u     f] //user@#fragment
[ u    q ] //user@?query
[ u    qf] //user@?query#fragment
[ u   p  ] ------- nil --------
[ u   p f] ------- nil --------
[ u   pq ] ------- nil --------
[ u   pqf] ------- nil --------
[ u  r   ] //user@:123
[ u  r  f] //user@:123#fragment
[ u  r q ] //user@:123?query
[ u  r qf] //user@:123?query#fragment
[ u  rp  ] ------- nil --------
[ u  rp f] ------- nil --------
[ u  rpq ] ------- nil --------
[ u  rpqf] ------- nil --------
[ u h    ] //user@host
[ u h   f] //user@host#fragment
[ u h  q ] //user@host?query
[ u h  qf] //user@host?query#fragment
[ u h p  ] ------- nil --------
[ u h p f] ------- nil --------
[ u h pq ] ------- nil --------
[ u h pqf] ------- nil --------
[ u hr   ] //user@host:123
[ u hr  f] //user@host:123#fragment
[ u hr q ] //user@host:123?query
[ u hr qf] //user@host:123?query#fragment
[ u hrp  ] ------- nil --------
[ u hrp f] ------- nil --------
[ u hrpq ] ------- nil --------
[ u hrpqf] ------- nil --------
[ uw     ] //user:password@
[ uw    f] //user:password@#fragment
[ uw   q ] //user:password@?query
[ uw   qf] //user:password@?query#fragment
[ uw  p  ] ------- nil --------
[ uw  p f] ------- nil --------
[ uw  pq ] ------- nil --------
[ uw  pqf] ------- nil --------
[ uw r   ] //user:password@:123
[ uw r  f] //user:password@:123#fragment
[ uw r q ] //user:password@:123?query
[ uw r qf] //user:password@:123?query#fragment
[ uw rp  ] ------- nil --------
[ uw rp f] ------- nil --------
[ uw rpq ] ------- nil --------
[ uw rpqf] ------- nil --------
[ uwh    ] //user:password@host
[ uwh   f] //user:password@host#fragment
[ uwh  q ] //user:password@host?query
[ uwh  qf] //user:password@host?query#fragment
[ uwh p  ] ------- nil --------
[ uwh p f] ------- nil --------
[ uwh pq ] ------- nil --------
[ uwh pqf] ------- nil --------
[ uwhr   ] //user:password@host:123
[ uwhr  f] //user:password@host:123#fragment
[ uwhr q ] //user:password@host:123?query
[ uwhr qf] //user:password@host:123?query#fragment
[ uwhrp  ] ------- nil --------
[ uwhrp f] ------- nil --------
[ uwhrpq ] ------- nil --------
[ uwhrpqf] ------- nil --------
[s       ] scheme:
[s      f] scheme:%23fragment
[s     q ] scheme:?query
[s     qf] scheme:?query%23fragment
[s    p  ] scheme:path
[s    p f] scheme:path%23fragment
[s    pq ] scheme:path?query
[s    pqf] scheme:path?query%23fragment
[s   r   ] scheme://:123
[s   r  f] scheme://:123#fragment
[s   r q ] scheme://:123?query
[s   r qf] scheme://:123?query#fragment
[s   rp  ] ------- nil --------
[s   rp f] ------- nil --------
[s   rpq ] ------- nil --------
[s   rpqf] ------- nil --------
[s  h    ] scheme://host
[s  h   f] scheme://host#fragment
[s  h  q ] scheme://host?query
[s  h  qf] scheme://host?query#fragment
[s  h p  ] ------- nil --------
[s  h p f] ------- nil --------
[s  h pq ] ------- nil --------
[s  h pqf] ------- nil --------
[s  hr   ] scheme://host:123
[s  hr  f] scheme://host:123#fragment
[s  hr q ] scheme://host:123?query
[s  hr qf] scheme://host:123?query#fragment
[s  hrp  ] ------- nil --------
[s  hrp f] ------- nil --------
[s  hrpq ] ------- nil --------
[s  hrpqf] ------- nil --------
[s w     ] scheme://:password@
[s w    f] scheme://:password@#fragment
[s w   q ] scheme://:password@?query
[s w   qf] scheme://:password@?query#fragment
[s w  p  ] ------- nil --------
[s w  p f] ------- nil --------
[s w  pq ] ------- nil --------
[s w  pqf] ------- nil --------
[s w r   ] scheme://:password@:123
[s w r  f] scheme://:password@:123#fragment
[s w r q ] scheme://:password@:123?query
[s w r qf] scheme://:password@:123?query#fragment
[s w rp  ] ------- nil --------
[s w rp f] ------- nil --------
[s w rpq ] ------- nil --------
[s w rpqf] ------- nil --------
[s wh    ] scheme://:password@host
[s wh   f] scheme://:password@host#fragment
[s wh  q ] scheme://:password@host?query
[s wh  qf] scheme://:password@host?query#fragment
[s wh p  ] ------- nil --------
[s wh p f] ------- nil --------
[s wh pq ] ------- nil --------
[s wh pqf] ------- nil --------
[s whr   ] scheme://:password@host:123
[s whr  f] scheme://:password@host:123#fragment
[s whr q ] scheme://:password@host:123?query
[s whr qf] scheme://:password@host:123?query#fragment
[s whrp  ] ------- nil --------
[s whrp f] ------- nil --------
[s whrpq ] ------- nil --------
[s whrpqf] ------- nil --------
[su      ] scheme://user@
[su     f] scheme://user@#fragment
[su    q ] scheme://user@?query
[su    qf] scheme://user@?query#fragment
[su   p  ] ------- nil --------
[su   p f] ------- nil --------
[su   pq ] ------- nil --------
[su   pqf] ------- nil --------
[su  r   ] scheme://user@:123
[su  r  f] scheme://user@:123#fragment
[su  r q ] scheme://user@:123?query
[su  r qf] scheme://user@:123?query#fragment
[su  rp  ] ------- nil --------
[su  rp f] ------- nil --------
[su  rpq ] ------- nil --------
[su  rpqf] ------- nil --------
[su h    ] scheme://user@host
[su h   f] scheme://user@host#fragment
[su h  q ] scheme://user@host?query
[su h  qf] scheme://user@host?query#fragment
[su h p  ] ------- nil --------
[su h p f] ------- nil --------
[su h pq ] ------- nil --------
[su h pqf] ------- nil --------
[su hr   ] scheme://user@host:123
[su hr  f] scheme://user@host:123#fragment
[su hr q ] scheme://user@host:123?query
[su hr qf] scheme://user@host:123?query#fragment
[su hrp  ] ------- nil --------
[su hrp f] ------- nil --------
[su hrpq ] ------- nil --------
[su hrpqf] ------- nil --------
[suw     ] scheme://user:password@
[suw    f] scheme://user:password@#fragment
[suw   q ] scheme://user:password@?query
[suw   qf] scheme://user:password@?query#fragment
[suw  p  ] ------- nil --------
[suw  p f] ------- nil --------
[suw  pq ] ------- nil --------
[suw  pqf] ------- nil --------
[suw r   ] scheme://user:password@:123
[suw r  f] scheme://user:password@:123#fragment
[suw r q ] scheme://user:password@:123?query
[suw r qf] scheme://user:password@:123?query#fragment
[suw rp  ] ------- nil --------
[suw rp f] ------- nil --------
[suw rpq ] ------- nil --------
[suw rpqf] ------- nil --------
[suwh    ] scheme://user:password@host
[suwh   f] scheme://user:password@host#fragment
[suwh  q ] scheme://user:password@host?query
[suwh  qf] scheme://user:password@host?query#fragment
[suwh p  ] ------- nil --------
[suwh p f] ------- nil --------
[suwh pq ] ------- nil --------
[suwh pqf] ------- nil --------
[suwhr   ] scheme://user:password@host:123
[suwhr  f] scheme://user:password@host:123#fragment
[suwhr q ] scheme://user:password@host:123?query
[suwhr qf] scheme://user:password@host:123?query#fragment
[suwhrp  ] ------- nil --------
[suwhrp f] ------- nil --------
[suwhrpq ] ------- nil --------
[suwhrpqf] ------- nil --------
Senseful
  • 73,679
  • 56
  • 267
  • 405