Skip to content

Commit 936ea73

Browse files
committed
get a correct encoded request
1 parent 143d744 commit 936ea73

File tree

3 files changed

+79
-147
lines changed

3 files changed

+79
-147
lines changed

lightbug_http/header.mojo

Lines changed: 59 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -243,60 +243,58 @@ struct RequestHeader:
243243
fn headers(self) -> String:
244244
return String(self.raw_headers)
245245

246-
fn parse_raw(inout self, inout r: Reader) raises -> None:
246+
fn parse_raw(inout self, inout r: Reader) raises -> Int:
247247
var n = 1
248-
while True:
249-
var first_byte = r.peek(n)
250-
if len(first_byte) == 0:
251-
raise Error("Failed to read first byte from header")
252-
253-
var buf: Bytes
254-
var e: Error
255-
256-
buf, e = r.peek(r.buffered())
257-
if e:
258-
raise Error("Failed to read header: " + e.__str__())
259-
if len(buf) == 0:
260-
raise Error("Failed to read header")
261-
262-
var end_of_first_line = self.parse_first_line(buf)
248+
# while True:
249+
var first_byte = r.peek(n)
250+
if len(first_byte) == 0:
251+
raise Error("Failed to read first byte from header")
252+
253+
var buf: Bytes
254+
var e: Error
255+
256+
buf, e = r.peek(r.buffered())
257+
if e:
258+
raise Error("Failed to read header: " + e.__str__())
259+
if len(buf) == 0:
260+
raise Error("Failed to read header")
261+
262+
var end_of_first_line = self.parse_first_line(buf)
263263

264-
_ = self.read_raw_headers(buf[end_of_first_line:])
264+
var header_len = self.read_raw_headers(buf[end_of_first_line:])
265265

266-
_ = self.parse_headers(buf[end_of_first_line:])
267-
268-
# var end_of_first_line_headers = end_of_first_line + end_of_headers
266+
self.parse_headers(buf[end_of_first_line:])
267+
268+
return end_of_first_line + header_len
269269

270270
fn parse_first_line(inout self, buf: Bytes) raises -> Int:
271271
var b_next = buf
272272
var b = Bytes()
273-
274273
while len(b) == 0:
275274
try:
276275
b, b_next = next_line(b_next)
277276
except e:
278277
raise Error("Failed to read first line from request, " + e.__str__())
279278

280-
var n = index_byte(b, bytes(whitespace, pop=False)[0])
281-
if n <= 0:
279+
var first_whitespace = index_byte(b, bytes(whitespace, pop=False)[0])
280+
if first_whitespace <= 0:
282281
raise Error("Could not find HTTP request method in the request: " + String(b))
283282

284-
_ = self.set_method_bytes(b[:n])
285-
b = b[n + 1:]
283+
_ = self.set_method_bytes(b[:first_whitespace])
286284

287-
n = last_index_byte(b, bytes(whitespace, pop=False)[0])
288-
if n < 0:
289-
raise Error("Could not find whitespace in request line: " + String(b))
290-
elif n == 0:
285+
var last_whitespace = last_index_byte(b, bytes(whitespace, pop=False)[0]) + 1
286+
287+
if last_whitespace < 0:
288+
raise Error("Could not find last whitespace in request line: " + String(b))
289+
elif last_whitespace == 0:
291290
raise Error("Request URI is empty: " + String(b))
292291

293-
var proto = b[n + 1 :]
294-
292+
var proto = b[last_whitespace :]
295293
if len(proto) != len(bytes(strHttp11, pop=False)):
296294
raise Error("Invalid protocol, HTTP version not supported: " + String(proto))
297295

298296
_ = self.set_protocol_bytes(proto)
299-
_ = self.set_request_uri_bytes(b[:n - 2]) # without the null terminator
297+
_ = self.set_request_uri_bytes(b[first_whitespace+1:last_whitespace])
300298

301299
return len(buf) - len(b_next)
302300

@@ -349,7 +347,7 @@ struct RequestHeader:
349347
return
350348

351349
fn read_raw_headers(inout self, buf: Bytes) raises -> Int:
352-
var n = index_byte(buf, bytes(nChar, pop=False)[0]) # does this work?
350+
var n = index_byte(buf, bytes(nChar, pop=False)[0])
353351

354352
if n == -1:
355353
self.raw_headers = self.raw_headers[:0]
@@ -782,6 +780,7 @@ struct headerScanner:
782780
self.set_initialized()
783781

