2023-06-18 13:21:06 +02:00
|
|
|
import structio
|
|
|
|
import sys
|
|
|
|
import time
|
|
|
|
|
|
|
|
_print = print
|
|
|
|
|
|
|
|
|
|
|
|
def print(*args, **kwargs):
|
|
|
|
sys.stdout.write(f"[{time.strftime('%H:%M:%S')}] ")
|
|
|
|
_print(*args, **kwargs)
|
|
|
|
|
|
|
|
|
2023-06-28 14:33:50 +02:00
|
|
|
async def test(host: str, port: int, bufsize: int = 4096, keepalive: bool = False):
|
2023-08-20 12:38:07 +02:00
|
|
|
print(f"Attempting a connection to {host}:{port} {'in keep-alive mode' if keepalive else ''}")
|
|
|
|
socket = await structio.socket.connect_tcp_ssl_socket(host, port)
|
2023-06-19 14:53:08 +02:00
|
|
|
buffer = b""
|
2023-06-18 13:21:06 +02:00
|
|
|
print("Connected")
|
|
|
|
# Ensures the code below doesn't run for more than 5 seconds
|
|
|
|
with structio.skip_after(5) as scope:
|
|
|
|
# Closes the socket automatically
|
|
|
|
async with socket:
|
2023-08-20 12:38:07 +02:00
|
|
|
print("Entered socket context manager, sending HTTP request data")
|
2023-06-18 13:21:06 +02:00
|
|
|
await socket.send_all(
|
2023-08-20 12:38:07 +02:00
|
|
|
f"GET / HTTP/1.1\r\nUser-Agent: Structio/0.1.0\r\nAccept: */*\r\nHost: {host}"
|
2023-06-28 14:33:50 +02:00
|
|
|
f"\r\nAccept-Encoding: gzip, deflate, br\r\nConnection: {'close' if not keepalive else 'keep-alive'}"
|
|
|
|
f"\r\n\r\n".encode()
|
2023-06-18 13:21:06 +02:00
|
|
|
)
|
|
|
|
print("Data sent")
|
2023-06-19 14:53:08 +02:00
|
|
|
while True:
|
|
|
|
# We purposely do NOT check for the end of the response (\r\n) so that when the
|
|
|
|
# connection is in keep-alive mode we hang and let our timeout expire the whole
|
|
|
|
# block
|
2023-06-19 17:34:44 +02:00
|
|
|
print(
|
|
|
|
f"Requesting up to {bufsize} bytes (current response size: {len(buffer)})"
|
|
|
|
)
|
2023-06-18 13:21:06 +02:00
|
|
|
data = await socket.receive(bufsize)
|
|
|
|
if data:
|
|
|
|
print(f"Received {len(data)} bytes")
|
|
|
|
buffer += data
|
|
|
|
else:
|
|
|
|
print("Received empty stream, closing connection")
|
|
|
|
break
|
|
|
|
if buffer:
|
|
|
|
data = buffer.decode().split("\r\n")
|
2023-06-19 17:34:44 +02:00
|
|
|
print(
|
2023-08-22 08:11:01 +02:00
|
|
|
f"HTTP Response below {'(might be incomplete)' if scope.timed_out else ''}:"
|
2023-06-19 17:34:44 +02:00
|
|
|
)
|
2023-06-18 13:21:06 +02:00
|
|
|
_print(f"Response: {data[0]}")
|
|
|
|
_print("Headers:")
|
|
|
|
content = False
|
|
|
|
for i, element in enumerate(data):
|
|
|
|
if i == 0:
|
|
|
|
continue
|
|
|
|
else:
|
|
|
|
if not element.strip() and not content:
|
|
|
|
sys.stdout.write("\nContent:")
|
|
|
|
content = True
|
|
|
|
if not content:
|
|
|
|
_print(f"\t{element}")
|
|
|
|
else:
|
|
|
|
for line in element.split("\n"):
|
|
|
|
_print(f"\t{line}")
|
|
|
|
_print("Done!")
|
|
|
|
|
|
|
|
|
|
|
|
structio.run(test, "google.com", 443, 256)
|
2023-06-28 14:33:50 +02:00
|
|
|
# With keep-alive on, our timeout will kick in
|
|
|
|
structio.run(test, "google.com", 443, 256, True)
|