docs: def urinorm(uri):
      '''
      Normalize a URI
      '''
      # TODO: use urllib.parse instead of these complex regular expressions
      if isinstance(uri, bytes):
          uri = str(uri, encoding='utf-8')
  
      uri = uri.encode('ascii', errors='oid_percent_escape').decode('utf-8')
      # _escapeme_re.sub(_pct_escape_unicode, uri).encode('ascii').decode()
  
      illegal_mo = uri_illegal_char_re.search(uri)
      if illegal_mo:
          raise ValueError('Illegal characters in URI: %r at position %s' %
                           (illegal_mo.group(), illegal_mo.start()))
  
      uri_mo = uri_re.match(uri)
  
      scheme = uri_mo.group(2)
      if scheme is None:
          raise ValueError('No scheme specified')
  
      scheme = scheme.lower()
      if scheme not in ('http', 'https'):
          raise ValueError('Not an absolute HTTP or HTTPS URI: %r' % (uri, ))
  
      authority = uri_mo.group(4)
      if authority is None:
          raise ValueError('Not an absolute URI: %r' % (uri, ))
  
      authority_mo = authority_re.match(authority)
      if authority_mo is None:
          raise ValueError('URI does not have a valid authority: %r' % (uri, ))
  
      userinfo, host, port = authority_mo.groups()
  
      if userinfo is None:
          userinfo = ''
  
      if '%' in host:
          host = host.lower()
          host = pct_encoded_re.sub(_pct_encoded_replace, host)
          host = host.encode('idna').decode()
      else:
          host = host.lower()
  
      if port:
          if (port == ':' or (scheme == 'http' and port == ':80') or
              (scheme == 'https' and port == ':443')):
              port = ''
      else:
          port = ''
  
      authority = userinfo + host + port
  
      path = uri_mo.group(5)
      path = pct_encoded_re.sub(_pct_encoded_replace_unreserved, path)
      path = remove_dot_segments(path)
      if not path:
          path = '/'
  
      query = uri_mo.group(6)
      if query is None:
          query = ''
  
      fragment = uri_mo.group(8)
      if fragment is None:
          fragment = ''
  
      return scheme + '://' + authority + path + query + fragment