| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #source("../../../../runtime/bin/http_parser.dart"); | 5 #source("../../../../runtime/bin/http_parser.dart"); |
| 6 | 6 |
| 7 class HttpParserTest { | 7 class HttpParserTest { |
| 8 static void runAllTests() { | 8 static void runAllTests() { |
| 9 testParseRequest(); | 9 testParseRequest(); |
| 10 testParseResponse(); | 10 testParseResponse(); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 testWrite(requestData, 10); | 94 testWrite(requestData, 10); |
| 95 testWrite(requestData, 1); | 95 testWrite(requestData, 1); |
| 96 } | 96 } |
| 97 | 97 |
| 98 static void _testParseResponse(String response, | 98 static void _testParseResponse(String response, |
| 99 int expectedStatusCode, | 99 int expectedStatusCode, |
| 100 String expectedReasonPhrase, | 100 String expectedReasonPhrase, |
| 101 [int expectedContentLength = 0, | 101 [int expectedContentLength = 0, |
| 102 int expectedBytesReceived = 0, | 102 int expectedBytesReceived = 0, |
| 103 Map expectedHeaders = null, | 103 Map expectedHeaders = null, |
| 104 bool chunked = false]) { | 104 bool chunked = false, |
| 105 bool close = false]) { |
| 105 _HttpParser httpParser; | 106 _HttpParser httpParser; |
| 106 bool headersCompleteCalled; | 107 bool headersCompleteCalled; |
| 107 bool dataEndCalled; | 108 bool dataEndCalled; |
| 108 int statusCode; | 109 int statusCode; |
| 109 String reasonPhrase; | 110 String reasonPhrase; |
| 110 Map headers; | 111 Map headers; |
| 111 int contentLength; | 112 int contentLength; |
| 112 int bytesReceived; | 113 int bytesReceived; |
| 113 | 114 |
| 114 void reset() { | 115 void reset() { |
| 115 httpParser = new _HttpParser(); | 116 httpParser = new _HttpParser(); |
| 116 httpParser.requestStart = (m, u) => Expect.fail("Expected response"); | 117 httpParser.requestStart = (m, u) => Expect.fail("Expected response"); |
| 117 httpParser.responseStart = (s, r) { | 118 httpParser.responseStart = (s, r) { |
| 118 statusCode = s; | 119 statusCode = s; |
| 119 reasonPhrase = r; | 120 reasonPhrase = r; |
| 120 }; | 121 }; |
| 121 httpParser.headerReceived = (f, v) { | 122 httpParser.headerReceived = (f, v) { |
| 122 Expect.isFalse(headersCompleteCalled); | 123 Expect.isFalse(headersCompleteCalled); |
| 123 headers[f] = v; | 124 headers[f] = v; |
| 124 }; | 125 }; |
| 125 httpParser.headersComplete = () { | 126 httpParser.headersComplete = () { |
| 126 Expect.isFalse(headersCompleteCalled); | 127 Expect.isFalse(headersCompleteCalled); |
| 127 if (!chunked) { | 128 if (!chunked && !close) { |
| 128 Expect.equals(expectedContentLength, httpParser.contentLength); | 129 Expect.equals(expectedContentLength, httpParser.contentLength); |
| 129 } else { | 130 } else { |
| 130 Expect.equals(-1, httpParser.contentLength); | 131 Expect.equals(-1, httpParser.contentLength); |
| 131 } | 132 } |
| 132 if (expectedHeaders != null) { | 133 if (expectedHeaders != null) { |
| 133 expectedHeaders.forEach((String name, String value) { | 134 expectedHeaders.forEach((String name, String value) { |
| 134 Expect.equals(value, headers[name]); | 135 Expect.equals(value, headers[name]); |
| 135 }); | 136 }); |
| 136 } | 137 } |
| 137 headersCompleteCalled = true; | 138 headersCompleteCalled = true; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 159 } | 160 } |
| 160 | 161 |
| 161 void testWrite(List<int> requestData, [int chunkSize = -1]) { | 162 void testWrite(List<int> requestData, [int chunkSize = -1]) { |
| 162 if (chunkSize == -1) chunkSize = requestData.length; | 163 if (chunkSize == -1) chunkSize = requestData.length; |
| 163 reset(); | 164 reset(); |
| 164 for (int pos = 0; pos < requestData.length; pos += chunkSize) { | 165 for (int pos = 0; pos < requestData.length; pos += chunkSize) { |
| 165 int remaining = requestData.length - pos; | 166 int remaining = requestData.length - pos; |
| 166 int writeLength = Math.min(chunkSize, remaining); | 167 int writeLength = Math.min(chunkSize, remaining); |
| 167 httpParser.writeList(requestData, pos, writeLength); | 168 httpParser.writeList(requestData, pos, writeLength); |
| 168 } | 169 } |
| 170 if (close) httpParser.connectionClosed(); |
| 169 checkExpectations(); | 171 checkExpectations(); |
| 170 } | 172 } |
| 171 | 173 |
| 172 void testWriteAll(List<int> requestData) { | 174 void testWriteAll(List<int> requestData) { |
| 173 reset(); | 175 reset(); |
| 174 httpParser.writeList(requestData, 0, requestData.length); | 176 httpParser.writeList(requestData, 0, requestData.length); |
| 175 checkExpectations(); | 177 checkExpectations(); |
| 176 } | 178 } |
| 177 | 179 |
| 178 // Test parsing the request three times delivering the data in | 180 // Test parsing the request three times delivering the data in |
| 179 // different chunks. | 181 // different chunks. |
| 180 List<int> responseData = response.charCodes(); | 182 List<int> responseData = response.charCodes(); |
| 181 testWrite(responseData); | 183 testWrite(responseData); |
| 182 testWrite(responseData, 10); | 184 testWrite(responseData, 10); |
| 183 testWrite(responseData, 1); | 185 testWrite(responseData, 1); |
| 184 } | 186 } |
| 185 | 187 |
| 186 static void testParseRequest() { | 188 static void testParseRequest() { |
| 187 String request; | 189 String request; |
| 188 Map headers; | 190 Map headers; |
| 189 request = "GET / HTTP/1.1\r\n\r\n"; | 191 request = "GET / HTTP/1.1\r\nContent-Length: 0\r\n\r\n"; |
| 190 _testParseRequest(request, "GET", "/"); | 192 _testParseRequest(request, "GET", "/"); |
| 191 | 193 |
| 192 request = "POST / HTTP/1.1\r\n\r\n"; | 194 request = "POST / HTTP/1.1\r\nContent-Length: 0\r\n\r\n"; |
| 193 _testParseRequest(request, "POST", "/"); | 195 _testParseRequest(request, "POST", "/"); |
| 194 | 196 |
| 195 request = "GET /index.html HTTP/1.1\r\n\r\n"; | 197 request = "GET /index.html HTTP/1.1\r\nContent-Length: 0\r\n\r\n"; |
| 196 _testParseRequest(request, "GET", "/index.html"); | 198 _testParseRequest(request, "GET", "/index.html"); |
| 197 | 199 |
| 198 request = "POST /index.html HTTP/1.1\r\n\r\n"; | 200 request = "POST /index.html HTTP/1.1\r\nContent-Length: 0\r\n\r\n"; |
| 199 _testParseRequest(request, "POST", "/index.html"); | 201 _testParseRequest(request, "POST", "/index.html"); |
| 200 | 202 |
| 201 request = "H /index.html HTTP/1.1\r\n\r\n"; | 203 request = "H /index.html HTTP/1.1\r\nContent-Length: 0\r\n\r\n"; |
| 202 _testParseRequest(request, "H", "/index.html"); | 204 _testParseRequest(request, "H", "/index.html"); |
| 203 | 205 |
| 204 request = "HT /index.html HTTP/1.1\r\n\r\n"; | 206 request = "HT /index.html HTTP/1.1\r\nContent-Length: 0\r\n\r\n"; |
| 205 _testParseRequest(request, "HT", "/index.html"); | 207 _testParseRequest(request, "HT", "/index.html"); |
| 206 | 208 |
| 207 request = "HTT /index.html HTTP/1.1\r\n\r\n"; | 209 request = "HTT /index.html HTTP/1.1\r\nContent-Length: 0\r\n\r\n"; |
| 208 _testParseRequest(request, "HTT", "/index.html"); | 210 _testParseRequest(request, "HTT", "/index.html"); |
| 209 | 211 |
| 210 request = "HTTP /index.html HTTP/1.1\r\n\r\n"; | 212 request = "HTTP /index.html HTTP/1.1\r\nContent-Length: 0\r\n\r\n"; |
| 211 _testParseRequest(request, "HTTP", "/index.html"); | 213 _testParseRequest(request, "HTTP", "/index.html"); |
| 212 | 214 |
| 213 request = """ | 215 request = """ |
| 214 POST /test HTTP/1.1\r | 216 POST /test HTTP/1.1\r |
| 215 AAA: AAA\r | 217 AAA: AAA\r |
| 216 Content-Length: 0\r | 218 Content-Length: 0\r |
| 217 \r | 219 \r |
| 218 """; | 220 """; |
| 219 _testParseRequest(request, "POST", "/test"); | 221 _testParseRequest(request, "POST", "/test"); |
| 220 | 222 |
| 221 request = """ | 223 request = """ |
| 222 POST /test HTTP/1.1\r | 224 POST /test HTTP/1.1\r |
| 223 content-length: 0\r | 225 content-length: 0\r |
| 224 \r | 226 \r |
| 225 """; | 227 """; |
| 226 _testParseRequest(request, "POST", "/test"); | 228 _testParseRequest(request, "POST", "/test"); |
| 227 | 229 |
| 228 request = """ | 230 request = """ |
| 229 POST /test HTTP/1.1\r | 231 POST /test HTTP/1.1\r |
| 232 Content-Length: 0\r |
| 230 Header-A: AAA\r | 233 Header-A: AAA\r |
| 231 X-Header-B: bbb\r | 234 X-Header-B: bbb\r |
| 232 \r | 235 \r |
| 233 """; | 236 """; |
| 234 headers = new Map(); | 237 headers = new Map(); |
| 235 headers["header-a"] = "AAA"; | 238 headers["header-a"] = "AAA"; |
| 236 headers["x-header-b"] = "bbb"; | 239 headers["x-header-b"] = "bbb"; |
| 237 _testParseRequest(request, "POST", "/test", 0, 0, headers); | 240 _testParseRequest(request, "POST", "/test", expectedHeaders: headers); |
| 238 | 241 |
| 239 request = """ | 242 request = """ |
| 240 POST /test HTTP/1.1\r | 243 POST /test HTTP/1.1\r |
| 244 Content-Length: 0\r |
| 241 Header-A: AAA\r | 245 Header-A: AAA\r |
| 242 X-Header-B:\t \t bbb\r | 246 X-Header-B:\t \t bbb\r |
| 243 \r | 247 \r |
| 244 """; | 248 """; |
| 245 headers = new Map(); | 249 headers = new Map(); |
| 246 headers["header-a"] = "AAA"; | 250 headers["header-a"] = "AAA"; |
| 247 headers["x-header-b"] = "bbb"; | 251 headers["x-header-b"] = "bbb"; |
| 248 _testParseRequest(request, "POST", "/test", 0, 0, headers); | 252 _testParseRequest(request, "POST", "/test", expectedHeaders: headers); |
| 249 | 253 |
| 250 request = """ | 254 request = """ |
| 251 POST /test HTTP/1.1\r | 255 POST /test HTTP/1.1\r |
| 256 Content-Length: 0\r |
| 252 Header-A: AA\r | 257 Header-A: AA\r |
| 253 A\r | 258 A\r |
| 254 X-Header-B: b\r | 259 X-Header-B: b\r |
| 255 b\r | 260 b\r |
| 256 \t b\r | 261 \t b\r |
| 257 \r | 262 \r |
| 258 """; | 263 """; |
| 259 headers = new Map(); | 264 headers = new Map(); |
| 260 headers["header-a"] = "AAA"; | 265 headers["header-a"] = "AAA"; |
| 261 headers["x-header-b"] = "bbb"; | 266 headers["x-header-b"] = "bbb"; |
| 262 _testParseRequest(request, "POST", "/test", 0, 0, headers); | 267 _testParseRequest(request, "POST", "/test", expectedHeaders: headers); |
| 263 | 268 |
| 264 request = """ | 269 request = """ |
| 265 POST /test HTTP/1.1\r | 270 POST /test HTTP/1.1\r |
| 266 Content-Length: 10\r | 271 Content-Length: 10\r |
| 267 \r | 272 \r |
| 268 0123456789"""; | 273 0123456789"""; |
| 269 _testParseRequest(request, "POST", "/test", 10, 10); | 274 _testParseRequest(request, |
| 275 "POST", |
| 276 "/test", |
| 277 expectedContentLength: 10, |
| 278 expectedBytesReceived: 10); |
| 270 | 279 |
| 271 // Test chunked encoding. | 280 // Test chunked encoding. |
| 272 request = """ | 281 request = """ |
| 273 POST /test HTTP/1.1\r | 282 POST /test HTTP/1.1\r |
| 274 Transfer-Encoding: chunked\r | 283 Transfer-Encoding: chunked\r |
| 275 \r | 284 \r |
| 276 5\r | 285 5\r |
| 277 01234\r | 286 01234\r |
| 278 5\r | 287 5\r |
| 279 56789\r | 288 56789\r |
| 280 0\r\n\r\n"""; | 289 0\r\n\r\n"""; |
| 281 _testParseRequest(request, "POST", "/test", -1, 10, null, true); | 290 _testParseRequest(request, |
| 291 "POST", |
| 292 "/test", |
| 293 expectedContentLength: -1, |
| 294 expectedBytesReceived: 10, |
| 295 chunked: true); |
| 282 | 296 |
| 283 // Test mixing chunked encoding and content length (content length | 297 // Test mixing chunked encoding and content length (content length |
| 284 // is ignored). | 298 // is ignored). |
| 285 request = """ | 299 request = """ |
| 286 POST /test HTTP/1.1\r | 300 POST /test HTTP/1.1\r |
| 287 Content-Length: 7\r | 301 Content-Length: 7\r |
| 288 Transfer-Encoding: chunked\r | 302 Transfer-Encoding: chunked\r |
| 289 \r | 303 \r |
| 290 5\r | 304 5\r |
| 291 01234\r | 305 01234\r |
| 292 5\r | 306 5\r |
| 293 56789\r | 307 56789\r |
| 294 0\r\n\r\n"""; | 308 0\r\n\r\n"""; |
| 295 _testParseRequest(request, "POST", "/test", -1, 10, null, true); | 309 _testParseRequest(request, |
| 310 "POST", |
| 311 "/test", |
| 312 expectedContentLength: -1, |
| 313 expectedBytesReceived: 10, |
| 314 chunked: true); |
| 296 | 315 |
| 297 // Test mixing chunked encoding and content length (content length | 316 // Test mixing chunked encoding and content length (content length |
| 298 // is ignored). | 317 // is ignored). |
| 299 request = """ | 318 request = """ |
| 300 POST /test HTTP/1.1\r | 319 POST /test HTTP/1.1\r |
| 301 Transfer-Encoding: chunked\r | 320 Transfer-Encoding: chunked\r |
| 302 Content-Length: 3\r | 321 Content-Length: 3\r |
| 303 \r | 322 \r |
| 304 5\r | 323 5\r |
| 305 01234\r | 324 01234\r |
| 306 5\r | 325 5\r |
| 307 56789\r | 326 56789\r |
| 308 0\r\n\r\n"""; | 327 0\r\n\r\n"""; |
| 309 _testParseRequest(request, "POST", "/test", -1, 10, null, true); | 328 _testParseRequest(request, |
| 329 "POST", |
| 330 "/test", |
| 331 expectedContentLength: -1, |
| 332 expectedBytesReceived: 10, |
| 333 chunked: true); |
| 310 | 334 |
| 311 // Test upper and lower case hex digits in chunked encoding. | 335 // Test upper and lower case hex digits in chunked encoding. |
| 312 request = """ | 336 request = """ |
| 313 POST /test HTTP/1.1\r | 337 POST /test HTTP/1.1\r |
| 314 Transfer-Encoding: chunked\r | 338 Transfer-Encoding: chunked\r |
| 315 \r | 339 \r |
| 316 1E\r | 340 1E\r |
| 317 012345678901234567890123456789\r | 341 012345678901234567890123456789\r |
| 318 1e\r | 342 1e\r |
| 319 012345678901234567890123456789\r | 343 012345678901234567890123456789\r |
| 320 0\r\n\r\n"""; | 344 0\r\n\r\n"""; |
| 321 _testParseRequest(request, "POST", "/test", -1, 60, null, true); | 345 _testParseRequest(request, |
| 346 "POST", |
| 347 "/test", |
| 348 expectedContentLength: -1, |
| 349 expectedBytesReceived: 60, |
| 350 chunked: true); |
| 322 } | 351 } |
| 323 | 352 |
| 324 static void testParseResponse() { | 353 static void testParseResponse() { |
| 325 String response; | 354 String response; |
| 326 Map headers; | 355 Map headers; |
| 327 response = "HTTP/1.1 200 OK\r\n\r\n"; | 356 response = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"; |
| 328 _testParseResponse(response, 200, "OK"); | 357 _testParseResponse(response, 200, "OK"); |
| 329 | 358 |
| 330 response = "HTTP/1.1 404 Not found\r\n\r\n"; | 359 response = "HTTP/1.1 404 Not found\r\nContent-Length: 0\r\n\r\n"; |
| 331 _testParseResponse(response, 404, "Not found"); | 360 _testParseResponse(response, 404, "Not found"); |
| 332 | 361 |
| 333 response = "HTTP/1.1 500 Server error\r\n\r\n"; | 362 response = "HTTP/1.1 500 Server error\r\nContent-Length: 0\r\n\r\n"; |
| 334 _testParseResponse(response, 500, "Server error"); | 363 _testParseResponse(response, 500, "Server error"); |
| 335 | 364 |
| 336 // Test content. | 365 // Test content. |
| 337 response = """ | 366 response = """ |
| 338 HTTP/1.1 200 OK\r | 367 HTTP/1.1 200 OK\r |
| 339 Content-Length: 20\r | 368 Content-Length: 20\r |
| 340 \r | 369 \r |
| 341 01234567890123456789"""; | 370 01234567890123456789"""; |
| 342 | 371 |
| 343 _testParseResponse(response, 200, "OK", 20, 20); | 372 _testParseResponse(response, |
| 373 200, |
| 374 "OK", |
| 375 expectedContentLength: 20, |
| 376 expectedBytesReceived: 20); |
| 377 |
| 344 // Test upper and lower case hex digits in chunked encoding. | 378 // Test upper and lower case hex digits in chunked encoding. |
| 345 response = """ | 379 response = """ |
| 346 HTTP/1.1 200 OK\r | 380 HTTP/1.1 200 OK\r |
| 347 Transfer-Encoding: chunked\r | 381 Transfer-Encoding: chunked\r |
| 348 \r | 382 \r |
| 349 1A\r | 383 1A\r |
| 350 01234567890123456789012345\r | 384 01234567890123456789012345\r |
| 351 1f\r | 385 1f\r |
| 352 0123456789012345678901234567890\r | 386 0123456789012345678901234567890\r |
| 353 0\r\n\r\n"""; | 387 0\r\n\r\n"""; |
| 354 _testParseResponse(response, 200, "OK", -1, 57, null, true); | 388 _testParseResponse(response, |
| 389 200, |
| 390 "OK", |
| 391 expectedContentLength: -1, |
| 392 expectedBytesReceived: 57, |
| 393 chunked: true); |
| 394 |
| 395 // Test HTTP response without any transfer length indications |
| 396 // where closing the connections indicated end of body. |
| 397 response = """ |
| 398 HTTP/1.1 200 OK\r |
| 399 \r |
| 400 01234567890123456789012345 |
| 401 0123456789012345678901234567890 |
| 402 """; |
| 403 _testParseResponse(response, |
| 404 200, |
| 405 "OK", |
| 406 expectedContentLength: -1, |
| 407 expectedBytesReceived: 59, |
| 408 close: true); |
| 355 } | 409 } |
| 356 } | 410 } |
| 357 | 411 |
| 358 | 412 |
| 359 void main() { | 413 void main() { |
| 360 HttpParserTest.runAllTests(); | 414 HttpParserTest.runAllTests(); |
| 361 } | 415 } |
| OLD | NEW |