http_parser.rb 0.5.1-x86-mswin32-60 → 0.5.2-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/Gemfile.lock +16 -16
  2. data/LICENSE-MIT +20 -0
  3. data/ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java +68 -11
  4. data/ext/ruby_http_parser/ruby_http_parser.c +74 -6
  5. data/ext/ruby_http_parser/vendor/http-parser-java/LICENSE-MIT +26 -1
  6. data/ext/ruby_http_parser/vendor/http-parser-java/README.md +23 -143
  7. data/ext/ruby_http_parser/vendor/http-parser-java/TODO +3 -0
  8. data/ext/ruby_http_parser/vendor/http-parser-java/build.xml +74 -0
  9. data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.c +115 -61
  10. data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.h +19 -3
  11. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPCallback.java +8 -0
  12. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPDataCallback.java +34 -0
  13. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPErrorCallback.java +12 -0
  14. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPException.java +4 -2
  15. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPMethod.java +64 -52
  16. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParser.java +5 -0
  17. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserSettings.java +323 -0
  18. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/{lolevel/Util.java → Util.java} +27 -28
  19. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPParser.java +259 -85
  20. data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/ParserSettings.java +1 -0
  21. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Message.java +324 -0
  22. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Requests.java +69 -0
  23. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Responses.java +51 -0
  24. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Test.java +15 -0
  25. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestHeaderOverflowError.java +47 -0
  26. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestLoaderNG.java +183 -447
  27. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestNoOverflowLongBody.java +61 -0
  28. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/UnitTest.java +2 -1
  29. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Upgrade.java +26 -0
  30. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Util.java +165 -0
  31. data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/WrongContentLength.java +58 -0
  32. data/ext/ruby_http_parser/vendor/http-parser-java/test.c +232 -29
  33. data/ext/ruby_http_parser/vendor/http-parser-java/test_permutations +1 -1
  34. data/ext/ruby_http_parser/vendor/http-parser-java/test_unit +1 -1
  35. data/ext/ruby_http_parser/vendor/http-parser-java/test_utf8 +1 -0
  36. data/ext/ruby_http_parser/vendor/http-parser-java/tests.dumped +154 -7
  37. data/ext/ruby_http_parser/vendor/http-parser-java/tests.utf8 +17 -0
  38. data/ext/ruby_http_parser/vendor/http-parser/LICENSE-MIT +1 -1
  39. data/ext/ruby_http_parser/vendor/http-parser/http_parser.c +52 -10
  40. data/ext/ruby_http_parser/vendor/http-parser/http_parser.h +3 -1
  41. data/ext/ruby_http_parser/vendor/http-parser/test.c +89 -3
  42. data/http_parser.rb.gemspec +8 -2
  43. data/lib/http_parser.rb +17 -0
  44. data/spec/parser_spec.rb +97 -6
  45. data/tasks/compile.rake +3 -1
  46. metadata +83 -20
  47. data/ext/ruby_http_parser/vendor/http-parser-java/CONTRIBUTIONS +0 -4
@@ -1 +1 @@
1
- javac -d classes/ `find src -name '*.java'` && java -cp classes http_parser.lolevel.TestLoaderNG tests.dumped
1
+ javac -cp ext/primitives.jar -d classes/ `find src -name '*.java'` && java -cp classes:ext/primitives.jar http_parser.lolevel.TestLoaderNG tests.dumped
@@ -1 +1 @@
1
- javac -d classes/ `find src -name '*.java'` && java -cp classes http_parser.lolevel.UnitTest
1
+ javac -cp ext/primitives.jar -d classes/ `find src -name '*.java'` && java -cp classes:ext/primitives.jar http_parser.lolevel.UnitTest
@@ -0,0 +1 @@
1
+ javac -cp ext/primitives.jar -d classes/ `find src -name '*.java'` && java -cp classes:ext/primitives.jar http_parser.lolevel.TestLoaderNG tests.utf8
@@ -304,12 +304,12 @@ http_major :1
304
304
  http_minor :1
305
305
 
306
306
  name :connect request
307
- raw :"CONNECT home.netscape.com:443 HTTP/1.0\r\nUser-agent: Mozilla/1.1N\r\nProxy-authorization: basic aGVsbG86d29ybGQ=\r\n\r\n"
307
+ raw :"CONNECT home0.netscape.com:443 HTTP/1.0\r\nUser-agent: Mozilla/1.1N\r\nProxy-authorization: basic aGVsbG86d29ybGQ=\r\n\r\n"
308
308
  type :HTTP_REQUEST