784782
var b_len = len(self.b())
783+
785784
if b_len >= 2 and (self.b()[0] == bytes(rChar, pop=False)[0]) and (self.b()[1] == bytes(nChar, pop=False)[0]):
786785
self.set_b(self.b()[2:])
787786
self.set_subslice_len(2)
@@ -792,69 +791,48 @@ struct headerScanner:
792791
self.set_subslice_len(self.subslice_len() + 1)
793792
return False
794793

795-
var n: Int
794+
var colon: Int
796795
if self.next_colon() >= 0:
797-
n = self.next_colon()
796+
colon = self.next_colon()
798797
self.set_next_colon(-1)
799798
else:
800-
n = index_byte(self.b(), bytes(colonChar, pop=False)[0])
801-
var x = index_byte(self.b(), bytes(nChar, pop=False)[0])
802-
if x > 0:
799+
colon = index_byte(self.b(), bytes(colonChar, pop=False)[0])
800+
var newline = index_byte(self.b(), bytes(nChar, pop=False)[0])
801+
if newline < 0:
803802
raise Error("Invalid header, did not find a newline at the end of the header")
804-
if x < n:
803+
if newline < colon:
805804
raise Error("Invalid header, found a newline before the colon")
806-
if n < 0:
805+
if colon < 0:
807806
raise Error("Invalid header, did not find a colon")
808807

809-
self.set_key(self.b()[:n])
810-
n += n
811-
while len(self.b()) > n and (self.b()[n] == bytes(whitespace, pop=False)[0]):
812-
n += 1
808+
var jump_to = colon + 1
809+
self.set_key(self.b()[:jump_to])
810+
811+
while len(self.b()) > jump_to and (self.b()[jump_to] == bytes(whitespace, pop=False)[0]):
812+
jump_to += 1
813813
self.set_next_line(self.next_line() - 1)
814814

815-
self.set_subslice_len(self.subslice_len() + n)
816-
self.set_b(self.b()[n:])
815+
self.set_subslice_len(self.subslice_len() + jump_to)
816+
self.set_b(self.b()[jump_to:])
817817

818818
if self.next_line() >= 0:
819-
n = self.next_line()
819+
jump_to = self.next_line()
820820
self.set_next_line(-1)
821821
else:
822-
n = index_byte(self.b(), bytes(nChar, pop=False)[0])
823-
if n < 0:
822+
jump_to = index_byte(self.b(), bytes(nChar, pop=False)[0])
823+
if jump_to < 0:
824824
raise Error("Invalid header, did not find a newline")
825825

826-
# var is_multi_line = False
827-
# while True:
828-
# if n + 1 >= len(self.b()):
829-
# break
830-
# if (self.b()[n + 1] != bytes(whitespace, pop=False)[0]) and (self.b()[n+1] != bytes(tab, pop=False)[0]):
831-
# break
832-
# var d = index_byte(self.b()[n + 1:], bytes(nChar, pop=False)[0])
833-
# if d <= 0:
834-
# break
835-
# elif d == 1 and (self.b()[n + 1] == bytes(rChar, pop=False)[0]):
836-
# break
837-
# var e = n + d + 1
838-
# var c = index_byte(self.b()[n+1:e], bytes(colonChar, pop=False)[0])
839-
# if c >= 0:
840-
# self.set_next_colon(c)
841-
# self.set_next_line(d - c - 1)
842-
# break
843-
# is_multi_line = True
844-
# n = e
845-
846-
self.set_value(self.b()[:n])
847-
self.set_subslice_len(self.subslice_len() + n + 1)
848-
self.set_b(self.b()[n + 1:])
849-
850-
if n > 0 and (self.value()[n-1] == bytes(rChar, pop=False)[0]):
851-
n -= 1
852-
while n > 0 and (self.value()[n-1] == bytes(whitespace, pop=False)[0]):
853-
n -= 1
854-
self.set_value(self.value()[:n])
855-
856-
# if is_multi_line:
857-
# normalize multi-line header values
826+
jump_to += 1
827+
self.set_value(self.b()[:jump_to])
828+
self.set_subslice_len(self.subslice_len() + jump_to)
829+
self.set_b(self.b()[jump_to:])
830+
831+
if jump_to > 0 and (self.value()[jump_to-1] == bytes(rChar, pop=False)[0]):
832+
jump_to -= 1
833+
while jump_to > 0 and (self.value()[jump_to-1] == bytes(whitespace, pop=False)[0]):
834+
jump_to -= 1
835+
self.set_value(self.value()[:jump_to])
858836

859837
return True
860838

lightbug_http/http.mojo

Lines changed: 11 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -165,62 +165,16 @@ struct HTTPRequest(Request):
165165
fn connection_close(self) -> Bool:
166166
return self.header.connection_close()
167167

