@@ -74,11 +74,31 @@ impl Http1Transaction for ServerTransaction {
74
74
75
75
fn decoder ( head : & MessageHead < Self :: Incoming > ) -> :: Result < Decoder > {
76
76
use :: header;
77
- if let Some ( & header:: ContentLength ( len) ) = head. headers . get ( ) {
77
+ // According to https://tools.ietf.org/html/rfc7230#section-3.3.3
78
+ // 1. (irrelevant to Request)
79
+ // 2. (irrelevant to Request)
80
+ // 3. Transfer-Encoding: chunked has a chunked body.
81
+ // 4. If multiple differing Content-Length headers or invalid, close connection.
82
+ // 5. Content-Length header has a sized body.
83
+ // 6. Length 0.
84
+ // 7. (irrelevant to Request)
85
+
86
+ if let Some ( & header:: TransferEncoding ( ref encodings) ) = head. headers . get ( ) {
87
+ // https://tools.ietf.org/html/rfc7230#section-3.3.3
88
+ // If Transfer-Encoding header is present, and 'chunked' is
89
+ // not the final encoding, and this is a Request, then it is
90
+ // mal-formed. A server should responsed with 400 Bad Request.
91
+ if encodings. last ( ) == Some ( & header:: Encoding :: Chunked ) {
92
+ Ok ( Decoder :: chunked ( ) )
93
+ } else {
94
+ debug ! ( "request with transfer-encoding header, but not chunked, bad request" ) ;
95
+ Err ( :: Error :: Header )
96
+ }
97
+ } else if let Some ( & header:: ContentLength ( len) ) = head. headers . get ( ) {
78
98
Ok ( Decoder :: length ( len) )
79
- } else if head. headers . has :: < header:: TransferEncoding > ( ) {
80
- //TODO: check for Transfer-Encoding: chunked
81
- Ok ( Decoder :: chunked ( ) )
99
+ } else if head. headers . has :: < header:: ContentLength > ( ) {
100
+ debug ! ( "illegal Content-Length: {:?}" , head . headers . get_raw ( "Content-Length" ) ) ;
101
+ Err ( :: Error :: Header )
82
102
} else {
83
103
Ok ( Decoder :: length ( 0 ) )
84
104
}
@@ -201,7 +221,7 @@ impl Http1Transaction for ClientTransaction {
201
221
// 3. Transfer-Encoding: chunked has a chunked body.
202
222
// 4. If multiple differing Content-Length headers or invalid, close connection.
203
223
// 5. Content-Length header has a sized body.
204
- // 6. Not Client.
224
+ // 6. (irrelevant to Response)
205
225
// 7. Read till EOF.
206
226
207
227
//TODO: need a way to pass the Method that caused this Response
@@ -223,7 +243,7 @@ impl Http1Transaction for ClientTransaction {
223
243
} else if let Some ( & header:: ContentLength ( len) ) = inc. headers . get ( ) {
224
244
Ok ( Decoder :: length ( len) )
225
245
} else if inc. headers . has :: < header:: ContentLength > ( ) {
226
- trace ! ( "illegal Content-Length: {:?}" , inc. headers. get_raw( "Content-Length" ) ) ;
246
+ debug ! ( "illegal Content-Length: {:?}" , inc. headers. get_raw( "Content-Length" ) ) ;
227
247
Err ( :: Error :: Header )
228
248
} else {
229
249
trace ! ( "neither Transfer-Encoding nor Content-Length" ) ;
@@ -396,6 +416,39 @@ mod tests {
396
416
assert_eq ! ( res. subject. 1 , "Howdy" ) ;
397
417
}
398
418
419
+
420
+ #[ test]
421
+ fn test_decoder_request ( ) {
422
+ use super :: Decoder ;
423
+
424
+ let mut head = MessageHead :: < :: http:: RequestLine > :: default ( ) ;
425
+
426
+ head. subject . 0 = :: Method :: Get ;
427
+ assert_eq ! ( Decoder :: length( 0 ) , ServerTransaction :: decoder( & head) . unwrap( ) ) ;
428
+ head. subject . 0 = :: Method :: Post ;
429
+ assert_eq ! ( Decoder :: length( 0 ) , ServerTransaction :: decoder( & head) . unwrap( ) ) ;
430
+
431
+ head. headers . set ( TransferEncoding :: chunked ( ) ) ;
432
+ assert_eq ! ( Decoder :: chunked( ) , ServerTransaction :: decoder( & head) . unwrap( ) ) ;
433
+ // transfer-encoding and content-length = chunked
434
+ head. headers . set ( ContentLength ( 10 ) ) ;
435
+ assert_eq ! ( Decoder :: chunked( ) , ServerTransaction :: decoder( & head) . unwrap( ) ) ;
436
+
437
+ head. headers . remove :: < TransferEncoding > ( ) ;
438
+ assert_eq ! ( Decoder :: length( 10 ) , ServerTransaction :: decoder( & head) . unwrap( ) ) ;
439
+
440
+ head. headers . set_raw ( "Content-Length" , vec ! [ b"5" . to_vec( ) , b"5" . to_vec( ) ] ) ;
441
+ assert_eq ! ( Decoder :: length( 5 ) , ServerTransaction :: decoder( & head) . unwrap( ) ) ;
442
+
443
+ head. headers . set_raw ( "Content-Length" , vec ! [ b"10" . to_vec( ) , b"11" . to_vec( ) ] ) ;
444
+ ServerTransaction :: decoder ( & head) . unwrap_err ( ) ;
445
+
446
+ head. headers . remove :: < ContentLength > ( ) ;
447
+
448
+ head. headers . set_raw ( "Transfer-Encoding" , "gzip" ) ;
449
+ ServerTransaction :: decoder ( & head) . unwrap_err ( ) ;
450
+ }
451
+
399
452
#[ test]
400
453
fn test_decoder_response ( ) {
401
454
use super :: Decoder ;
@@ -413,8 +466,11 @@ mod tests {
413
466
head. headers . set ( TransferEncoding :: chunked ( ) ) ;
414
467
assert_eq ! ( Decoder :: chunked( ) , ClientTransaction :: decoder( & head) . unwrap( ) ) ;
415
468
416
- head . headers . remove :: < TransferEncoding > ( ) ;
469
+ // transfer-encoding and content-length = chunked
417
470
head. headers . set ( ContentLength ( 10 ) ) ;
471
+ assert_eq ! ( Decoder :: chunked( ) , ClientTransaction :: decoder( & head) . unwrap( ) ) ;
472
+
473
+ head. headers . remove :: < TransferEncoding > ( ) ;
418
474
assert_eq ! ( Decoder :: length( 10 ) , ClientTransaction :: decoder( & head) . unwrap( ) ) ;
419
475
420
476
head. headers . set_raw ( "Content-Length" , vec ! [ b"5" . to_vec( ) , b"5" . to_vec( ) ] ) ;
0 commit comments