Skip to content

Commit 86d8438

Browse files
committed
fix: ext chunk
1 parent 9fb1d6e commit 86d8438

File tree

7 files changed

+50
-65
lines changed

7 files changed

+50
-65
lines changed

src/Std/Internal/Http/Protocol/H1.lean

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,6 @@ private def resetForNextMessage (machine : Machine ty) : Machine ty :=
247247
knownSize := none,
248248
messageHead := {},
249249
userClosedBody := false,
250-
canSendData := true,
251250
sentMessage := false
252251
},
253252
events := machine.events.push .next,
@@ -347,7 +346,7 @@ def closeReader (machine : Machine dir) : Machine dir :=
347346
/-- Signal that the writer cannot send more messages because the socket closed. -/
348347
@[inline]
349348
def closeWriter (machine : Machine dir) : Machine dir :=
350-
machine.modifyWriter ({ · with canSendData := false })
349+
machine.modifyWriter ({ · with state := .closed, userClosedBody := true })
351350

352351
/-- Signal that the user is not sending data anymore. -/
353352
@[inline]
@@ -416,16 +415,9 @@ def startNextCycle (machine : Machine dir) : Machine dir :=
416415
partial def processWrite (machine : Machine dir) : Machine dir :=
417416
match machine.writer.state with
418417
| .pending =>
419-
if ¬machine.writer.canSendData ∨ machine.isReaderClosed then
420-
machine.setWriterState .closed
421-
else
422-
machine
418+
machine
423419
| .waitingHeaders =>
424-
if ¬machine.writer.canSendData then
425-
machine.setWriterState .closed
426-
else
427-
machine.addEvent .needAnswer
428-
420+
machine.addEvent .needAnswer
429421
| .waitingForFlush =>
430422
if machine.shouldFlush then
431423
machine.setHeaders machine.writer.messageHead
@@ -553,25 +545,24 @@ partial def processRead (machine : Machine dir) : Machine dir :=
553545
match result with
554546
| some (size, ext) =>
555547
machine
556-
|>.setReaderState (.needChunkedBody size)
557-
|>.setEvent (some ext <&> .chunkExt)
548+
|>.setReaderState (.needChunkedBody ext size)
558549
|> processRead
559550
| none =>
560551
machine
561552

562-
| .needChunkedBody 0 =>
553+
| .needChunkedBody ext 0 =>
563554
let (machine, result) := parseWith machine (parseLastChunkBody machine.config) (limit := some 1)
564555

565556
match result with
566557
| some _ =>
567558
machine
568559
|>.setReaderState .complete
569-
|>.addEvent (.gotData true .empty)
560+
|>.addEvent (.gotData true ext .empty)
570561
|> processRead
571562
| none =>
572563
machine
573564

574-
| .needChunkedBody size =>
565+
| .needChunkedBody ext size =>
575566
let (machine, result) := parseWith machine
576567
(parseChunkedSizedData size) (limit := none) (some size)
577568

@@ -580,19 +571,19 @@ partial def processRead (machine : Machine dir) : Machine dir :=
580571
| .complete body =>
581572
machine
582573
|>.setReaderState .needChunkedSize
583-
|>.addEvent (.gotData false body)
574+
|>.addEvent (.gotData false ext body)
584575
|> processRead
585576
| .incomplete body remaining =>
586577
machine
587-
|>.setReaderState (.needChunkedBody remaining)
588-
|>.addEvent (.gotData false body)
578+
|>.setReaderState (.needChunkedBody ext remaining)
579+
|>.addEvent (.gotData false ext body)
589580
else
590581
machine
591582

