Skip to content

Commit 9b4e098

Browse files
committed
encode request sent with a client
1 parent dbb295c commit 9b4e098

File tree

7 files changed

+141
-20
lines changed

7 files changed

+141
-20
lines changed

lightbug_http/header.mojo

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,21 @@ struct RequestHeader:
4444
self.raw_headers = Bytes()
4545
self.__trailer = Bytes()
4646

47+
fn __init__(inout self, host: String) -> None:
48+
self.disable_normalization = False
49+
self.no_http_1_1 = False
50+
self.__connection_close = False
51+
self.content_length = 0
52+
self.content_length_bytes = Bytes()
53+
self.__method = Bytes()
54+
self.__request_uri = Bytes()
55+
self.proto = Bytes()
56+
self.__host = host._buffer
57+
self.__content_type = Bytes()
58+
self.__user_agent = Bytes()
59+
self.raw_headers = Bytes()
60+
self.__trailer = Bytes()
61+
4762
fn __init__(inout self, rawheaders: Bytes) -> None:
4863
self.disable_normalization = False
4964
self.no_http_1_1 = False

lightbug_http/http.mojo

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ struct HTTPRequest(Request):
8383
var disable_redirect_path_normalization: Bool
8484

8585
fn __init__(inout self, uri: URI):
86+
self.header = RequestHeader(String("127.0.0.1"))
87+
self.__uri = uri
88+
self.body_raw = Bytes()
89+
self.parsed_uri = False
90+
self.server_is_tls = False
91+
self.timeout = Duration()
92+
self.disable_redirect_path_normalization = False
93+
94+
fn __init__(inout self, uri: URI, headers: RequestHeader):
8695
self.header = RequestHeader()
8796
self.__uri = uri
8897
self.body_raw = Bytes()
@@ -227,6 +236,48 @@ fn OK(body: Bytes, content_type: String) -> HTTPResponse:
227236
)
228237

229238

239+
fn encode(req: HTTPRequest) raises -> Bytes:
240+
var res_str = String()
241+
var protocol = strHttp11
242+
var current_time = String()
243+
244+
var builder = StringBuilder()
245+
246+
_ = builder.write(req.header.method())
247+
_ = builder.write_string(String(" "))
248+
_ = builder.write(req.header.request_uri())
249+
_ = builder.write_string(String(" "))
250+
_ = builder.write(protocol)
251+
_ = builder.write_string(String("\r\n"))
252+
253+
_ = builder.write_string(String("Host: " + req.host()))
254+
_ = builder.write_string(String("\r\n"))
255+
256+
if len(req.body_raw) > 0:
257+
_ = builder.write_string(String("Content-Type: "))
258+
_ = builder.write(req.header.content_type())
259+
_ = builder.write_string(String("\r\n"))
260+
261+
_ = builder.write_string(String("Content-Length: "))
262+
_ = builder.write_string(String(len(req.body_raw)))
263+
_ = builder.write_string(String("\r\n"))
264+
265+
_ = builder.write_string(String("Connection: "))
266+
if req.connection_close():
267+
_ = builder.write_string(String("close"))
268+
else:
269+
_ = builder.write_string(String("keep-alive"))
270+
_ = builder.write_string(String("\r\n"))
271+
272+
_ = builder.write_string(String("\r\n"))
273+
if len(req.body_raw) > 0:
274+
_ = builder.write_string(String("\r\n"))
275+
_ = builder.write(req.body_raw)
276+
277+
# Currently the server is expecting a null terminated string for conn.send().
278+
return builder.get_null_terminated_bytes()
279+
280+
230281
fn encode(res: HTTPResponse) raises -> Bytes:
231282
var res_str = String()
232283
var protocol = strHttp11
@@ -236,38 +287,45 @@ fn encode(res: HTTPResponse) raises -> Bytes:
236287
except e:
237288
print("Error getting current time: " + str(e))
238289
current_time = str(now())
290+
239291
var builder = StringBuilder()
292+
240293
_ = builder.write(protocol)
241294
_ = builder.write_string(String(" "))
242295
_ = builder.write_string(String(res.header.status_code()))
243296
_ = builder.write_string(String(" "))
244297
_ = builder.write(res.header.status_message())
245298
_ = builder.write_string(String("\r\n"))
299+
246300
_ = builder.write_string(String("Server: lightbug_http"))
247301
_ = builder.write_string(String("\r\n"))
302+
248303
_ = builder.write_string(String("Content-Type: "))
249304
_ = builder.write(res.header.content_type())
305+
_ = builder.write_string(String("\r\n"))
306+
250307
# TODO: propagate charset
251308
# res_str += String("; charset=utf-8")
252-
_ = builder.write_string(String("\r\n"))
253-
_ = builder.write_string(String("Content-Length: "))
254-
# TODO: fix this
255-
_ = builder.write_string(String(len(res.body_raw)))
256-
_ = builder.write_string(String("\r\n"))
309+
310+
if len(res.body_raw) > 0:
311+
_ = builder.write_string(String("Content-Length: "))
312+
_ = builder.write_string(String(len(res.body_raw)))
313+
_ = builder.write_string(String("\r\n"))
314+
257315
_ = builder.write_string(String("Connection: "))
258316
if res.connection_close():
259317
_ = builder.write_string(String("close"))
260318
else:
261319
_ = builder.write_string(String("keep-alive"))
262320
_ = builder.write_string(String("\r\n"))
321+
263322
_ = builder.write_string(String("Date: "))
264323
_ = builder.write_string(String(current_time))
265-
_ = builder.write_string(String("\r\n"))
266-
_ = builder.write_string(String("\r\n"))
267-
# _ = builder.write_string("<div>hello frend</div>")
268-
# _ = builder.write(String("\r\n"))
269-
# _ = builder.write(res.body())
270-
_ = builder.write(res.body_raw)
324+
325+
if len(res.body_raw) > 0:
326+
_ = builder.write_string(String("\r\n"))
327+
_ = builder.write_string(String("\r\n"))
328+
_ = builder.write(res.body_raw)
271329

