2024-11-25 21:27:45 -08:00
|
|
|
import socket
|
|
|
|
import ssl
|
|
|
|
|
|
|
|
|
|
|
|
class URL:
|
|
|
|
def __init__(self, url: str):
|
|
|
|
self.scheme, url = url.split("://", 1)
|
|
|
|
assert self.scheme in ["http", "https"]
|
|
|
|
if "/" not in url:
|
|
|
|
url = url + "/"
|
|
|
|
self.host, url = url.split("/", 1)
|
|
|
|
self.path = "/" + url
|
|
|
|
|
|
|
|
if self.scheme == "http":
|
|
|
|
self.port = 80
|
|
|
|
elif self.scheme == "https":
|
|
|
|
self.port = 443
|
|
|
|
|
|
|
|
if ":" in self.host:
|
|
|
|
self.host, port = self.host.split(":", 1)
|
|
|
|
self.port = int(port)
|
|
|
|
|
|
|
|
def request(self) -> str:
|
|
|
|
s = socket.socket(
|
|
|
|
family=socket.AF_INET,
|
|
|
|
type=socket.SOCK_STREAM,
|
|
|
|
proto=socket.IPPROTO_TCP,
|
|
|
|
)
|
|
|
|
s.connect((self.host, self.port))
|
|
|
|
if self.scheme == "https":
|
2024-11-27 19:36:39 -08:00
|
|
|
ssl.create_default_context()
|
|
|
|
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
|
2024-11-25 21:27:45 -08:00
|
|
|
s = context.wrap_socket(s, server_hostname=self.host)
|
|
|
|
|
|
|
|
request_str = f"GET {self.path} HTTP/1.0\r\n"
|
|
|
|
request_str += f"Host: {self.host}\r\n"
|
|
|
|
request_str += "\r\n"
|
|
|
|
s.send(request_str.encode("utf8"))
|
|
|
|
|
|
|
|
response = s.makefile("r", encoding="utf8", newline="\r\n")
|
|
|
|
status_line = response.readline()
|
|
|
|
version, status, explanation = status_line.split(" ", 2)
|
|
|
|
|
|
|
|
response_headers = {}
|
|
|
|
while True:
|
|
|
|
line = response.readline()
|
|
|
|
if line == "\r\n":
|
|
|
|
break
|
|
|
|
header, value = line.split(":", 1)
|
|
|
|
response_headers[header.casefold()] = value.strip()
|
|
|
|
|
|
|
|
assert "transfer-encoding" not in response_headers
|
|
|
|
assert "content-encoding" not in response_headers
|
|
|
|
|
|
|
|
content = response.read()
|
|
|
|
s.close()
|
|
|
|
return content
|
|
|
|
|
|
|
|
|
|
|
|
def show(body: str) -> None:
|
|
|
|
in_tag = False
|
|
|
|
for char in body:
|
|
|
|
if char == "<":
|
|
|
|
in_tag = True
|
|
|
|
elif char == ">":
|
|
|
|
in_tag = False
|
|
|
|
elif not in_tag:
|
|
|
|
print(char, end="")
|
|
|
|
|
|
|
|
|
|
|
|
def load(url: URL):
|
|
|
|
body = url.request()
|
|
|
|
show(body)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
import sys
|
|
|
|
load(URL(sys.argv[1]))
|