Python 3: Port some html tests following Python file handlers porting guide (#23363)

This is a rework on https://github.com/web-platform-tests/wpt/pull/22402
This change follows the porting guide discussed in RFC49:
https://github.com/web-platform-tests/rfcs/pull/49

Co-authored-by: Robert Ma <bob1211@gmail.com>
diff --git a/cookies/resources/set-cookie.py b/cookies/resources/set-cookie.py
index 1eee832..38325f0 100644
--- a/cookies/resources/set-cookie.py
+++ b/cookies/resources/set-cookie.py
@@ -1,7 +1,3 @@
-
-import sys
-import urlparse
-
 def main(request, response):
     """
     Returns cookie name and path from query params in a Set-Cookie header.
@@ -20,10 +16,14 @@
     < Date: Tue, 04 Oct 2016 18:16:06 GMT
     < Content-Length: 80
     """
-    params = urlparse.parse_qs(request.url_parts.query)
+
+    name = request.GET[b'name']
+    path = request.GET[b'path']
+    cookie = b"%s=1; Path=%s; Expires=Wed, 09 Jun 2021 10:18:14 GMT" % (name, path)
+
     headers = [
-        ("Content-Type", "application/json"),
-        ("Set-Cookie", "{name[0]}=1; Path={path[0]}; Expires=Wed, 09 Jun 2021 10:18:14 GMT".format(**params))
+        (b"Content-Type", b"application/json"),
+        (b"Set-Cookie", cookie)
     ]
-    body = "{}"
+    body = b"{}"
     return headers, body
diff --git a/html/semantics/embedded-content/media-elements/track/track-element/cors/support/cors-tester.py b/html/semantics/embedded-content/media-elements/track/track-element/cors/support/cors-tester.py
index 7ec7b16..ad1cce1 100644
--- a/html/semantics/embedded-content/media-elements/track/track-element/cors/support/cors-tester.py
+++ b/html/semantics/embedded-content/media-elements/track/track-element/cors/support/cors-tester.py
@@ -1,51 +1,50 @@
 from wptserve.handlers import HTTPException
-import urllib
 
 def main(request, response):
-    if request.method != "GET":
-        raise HTTPException(400, message="Method was not GET")
+    if request.method != u"GET":
+        raise HTTPException(400, message=u"Method was not GET")
 
-    if not "id" in request.GET:
-        raise HTTPException(400, message="No id")
+    if not b"id" in request.GET:
+        raise HTTPException(400, message=u"No id")
 
-    id = request.GET['id']
-
-    if "read" in request.GET:
+    id = request.GET[b'id']
+    if b"read" in request.GET:
         data = request.server.stash.take(id)
         if data is None:
-            response.set_error(404, "Tried to read data not yet set")
+            response.set_error(404, u"Tried to read data not yet set")
             return
-        return [("Content-Type", "text/plain")], data
+        return [(b"Content-Type", b"text/plain")], data
 
-    elif "cleanup" in request.GET:
+    elif b"cleanup" in request.GET:
         request.server.stash.take(id)
-        return "OK"
+        return b"OK"
 
-    elif "delete-cookie" in request.GET:
+    elif b"delete-cookie" in request.GET:
         response.delete_cookie(id)
-        return [("Content-Type", "text/plain")], "OK"
+        return [(b"Content-Type", b"text/plain")], b"OK"
 
-    if "origin" in request.GET:
-        response.headers.set('Access-Control-Allow-Origin', request.GET['origin'])
-        response.headers.set('Access-Control-Allow-Credentials', 'true')
+    if b"origin" in request.GET:
+        response.headers.set(b'Access-Control-Allow-Origin', request.GET[b'origin'])
+        response.headers.set(b'Access-Control-Allow-Credentials', b'true')
 
-    cors = request.headers.get("origin", "no")
+    cors = request.headers.get(b"origin", b"no")
 
     cookie = request.cookies.first(id, None)
-    cookie_value = cookie.value if cookie is not None else "no"
-    line = 'cors = ' + cors + ' | cookie = ' + cookie_value;
+    cookie_value = cookie.value if cookie is not None else b"no"
+
+    line = b'cors = ' + cors + b' | cookie = ' + cookie_value
 
     data = request.server.stash.take(id)
     if data is not None:
-        line = data + "\n" + line
+        line = data + b"\n" + line
 
     request.server.stash.put(id, line)
 
-    if "redirect" in request.GET:
+    if b"redirect" in request.GET:
         response.status = 302
-        response.headers.set('Location', request.GET['redirect'])
+        response.headers.set(b'Location', request.GET[b'redirect'])
     else:
-        return """WEBVTT
+        return b"""WEBVTT
 
 00:00:00.000 --> 00:00:10.000
 Test"""
diff --git a/html/semantics/embedded-content/the-img-element/404-response-with-actual-image-data.py b/html/semantics/embedded-content/the-img-element/404-response-with-actual-image-data.py
index e4216c6..3e2d991 100644
--- a/html/semantics/embedded-content/the-img-element/404-response-with-actual-image-data.py
+++ b/html/semantics/embedded-content/the-img-element/404-response-with-actual-image-data.py
@@ -1,3 +1,3 @@
 import base64
 def main(req, res):
-    return 404, [('Content-Type', 'image/png')], base64.decodestring("iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAhSURBVDhPY3wro/KfgQLABKXJBqMGjBoAAqMGDLwBDAwAEsoCTFWunmQAAAAASUVORK5CYII=")
+    return 404, [(b'Content-Type', b'image/png')], base64.decodestring(b"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAhSURBVDhPY3wro/KfgQLABKXJBqMGjBoAAqMGDLwBDAwAEsoCTFWunmQAAAAASUVORK5CYII=")
diff --git a/html/semantics/forms/form-submission-0/resources/form-submission.py b/html/semantics/forms/form-submission-0/resources/form-submission.py
index b296ac4..f0c2d4c 100644
--- a/html/semantics/forms/form-submission-0/resources/form-submission.py
+++ b/html/semantics/forms/form-submission-0/resources/form-submission.py
@@ -1,12 +1,12 @@
 def main(request, response):
-    if request.headers.get('Content-Type') == 'application/x-www-form-urlencoded':
-        result = request.body == 'foo=bara'
-    elif request.headers.get('Content-Type') == 'text/plain':
-        result = request.body == 'qux=baz\r\n'
+    if request.headers.get(b'Content-Type') == b'application/x-www-form-urlencoded':
+        result = request.body == b'foo=bara'
+    elif request.headers.get(b'Content-Type') == b'text/plain':
+        result = request.body == b'qux=baz\r\n'
     else:
-        result = request.POST.first('foo') == 'bar'
+        result = request.POST.first(b'foo') == b'bar'
 
-    result = result and request.url_parts.query == 'query=1'
+    result = result and request.url_parts.query == u'query=1'
 
-    return ([("Content-Type", "text/plain")],
-            "OK" if result else "FAIL")
+    return ([(b"Content-Type", b"text/plain")],
+            b"OK" if result else b"FAIL")
diff --git a/html/semantics/scripting-1/the-script-element/module/resources/check-cookie.py b/html/semantics/scripting-1/the-script-element/module/resources/check-cookie.py
index cf6f72f..ec5fdc8 100644
--- a/html/semantics/scripting-1/the-script-element/module/resources/check-cookie.py
+++ b/html/semantics/scripting-1/the-script-element/module/resources/check-cookie.py
@@ -1,20 +1,20 @@
 def main(request, response):
     headers = [
-        ("Content-Type", "text/javascript"),
-        ("Access-Control-Allow-Origin", request.headers.get("Origin")),
-        ("Access-Control-Allow-Credentials", "true")
+        (b"Content-Type", b"text/javascript"),
+        (b"Access-Control-Allow-Origin", request.headers.get(b"Origin")),
+        (b"Access-Control-Allow-Credentials", b"true")
     ]
-    identifier = request.GET.first("id")
-    cookie_name = request.GET.first("cookieName")
+    identifier = request.GET.first(b"id")
+    cookie_name = request.GET.first(b"cookieName")
     cookie = request.cookies.first(cookie_name, None)
     if identifier is None or cookie_name is None:
-        return headers, ""
+        return headers, b""
 
     if cookie is None:
-        result = "not found"
-    elif cookie.value == "1":
-        result = "found"
+        result = b"not found"
+    elif cookie.value == b"1":
+        result = b"found"
     else:
-        result = "different value: " + cookie.value
+        result = b"different value: " + cookie.value
 
-    return headers, "window." + identifier + " = '" + result + "';"
+    return headers, b"window." + identifier + b" = '" + result + b"';"
diff --git a/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py b/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py
index b652cbe..413f48d 100644
--- a/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py
+++ b/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py
@@ -1,6 +1,6 @@
 def main(request, response):
-    referrer = request.headers.get("referer", "")
-    response_headers = [("Content-Type", "text/javascript"),
-                        ("Access-Control-Allow-Origin", "*")];
+    referrer = request.headers.get(b"referer", b"")
+    response_headers = [(b"Content-Type", b"text/javascript"),
+                        (b"Access-Control-Allow-Origin", b"*")]
     return (200, response_headers,
-            "export const referrer = '" + referrer + "';")
+            b"export const referrer = '" + referrer + b"';")
diff --git a/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/slow-png.py b/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/slow-png.py
index 5fa2fd9..7869856 100644
--- a/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/slow-png.py
+++ b/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/slow-png.py
@@ -1,7 +1,7 @@
 from base64 import decodestring
 import time
 
-png_response = decodestring('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVR4nGNiAAAABgADNjd8qAAAAABJRU5ErkJggg==')
+png_response = decodestring(b'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVR4nGNiAAAABgADNjd8qAAAAABJRU5ErkJggg==')
 
 def main(request, response):
     time.sleep(2)
diff --git a/xhr/resources/inspect-headers.py b/xhr/resources/inspect-headers.py
index e71f671..68cece4 100644
--- a/xhr/resources/inspect-headers.py
+++ b/xhr/resources/inspect-headers.py
@@ -1,33 +1,50 @@
+from six import PY3
+
 def get_response(raw_headers, filter_value, filter_name):
-    result = ""
-    for line in raw_headers.headers:
-        if line[-2:] != '\r\n':
-            return "Syntax error: missing CRLF: " + line
+    result = b""
+    # Type of raw_headers is <httplib.HTTPMessage> in Python 2 and <http.client.HTTPMessage> in
+    # Python 3. <http.client.HTTPMessage> doesn't have 'headers" attribute or equivalent
+    # [https://bugs.python.org/issue4773].
+    # In Python 2, variable raw_headers.headers returns a completely uninterpreted list of lines
+    # contained in the header. In Python 3, raw_headers.as_string() returns entire formatted
+    # message as a string. Here is to construct an equivalent "headers" variable to support tests
+    # in Python 3.
+    if PY3:
+        header_list = [
+            (s + u'\r\n').encode("iso-8859-1") for s in raw_headers.as_string().splitlines() if s
+        ]
+    else:
+        header_list = raw_headers.headers
+    for line in header_list:
+        if line[-2:] != b'\r\n':
+            return b"Syntax error: missing CRLF: " + line
         line = line[:-2]
 
-        if ': ' not in line:
-            return "Syntax error: no colon and space found: " + line
-        name, value = line.split(': ', 1)
+        if b': ' not in line:
+            return b"Syntax error: no colon and space found: " + line
+        name, value = line.split(b': ', 1)
 
         if filter_value:
             if value == filter_value:
-                result += name + ","
+                result += name + b","
         elif name.lower() == filter_name:
-            result += name + ": " + value + "\n"
+            result += name + b": " + value + b"\n"
     return result
 
 def main(request, response):
     headers = []
     if "cors" in request.GET:
-        headers.append(("Access-Control-Allow-Origin", "*"))
-        headers.append(("Access-Control-Allow-Credentials", "true"))
-        headers.append(("Access-Control-Allow-Methods", "GET, POST, PUT, FOO"))
-        headers.append(("Access-Control-Allow-Headers", "x-test, x-foo"))
-        headers.append(("Access-Control-Expose-Headers", "x-request-method, x-request-content-type, x-request-query, x-request-content-length"))
-    headers.append(("content-type", "text/plain"))
+        headers.append((b"Access-Control-Allow-Origin", b"*"))
+        headers.append((b"Access-Control-Allow-Credentials", b"true"))
+        headers.append((b"Access-Control-Allow-Methods", b"GET, POST, PUT, FOO"))
+        headers.append((b"Access-Control-Allow-Headers", b"x-test, x-foo"))
+        headers.append((
+            b"Access-Control-Expose-Headers",
+            b"x-request-method, x-request-content-type, x-request-query, x-request-content-length"))
+    headers.append((b"content-type", b"text/plain"))
 
-    filter_value = request.GET.first("filter_value", "")
-    filter_name = request.GET.first("filter_name", "").lower()
+    filter_value = request.GET.first(b"filter_value", b"")
+    filter_name = request.GET.first(b"filter_name", b"").lower()
     result = get_response(request.raw_headers, filter_value, filter_name)
 
     return headers, result