309
309
  method: HTTP_CONNECT
310
310
  status_code :0
311
311
  request_path:
312
- request_url :home.netscape.com:443
312
+ request_url :home0.netscape.com:443
313
313
  fragment :
314
314
  query_string:
315
315
  body :""
@@ -324,7 +324,7 @@ http_minor :0
324
324
  name :report request
325
325
  raw :"REPORT /test HTTP/1.1\r\n\r\n"
326
326
  type :HTTP_REQUEST
327
- method: REPORT
327
+ method: HTTP_REPORT
328
328
  status_code :0
329
329
  request_path:/test
330
330
  request_url :/test
@@ -337,8 +337,108 @@ upgrade :0
337
337
  http_major :1
338
338
  http_minor :1
339
339
 
340
+ name :request with no http version
341
+ raw :"GET /\r\n\r\n"
342
+ type :HTTP_REQUEST
343
+ method: HTTP_GET
344
+ status_code :0
345
+ request_path:/
346
+ request_url :/
347
+ fragment :
348
+ query_string:
349
+ body :""
350
+ body_size :0
351
+ should_keep_alive :0
352
+ upgrade :0
353
+ http_major :0
354
+ http_minor :9
355
+
356
+ name :m-search request
357
+ raw :"M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nST: \"ssdp:all\"\r\n\r\n"
358
+ type :HTTP_REQUEST
359
+ method: HTTP_MSEARCH
360
+ status_code :0
361
+ request_path:*
362
+ request_url :*
363
+ fragment :
364
+ query_string:
365
+ body :""
366
+ body_size :0
367
+ header_0 :{ "HOST": "239.255.255.250:1900"}
368
+ header_1 :{ "MAN": ""ssdp:discover""}
369
+ header_2 :{ "ST": ""ssdp:all""}
370
+ should_keep_alive :1
371
+ upgrade :0
372
+ http_major :1
373
+ http_minor :1
374
+
375
+ name :utf-8 path request
376
+ raw :"GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\nHost: github.com\r\n\r\n"
377
+ type :HTTP_REQUEST
378
+ method: HTTP_GET
379
+ status_code :0
380
+ request_path:/δ¶/δt/pope
381
+ request_url :/δ¶/δt/pope?q=1#narf
382
+ fragment :narf
383
+ query_string:q=1
384
+ body :""
385
+ body_size :0
386
+ header_0 :{ "Host": "github.com"}
387
+ should_keep_alive :1
388
+ upgrade :0
389
+ http_major :1
390
+ http_minor :1
391
+
392
+ name :host terminated by a query string
393
+ raw :"GET http://hypnotoad.org?hail=all HTTP/1.1\r\n\r\n"
394
+ type :HTTP_REQUEST
395
+ method: HTTP_GET
396
+ status_code :0
397
+ request_path:
398
+ request_url :http://hypnotoad.org?hail=all
399
+ fragment :
400
+ query_string:hail=all
401
+ body :""
402
+ body_size :0
403
+ should_keep_alive :1
404
+ upgrade :0
405
+ http_major :1
406
+ http_minor :1
407
+
408
+ name :host:port terminated by a query string
409
+ raw :"GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n\r\n"
410
+ type :HTTP_REQUEST
411
+ method: HTTP_GET
412
+ status_code :0
413
+ request_path:
414
+ request_url :http://hypnotoad.org:1234?hail=all
415
+ fragment :
416
+ query_string:hail=all
417
+ body :""
418
+ body_size :0
419
+ should_keep_alive :1
420
+ upgrade :0
421
+ http_major :1
422
+ http_minor :1
423
+
424
+ name :host:port terminated by a space
425
+ raw :"GET http://hypnotoad.org:1234 HTTP/1.1\r\n\r\n"
426
+ type :HTTP_REQUEST
427
+ method: HTTP_GET
428
+ status_code :0
429
+ request_path:
430
+ request_url :http://hypnotoad.org:1234
431
+ fragment :
432
+ query_string:
433
+ body :""
434
+ body_size :0
435
+ should_keep_alive :1
436
+ upgrade :0
437
+ http_major :1
438
+ http_minor :1
439
+
340
440
  name :google 301