168-
fn read_body(inout self, inout r: Reader, content_length: Int, max_body_size: Int) raises -> None:
169-
var body_buf = self.body_raw
170-
171-
if content_length == 0:
172-
return
173-
168+
fn read_body(inout self, inout r: Reader, content_length: Int, header_len: Int, max_body_size: Int) raises -> None:
174169
if content_length > max_body_size:
175170
raise Error("Request body too large")
176-
177-
var offset = len(body_buf)
178-
var dst_len = offset + content_length
179-
if dst_len > max_body_size:
180-
raise Error("Buffer overflow risk")
181-
182-
body_buf.resize(dst_len)
183-
184-
while offset < dst_len:
185-
var buffer_after_offset = body_buf[offset:]
186-
var read_length: Int
187-
var read_error: Error
188-
read_length, read_error = r.read(buffer_after_offset)
189-
if read_length <= 0:
190-
if read_error:
191-
raise read_error
192-
break
193-
offset += read_length
194-
195-
_ = self.set_body_bytes(body_buf[:offset])
196171

197-
# var body_buf = self.body_raw
198-
199-
# if content_length == 0:
200-
# return body_buf
201-
202-
# if max_body_size > 0 and content_length > max_body_size:
203-
# raise Error("Request body too large")
204-
205-
# if len(body_buf) > max_body_size:
206-
# raise Error("Request body too large")
207-
208-
# var offset = len(body_buf)
209-
# var dst_len = offset + content_length
210-
# if dst_len > max_body_size:
211-
# body_buf.resize(dst_len)
212-
213-
# while True:
214-
# var buffer_after_offset = body_buf[offset:]
215-
# var len: Int
216-
# len, _ = r.read(buffer_after_offset)
217-
# if len <= 0:
218-
# return body_buf[:offset]
219-
# offset += len
220-
# if offset == dst_len:
221-
# return body_buf
222-
172+
_ = r.discard(header_len)
223173

174+
var body_buf: Bytes
175+
body_buf, _ = r.peek(r.buffered())
176+
177+
_ = self.set_body_bytes(bytes(body_buf))
224178

225179
@value
226180
struct HTTPResponse(Response):
@@ -311,20 +265,18 @@ fn NotFound(path: String) -> HTTPResponse:
311265
ResponseHeader(404, bytes("Not Found"), bytes("text/plain")), bytes("path " + path + " not found"),
312266
)
313267

314-
fn encode(req: HTTPRequest, uri: URI) raises -> StringSlice[False, ImmutableStaticLifetime]:
268+
fn encode(req: HTTPRequest) raises -> StringSlice[False, ImmutableStaticLifetime]:
315269
var builder = StringBuilder()
316270

317271
_ = builder.write(req.header.method())
318272
_ = builder.write_string(whitespace)
319-
if len(uri.request_uri()) > 1:
320-
_ = builder.write(uri.request_uri())
273+
if len(req.header.request_uri()) > 1:
274+
_ = builder.write(req.header.request_uri())
321275
else:
322276
_ = builder.write_string(strSlash)
323277
_ = builder.write_string(whitespace)
324-
325-
# _ = builder.write(req.header.protocol())
326-
# hardcoded for now
327-
_ = builder.write_string("HTTP/1.1")
278+
279+
_ = builder.write(req.header.protocol())
328280

329281
_ = builder.write_string(rChar)
330282
_ = builder.write_string(nChar)

lightbug_http/sys/server.mojo

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,11 @@ struct SysServer:
185185
error = Error("Failed to read first byte from connection")
186186

187187
var header = RequestHeader()
188-
# var end_of_first_line_headers: Int
189-
188+
var first_line_and_headers_len = 0
190189
try:
191-
_ = header.parse_raw(reader)
190+
first_line_and_headers_len = header.parse_raw(reader)
192191
except e:
193192
error = Error("Failed to parse request headers: " + e.__str__())
194-
195193

196194
var uri = URI(self.address() + String(header.request_uri()))
197195
try:
@@ -209,15 +207,19 @@ struct SysServer:
209207
# var read_len = conn.read(remaining_body)
210208
# buf.extend(remaining_body)
211209
# remaining_len -= read_len
212-
210+
213211
var request = HTTPRequest(
214212
uri,
215213
Bytes(),
216214
header,
217215
)
218216

219-
_ = request.read_body(reader, header.content_length(), max_request_body_size)
220-
print(encode(request, uri))
217+
try:
218+
request.read_body(reader, header.content_length(), first_line_and_headers_len, max_request_body_size)
219+
except e:
220+
error = Error("Failed to read request body: " + e.__str__())
221+
222+
print(encode(request))
221223
var res = handler.func(request)
222224

223225
# if not self.tcp_keep_alive:

0 commit comments

Comments
 (0)