from datetime import datetime
import http.server
import socket

import werkzeug.http


# https://www.iana.org/assignments/http-methods/http-methods.xhtml
KNOWN_METHODS = ['ACL', 'BASELINE-CONTROL', 'BIND', 'CHECKIN', 'CHECKOUT',
                 'CONNECT', 'COPY', 'DELETE', 'GET', 'HEAD', 'LABEL', 'LINK',
                 'LOCK', 'MERGE', 'MKACTIVITY', 'MKCALENDAR', 'MKCOL',
                 'MKREDIRECTREF', 'MKWORKSPACE', 'MOVE', 'OPTIONS',
                 'ORDERPATCH', 'PATCH', 'POST', 'PRI', 'PROPFIND', 'PROPPATCH',
                 'PUT', 'REBIND', 'REPORT', 'SEARCH', 'TRACE', 'UNBIND',
                 'UNCHECKOUT', 'UNLINK', 'UNLOCK', 'UPDATE',
                 'UPDATEREDIRECTREF', 'VERSION-CONTROL']


def default_reason(status_code):
    common_phrases = http.server.BaseHTTPRequestHandler.responses
    (reason, _) = common_phrases.get(status_code, ('Unknown', None))
    return reason


def error_explanation(status_code):
    common_phrases = http.server.BaseHTTPRequestHandler.responses
    (_, explanation) = common_phrases.get(status_code,
                                          (None, 'Something is wrong'))
    return explanation


def date():
    return werkzeug.http.http_date(datetime.utcnow())


def nice_header_name(name):
    # "cache-control" -> "Cache-Control"
    return '-'.join(word.capitalize() for word in name.split('-'))


def guess_external_url(local_host, port):
    """Return a URL that is most likely to route to `local_host` from outside.

    The point is that we may be running on a remote host from the user's
    point of view, so they can't access `local_host` from a Web browser just
    by typing ``http://localhost:12345/``.
    """
    if local_host in ['0.0.0.0', '::']:         # Listening on all interfaces
        local_host = socket.getfqdn()
        # https://github.com/vfaronov/turq/issues/9
        if local_host.lower().rstrip('.').endswith('.arpa'):
            local_host = 'localhost'          # Welp, not much we can do here.
    if ':' in local_host:     # IPv6 literal
        local_host = '[%s]' % local_host
    return 'http://%s:%d/' % (local_host, port)

@@ -42,16 +42,60 @@
 .server%0A
+from ipaddress import IPv6Address%0Aimport re%0A
 import s
@@ -756,16 +756,277 @@
 ROL'%5D%0A%0A%0A
+IPV4_REVERSE_DNS = re.compile(r'%5E' + r'(%5B0-9%5D+)%5C.' * 4 + r'in-addr%5C.arpa%5C.?$',%0A                              flags=re.IGNORECASE)%0AIPV6_REVERSE_DNS = re.compile(r'%5E' + r'(%5B0-9a-f%5D)%5C.' * 32 + r'ip6%5C.arpa%5C.?$',%0A                              flags=re.IGNORECASE)%0A%0A%0A
 def defa
@@ -2027,17 +2027,17 @@
 , '::'%5D:
- 
+%0A
         
@@ -2038,17 +2038,31 @@
       # 
-L
+The server is l
 istening
@@ -2079,16 +2079,93 @@
 terfaces
+, but we have to pick one.%0A        # The system's FQDN should give us a hint.
 %0A       
@@ -2195,16 +2195,17 @@
 tfqdn()%0A
+%0A
         
@@ -2260,61 +2260,298 @@
     
-if local_host.lower().rstrip('.').endswith('.arpa'):%0A
+match = IPV4_REVERSE_DNS.match(local_host)%0A        if match:%0A            local_host = '.'.join(reversed(match.groups()))%0A        else:%0A            match = IPV6_REVERSE_DNS.match(local_host)%0A            if match:%0A                address_as_int = int(''.join(reversed(match.groups())), 16)%0A  
     
@@ -2550,32 +2550,34 @@
 )%0A              
+  
 local_host = 'lo
@@ -2577,27 +2577,76 @@
 t = 
-'
+str(IPv6Address(address_as_int))%0A%0A    if ':' in 
 local
+_
 host
-'
+:%0A
         
   # 
@@ -2645,87 +2645,357 @@
     
-  # Welp, not much we can do here.%0A    if ':' in local_host:     # IPv6 literal
+# Looks like an IPv6 literal. Has to be wrapped in brackets in a URL.%0A        # Also, an IPv6 address can have a zone ID tacked on the end,%0A        # like %22%253%22. RFC 6874 allows encoding them in URLs as well,%0A        # but in my experiments on Windows 8.1, I had more success%0A        # removing the zone ID altogether. After all this is just a guess.
 %0A   
@@ -3031,16 +3031,35 @@
 cal_host
+.rsplit('%25', 1)%5B0%5D%0A
 %0A    ret

Improve guess_external_url