341
- raw :"HTTP/1.1 301 Moved Permanently\r\nLocation: http://www.google.com/\r\nContent-Type: text/html; charset=UTF-8\r\nDate: Sun, 26 Apr 2009 11:11:49 GMT\r\nExpires: Tue, 26 May 2009 11:11:49 GMT\r\nCache-Control: public, max-age=2592000\r\nServer: gws\r\nContent-Length: 219\r\n\r\n<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n<TITLE>301 Moved</TITLE></HEAD><BODY>\n<H1>301 Moved</H1>\nThe document has moved\n<A HREF=\"http://www.google.com/\">here</A>.\r\n</BODY></HTML>\r\n"
441
+ raw :"HTTP/1.1 301 Moved Permanently\r\nLocation: http://www.google.com/\r\nContent-Type: text/html; charset=UTF-8\r\nDate: Sun, 26 Apr 2009 11:11:49 GMT\r\nExpires: Tue, 26 May 2009 11:11:49 GMT\r\nX-$PrototypeBI-Version: 1.6.0.3\r\nCache-Control: public, max-age=2592000\r\nServer: gws\r\nContent-Length: 219 \r\n\r\n<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n<TITLE>301 Moved</TITLE></HEAD><BODY>\n<H1>301 Moved</H1>\nThe document has moved\n<A HREF=\"http://www.google.com/\">here</A>.\r\n</BODY></HTML>\r\n"
342
442
  type :HTTP_RESPONSE
343
443
  method: HTTP_DELETE
344
444
  status_code :301
@@ -352,9 +452,10 @@ header_0 :{ "Location": "http://www.google.com/"}
352
452
  header_1 :{ "Content-Type": "text/html; charset=UTF-8"}
353
453
  header_2 :{ "Date": "Sun, 26 Apr 2009 11:11:49 GMT"}
354
454
  header_3 :{ "Expires": "Tue, 26 May 2009 11:11:49 GMT"}
355
- header_4 :{ "Cache-Control": "public, max-age=2592000"}
356
- header_5 :{ "Server": "gws"}
357
- header_6 :{ "Content-Length": "219"}
455
+ header_4 :{ "X-$PrototypeBI-Version": "1.6.0.3"}
456
+ header_5 :{ "Cache-Control": "public, max-age=2592000"}
457
+ header_6 :{ "Server": "gws"}
458
+ header_7 :{ "Content-Length": "219 "}
358
459
  should_keep_alive :1
359
460
  upgrade :0
360
461
  http_major :1
@@ -537,3 +638,49 @@ upgrade :0
537
638
  http_major :1
538
639
  http_minor :1
539
640
 