272330
# Currently the server is expecting a null terminated string for conn.send().
273331
return builder.get_null_terminated_bytes()

lightbug_http/strings.mojo

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ from lightbug_http.io.bytes import Bytes
22

33
alias strSlash = String("/").as_bytes()
44
alias strHttp = String("http").as_bytes()
5+
alias http = String("http")
56
alias strHttps = String("https").as_bytes()
7+
alias https = String("https")
68
alias strHttp11 = String("HTTP/1.1").as_bytes()
79
alias strHttp10 = String("HTTP/1.0").as_bytes()
810

lightbug_http/sys/client.mojo

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from lightbug_http.client import Client
2-
from lightbug_http.http import HTTPRequest, HTTPResponse
2+
from lightbug_http.http import HTTPRequest, HTTPResponse, encode
33
from lightbug_http.sys.net import create_connection
44
from lightbug_http.io.bytes import Bytes
55
from external.libc import (
@@ -71,6 +71,7 @@ struct MojoClient(Client):
7171
if host == "":
7272
raise Error("URI is nil")
7373
var is_tls = False
74+
7475
if uri.is_https():
7576
is_tls = True
7677

@@ -90,12 +91,14 @@ struct MojoClient(Client):
9091

9192
var conn = create_connection(self.fd, host_str, port)
9293

93-
var bytes_sent = conn.write(req.get_body())
94+
var req_encoded = encode(req)
95+
var bytes_sent = conn.write(req_encoded)
9496
if bytes_sent == -1:
9597
raise Error("Failed to send message")
9698

9799
var response: String = ""
98100
var new_buf = Bytes()
101+
99102
while True:
100103
var bytes_recv = conn.read(new_buf)
101104
if bytes_recv == -1:

lightbug_http/tests/run.mojo

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ from lightbug_http.sys.client import MojoClient
33
from lightbug_http.tests.test_client import (
44
test_python_client_lightbug,
55
test_mojo_client_lightbug,
6+
test_mojo_client_lightbug_external_req,
67
)
78

89

@@ -13,6 +14,7 @@ fn run_tests() raises:
1314
fn run_client_tests() raises:
1415
var py_client = PythonClient()
1516
var mojo_client = MojoClient()
17+
# test_mojo_client_lightbug_external_req(mojo_client)
1618
test_mojo_client_lightbug(mojo_client)
1719
test_python_client_lightbug(py_client)
1820

lightbug_http/tests/test_client.mojo

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import testing
22
from lightbug_http.python.client import PythonClient
33
from lightbug_http.sys.client import MojoClient
4-
from lightbug_http.http import HTTPRequest
4+
from lightbug_http.http import HTTPRequest, encode
55
from lightbug_http.uri import URI
66
from lightbug_http.header import RequestHeader
77
from external.morrow import Morrow
@@ -28,6 +28,17 @@ fn test_mojo_client_lightbug(client: MojoClient) raises:
2828
)
2929

3030

