add initial support for data scheme
This commit is contained in:
parent
015e46134e
commit
5f4826cc73
55
browser.py
55
browser.py
@ -8,6 +8,7 @@ SUPPORTED_SCHEMES = [
|
||||
"http",
|
||||
"https",
|
||||
"file",
|
||||
"data"
|
||||
]
|
||||
|
||||
DEFAULT_FILE = "default.html"
|
||||
@ -22,6 +23,9 @@ class URL:
|
||||
self.query: str = ""
|
||||
self.fragment: str = ""
|
||||
self.default_port = False
|
||||
self.media_type = ""
|
||||
self.media_encoding = ""
|
||||
self.data = ""
|
||||
if url_string is not None:
|
||||
parse_url(url_string, self)
|
||||
|
||||
@ -75,10 +79,13 @@ class Request:
|
||||
self.request_string += "\r\n"
|
||||
|
||||
def send_request(self, *args, **kwargs):
|
||||
if self.url.scheme in ["http", "https"]:
|
||||
return self.http_request(*args, **kwargs)
|
||||
elif self.url.scheme == "file":
|
||||
return self.file_request()
|
||||
if hasattr(self, f"{self.url.scheme.lower()}_request"):
|
||||
request = getattr(self, f"{self.url.scheme.lower()}_request")
|
||||
return request(*args, **kwargs)
|
||||
raise ValueError(f"scheme '{self.url.scheme}' is not supported.")
|
||||
|
||||
def https_request(self, *args, **kwargs):
|
||||
return self.http_request(*args, **kwargs)
|
||||
|
||||
def http_request(self, method: str = "GET", headers: dict = None) -> str:
|
||||
if headers is not None:
|
||||
@ -121,6 +128,9 @@ class Request:
|
||||
with open(self.url.path) as f:
|
||||
return f.read()
|
||||
|
||||
def data_request(self):
|
||||
return self.url.data
|
||||
|
||||
|
||||
def parse_url(url_string: str, url: URL | None = None) -> tuple[URL, bool]:
|
||||
has_authority = False
|
||||
@ -164,26 +174,29 @@ def parse_url(url_string: str, url: URL | None = None) -> tuple[URL, bool]:
|
||||
if url_string.startswith("#"):
|
||||
url.fragment = url_string[1:]
|
||||
|
||||
if url.scheme == "http":
|
||||
url.port = 80
|
||||
url.default_port = True
|
||||
elif url.scheme == "https":
|
||||
url.port = 443
|
||||
url.default_port = False
|
||||
match url.scheme:
|
||||
case "http":
|
||||
url.port = 80
|
||||
url.default_port = True
|
||||
case "https":
|
||||
url.port = 443
|
||||
url.default_port = False
|
||||
case "file":
|
||||
if sys.platform == "win32" and url.path.startswith("/") and ":" in url.path:
|
||||
url.path = url.path[1:]
|
||||
if url.path == "" or url.path == "/":
|
||||
return url, False
|
||||
case "data":
|
||||
if url.host != "":
|
||||
return url, False
|
||||
url.media_type, url.data = url.path.split(",", 1)
|
||||
if ";" in url.media_type:
|
||||
url.media_type, url.media_encoding = url.media_type.split(";", 1)
|
||||
|
||||
if url.scheme in ["http", "https"]:
|
||||
if url.path == "" or url.path is None:
|
||||
url.path = "/"
|
||||
if url.scheme == "file":
|
||||
print(f"{url.scheme=}")
|
||||
print(f"{url.host=}")
|
||||
print(f"{url.port=}")
|
||||
print(f"{url.path=}")
|
||||
print(f"{url.query=}")
|
||||
print(f"{url.fragment=}")
|
||||
if sys.platform == "win32" and url.path.startswith("/") and ":" in url.path:
|
||||
url.path = url.path[1:]
|
||||
if url.path == "" or url.path == "/":
|
||||
return url, False
|
||||
|
||||
|
||||
if ":" in url.host:
|
||||
url.host, port = url.host.split(":", 1)
|
||||
|
@ -147,6 +147,16 @@ from browser import Request
|
||||
"",
|
||||
True,
|
||||
),
|
||||
(
|
||||
"data:text,This is some text",
|
||||
"data",
|
||||
"",
|
||||
-1,
|
||||
"text,This is some text",
|
||||
"",
|
||||
"",
|
||||
True,
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_url_parsing(url_string, scheme, host, port, path, query, fragment, parse_success):
|
||||
@ -160,6 +170,40 @@ def test_url_parsing(url_string, scheme, host, port, path, query, fragment, pars
|
||||
assert success == parse_success
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"url_string,media_type,media_encoding,data,parse_success",
|
||||
[
|
||||
(
|
||||
"data:text,This is some text",
|
||||
"text",
|
||||
"",
|
||||
"This is some text",
|
||||
True,
|
||||
),
|
||||
(
|
||||
"data:text/plain,This is some text",
|
||||
"text/plain",
|
||||
"",
|
||||
"This is some text",
|
||||
True,
|
||||
),
|
||||
(
|
||||
"data:text/plain;base64,This is some text",
|
||||
"text/plain",
|
||||
"base64",
|
||||
"This is some text",
|
||||
True,
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_data_url_parsing(url_string, media_type, media_encoding, data, parse_success):
|
||||
url, success = parse_url(url_string)
|
||||
assert url.media_type == media_type
|
||||
assert url.media_encoding == media_encoding
|
||||
assert url.data == data
|
||||
assert success == parse_success
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"http_server,url_string",
|
||||
[
|
||||
|
Loading…
x
Reference in New Issue
Block a user