641
+ name :field underscore
642
+ raw :"HTTP/1.1 200 OK\r\nDate: Tue, 28 Sep 2010 01:14:13 GMT\r\nServer: Apache\r\nCache-Control: no-cache, must-revalidate\r\nExpires: Mon, 26 Jul 1997 05:00:00 GMT\r\n.et-Cookie: PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com\r\nVary: Accept-Encoding\r\n_eep-Alive: timeout=45\r\n_onnection: Keep-Alive\r\nTransfer-Encoding: chunked\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n0\r\n\r\n"
643
+ type :HTTP_RESPONSE
644
+ method: HTTP_DELETE
645
+ status_code :200
646
+ request_path:
647
+ request_url :
648
+ fragment :
649
+ query_string:
650
+ body :""
651
+ body_size :0
652
+ header_0 :{ "Date": "Tue, 28 Sep 2010 01:14:13 GMT"}
653
+ header_1 :{ "Server": "Apache"}
654
+ header_2 :{ "Cache-Control": "no-cache, must-revalidate"}
655
+ header_3 :{ "Expires": "Mon, 26 Jul 1997 05:00:00 GMT"}
656
+ header_4 :{ ".et-Cookie": "PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com"}
657
+ header_5 :{ "Vary": "Accept-Encoding"}
658
+ header_6 :{ "_eep-Alive": "timeout=45"}
659
+ header_7 :{ "_onnection": "Keep-Alive"}
660
+ header_8 :{ "Transfer-Encoding": "chunked"}
661
+ header_9 :{ "Content-Type": "text/html"}
662
+ header_10 :{ "Connection": "close"}
663
+ should_keep_alive :0
664
+ upgrade :0
665
+ http_major :1
666
+ http_minor :1
667
+
668
+ name :non-ASCII in status line
669
+ raw :"HTTP/1.1 500 Oriëntatieprobleem\r\nDate: Fri, 5 Nov 2010 23:07:12 GMT+2\r\nContent-Length: 0\r\nConnection: close\r\n\r\n"
670
+ type :HTTP_RESPONSE
671
+ method: HTTP_DELETE
672
+ status_code :500
673
+ request_path:
674
+ request_url :
675
+ fragment :
676
+ query_string:
677
+ body :""
678
+ body_size :0
679
+ header_0 :{ "Date": "Fri, 5 Nov 2010 23:07:12 GMT+2"}
680
+ header_1 :{ "Content-Length": "0"}
681
+ header_2 :{ "Connection": "close"}
682
+ should_keep_alive :0
683
+ upgrade :0
684
+ http_major :1
685
+ http_minor :1
686
+
@@ -0,0 +1,17 @@
1
+ name :utf-8 path request
2
+ raw :"GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\nHost: github.com\r\n\r\n"
3
+ type :HTTP_REQUEST
4
+ method: HTTP_GET
5
+ status_code :0
6
+ request_path:/δ¶/δt/pope
7
+ request_url :/δ¶/δt/pope?q=1#narf
8
+ fragment :narf
9
+ query_string:q=1
10
+ body :""
11
+ body_size :0
12
+ header_0 :{ "Host": "github.com"}
13
+ should_keep_alive :1
14
+ upgrade :0
15
+ http_major :1
16
+ http_minor :1
17
+
@@ -1,4 +1,4 @@
1
- Copyright 2009,2010 Ryan Dahl <ry@tinyclouds.org>
1
+ Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to
@@ -1,4 +1,4 @@
1
- /* Copyright 2009,2010 Ryan Dahl <ry@tinyclouds.org>
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
2
  *
3
3
  * Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  * of this software and associated documentation files (the "Software"), to
@@ -186,7 +186,28 @@ static const uint8_t normal_url_char[256] = {
186
186
  /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
187
187
  1, 1, 1, 1, 1, 1, 1, 1,
188
188
  /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
189
- 1, 1, 1, 1, 1, 1, 1, 0 };
189
+ 1, 1, 1, 1, 1, 1, 1, 0,
190
+
191
+ /* Remainder of non-ASCII range are accepted as-is to support implicitly UTF-8
192
+ encoded paths. This is out of spec, but clients generate this and most other
193
+ HTTP servers support it. We should, too. */
194
+
195
+ 1, 1, 1, 1, 1, 1, 1, 1,
196
+ 1, 1, 1, 1, 1, 1, 1, 1,
197
+ 1, 1, 1, 1, 1, 1, 1, 1,
198
+ 1, 1, 1, 1, 1, 1, 1, 1,
199
+ 1, 1, 1, 1, 1, 1, 1, 1,
200
+ 1, 1, 1, 1, 1, 1, 1, 1,
201
+ 1, 1, 1, 1, 1, 1, 1, 1,
202
+ 1, 1, 1, 1, 1, 1, 1, 1,
203
+ 1, 1, 1, 1, 1, 1, 1, 1,
204
+ 1, 1, 1, 1, 1, 1, 1, 1,
205
+ 1, 1, 1, 1, 1, 1, 1, 1,
206
+ 1, 1, 1, 1, 1, 1, 1, 1,
207
+ 1, 1, 1, 1, 1, 1, 1, 1,
208
+ 1, 1, 1, 1, 1, 1, 1, 1,
209
+ 1, 1, 1, 1, 1, 1, 1, 1,
210
+ 1, 1, 1, 1, 1, 1, 1, 1 };
190
211
 
191
212
 
192
213
  enum state
@@ -240,15 +261,17 @@ enum state
240
261
 
241
262
  , s_header_almost_done
242
263
 
264
+ , s_chunk_size_start
265
+ , s_chunk_size
266
+ , s_chunk_parameters
267
+ , s_chunk_size_almost_done
268
+
243
269
  , s_headers_almost_done
244
270
  /* Important: 's_headers_almost_done' must be the last 'header' state. All
245
271
  * states beyond this must be 'body' states. It is used for overflow
246
272
  * checking. See the PARSING_HEADER() macro.
247
273
  */
