/
^(https?:\/\/)?                                                # optional scheme
  ((?:[-a-z0-9._~!$&\'()*+,;=]|%[0-9a-f]{2})+                  # optional username@,
   (?::(?:[-a-z0-9._~!$&\'()*+,;=]|%[0-9a-f]{2})+)?@)?         #          or username:password@
  (?:((?:(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]))    # IPv4 address
    |((?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z][a-z0-9-]*[a-z0-9]))                           # or dot-separated domain labels
  (:\d+)?                                                      # optional port number
  ((?:\/(?:[-a-z0-9._~!$&\'()*+,;=:@]|%[0-9a-f]{2})+)*\/?)     # path (possibly empty, may end in /, no double-// allowed)
  (\?(?:[-a-z0-9._~!$&\'()*+,;=:@\/?]|%[0-9a-f]{2})*)?         # optional querystring
  (\#(?:[-a-z0-9._~!$&\'()*+,;=:@\/?]|%[0-9a-f]{2})*)?$        # optional fragment
/
ix