@@ -28,6 +28,7 @@ import glisten/transport
2828
2929import gramps/websocket as ws
3030
31+ import ewe/internal/buffer . { type Buffer }
3132import ewe/internal/decoder . {
3233 AbsPath , HttpBin , HttpEoh , HttpHeader , HttpRequest , HttphBin , More , Packet ,
3334}
@@ -74,7 +75,7 @@ pub type Connection {
7475 Connection (
7576 transport : transport . Transport ,
7677 socket : socket . Socket ,
77- buffer : BitArray ,
78+ buffer : buffer . Buffer ,
7879 http_version : option . Option ( HttpVersion ) ,
7980 )
8081}
@@ -99,9 +100,9 @@ pub type UpgradeWebsocketError {
99100
100101// Chunked body parsing result
101102type BodyChunk {
102- Done ( rest : BitArray )
103+ Done ( rest : Buffer )
103104 Incomplete
104- Chunk ( BitArray , rest : BitArray )
105+ Chunk ( BitArray , rest : Buffer )
105106}
106107
107108// -----------------------------------------------------------------------------
@@ -120,20 +121,20 @@ pub fn transform_connection(connection: glisten.Connection(a)) -> Connection {
120121 Connection (
121122 transport : connection . transport ,
122123 socket : connection . socket ,
123- buffer : << >> ,
124+ buffer : buffer . empty ( ) ,
124125 http_version : option . None ,
125126 )
126127}
127128
128129/// Parses an HTTP request from the given buffer
129130pub fn parse_request (
130131 connection : Connection ,
131- buffer : BitArray ,
132+ buffer : Buffer ,
132133) -> Result ( Request ( Connection ) , ParseError ) {
133134 let transport = connection . transport
134135 let socket = connection . socket
135136
136- case decoder . decode_packet ( HttpBin , buffer , [ ] ) {
137+ case decoder . decode_packet ( HttpBin , buffer . data , [ ] ) {
137138 Ok ( Packet ( HttpRequest ( atom_method , AbsPath ( target ) , version ) , rest ) ) -> {
138139 // Request Line
139140 use method <- try (
@@ -157,7 +158,7 @@ pub fn parse_request(
157158 use # ( headers , rest ) <- try ( parse_headers (
158159 transport ,
159160 socket ,
160- rest ,
161+ buffer . new ( rest ) ,
161162 dict . new ( ) ,
162163 ) )
163164
@@ -185,7 +186,7 @@ pub fn parse_request(
185186 headers : dict . to_list ( headers ) ,
186187 body : Connection (
187188 .. connection ,
188- buffer : rest ,
189+ buffer : buffer . new ( rest ) ,
189190 http_version : option . Some ( version ) ,
190191 ) ,
191192 scheme : ,
@@ -198,15 +199,16 @@ pub fn parse_request(
198199 Ok ( More ( size ) ) -> {
199200 let read_size = option . unwrap ( size , 0 )
200201
201- use buffer <- try ( read_from_socket (
202+ let sized_buffer = buffer . sized ( connection . buffer , read_size )
203+
204+ use new_buffer <- try ( read_from_socket (
202205 transport ,
203206 socket ,
204- amount : read_size ,
205- buffer : connection . buffer ,
207+ sized_buffer ,
206208 on_error : MalformedRequest ,
207209 ) )
208210
209- parse_request ( connection , buffer )
211+ parse_request ( connection , new_buffer )
210212 }
211213 _ -> Error ( PacketDiscard )
212214 }
@@ -228,7 +230,7 @@ pub fn read_body(
228230
229231 case transfer_encoding {
230232 Ok ( "chunked" ) -> {
231- use # ( body , rest ) <- try ( read_chunked_body (
233+ use # ( body , rest_buffer ) <- try ( read_chunked_body (
232234 transport ,
233235 socket ,
234236 req . body . buffer ,
@@ -248,7 +250,7 @@ pub fn read_body(
248250 set . insert ( set , string . trim ( field ) |> string . lowercase ( ) )
249251 } )
250252
251- Ok ( handle_trailers ( req , set , rest ) )
253+ Ok ( handle_trailers ( req , set , rest_buffer ) )
252254 }
253255 Error ( Nil ) -> Ok ( req )
254256 }
@@ -261,19 +263,19 @@ pub fn read_body(
261263
262264 use <- bool . guard ( content_length > size_limit , Error ( BodyTooLarge ) )
263265
264- let left = content_length - bit_array . byte_size ( req . body . buffer )
266+ let left = content_length - bit_array . byte_size ( req . body . buffer . data )
265267
266268 case content_length , left {
267269 0 , 0 -> Ok ( << >> )
268- 0 , _l | _cl , 0 -> Ok ( req . body . buffer )
270+ 0 , _l | _cl , 0 -> Ok ( req . body . buffer . data )
269271 _cl , _l ->
270272 read_from_socket (
271273 transport ,
272274 socket ,
273- amount : left ,
274- buffer : req . body . buffer ,
275+ buffer : buffer . sized ( req . body . buffer , left ) ,
275276 on_error : InvalidBody ,
276277 )
278+ |> result . map ( fn ( buffer ) { buffer . data } )
277279 }
278280 |> result . map ( request . set_body ( req , _) )
279281 }
@@ -379,23 +381,21 @@ pub fn append_default_headers(
379381fn read_from_socket (
380382 transport : transport . Transport ,
381383 socket : socket . Socket ,
382- amount amount : Int ,
383- buffer buffer : BitArray ,
384+ buffer buffer : Buffer ,
384385 on_error on_error : ParseError ,
385- ) -> Result ( BitArray , ParseError ) {
386- let read_size = int . min ( amount , max_reading_size )
386+ ) -> Result ( Buffer , ParseError ) {
387+ let read_size = int . min ( buffer . remaining , max_reading_size )
387388
388389 use data <- try (
389390 transport . receive_timeout ( transport , socket , read_size , 10_000 )
390391 |> replace_error ( on_error ) ,
391392 )
392393
393- let amount = amount - read_size
394- let buffer = << buffer : bits , data : bits >>
394+ let new_buffer = buffer . append_size ( buffer , data , read_size )
395395
396- case amount > 0 {
397- True -> read_from_socket ( transport , socket , amount : , buffer : , on_error : )
398- False -> Ok ( buffer )
396+ case new_buffer . remaining {
397+ 0 -> Ok ( new_buffer )
398+ _ -> read_from_socket ( transport , socket , new_buffer , on_error : )
399399 }
400400}
401401
@@ -407,10 +407,10 @@ fn read_from_socket(
407407fn parse_headers (
408408 transport : transport . Transport ,
409409 socket : socket . Socket ,
410- buffer : BitArray ,
410+ buffer : Buffer ,
411411 headers : Dict ( String , String ) ,
412412) {
413- case decoder . decode_packet ( HttphBin , buffer , [ ] ) {
413+ case decoder . decode_packet ( HttphBin , buffer . data , [ ] ) {
414414 Ok ( Packet ( HttpEoh , rest ) ) -> Ok ( # ( headers , rest ) )
415415 Ok ( Packet ( HttpHeader ( idx , field , value ) , rest ) ) -> {
416416 use field <- try ( case decoder . formatted_field_by_idx ( idx ) {
@@ -427,21 +427,24 @@ fn parse_headers(
427427 |> replace_error ( InvalidHeaders ) ,
428428 )
429429
430+ let new_buffer = buffer . new ( rest )
431+
430432 insert_header ( headers , field , value )
431- |> parse_headers ( transport , socket , rest , _)
433+ |> parse_headers ( transport , socket , new_buffer , _)
432434 }
433435 Ok ( More ( size ) ) -> {
434436 let read_size = option . unwrap ( size , 0 )
435437
436- use buffer <- try ( read_from_socket (
438+ let sized_buffer = buffer . sized ( buffer , read_size )
439+
440+ use new_buffer <- try ( read_from_socket (
437441 transport ,
438442 socket ,
439- amount : read_size ,
440- buffer : ,
443+ sized_buffer ,
441444 on_error : InvalidHeaders ,
442445 ) )
443446
444- parse_headers ( transport , socket , buffer , headers )
447+ parse_headers ( transport , socket , new_buffer , headers )
445448 }
446449 _ -> Error ( InvalidHeaders )
447450 }
@@ -510,25 +513,31 @@ fn handle_continue(req: Request(Connection)) -> Result(Nil, ParseError) {
510513fn read_chunked_body (
511514 transport : transport . Transport ,
512515 socket : socket . Socket ,
513- buffer : BitArray ,
516+ buffer : Buffer ,
514517 body : BitArray ,
515518 size_limit : Int ,
516519 total_size : Int ,
517- ) -> Result ( # ( BitArray , BitArray ) , ParseError ) {
520+ ) -> Result ( # ( BitArray , Buffer ) , ParseError ) {
518521 use <- bool . guard ( total_size > size_limit , Error ( BodyTooLarge ) )
519522
520523 case parse_body_chunk ( buffer ) {
521524 Ok ( Done ( rest ) ) -> Ok ( # ( body , rest ) )
522525 Ok ( Incomplete ) -> {
523- use buffer <- try ( read_from_socket (
526+ use new_buffer <- try ( read_from_socket (
524527 transport ,
525528 socket ,
526- amount : 0 ,
527- buffer : ,
529+ buffer ,
528530 on_error : InvalidBody ,
529531 ) )
530532
531- read_chunked_body ( transport , socket , buffer , body , size_limit , total_size )
533+ read_chunked_body (
534+ transport ,
535+ socket ,
536+ new_buffer ,
537+ body ,
538+ size_limit ,
539+ total_size ,
540+ )
532541 }
533542 Ok ( Chunk ( chunk , rest ) ) -> {
534543 let body = << body : bits , chunk : bits >>
@@ -541,9 +550,9 @@ fn read_chunked_body(
541550}
542551
543552/// Parses a single chunk from the chunked body
544- fn parse_body_chunk ( buffer : BitArray ) -> Result ( BodyChunk , ParseError ) {
545- case split ( buffer , << "\r \n " >> , [ ] ) {
546- [ << "0" >> , rest ] -> Ok ( Done ( rest ) )
553+ fn parse_body_chunk ( buffer : Buffer ) -> Result ( BodyChunk , ParseError ) {
554+ case split ( buffer . data , << "\r \n " >> , [ ] ) {
555+ [ << "0" >> , rest ] -> Ok ( Done ( buffer . new ( rest ) ) )
547556 [ chunk_size , rest ] -> {
548557 use size <- try (
549558 bit_array . to_string ( chunk_size )
@@ -554,7 +563,7 @@ fn parse_body_chunk(buffer: BitArray) -> Result(BodyChunk, ParseError) {
554563 case split ( rest , << "\r \n " >> , [ ] ) {
555564 [ chunk , rest ] -> {
556565 case bit_array . byte_size ( chunk ) == size {
557- True -> Ok ( Chunk ( chunk , rest ) )
566+ True -> Ok ( Chunk ( chunk , buffer . new ( rest ) ) )
558567 False -> Error ( InvalidBody )
559568 }
560569 }
@@ -573,27 +582,29 @@ fn parse_body_chunk(buffer: BitArray) -> Result(BodyChunk, ParseError) {
573582fn handle_trailers (
574583 req : Request ( BitArray ) ,
575584 set : set . Set ( String ) ,
576- rest : BitArray ,
585+ rest : Buffer ,
577586) -> Request ( BitArray ) {
578- case decoder . decode_packet ( HttphBin , rest , [ ] ) {
587+ case decoder . decode_packet ( HttphBin , rest . data , [ ] ) {
579588 Ok ( Packet ( HttpEoh , _ ) ) -> req
580- Ok ( Packet ( HttpHeader ( idx , field , value ) , rest ) ) -> {
581- let field = case decoder . formatted_field_by_idx ( idx ) {
582- Ok ( field ) -> Ok ( field )
589+ Ok ( Packet ( HttpHeader ( idx , field , value ) , header_rest ) ) -> {
590+ let field_name = case decoder . formatted_field_by_idx ( idx ) {
591+ Ok ( field_name ) -> Ok ( field_name )
583592 Error ( Nil ) -> {
584593 bit_array . to_string ( field )
585594 |> result . map ( string . lowercase )
586595 }
587596 }
588597
589- case field {
590- Ok ( field ) -> {
591- case set . contains ( set , field ) && ! is_forbidden_trailer ( field ) {
598+ case field_name {
599+ Ok ( field_name ) -> {
600+ case
601+ set . contains ( set , field_name ) && ! is_forbidden_trailer ( field_name )
602+ {
592603 True -> {
593604 case bit_array . to_string ( value ) {
594605 Ok ( value ) -> {
595- request . set_header ( req , field , value )
596- |> handle_trailers ( set , rest )
606+ request . set_header ( req , field_name , value )
607+ |> handle_trailers ( set , buffer . new ( header_rest ) )
597608 }
598609 Error ( Nil ) -> handle_trailers ( req , set , rest )
599610 }
0 commit comments