248
- , s_chunk_size_start
249
- , s_chunk_size
250
- , s_chunk_size_almost_done
251
- , s_chunk_parameters
274
+
252
275
  , s_chunk_data
253
276
  , s_chunk_data_almost_done
254
277
  , s_chunk_data_done
@@ -258,7 +281,7 @@ enum state
258
281
  };
259
282
 
260
283
 
261
- #define PARSING_HEADER(state) (state <= s_headers_almost_done && 0 == (parser->flags & F_TRAILING))
284
+ #define PARSING_HEADER(state) (state <= s_headers_almost_done)
262
285
 
263
286
 
264
287
  enum header_states
@@ -331,10 +354,20 @@ size_t http_parser_execute (http_parser *parser,
331
354
  uint64_t nread = parser->nread;
332
355
 
333
356
  if (len == 0) {
334
- if (state == s_body_identity_eof) {
335
- CALLBACK2(message_complete);
357
+ switch (state) {
358
+ case s_body_identity_eof:
359
+ CALLBACK2(message_complete);
360
+ return 0;
361
+
362
+ case s_dead:
363
+ case s_start_req_or_res:
364
+ case s_start_res:
365
+ case s_start_req:
366
+ return 0;
367
+
368
+ default:
369
+ return 1; // error
336
370
  }
337
- return 0;
338
371
  }
339
372
 
340
373
  /* technically we could combine all of these (except for url_mark) into one
@@ -707,6 +740,9 @@ size_t http_parser_execute (http_parser *parser,
707
740
  CALLBACK(url);
708
741
  state = s_req_http_start;
709
742
  break;
743
+ case '?':
744
+ state = s_req_query_string_start;
745
+ break;
710
746
  default:
711
747
  goto error;
712
748
  }
@@ -729,6 +765,9 @@ size_t http_parser_execute (http_parser *parser,
729
765
  CALLBACK(url);
730
766
  state = s_req_http_start;
731
767
  break;
768
+ case '?':
769
+ state = s_req_query_string_start;
770
+ break;
732
771
  default:
733
772
  goto error;
734
773
  }
@@ -1448,6 +1487,7 @@ size_t http_parser_execute (http_parser *parser,
1448
1487
 
1449
1488
  case s_chunk_size_start:
1450
1489
  {
1490
+ assert(nread == 1);
1451
1491
  assert(parser->flags & F_CHUNKED);
1452
1492
 
1453
1493
  c = unhex[(unsigned char)ch];
@@ -1497,6 +1537,8 @@ size_t http_parser_execute (http_parser *parser,
1497
1537
  assert(parser->flags & F_CHUNKED);
1498
1538
  STRICT_CHECK(ch != LF);
1499
1539
 
1540
+ nread = 0;
1541
+
1500
1542
  if (parser->content_length == 0) {
1501
1543
  parser->flags |= F_TRAILING;
1502
1544
  state = s_header_field_start;
@@ -1,4 +1,4 @@
1
- /* Copyright 2009,2010 Ryan Dahl <ry@tinyclouds.org>
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
2
  *
3
3
  * Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  * of this software and associated documentation files (the "Software"), to
@@ -24,6 +24,8 @@
24
24
  extern "C" {
25
25
  #endif
26
26
 
27
+ #define HTTP_PARSER_VERSION_MAJOR 1
28
+ #define HTTP_PARSER_VERSION_MINOR 0
27
29
 
28
30
  #include <sys/types.h>
29
31
  #if defined(_WIN32) && !defined(__MINGW32__)
@@ -1,4 +1,4 @@
1
- /* Copyright 2009,2010 Ryan Dahl <ry@tinyclouds.org>
1
+ /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2
2
  *
3
3
  * Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  * of this software and associated documentation files (the "Software"), to
@@ -557,7 +557,7 @@ const struct message requests[] =
557
557
  ,.body= ""
558
558
  }
559
559
 
560
- #define MSEARCH_REQ 19
560
+ #define MSEARCH_REQ 20
561
561
  , {.name= "m-search request"
562
562
  ,.type= HTTP_REQUEST
563
563
  ,.raw= "M-SEARCH * HTTP/1.1\r\n"
@@ -582,6 +582,84 @@ const struct message requests[] =
582
582
  ,.body= ""
583
583
  }
584
584
 
585
+ #define UTF8_PATH_REQ 21
586
+ , {.name= "utf-8 path request"
587
+ ,.type= HTTP_REQUEST
588
+ ,.raw= "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\n"
589
+ "Host: github.com\r\n"
590
+ "\r\n"
591
+ ,.should_keep_alive= TRUE
592
+ ,.message_complete_on_eof= FALSE
593
+ ,.http_major= 1
594
+ ,.http_minor= 1
595
+ ,.method= HTTP_GET
596
+ ,.query_string= "q=1"
597
+ ,.fragment= "narf"
598
+ ,.request_path= "/δ¶/δt/pope"
599
+ ,.request_url= "/δ¶/δt/pope?q=1#narf"
600
+ ,.num_headers= 1
601
+ ,.headers= { {"Host", "github.com" }
602
+ }
603
+ ,.body= ""
604
+ }
605
+
606
+ #define QUERY_TERMINATED_HOST 22
607
+ , {.name= "host terminated by a query string"
608
+ ,.type= HTTP_REQUEST
609
+ ,.raw= "GET http://hypnotoad.org?hail=all HTTP/1.1\r\n"
610
+ "\r\n"
611
+ ,.should_keep_alive= TRUE
612
+ ,.message_complete_on_eof= FALSE
613
+ ,.http_major= 1
614
+ ,.http_minor= 1
615
+ ,.method= HTTP_GET
616
+ ,.query_string= "hail=all"
617
+ ,.fragment= ""
618
+ ,.request_path= ""
619
+ ,.request_url= "http://hypnotoad.org?hail=all"
620
+ ,.num_headers= 0
621
+ ,.headers= { }
622
+ ,.body= ""
623
+ }
624
+
625
+ #define QUERY_TERMINATED_HOSTPORT 23
626
+ , {.name= "host:port terminated by a query string"
627
+ ,.type= HTTP_REQUEST
628
+ ,.raw= "GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n"
629
+ "\r\n"
630
+ ,.should_keep_alive= TRUE
631
+ ,.message_complete_on_eof= FALSE
632
+ ,.http_major= 1
633
+ ,.http_minor= 1
634
+ ,.method= HTTP_GET
635
+ ,.query_string= "hail=all"
636
+ ,.fragment= ""
637
+ ,.request_path= ""
638
+ ,.request_url= "http://hypnotoad.org:1234?hail=all"
639
+ ,.num_headers= 0
640
+ ,.headers= { }
641
+ ,.body= ""
642
+ }
643
+
644
+ #define SPACE_TERMINATED_HOSTPORT 24
645
+ , {.name= "host:port terminated by a space"
646
+ ,.type= HTTP_REQUEST
647
+ ,.raw= "GET http://hypnotoad.org:1234 HTTP/1.1\r\n"
648
+ "\r\n"
649
+ ,.should_keep_alive= TRUE
650
+ ,.message_complete_on_eof= FALSE
651
+ ,.http_major= 1
652
+ ,.http_minor= 1
653
+ ,.method= HTTP_GET
654
+ ,.query_string= ""
655
+ ,.fragment= ""
656
+ ,.request_path= ""
657
+ ,.request_url= "http://hypnotoad.org:1234"
658
+ ,.num_headers= 0
659
+ ,.headers= { }
660
+ ,.body= ""
661
+ }
662
+
585
663
  , {.name= NULL } /* sentinel */
586
664
  };
587
665
 
@@ -1735,14 +1813,22 @@ main (void)
1735
1813
 
1736
1814
  /// REQUESTS
1737
1815
 
1738
-
1739
1816
  test_simple("hello world", 0);
1740
1817
  test_simple("GET / HTP/1.1\r\n\r\n", 0);
1741
1818
 
1819
+
1742
1820
  test_simple("ASDF / HTTP/1.1\r\n\r\n", 0);
1743
1821
  test_simple("PROPPATCHA / HTTP/1.1\r\n\r\n", 0);
1744
1822
  test_simple("GETA / HTTP/1.1\r\n\r\n", 0);
1745
1823
 
1824
+ // Well-formed but incomplete
1825
+ test_simple("GET / HTTP/1.1\r\n"
1826
+ "Content-Type: text/plain\r\n"
1827
+ "Content-Length: 6\r\n"
1828
+ "\r\n"
1829
+ "fooba",
1830
+ 0);
1831
+
1746
1832
  static const char *all_methods[] = {
1747
1833
  "DELETE",
1748
1834
  "GET",