add initial support for data scheme
This commit is contained in:
parent
015e46134e
commit
5f4826cc73
43
browser.py
43
browser.py
@ -8,6 +8,7 @@ SUPPORTED_SCHEMES = [
|
|||||||
"http",
|
"http",
|
||||||
"https",
|
"https",
|
||||||
"file",
|
"file",
|
||||||
|
"data"
|
||||||
]
|
]
|
||||||
|
|
||||||
DEFAULT_FILE = "default.html"
|
DEFAULT_FILE = "default.html"
|
||||||
@ -22,6 +23,9 @@ class URL:
|
|||||||
self.query: str = ""
|
self.query: str = ""
|
||||||
self.fragment: str = ""
|
self.fragment: str = ""
|
||||||
self.default_port = False
|
self.default_port = False
|
||||||
|
self.media_type = ""
|
||||||
|
self.media_encoding = ""
|
||||||
|
self.data = ""
|
||||||
if url_string is not None:
|
if url_string is not None:
|
||||||
parse_url(url_string, self)
|
parse_url(url_string, self)
|
||||||
|
|
||||||
@ -75,10 +79,13 @@ class Request:
|
|||||||
self.request_string += "\r\n"
|
self.request_string += "\r\n"
|
||||||
|
|
||||||
def send_request(self, *args, **kwargs):
|
def send_request(self, *args, **kwargs):
|
||||||
if self.url.scheme in ["http", "https"]:
|
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)
|
return self.http_request(*args, **kwargs)
|
||||||
elif self.url.scheme == "file":
|
|
||||||
return self.file_request()
|
|
||||||
|
|
||||||
def http_request(self, method: str = "GET", headers: dict = None) -> str:
|
def http_request(self, method: str = "GET", headers: dict = None) -> str:
|
||||||
if headers is not None:
|
if headers is not None:
|
||||||
@ -121,6 +128,9 @@ class Request:
|
|||||||
with open(self.url.path) as f:
|
with open(self.url.path) as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
|
|
||||||
|
def data_request(self):
|
||||||
|
return self.url.data
|
||||||
|
|
||||||
|
|
||||||
def parse_url(url_string: str, url: URL | None = None) -> tuple[URL, bool]:
|
def parse_url(url_string: str, url: URL | None = None) -> tuple[URL, bool]:
|
||||||
has_authority = False
|
has_authority = False
|
||||||
@ -164,26 +174,29 @@ def parse_url(url_string: str, url: URL | None = None) -> tuple[URL, bool]:
|
|||||||
if url_string.startswith("#"):
|
if url_string.startswith("#"):
|
||||||
url.fragment = url_string[1:]
|
url.fragment = url_string[1:]
|
||||||
|
|
||||||
if url.scheme == "http":
|
match url.scheme:
|
||||||
|
case "http":
|
||||||
url.port = 80
|
url.port = 80
|
||||||
url.default_port = True
|
url.default_port = True
|
||||||
elif url.scheme == "https":
|
case "https":
|
||||||
url.port = 443
|
url.port = 443
|
||||||
url.default_port = False
|
url.default_port = False
|
||||||
if url.scheme in ["http", "https"]:
|
case "file":
|
||||||
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:
|
if sys.platform == "win32" and url.path.startswith("/") and ":" in url.path:
|
||||||
url.path = url.path[1:]
|
url.path = url.path[1:]
|
||||||
if url.path == "" or url.path == "/":
|
if url.path == "" or url.path == "/":
|
||||||
return url, False
|
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 ":" in url.host:
|
if ":" in url.host:
|
||||||
url.host, port = url.host.split(":", 1)
|
url.host, port = url.host.split(":", 1)
|
||||||
|
@ -147,6 +147,16 @@ from browser import Request
|
|||||||
"",
|
"",
|
||||||
True,
|
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):
|
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
|
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(
|
@pytest.mark.parametrize(
|
||||||
"http_server,url_string",
|
"http_server,url_string",
|
||||||
[
|
[
|
||||||
|
Loading…
x
Reference in New Issue
Block a user