@@ -18,23 +18,19 @@ import NIOHTTP1
18
18
struct HTTPRequestStateMachine {
19
19
fileprivate enum State {
20
20
/// The initial state machine state. The only valid mutation is `start()`. The state will
21
- /// transition to `.verifyingRequest`
21
+ /// transitions to:
22
+ /// - `.waitForChannelToBecomeWritable`
23
+ /// - `.running(.streaming, .initialized)` (if the Channel is writable and if a request body is expected)
24
+ /// - `.running(.endSent, .initialized)` (if the Channel is writable and no request body is expected)
22
25
case initialized
23
- /// During this state the request's soundness is checked, before sending it out on the wire.
24
- /// Valid transitions are:
25
- /// - .waitForChannelToBecomeWritable (if the Channel is not writable)
26
- /// - .running(.streaming, .initialized) (if the Channel is writable and a request body is expected)
27
- /// - .running(.endSent, .initialized) (if the Channel is writable and no request body is expected)
28
- /// - .failed (if an error was found in the request soundness check)
29
- case verifyingRequest
30
26
/// Waiting for the channel to be writable. Valid transitions are:
31
- /// - .running(.streaming, .initialized) (once the Channel is writable again and if a request body is expected)
32
- /// - .running(.endSent, .initialized) (once the Channel is writable again and no request body is expected)
33
- /// - .failed (if a connection error occurred)
34
- case waitForChannelToBecomeWritable( HTTPRequestHead )
27
+ /// - ` .running(.streaming, .initialized)` (once the Channel is writable again and if a request body is expected)
28
+ /// - ` .running(.endSent, .initialized)` (once the Channel is writable again and no request body is expected)
29
+ /// - ` .failed` (if a connection error occurred)
30
+ case waitForChannelToBecomeWritable( HTTPRequestHead , RequestFramingMetadata )
35
31
/// A request is on the wire. Valid transitions are:
36
- /// - .finished
37
- /// - .failed
32
+ /// - ` .finished`
33
+ /// - ` .failed`
38
34
case running( RequestState , ResponseState )
39
35
/// The request has completed successfully
40
36
case finished
@@ -89,8 +85,6 @@ struct HTTPRequestStateMachine {
89
85
case none
90
86
}
91
87
92
- case verifyRequest
93
-
94
88
case sendRequestHead( HTTPRequestHead , startBody: Bool )
95
89
case sendBodyPart( IOData )
96
90
case sendRequestEnd
@@ -118,12 +112,17 @@ struct HTTPRequestStateMachine {
118
112
self . idleReadTimeout = idleReadTimeout
119
113
}
120
114
121
- mutating func start ( ) -> Action {
115
+ mutating func startRequest ( head : HTTPRequestHead , metadata : RequestFramingMetadata ) -> Action {
122
116
guard case . initialized = self . state else {
123
117
preconditionFailure ( " `start()` must be called first, and exactly once. Invalid state: \( self . state) " )
124
118
}
125
- self . state = . verifyingRequest
126
- return . verifyRequest
119
+
120
+ guard self . isChannelWritable else {
121
+ self . state = . waitForChannelToBecomeWritable( head, metadata)
122
+ return . wait
123
+ }
124
+
125
+ return self . startSendingRequest ( head: head, metadata: metadata)
127
126
}
128
127
129
128
mutating func writabilityChanged( writable: Bool ) -> Action {
@@ -139,15 +138,14 @@ struct HTTPRequestStateMachine {
139
138
140
139
switch self . state {
141
140
case . initialized,
142
- . verifyingRequest,
143
141
. running( . streaming( _, _, producer: . producing) , _) ,
144
142
. running( . endSent, _) ,
145
143
. finished,
146
144
. failed:
147
145
return . wait
148
146
149
- case . waitForChannelToBecomeWritable( let head) :
150
- return self . startSendingRequestHead ( head)
147
+ case . waitForChannelToBecomeWritable( let head, let metadata ) :
148
+ return self . startSendingRequest ( head: head , metadata : metadata )
151
149
152
150
case . running( . streaming( _, _, producer: . paused) , . receivingBody( let head, _) ) where head. status. code >= 300 :
153
151
// If we are receiving a response with a status of >= 300, we should not send out
@@ -172,7 +170,6 @@ struct HTTPRequestStateMachine {
172
170
173
171
switch self . state {
174
172
case . initialized,
175
- . verifyingRequest,
176
173
. waitForChannelToBecomeWritable,
177
174
. running( . streaming( _, _, producer: . paused) , _) ,
178
175
. running( . endSent, _) ,
@@ -194,7 +191,6 @@ struct HTTPRequestStateMachine {
194
191
mutating func readEventCaught( ) -> Action {
195
192
switch self . state {
196
193
case . initialized,
197
- . verifyingRequest,
198
194
. waitForChannelToBecomeWritable,
199
195
. running( _, . waitingForHead) ,
200
196
. running( _, . endReceived) ,
@@ -220,7 +216,7 @@ struct HTTPRequestStateMachine {
220
216
switch self . state {
221
217
case . initialized:
222
218
preconditionFailure ( " After the state machine has been initialized, start must be called immediately. Thus this state is unreachable " )
223
- case . verifyingRequest , . waitForChannelToBecomeWritable:
219
+ case . waitForChannelToBecomeWritable:
224
220
// the request failed, before it was sent onto the wire.
225
221
self . state = . failed( error)
226
222
return . failRequest( error, . none)
@@ -232,24 +228,10 @@ struct HTTPRequestStateMachine {
232
228
}
233
229
}
234
230
235
- mutating func requestVerified( _ head: HTTPRequestHead ) -> Action {
236
- guard case . verifyingRequest = self . state else {
237
- preconditionFailure ( " Invalid state: \( self . state) " )
238
- }
239
-
240
- guard self . isChannelWritable else {
241
- self . state = . waitForChannelToBecomeWritable( head)
242
- return . wait
243
- }
244
-
245
- return self . startSendingRequestHead ( head)
246
- }
247
-
248
231
mutating func requestStreamPartReceived( _ part: IOData ) -> Action {
249
232
switch self . state {
250
233
case . initialized,
251
234
. waitForChannelToBecomeWritable,
252
- . verifyingRequest,
253
235
. running( . endSent, _) :
254
236
preconditionFailure ( " We must be in the request streaming phase, if we receive further body parts. Invalid state: \( self . state) " )
255
237
@@ -310,7 +292,6 @@ struct HTTPRequestStateMachine {
310
292
mutating func requestStreamFinished( ) -> Action {
311
293
switch self . state {
312
294
case . initialized,
313
- . verifyingRequest,
314
295
. waitForChannelToBecomeWritable,
315
296
. running( . endSent, _) ,
316
297
. finished:
@@ -355,7 +336,7 @@ struct HTTPRequestStateMachine {
355
336
356
337
mutating func requestCancelled( ) -> Action {
357
338
switch self . state {
358
- case . initialized, . verifyingRequest , . waitForChannelToBecomeWritable:
339
+ case . initialized, . waitForChannelToBecomeWritable:
359
340
let error = HTTPClientError . cancelled
360
341
self . state = . failed( error)
361
342
return . failRequest( error, . none)
@@ -372,7 +353,7 @@ struct HTTPRequestStateMachine {
372
353
373
354
mutating func channelInactive( ) -> Action {
374
355
switch self . state {
375
- case . initialized, . verifyingRequest , . waitForChannelToBecomeWritable, . running:
356
+ case . initialized, . waitForChannelToBecomeWritable, . running:
376
357
let error = HTTPClientError . remoteConnectionClosed
377
358
self . state = . failed( error)
378
359
return . failRequest( error, . none)
@@ -388,7 +369,7 @@ struct HTTPRequestStateMachine {
388
369
389
370
mutating func receivedHTTPResponseHead( _ head: HTTPResponseHead ) -> Action {
390
371
switch self . state {
391
- case . initialized, . verifyingRequest , . waitForChannelToBecomeWritable:
372
+ case . initialized, . waitForChannelToBecomeWritable:
392
373
preconditionFailure ( " How can we receive a response head before sending a request head ourselves " )
393
374
394
375
case . running( . streaming( let expectedBodyLength, let sentBodyBytes, producer: . paused) , . waitingForHead) :
@@ -431,7 +412,7 @@ struct HTTPRequestStateMachine {
431
412
432
413
mutating func receivedHTTPResponseBodyPart( _ body: ByteBuffer ) -> Action {
433
414
switch self . state {
434
- case . initialized, . verifyingRequest , . waitForChannelToBecomeWritable:
415
+ case . initialized, . waitForChannelToBecomeWritable:
435
416
preconditionFailure ( " How can we receive a response head before sending a request head ourselves. Invalid state: \( self . state) " )
436
417
437
418
case . running( _, . waitingForHead) :
@@ -455,7 +436,7 @@ struct HTTPRequestStateMachine {
455
436
456
437
mutating func receivedHTTPResponseEnd( ) -> Action {
457
438
switch self . state {
458
- case . initialized, . verifyingRequest , . waitForChannelToBecomeWritable:
439
+ case . initialized, . waitForChannelToBecomeWritable:
459
440
preconditionFailure ( " How can we receive a response head before sending a request head ourselves. Invalid state: \( self . state) " )
460
441
461
442
case . running( _, . waitingForHead) :
@@ -496,7 +477,6 @@ struct HTTPRequestStateMachine {
496
477
mutating func forwardMoreBodyParts( ) -> Action {
497
478
switch self . state {
498
479
case . initialized,
499
- . verifyingRequest,
500
480
. running( _, . waitingForHead) ,
501
481
. waitForChannelToBecomeWritable:
502
482
preconditionFailure ( " The response is expected to only ask for more data after the response head was forwarded " )
@@ -520,7 +500,6 @@ struct HTTPRequestStateMachine {
520
500
mutating func idleReadTimeoutTriggered( ) -> Action {
521
501
switch self . state {
522
502
case . initialized,
523
- . verifyingRequest,
524
503
. waitForChannelToBecomeWritable,
525
504
. running( . streaming, _) :
526
505
preconditionFailure ( " We only schedule idle read timeouts after we have sent the complete request. Invalid state: \( self . state) " )
@@ -538,14 +517,16 @@ struct HTTPRequestStateMachine {
538
517
}
539
518
}
540
519
541
- private mutating func startSendingRequestHead( _ head: HTTPRequestHead ) -> Action {
542
- if let value = head. headers. first ( name: " content-length " ) , let length = Int ( value) , length > 0 {
543
- self . state = . running( . streaming( expectedBodyLength: length, sentBodyBytes: 0 , producer: . producing) , . waitingForHead)
544
- return . sendRequestHead( head, startBody: true )
545
- } else if head. headers. contains ( name: " transfer-encoding " ) {
520
+ private mutating func startSendingRequest( head: HTTPRequestHead , metadata: RequestFramingMetadata ) -> Action {
521
+ switch metadata. body {
522
+ case . stream:
546
523
self . state = . running( . streaming( expectedBodyLength: nil , sentBodyBytes: 0 , producer: . producing) , . waitingForHead)
547
524
return . sendRequestHead( head, startBody: true )
548
- } else {
525
+ case . fixedSize( let length) where length > 0 :
526
+ self . state = . running( . streaming( expectedBodyLength: length, sentBodyBytes: 0 , producer: . producing) , . waitingForHead)
527
+ return . sendRequestHead( head, startBody: true )
528
+ case . none, . fixedSize:
529
+ // fallback if fixed size is 0
549
530
self . state = . running( . endSent, . waitingForHead)
550
531
return . sendRequestHead( head, startBody: false )
551
532
}
@@ -557,8 +538,6 @@ extension HTTPRequestStateMachine: CustomStringConvertible {
557
538
switch self . state {
558
539
case . initialized:
559
540
return " HTTPRequestStateMachine(.initialized, isWritable: \( self . isChannelWritable) ) "
560
- case . verifyingRequest:
561
- return " HTTPRequestStateMachine(.verifyingRequest, isWritable: \( self . isChannelWritable) ) "
562
541
case . waitForChannelToBecomeWritable:
563
542
return " HTTPRequestStateMachine(.waitForChannelToBecomeWritable, isWritable: \( self . isChannelWritable) ) "
564
543
case . running( let requestState, let responseState) :
0 commit comments