592583
| .needFixedBody 0 =>
593584
machine
594585
|>.setReaderState .complete
595-
|>.addEvent (.gotData true .empty)
586+
|>.addEvent (.gotData true #[] .empty)
596587
|> processRead
597588

598589
| .needFixedBody size =>
@@ -603,20 +594,17 @@ partial def processRead (machine : Machine dir) : Machine dir :=
603594
| .complete body =>
604595
machine
605596
|>.setReaderState .complete
606-
|>.addEvent (.gotData true body)
597+
|>.addEvent (.gotData true #[] body)
607598
|> processRead
608599
| .incomplete body remaining =>
609600
machine
610601
|>.setReaderState (.needFixedBody remaining)
611-
|>.addEvent (.gotData false body)
602+
|>.addEvent (.gotData false #[] body)
612603
else
613604
machine
614605

615-
| .requireOutgoing _ =>
616-
machine
617-
618606
| .complete =>
619-
if ¬machine.keepAlive then
607+
if ¬machine.keepAlive ∨ machine.reader.noMoreInput then
620608
machine.setReaderState .closed
621609
else
622610
machine

src/Std/Internal/Http/Protocol/H1/Event.lean

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,6 @@ namespace Std.Http.Protocol.H1
2222
Events that can occur during HTTP message processing.
2323
-/
2424
inductive Event (dir : Direction)
25-
/--
26-
Event received when chunk extension data is encountered in chunked encoding.
27-
-/
28-
| chunkExt (ext : Array (String × Option String))
29-
3025
/--
3126
Event received when the headers end.
3227
-/
@@ -35,7 +30,7 @@ inductive Event (dir : Direction)
3530
/--
3631
Event received when some data arrives from the received message.
3732
-/
38-
| gotData (final : Bool) (data : ByteSlice)
33+
| gotData (final : Bool) (ext : Array (String × Option String)) (data : ByteSlice)
3934

4035
/--
4136
Event received when the input ends and more data is required to continue

src/Std/Internal/Http/Protocol/H1/Parser.lean

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@ def token (limit : Nat) : Parser ByteSlice :=
7878
takeWhileUpTo1 isTokenCharacter limit
7979

8080
@[inline]
81-
def crlf : Parser Unit :=
82-
skipBytes "\r\n".toUTF8
81+
def crlf : Parser Unit := do
82+
discard <| optional (skipByte '\r'.toUInt8)
83+
skipByte '\n'.toUInt8
8384

8485
@[inline]
8586
def rsp (limits : H1.Config) : Parser Unit :=
@@ -118,9 +119,16 @@ def parseHttpVersion : Parser Version := do
118119
opt <| Version.fromNumber? (major - 48 |>.toNat) (minor - 48 |>.toNat)
119120

120121
-- method = token
121-
def parseMethod (limits : H1.Config) : Parser Method := do
122-
let method ← token limits.maxMethodLength
123-
opt <| Method.fromString? =<< (String.fromUTF8? method.toByteArray)
122+
def parseMethod : Parser Method :=
123+
(skipBytes "GET".toUTF8 <&> fun _ => Method.get)
124+
<|> (skipBytes "HEAD".toUTF8 <&> fun _ => Method.head)
125+
<|> (attempt <| skipBytes "POST".toUTF8 <&> fun _ => Method.post)
126+
<|> (skipBytes "PUT".toUTF8 <&> fun _ => Method.put)
127+
<|> (skipBytes "DELETE".toUTF8 <&> fun _ => Method.delete)
128+
<|> (skipBytes "CONNECT".toUTF8 <&> fun _ => Method.connect)
129+
<|> (skipBytes "OPTIONS".toUTF8 <&> fun _ => Method.options)
130+
<|> (skipBytes "TRACE".toUTF8 <&> fun _ => Method.trace)
131+
<|> (skipBytes "PATCH".toUTF8 <&> fun _ => Method.patch)
124132

125133
def parseURI (limits : H1.Config) : Parser ByteArray := do
126134
let uri ← takeUntilUpTo (· == ' '.toUInt8) limits.maxUriLength
@@ -132,7 +140,7 @@ Parses a request line
132140
request-line = method SP request-target SP HTTP-version
133141
-/
134142
public def parseRequestLine (limits : H1.Config) : Parser Request.Head := do
135-
let method ← parseMethod limits <* rsp limits
143+
let method ← parseMethod <* rsp limits
136144
let uri ← parseURI limits <* rsp limits
137145

138146
let uri ← match (Std.Http.Parser.parseRequestTarget <* eof).run uri with
@@ -157,8 +165,12 @@ Parses a single header.
157165
158166
field-line CRLF / CRLF
159167
-/
160-
public def parseSingleHeader (limits : H1.Config) : Parser (Option (String × String)) :=
161-
optional (attempt <| parseFieldLine limits) <* crlf
168+
public def parseSingleHeader (limits : H1.Config) : Parser (Option (String × String)) := do
169+
if (← peek?) == some '\r'.toUInt8 ∨ (← peek?) == some '\n'.toUInt8 then
170+
crlf
171+
pure none
172+
else
173+
some <$> (parseFieldLine limits <* crlf)
162174

163175
-- quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
164176
def parseQuotedPair : Parser UInt8 := do

src/Std/Internal/Http/Protocol/H1/Reader.lean

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,13 @@ inductive Reader.State (dir : Direction) : Type
3737
/--
3838
State waiting for chunk body data of specified size.
3939
-/
40-
| needChunkedBody : Nat → State dir
40+
| needChunkedBody : Array (String × Option String) → Nat → State dir
4141

4242
/--
4343
State waiting for fixed-length body data of specified size.
4444
-/
4545
| needFixedBody : Nat → State dir
4646

47-
/--
48-
Requires the outgoing message to continue.
49-
-/
50-
| requireOutgoing : Body.Length → State dir
51-
5247
/--
5348
State that it completed a single request and can go to the next one
5449
-/

src/Std/Internal/Http/Protocol/H1/Writer.lean

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,6 @@ structure Writer (dir : Direction) where
103103
-/
104104
userClosedBody : Bool := false
105105

106-
/--
107-
Can send data to the output, it's used when the connection is closed and cannot send more data.
108-
-/
109-
canSendData : Bool := true
110-
111106
namespace Writer
112107

113108
/--

src/Std/Internal/Http/Server/Config.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ structure Config where
4444
/--
4545
Timeout for keep-alive connections
4646
-/
47-
keepAliveTimeout : { x : Time.Millisecond.Offset // 0 < x } := ⟨45000, by decide⟩
47+
keepAliveTimeout : { x : Time.Millisecond.Offset // 0 < x } := ⟨12000, by decide⟩
4848

4949
/--
5050
Maximum timeout time for request more data.
5151
-/
52-
requestTimeout : { x : Time.Millisecond.Offset // 0 < x } := ⟨10000, by decide⟩
52+
requestTimeout : { x : Time.Millisecond.Offset // 0 < x } := ⟨13000, by decide⟩
5353

5454
/--
5555
Whether to enable keep-alive connections by default.

src/Std/Internal/Http/Server/Connection.lean

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,6 @@ private def handle
131131
if step.output.size > 0 then
132132
Transport.sendAll socket step.output.data
133133

134-
if machine.reader.state == .closed ∧ ¬waitingResponse then
135-
machine := machine.closeWriter
136-
137134
for event in step.events do
138135
match event with
139136
| .needMoreData expect => do
@@ -157,8 +154,8 @@ private def handle
157154

158155
BaseIO.chainTask task fun x => discard <| response.resolve x
159156

160-
| .gotData final data =>
161-
discard <| requestStream.write data.toByteArray
157+
| .gotData final ext data =>
158+
requestStream.writeChunk { data := data.toByteArray, extensions := ext }
162159

163160
if final then
164161
requestStream.close
@@ -170,13 +167,10 @@ private def handle
170167
respStream := none
171168

172169
| .failed _ =>
173-
do pure ()
170+
pure ()
174171

175172
| .close =>
176-
do pure ()
177-
178-
| .chunkExt _=>
179-
do pure ()
173+
pure ()
180174

181175
if requiresData ∨ needAnswer ∨ respStream.isSome then
182176
let socket := if requiresData then some socket else none
@@ -204,18 +198,24 @@ private def handle
204198
machine := machine.closeReader
205199
if machine.isWaitingMessage ∧ waitingResponse then
206200
waitingResponse := false
207-
machine := machine.send { status := .requestTimeout }
201+
machine := machine.send { status := .requestTimeout, headers := .empty |>.insert (.new "connection") (.new "close") }
208202
machine := machine.userClosedBody
203+
machine := machine.noMoreInput
209204
respStream := none
210205
else
211206
machine := machine.closeWriter
207+
|>.noMoreInput
212208

213209
| .response (.error _) =>
214210
if machine.isWaitingMessage ∧ waitingResponse then
215211
waitingResponse := false
216-
machine := machine.send { status := .internalServerError }
212+
machine := machine.send { status := .internalServerError, headers := .empty |>.insert (.new "connection") (.new "close") }
217213
machine := machine.userClosedBody
218214
machine := machine.closeReader
215+
machine := machine.noMoreInput
216+
else
217+
machine := machine.closeWriter
218+
|>.noMoreInput
219219

220220
| .response (.ok res) =>
221221
machine := machine.send res.head

0 commit comments

Comments
 (0)