31+
fn test_mojo_client_lightbug_external_req(client: MojoClient) raises:
32+
var req = HTTPRequest(
33+
URI("http://grandinnerastoundingspell.neverssl.com/online/"),
34+
)
35+
try:
36+
var res = client.do(req)
37+
testing.assert_equal(res.header.status_code(), 200)
38+
except e:
39+
print(e)
40+
41+
3142
fn test_python_client_lightbug(client: PythonClient) raises:
3243
var res = client.do(
3344
HTTPRequest(

lightbug_http/uri.mojo

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ from lightbug_http.strings import (
44
strHttp11,
55
strHttp10,
66
strHttp,
7+
http,
78
strHttps,
9+
https,
810
)
911

1012

11-
# TODO: convenience type, not currently used properly but will be helpful in the future
13+
# TODO: this really needs refactoring
1214
@value
1315
struct URI:
1416
var __path_original: Bytes
@@ -17,6 +19,7 @@ struct URI:
1719
var __query_string: Bytes
1820
var __hash: Bytes
1921
var __host: Bytes
22+
var __http_version: Bytes
2023

2124
var disable_path_normalization: Bool
2225

@@ -35,7 +38,8 @@ struct URI:
3538
self.__path = Bytes()
3639
self.__query_string = Bytes()
3740
self.__hash = Bytes()
38-
self.__host = Bytes()
41+
self.__host = String("127.0.0.1")._buffer
42+
self.__http_version = Bytes()
3943
self.disable_path_normalization = False
4044
self.__full_uri = full_uri._buffer
4145
self.__request_uri = Bytes()
@@ -54,6 +58,7 @@ struct URI:
5458
self.__query_string = Bytes()
5559
self.__hash = Bytes()
5660
self.__host = host._buffer
61+
self.__http_version = Bytes()
5762
self.disable_path_normalization = False
5863
self.__full_uri = Bytes()
5964
self.__request_uri = Bytes()
@@ -68,6 +73,7 @@ struct URI:
6873
query_string: Bytes,
6974
hash: Bytes,
7075
host: Bytes,
76+
http_version: Bytes,
7177
disable_path_normalization: Bool,
7278
full_uri: Bytes,
7379
request_uri: Bytes,
@@ -80,6 +86,7 @@ struct URI:
8086
self.__query_string = query_string
8187
self.__hash = hash
8288
self.__host = host
89+
self.__http_version = http_version
8390
self.disable_path_normalization = disable_path_normalization
8491
self.__full_uri = full_uri
8592
self.__request_uri = request_uri
@@ -117,11 +124,24 @@ struct URI:
117124
processed_scheme = strHttp
118125
return processed_scheme
119126

127+
fn http_version(self) -> Bytes:
128+
return self.__http_version
129+
130+
fn set_http_version(inout self, http_version: String) -> Self:
131+
self.__http_version = http_version._buffer
132+
return self
133+
134+
fn is_http_1_1(self) -> Bool:
135+
return bytes_equal(self.__http_version, strHttp11)
136+
137+
fn is_http_1_0(self) -> Bool:
138+
return bytes_equal(self.__http_version, strHttp10)
139+
120140
fn is_https(self) -> Bool:
121-
return bytes_equal(self.__scheme, strHttps)
141+
return bytes_equal(self.__scheme, https._buffer)
122142

123143
fn is_http(self) -> Bool:
124-
return bytes_equal(self.__scheme, strHttp) or len(self.__scheme) == 0
144+
return bytes_equal(self.__scheme, http._buffer) or len(self.__scheme) == 0
125145

126146
fn set_request_uri(inout self, request_uri: String) -> Self:
127147
self.__request_uri = request_uri._buffer
@@ -171,7 +191,6 @@ struct URI:
171191
var n = raw_uri.rfind(" ")
172192
if n < 0:
173193
n = len(raw_uri)
174-
proto_str = strHttp10
175194
elif n == 0:
176195
raise Error("Request URI cannot be empty")
177196
else:
@@ -183,8 +202,15 @@ struct URI:
183202

184203
# Parse host from requestURI
185204
n = request_uri.find("://")
205+
206+
var is_https = False
207+
186208
if n >= 0:
187209
var host_and_port = request_uri[n + 3 :]
210+
211+
if request_uri[:n] == https:
212+
is_https = True
213+
188214
n = host_and_port.find("/")
189215
if n >= 0:
190216
self.__host = host_and_port[:n]._buffer
@@ -201,6 +227,11 @@ struct URI:
201227
self.__host = request_uri._buffer
202228
request_uri = strSlash
203229

230+
if is_https:
231+
_ = self.set_scheme(https)
232+
else:
233+
_ = self.set_scheme(http)
234+
204235
# Parse path
205236
n = request_uri.find("?")
206237
if n >= 0:
@@ -212,7 +243,6 @@ struct URI:
212243

213244
self.__path = normalise_path(self.__path_original, self.__path_original)
214245

215-
_ = self.set_scheme(proto_str)
216246
_ = self.set_request_uri(request_uri)
217247

218248
fn request_uri(self) -> Bytes:

0 commit comments

Comments
 (0)