@@ -42,32 +42,14 @@ class RequestValidationTests: XCTestCase {
4242 XCTAssertEqual ( headers. first ( name: " Content-Length " ) , " 200 " )
4343 }
4444
45- func testChunkedEncodingDoesNotHaveContentLengthHeader( ) {
46- var headers = HTTPHeaders ( [
47- ( " Content-Length " , " 200 " ) ,
48- ( " Transfer-Encoding " , " chunked " ) ,
49- ] )
50- var buffer = ByteBufferAllocator ( ) . buffer ( capacity: 200 )
51- buffer. writeBytes ( [ UInt8] ( repeating: 12 , count: 200 ) )
52- XCTAssertNoThrow ( try headers. validate ( method: . PUT, body: . byteBuffer( buffer) ) )
53-
54- // https://tools.ietf.org/html/rfc7230#section-3.3.2
55- // A sender MUST NOT send a Content-Length header field in any message
56- // that contains a Transfer-Encoding header field.
57-
58- XCTAssertNil ( headers. first ( name: " Content-Length " ) )
59- XCTAssertEqual ( headers. first ( name: " Transfer-Encoding " ) , " chunked " )
60- }
61-
6245 func testTRACERequestMustNotHaveBody( ) {
63- var headers = HTTPHeaders ( [
64- ( " Content-Length " , " 200 " ) ,
65- ( " Transfer-Encoding " , " chunked " ) ,
66- ] )
67- var buffer = ByteBufferAllocator ( ) . buffer ( capacity: 200 )
68- buffer. writeBytes ( [ UInt8] ( repeating: 12 , count: 200 ) )
69- XCTAssertThrowsError ( try headers. validate ( method: . TRACE, body: . byteBuffer( buffer) ) ) {
70- XCTAssertEqual ( $0 as? HTTPClientError , . traceRequestWithBody)
46+ for header in [ ( " Content-Length " , " 200 " ) , ( " Transfer-Encoding " , " chunked " ) ] {
47+ var headers = HTTPHeaders ( [ header] )
48+ var buffer = ByteBufferAllocator ( ) . buffer ( capacity: 200 )
49+ buffer. writeBytes ( [ UInt8] ( repeating: 12 , count: 200 ) )
50+ XCTAssertThrowsError ( try headers. validate ( method: . TRACE, body: . byteBuffer( buffer) ) ) {
51+ XCTAssertEqual ( $0 as? HTTPClientError , . traceRequestWithBody)
52+ }
7153 }
7254 }
7355
@@ -105,13 +87,178 @@ class RequestValidationTests: XCTestCase {
10587 XCTAssertNoThrow ( try headers. validate ( method: . GET, body: nil ) )
10688 }
10789
108- func testMultipleContentLengthOnNilStreamLength( ) {
109- var headers = HTTPHeaders ( [ ( " Content-Length " , " 1 " ) , ( " Content-Length " , " 2 " ) ] )
110- var buffer = ByteBufferAllocator ( ) . buffer ( capacity: 10 )
111- buffer. writeBytes ( [ UInt8] ( repeating: 12 , count: 10 ) )
112- let body : HTTPClient . Body = . stream { writer in
113- writer. write ( . byteBuffer( buffer) )
90+ // MARK: - Content-Length/Transfer-Encoding Matrix
91+
92+ // Method kind User sets Body Expectation
93+ // ----------------------------------------------------------------------------------
94+ // .GET, .HEAD, .DELETE, .CONNECT, .TRACE nothing nil Neither CL nor chunked
95+ // other nothing nil chunked
96+ func testNoHeadersNoBody( ) throws {
97+ for method : HTTPMethod in [ . GET, . HEAD, . DELETE, . CONNECT, . TRACE] {
98+ var headers : HTTPHeaders = . init( )
99+ XCTAssertNoThrow ( try headers. validate ( method: method, body: nil ) )
100+ XCTAssertTrue ( headers [ " content-length " ] . isEmpty)
101+ XCTAssertTrue ( headers [ " transfer-encoding " ] . isEmpty)
102+ }
103+
104+ for method : HTTPMethod in [ . POST, . PUT] {
105+ var headers : HTTPHeaders = . init( )
106+ XCTAssertNoThrow ( try headers. validate ( method: method, body: nil ) )
107+ // TODO: This should be CL=0 ??? https://tools.ietf.org/html/rfc7230#section-3.3.2
108+ XCTAssertTrue ( headers [ " content-length " ] . isEmpty)
109+ XCTAssertTrue ( headers [ " transfer-encoding " ] . contains ( " chunked " ) )
110+ }
111+ }
112+
113+ // Method kind User sets Body Expectation
114+ // --------------------------------------------------------------------------------------
115+ // .GET, .HEAD, .DELETE, .CONNECT, .TRACE nothing not nil Neither CL nor chunked
116+ // other nothing not nil chunked
117+ func testNoHeadersHasBody( ) throws {
118+ for method : HTTPMethod in [ . GET, . HEAD, . DELETE, . CONNECT] {
119+ var headers : HTTPHeaders = . init( )
120+ XCTAssertNoThrow ( try headers. validate ( method: method, body: . byteBuffer( ByteBuffer ( bytes: [ 0 ] ) ) ) )
121+
122+ // TODO: Logically, this should be a Content-Length: 1
123+
124+ XCTAssertTrue ( headers [ " content-length " ] . isEmpty)
125+ XCTAssertTrue ( headers [ " transfer-encoding " ] . isEmpty)
126+ }
127+
128+ for method : HTTPMethod in [ . POST, . PUT] {
129+ var headers : HTTPHeaders = . init( )
130+ XCTAssertNoThrow ( try headers. validate ( method: method, body: . byteBuffer( ByteBuffer ( bytes: [ 0 ] ) ) ) )
131+
132+ // TODO: Logically, this should be a Content-Length: 1 since we know size, or chunked if we don't
133+
134+ XCTAssertTrue ( headers [ " content-length " ] . isEmpty)
135+ XCTAssertTrue ( headers [ " transfer-encoding " ] . contains ( " chunked " ) )
136+ }
137+
138+ for method : HTTPMethod in [ . POST, . PUT] {
139+ var headers : HTTPHeaders = . init( )
140+ let body : HTTPClient . Body = . stream { writer in
141+ writer. write ( . byteBuffer( ByteBuffer ( bytes: [ 0 ] ) ) )
142+ }
143+ XCTAssertNoThrow ( try headers. validate ( method: method, body: body) )
144+
145+ // TODO: Logically, this should be a Content-Length: 1 since we know size, or chunked if we don't
146+
147+ XCTAssertTrue ( headers [ " content-length " ] . isEmpty)
148+ XCTAssertTrue ( headers [ " transfer-encoding " ] . contains ( " chunked " ) )
149+ }
150+ }
151+
152+ // Method kind User sets Body Expectation
153+ // ------------------------------------------------------------------------------
154+ // .GET, .HEAD, .DELETE, .CONNECT, .TRACE content-length nil CL=0
155+ // other content-length nil CL=0
156+ func testContentLengthHeaderNoBody( ) throws {
157+ for method : HTTPMethod in [ . GET, . HEAD, . DELETE, . CONNECT, . TRACE] {
158+ var headers : HTTPHeaders = . init( [ ( " Content-Length " , " 1 " ) ] )
159+ XCTAssertNoThrow ( try headers. validate ( method: method, body: nil ) )
160+ // TODO: this should be Neither CL nor chunked https://tools.ietf.org/html/rfc7230#section-3.3.2
161+ XCTAssertEqual ( headers [ " content-length " ] . first, " 0 " )
162+ XCTAssertTrue ( headers [ " transfer-encoding " ] . isEmpty)
163+ }
164+
165+ for method : HTTPMethod in [ . POST, . PUT] {
166+ var headers : HTTPHeaders = . init( [ ( " Content-Length " , " 1 " ) ] )
167+ XCTAssertNoThrow ( try headers. validate ( method: method, body: nil ) )
168+ XCTAssertEqual ( headers [ " content-length " ] . first, " 0 " )
169+ XCTAssertTrue ( headers [ " transfer-encoding " ] . isEmpty)
170+ }
171+ }
172+
173+ // Method kind User sets Body Expectation
174+ // ----------------------------------------------------------------------------------
175+ // .GET, .HEAD, .DELETE, .CONNECT, .TRACE content-length not nil CL=1
176+ // other content-length nit nil CL=1
177+ func testContentLengthHeaderHasBody( ) throws {
178+ for method : HTTPMethod in [ . GET, . HEAD, . DELETE, . CONNECT] {
179+ var headers : HTTPHeaders = . init( [ ( " Content-Length " , " 1 " ) ] )
180+ XCTAssertNoThrow ( try headers. validate ( method: method, body: . byteBuffer( ByteBuffer ( bytes: [ 0 ] ) ) ) )
181+ XCTAssertEqual ( headers [ " content-length " ] . first, " 1 " )
182+ XCTAssertTrue ( headers [ " transfer-encoding " ] . isEmpty)
183+ }
184+
185+ for method : HTTPMethod in [ . POST, . PUT] {
186+ var headers : HTTPHeaders = . init( [ ( " Content-Length " , " 1 " ) ] )
187+ XCTAssertNoThrow ( try headers. validate ( method: method, body: . byteBuffer( ByteBuffer ( bytes: [ 0 ] ) ) ) )
188+ XCTAssertEqual ( headers [ " content-length " ] . first, " 1 " )
189+ XCTAssertTrue ( headers [ " transfer-encoding " ] . isEmpty)
190+ }
191+ }
192+
193+ // Method kind User sets Body Expectation
194+ // ------------------------------------------------------------------------------------------
195+ // .GET, .HEAD, .DELETE, .CONNECT, .TRACE transfer-encoding: chunked nil chunked
196+ // other transfer-encoding: chunked nil chunked
197+ func testTransferEncodingHeaderNoBody( ) throws {
198+ for method : HTTPMethod in [ . GET, . HEAD, . DELETE, . CONNECT, . TRACE] {
199+ var headers : HTTPHeaders = . init( [ ( " Transfer-Encoding " , " chunked " ) ] )
200+ XCTAssertNoThrow ( try headers. validate ( method: method, body: nil ) )
201+ XCTAssertTrue ( headers [ " content-length " ] . isEmpty)
202+ XCTAssertTrue ( headers [ " transfer-encoding " ] . contains ( " chunked " ) )
203+ }
204+
205+ for method : HTTPMethod in [ . POST, . PUT] {
206+ var headers : HTTPHeaders = . init( [ ( " Transfer-Encoding " , " chunked " ) ] )
207+ XCTAssertNoThrow ( try headers. validate ( method: method, body: nil ) )
208+ XCTAssertTrue ( headers [ " content-length " ] . isEmpty)
209+ XCTAssertTrue ( headers [ " transfer-encoding " ] . contains ( " chunked " ) )
210+ }
211+ }
212+
213+ // Method kind User sets Body Expectation
214+ // --------------------------------------------------------------------------------------
215+ // .GET, .HEAD, .DELETE, .CONNECT transfer-encoding: chunked not nil chunked
216+ // other transfer-encoding: chunked not nil chunked
217+ func testTransferEncodingHeaderHasBody( ) throws {
218+ for method : HTTPMethod in [ . GET, . HEAD, . DELETE, . CONNECT] {
219+ var headers : HTTPHeaders = . init( [ ( " Transfer-Encoding " , " chunked " ) ] )
220+ XCTAssertNoThrow ( try headers. validate ( method: method, body: . byteBuffer( ByteBuffer ( bytes: [ 0 ] ) ) ) )
221+ XCTAssertTrue ( headers [ " content-length " ] . isEmpty)
222+ XCTAssertTrue ( headers [ " transfer-encoding " ] . contains ( " chunked " ) )
223+ }
224+
225+ for method : HTTPMethod in [ . POST, . PUT] {
226+ var headers : HTTPHeaders = . init( [ ( " Transfer-Encoding " , " chunked " ) ] )
227+ XCTAssertNoThrow ( try headers. validate ( method: method, body: . byteBuffer( ByteBuffer ( bytes: [ 0 ] ) ) ) )
228+ XCTAssertTrue ( headers [ " content-length " ] . isEmpty)
229+ XCTAssertTrue ( headers [ " transfer-encoding " ] . contains ( " chunked " ) )
230+ }
231+ }
232+
233+ // Method kind User sets Body Expectation
234+ // ---------------------------------------------------------------------------------------
235+ // .GET, .HEAD, .DELETE, .CONNECT, .TRACE CL & chunked (illegal) nil throws error
236+ // other CL & chunked (illegal) nil throws error
237+ func testBothHeadersNoBody( ) throws {
238+ for method : HTTPMethod in [ . GET, . HEAD, . DELETE, . CONNECT, . TRACE] {
239+ var headers : HTTPHeaders = . init( [ ( " Content-Length " , " 1 " ) , ( " Transfer-Encoding " , " chunked " ) ] )
240+ XCTAssertThrowsError ( try headers. validate ( method: method, body: nil ) )
241+ }
242+
243+ for method : HTTPMethod in [ . POST, . PUT] {
244+ var headers : HTTPHeaders = . init( [ ( " Content-Length " , " 1 " ) , ( " Transfer-Encoding " , " chunked " ) ] )
245+ XCTAssertThrowsError ( try headers. validate ( method: method, body: nil ) )
246+ }
247+ }
248+
249+ // Method kind User sets Body Expectation
250+ // -------------------------------------------------------------------------------------------
251+ // .GET, .HEAD, .DELETE, .CONNECT, .TRACE CL & chunked (illegal) not nil throws error
252+ // other CL & chunked (illegal) not nil throws error
253+ func testBothHeadersHasBody( ) throws {
254+ for method : HTTPMethod in [ . GET, . HEAD, . DELETE, . CONNECT, . TRACE] {
255+ var headers : HTTPHeaders = . init( [ ( " Content-Length " , " 1 " ) , ( " Transfer-Encoding " , " chunked " ) ] )
256+ XCTAssertThrowsError ( try headers. validate ( method: method, body: . byteBuffer( ByteBuffer ( bytes: [ 0 ] ) ) ) )
257+ }
258+
259+ for method : HTTPMethod in [ . POST, . PUT] {
260+ var headers : HTTPHeaders = . init( [ ( " Content-Length " , " 1 " ) , ( " Transfer-Encoding " , " chunked " ) ] )
261+ XCTAssertThrowsError ( try headers. validate ( method: method, body: . byteBuffer( ByteBuffer ( bytes: [ 0 ] ) ) ) )
114262 }
115- XCTAssertThrowsError ( try headers. validate ( method: . PUT, body: body) )
116263 }
117264}
0 commit comments