|
| 1 | +from lightbug_http.client import Client |
| 2 | +from lightbug_http.http import HTTPRequest, HTTPResponse |
| 3 | +from external.libc import ( |
| 4 | + c_void, |
| 5 | + c_int, |
| 6 | + c_uint, |
| 7 | + c_char, |
| 8 | + sockaddr, |
| 9 | + sockaddr_in, |
| 10 | + AF_INET, |
| 11 | + SOCK_STREAM, |
| 12 | + SHUT_RDWR, |
| 13 | + htons, |
| 14 | + inet_pton, |
| 15 | + to_char_ptr, |
| 16 | + socket, |
| 17 | + connect, |
| 18 | + send, |
| 19 | + recv, |
| 20 | + shutdown, |
| 21 | + close, |
| 22 | +) |
| 23 | + |
| 24 | +struct MojoClient(Client): |
| 25 | + var fd: c_int |
| 26 | + var name: String |
| 27 | + |
| 28 | + var host: StringLiteral |
| 29 | + var port: Int |
| 30 | + |
| 31 | + fn __init__(inout self) raises: |
| 32 | + self.fd = socket(AF_INET, SOCK_STREAM, 0) |
| 33 | + self.host = "127.0.0.1" |
| 34 | + self.port = 8888 |
| 35 | + self.name = "lightbug_http_client" |
| 36 | + |
| 37 | + fn __init__(inout self, host: StringLiteral, port: Int) raises: |
| 38 | + self.fd = socket(AF_INET, SOCK_STREAM, 0) |
| 39 | + self.host = host |
| 40 | + self.port = port |
| 41 | + self.name = "lightbug_http_client" |
| 42 | + |
| 43 | + fn close(self) raises: |
| 44 | + _ = shutdown(self.fd, SHUT_RDWR) |
| 45 | + var close_status = close(self.fd) |
| 46 | + if close_status == -1: |
| 47 | + print("Failed to close new_sockfd") |
| 48 | + |
| 49 | + fn do(self, req: HTTPRequest) raises -> HTTPResponse: |
| 50 | + var uri = req.uri() |
| 51 | + try: |
| 52 | + _ = uri.parse() |
| 53 | + except e: |
| 54 | + print("error parsing uri: " + e.__str__()) |
| 55 | + |
| 56 | + var host = String(uri.host()) |
| 57 | + |
| 58 | + if host == "": |
| 59 | + raise Error("URI is nil") |
| 60 | + var is_tls = False |
| 61 | + if uri.is_https(): |
| 62 | + is_tls = True |
| 63 | + |
| 64 | + var host_port = host.split(":") |
| 65 | + var host_str = host_port[0] |
| 66 | + |
| 67 | + var ip_buf = Pointer[c_void].alloc(4) |
| 68 | + var conv_status = inet_pton(AF_INET, to_char_ptr(host_str), ip_buf) |
| 69 | + var raw_ip = ip_buf.bitcast[c_uint]().load() |
| 70 | + |
| 71 | + var port = atol(host_port[1]) |
| 72 | + |
| 73 | + var bin_port = htons(UInt16(port)) |
| 74 | + |
| 75 | + var ai = sockaddr_in(AF_INET, bin_port, raw_ip, StaticTuple[c_char, 8]()) |
| 76 | + var ai_ptr = Pointer[sockaddr_in].address_of(ai).bitcast[sockaddr]() |
| 77 | + |
| 78 | + if connect(self.fd, ai_ptr, sizeof[sockaddr_in]()) == -1: |
| 79 | + _ = shutdown(self.fd, SHUT_RDWR) |
| 80 | + raise Error("Connection error") # Ensure to exit if connection fails |
| 81 | + |
| 82 | + var bytes_sent = send(self.fd, to_char_ptr(req.body_raw), len(req.body_raw), 0) |
| 83 | + if bytes_sent == -1: |
| 84 | + print("Failed to send message") |
| 85 | + |
| 86 | + var buf_size = 1024 |
| 87 | + var buf = Pointer[UInt8]().alloc(buf_size) |
| 88 | + var bytes_recv = recv(self.fd, buf, buf_size, 0) |
| 89 | + var bytes_str = String(buf.bitcast[Int8](), bytes_recv) |
| 90 | + _ = close(self.fd) |
| 91 | + |
| 92 | + return HTTPResponse(bytes_str._buffer) |
0 commit comments