http_parser.rb 0.5.1 → 0.6.0.beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitmodules +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +11 -4
- data/LICENSE-MIT +20 -0
- data/README.md +51 -46
- data/bench/standalone.rb +23 -0
- data/bench/thin.rb +1 -0
- data/ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java +121 -56
- data/ext/ruby_http_parser/ruby_http_parser.c +89 -48
- data/ext/ruby_http_parser/vendor/http-parser/AUTHORS +32 -0
- data/ext/ruby_http_parser/vendor/http-parser/LICENSE-MIT +5 -1
- data/ext/ruby_http_parser/vendor/http-parser/Makefile +34 -17
- data/ext/ruby_http_parser/vendor/http-parser/README.md +9 -2
- data/ext/ruby_http_parser/vendor/http-parser/http_parser.c +1045 -589
- data/ext/ruby_http_parser/vendor/http-parser/http_parser.gyp +79 -0
- data/ext/ruby_http_parser/vendor/http-parser/http_parser.h +148 -17
- data/ext/ruby_http_parser/vendor/http-parser/test.c +1138 -128
- data/ext/ruby_http_parser/vendor/http-parser-java/AUTHORS +32 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/LICENSE-MIT +30 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/Makefile +34 -17
- data/ext/ruby_http_parser/vendor/http-parser-java/README.md +30 -18
- data/ext/ruby_http_parser/vendor/http-parser-java/TODO +9 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/build.xml +74 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/ext/primitives.jar +0 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.c +1075 -607
- data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.gyp +79 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.h +190 -40
- data/ext/ruby_http_parser/vendor/http-parser-java/src/Http-parser.java.iml +22 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/FieldData.java +41 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPCallback.java +8 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPDataCallback.java +34 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPErrorCallback.java +12 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPException.java +4 -2
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPHeadersCompleteCallback.java +13 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPMethod.java +67 -52
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParser.java +5 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParserUrl.java +76 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserSettings.java +323 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/{lolevel/Util.java → Util.java} +34 -35
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPHeadersCompleteCallback.java +12 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPParser.java +839 -587
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/ParserSettings.java +2 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Message.java +374 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/ParseUrl.java +51 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Requests.java +69 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Responses.java +52 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Test.java +16 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestHeaderOverflowError.java +48 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestLoaderNG.java +171 -446
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestNoOverflowLongBody.java +62 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/UnitTest.java +3 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Upgrade.java +27 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Url.java +127 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Util.java +236 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/WrongContentLength.java +59 -0
- data/ext/ruby_http_parser/vendor/http-parser-java/test.c +1318 -184
- data/ext/ruby_http_parser/vendor/http-parser-java/tests.dumped +355 -49
- data/ext/ruby_http_parser/vendor/http-parser-java/tests.utf8 +17 -0
- data/http_parser.rb.gemspec +10 -2
- data/lib/http_parser.rb +17 -0
- data/spec/parser_spec.rb +157 -23
- data/spec/support/requests.json +236 -24
- data/spec/support/responses.json +182 -36
- data/tasks/compile.rake +5 -3
- data/tasks/fixtures.rake +8 -2
- metadata +209 -127
- data/ext/ruby_http_parser/vendor/http-parser-java/CONTRIBUTIONS +0 -4
- data/ext/ruby_http_parser/vendor/http-parser-java/compile +0 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/test_permutations +0 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/test_unit +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Copyright
|
|
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
|
|
@@ -50,12 +50,13 @@ struct message {
|
|
|
50
50
|
char query_string[MAX_ELEMENT_SIZE];
|
|
51
51
|
char body[MAX_ELEMENT_SIZE];
|
|
52
52
|
size_t body_size;
|
|
53
|
+
uint16_t port;
|
|
53
54
|
int num_headers;
|
|
54
55
|
enum { NONE=0, FIELD, VALUE } last_header_element;
|
|
55
56
|
char headers [MAX_HEADERS][2][MAX_ELEMENT_SIZE];
|
|
56
57
|
int should_keep_alive;
|
|
57
58
|
|
|
58
|
-
|
|
59
|
+
const char *upgrade; // upgraded body
|
|
59
60
|
|
|
60
61
|
unsigned short http_major;
|
|
61
62
|
unsigned short http_minor;
|
|
@@ -70,6 +71,7 @@ static int currently_parsing_eof;
|
|
|
70
71
|
|
|
71
72
|
static struct message messages[5];
|
|
72
73
|
static int num_messages;
|
|
74
|
+
static http_parser_settings *current_pause_parser;
|
|
73
75
|
|
|
74
76
|
/* * R E Q U E S T S * */
|
|
75
77
|
const struct message requests[] =
|
|
@@ -473,6 +475,7 @@ const struct message requests[] =
|
|
|
473
475
|
"Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
|
|
474
476
|
"Origin: http://example.com\r\n"
|
|
475
477
|
"\r\n"
|
|
478
|
+
"Hot diggity dogg"
|
|
476
479
|
,.should_keep_alive= TRUE
|
|
477
480
|
,.message_complete_on_eof= FALSE
|
|
478
481
|
,.http_major= 1
|
|
@@ -483,7 +486,7 @@ const struct message requests[] =
|
|
|
483
486
|
,.request_path= "/demo"
|
|
484
487
|
,.request_url= "/demo"
|
|
485
488
|
,.num_headers= 7
|
|
486
|
-
,.upgrade=
|
|
489
|
+
,.upgrade="Hot diggity dogg"
|
|
487
490
|
,.headers= { { "Host", "example.com" }
|
|
488
491
|
, { "Connection", "Upgrade" }
|
|
489
492
|
, { "Sec-WebSocket-Key2", "12998 5 Y3 1 .P00" }
|
|
@@ -498,10 +501,12 @@ const struct message requests[] =
|
|
|
498
501
|
#define CONNECT_REQUEST 17
|
|
499
502
|
, {.name = "connect request"
|
|
500
503
|
,.type= HTTP_REQUEST
|
|
501
|
-
,.raw= "CONNECT home0.netscape.com:443 HTTP/1.0\r\n"
|
|
504
|
+
,.raw= "CONNECT 0-home0.netscape.com:443 HTTP/1.0\r\n"
|
|
502
505
|
"User-agent: Mozilla/1.1N\r\n"
|
|
503
506
|
"Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n"
|
|
504
507
|
"\r\n"
|
|
508
|
+
"some data\r\n"
|
|
509
|
+
"and yet even more data"
|
|
505
510
|
,.should_keep_alive= FALSE
|
|
506
511
|
,.message_complete_on_eof= FALSE
|
|
507
512
|
,.http_major= 1
|
|
@@ -510,9 +515,9 @@ const struct message requests[] =
|
|
|
510
515
|
,.query_string= ""
|
|
511
516
|
,.fragment= ""
|
|
512
517
|
,.request_path= ""
|
|
513
|
-
,.request_url= "home0.netscape.com:443"
|
|
518
|
+
,.request_url= "0-home0.netscape.com:443"
|
|
514
519
|
,.num_headers= 2
|
|
515
|
-
,.upgrade=
|
|
520
|
+
,.upgrade="some data\r\nand yet even more data"
|
|
516
521
|
,.headers= { { "User-agent", "Mozilla/1.1N" }
|
|
517
522
|
, { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" }
|
|
518
523
|
}
|
|
@@ -557,7 +562,7 @@ const struct message requests[] =
|
|
|
557
562
|
,.body= ""
|
|
558
563
|
}
|
|
559
564
|
|
|
560
|
-
#define MSEARCH_REQ
|
|
565
|
+
#define MSEARCH_REQ 20
|
|
561
566
|
, {.name= "m-search request"
|
|
562
567
|
,.type= HTTP_REQUEST
|
|
563
568
|
,.raw= "M-SEARCH * HTTP/1.1\r\n"
|
|
@@ -582,6 +587,269 @@ const struct message requests[] =
|
|
|
582
587
|
,.body= ""
|
|
583
588
|
}
|
|
584
589
|
|
|
590
|
+
#define LINE_FOLDING_IN_HEADER 20
|
|
591
|
+
, {.name= "line folding in header value"
|
|
592
|
+
,.type= HTTP_REQUEST
|
|
593
|
+
,.raw= "GET / HTTP/1.1\r\n"
|
|
594
|
+
"Line1: abc\r\n"
|
|
595
|
+
"\tdef\r\n"
|
|
596
|
+
" ghi\r\n"
|
|
597
|
+
"\t\tjkl\r\n"
|
|
598
|
+
" mno \r\n"
|
|
599
|
+
"\t \tqrs\r\n"
|
|
600
|
+
"Line2: \t line2\t\r\n"
|
|
601
|
+
"\r\n"
|
|
602
|
+
,.should_keep_alive= TRUE
|
|
603
|
+
,.message_complete_on_eof= FALSE
|
|
604
|
+
,.http_major= 1
|
|
605
|
+
,.http_minor= 1
|
|
606
|
+
,.method= HTTP_GET
|
|
607
|
+
,.query_string= ""
|
|
608
|
+
,.fragment= ""
|
|
609
|
+
,.request_path= "/"
|
|
610
|
+
,.request_url= "/"
|
|
611
|
+
,.num_headers= 2
|
|
612
|
+
,.headers= { { "Line1", "abcdefghijklmno qrs" }
|
|
613
|
+
, { "Line2", "line2\t" }
|
|
614
|
+
}
|
|
615
|
+
,.body= ""
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
#define QUERY_TERMINATED_HOST 21
|
|
620
|
+
, {.name= "host terminated by a query string"
|
|
621
|
+
,.type= HTTP_REQUEST
|
|
622
|
+
,.raw= "GET http://hypnotoad.org?hail=all HTTP/1.1\r\n"
|
|
623
|
+
"\r\n"
|
|
624
|
+
,.should_keep_alive= TRUE
|
|
625
|
+
,.message_complete_on_eof= FALSE
|
|
626
|
+
,.http_major= 1
|
|
627
|
+
,.http_minor= 1
|
|
628
|
+
,.method= HTTP_GET
|
|
629
|
+
,.query_string= "hail=all"
|
|
630
|
+
,.fragment= ""
|
|
631
|
+
,.request_path= ""
|
|
632
|
+
,.request_url= "http://hypnotoad.org?hail=all"
|
|
633
|
+
,.num_headers= 0
|
|
634
|
+
,.headers= { }
|
|
635
|
+
,.body= ""
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
#define QUERY_TERMINATED_HOSTPORT 22
|
|
639
|
+
, {.name= "host:port terminated by a query string"
|
|
640
|
+
,.type= HTTP_REQUEST
|
|
641
|
+
,.raw= "GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n"
|
|
642
|
+
"\r\n"
|
|
643
|
+
,.should_keep_alive= TRUE
|
|
644
|
+
,.message_complete_on_eof= FALSE
|
|
645
|
+
,.http_major= 1
|
|
646
|
+
,.http_minor= 1
|
|
647
|
+
,.method= HTTP_GET
|
|
648
|
+
,.query_string= "hail=all"
|
|
649
|
+
,.fragment= ""
|
|
650
|
+
,.request_path= ""
|
|
651
|
+
,.request_url= "http://hypnotoad.org:1234?hail=all"
|
|
652
|
+
,.port= 1234
|
|
653
|
+
,.num_headers= 0
|
|
654
|
+
,.headers= { }
|
|
655
|
+
,.body= ""
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
#define SPACE_TERMINATED_HOSTPORT 23
|
|
659
|
+
, {.name= "host:port terminated by a space"
|
|
660
|
+
,.type= HTTP_REQUEST
|
|
661
|
+
,.raw= "GET http://hypnotoad.org:1234 HTTP/1.1\r\n"
|
|
662
|
+
"\r\n"
|
|
663
|
+
,.should_keep_alive= TRUE
|
|
664
|
+
,.message_complete_on_eof= FALSE
|
|
665
|
+
,.http_major= 1
|
|
666
|
+
,.http_minor= 1
|
|
667
|
+
,.method= HTTP_GET
|
|
668
|
+
,.query_string= ""
|
|
669
|
+
,.fragment= ""
|
|
670
|
+
,.request_path= ""
|
|
671
|
+
,.request_url= "http://hypnotoad.org:1234"
|
|
672
|
+
,.port= 1234
|
|
673
|
+
,.num_headers= 0
|
|
674
|
+
,.headers= { }
|
|
675
|
+
,.body= ""
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
#define PATCH_REQ 24
|
|
679
|
+
, {.name = "PATCH request"
|
|
680
|
+
,.type= HTTP_REQUEST
|
|
681
|
+
,.raw= "PATCH /file.txt HTTP/1.1\r\n"
|
|
682
|
+
"Host: www.example.com\r\n"
|
|
683
|
+
"Content-Type: application/example\r\n"
|
|
684
|
+
"If-Match: \"e0023aa4e\"\r\n"
|
|
685
|
+
"Content-Length: 10\r\n"
|
|
686
|
+
"\r\n"
|
|
687
|
+
"cccccccccc"
|
|
688
|
+
,.should_keep_alive= TRUE
|
|
689
|
+
,.message_complete_on_eof= FALSE
|
|
690
|
+
,.http_major= 1
|
|
691
|
+
,.http_minor= 1
|
|
692
|
+
,.method= HTTP_PATCH
|
|
693
|
+
,.query_string= ""
|
|
694
|
+
,.fragment= ""
|
|
695
|
+
,.request_path= "/file.txt"
|
|
696
|
+
,.request_url= "/file.txt"
|
|
697
|
+
,.num_headers= 4
|
|
698
|
+
,.headers= { { "Host", "www.example.com" }
|
|
699
|
+
, { "Content-Type", "application/example" }
|
|
700
|
+
, { "If-Match", "\"e0023aa4e\"" }
|
|
701
|
+
, { "Content-Length", "10" }
|
|
702
|
+
}
|
|
703
|
+
,.body= "cccccccccc"
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
#define CONNECT_CAPS_REQUEST 25
|
|
707
|
+
, {.name = "connect caps request"
|
|
708
|
+
,.type= HTTP_REQUEST
|
|
709
|
+
,.raw= "CONNECT HOME0.NETSCAPE.COM:443 HTTP/1.0\r\n"
|
|
710
|
+
"User-agent: Mozilla/1.1N\r\n"
|
|
711
|
+
"Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n"
|
|
712
|
+
"\r\n"
|
|
713
|
+
,.should_keep_alive= FALSE
|
|
714
|
+
,.message_complete_on_eof= FALSE
|
|
715
|
+
,.http_major= 1
|
|
716
|
+
,.http_minor= 0
|
|
717
|
+
,.method= HTTP_CONNECT
|
|
718
|
+
,.query_string= ""
|
|
719
|
+
,.fragment= ""
|
|
720
|
+
,.request_path= ""
|
|
721
|
+
,.request_url= "HOME0.NETSCAPE.COM:443"
|
|
722
|
+
,.num_headers= 2
|
|
723
|
+
,.upgrade=""
|
|
724
|
+
,.headers= { { "User-agent", "Mozilla/1.1N" }
|
|
725
|
+
, { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" }
|
|
726
|
+
}
|
|
727
|
+
,.body= ""
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
#if !HTTP_PARSER_STRICT
|
|
731
|
+
#define UTF8_PATH_REQ 26
|
|
732
|
+
, {.name= "utf-8 path request"
|
|
733
|
+
,.type= HTTP_REQUEST
|
|
734
|
+
,.raw= "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\n"
|
|
735
|
+
"Host: github.com\r\n"
|
|
736
|
+
"\r\n"
|
|
737
|
+
,.should_keep_alive= TRUE
|
|
738
|
+
,.message_complete_on_eof= FALSE
|
|
739
|
+
,.http_major= 1
|
|
740
|
+
,.http_minor= 1
|
|
741
|
+
,.method= HTTP_GET
|
|
742
|
+
,.query_string= "q=1"
|
|
743
|
+
,.fragment= "narf"
|
|
744
|
+
,.request_path= "/δ¶/δt/pope"
|
|
745
|
+
,.request_url= "/δ¶/δt/pope?q=1#narf"
|
|
746
|
+
,.num_headers= 1
|
|
747
|
+
,.headers= { {"Host", "github.com" }
|
|
748
|
+
}
|
|
749
|
+
,.body= ""
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
#define HOSTNAME_UNDERSCORE 27
|
|
753
|
+
, {.name = "hostname underscore"
|
|
754
|
+
,.type= HTTP_REQUEST
|
|
755
|
+
,.raw= "CONNECT home_0.netscape.com:443 HTTP/1.0\r\n"
|
|
756
|
+
"User-agent: Mozilla/1.1N\r\n"
|
|
757
|
+
"Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n"
|
|
758
|
+
"\r\n"
|
|
759
|
+
,.should_keep_alive= FALSE
|
|
760
|
+
,.message_complete_on_eof= FALSE
|
|
761
|
+
,.http_major= 1
|
|
762
|
+
,.http_minor= 0
|
|
763
|
+
,.method= HTTP_CONNECT
|
|
764
|
+
,.query_string= ""
|
|
765
|
+
,.fragment= ""
|
|
766
|
+
,.request_path= ""
|
|
767
|
+
,.request_url= "home_0.netscape.com:443"
|
|
768
|
+
,.num_headers= 2
|
|
769
|
+
,.upgrade=""
|
|
770
|
+
,.headers= { { "User-agent", "Mozilla/1.1N" }
|
|
771
|
+
, { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" }
|
|
772
|
+
}
|
|
773
|
+
,.body= ""
|
|
774
|
+
}
|
|
775
|
+
#endif /* !HTTP_PARSER_STRICT */
|
|
776
|
+
|
|
777
|
+
/* see https://github.com/ry/http-parser/issues/47 */
|
|
778
|
+
#define EAT_TRAILING_CRLF_NO_CONNECTION_CLOSE 28
|
|
779
|
+
, {.name = "eat CRLF between requests, no \"Connection: close\" header"
|
|
780
|
+
,.raw= "POST / HTTP/1.1\r\n"
|
|
781
|
+
"Host: www.example.com\r\n"
|
|
782
|
+
"Content-Type: application/x-www-form-urlencoded\r\n"
|
|
783
|
+
"Content-Length: 4\r\n"
|
|
784
|
+
"\r\n"
|
|
785
|
+
"q=42\r\n" /* note the trailing CRLF */
|
|
786
|
+
,.should_keep_alive= TRUE
|
|
787
|
+
,.message_complete_on_eof= FALSE
|
|
788
|
+
,.http_major= 1
|
|
789
|
+
,.http_minor= 1
|
|
790
|
+
,.method= HTTP_POST
|
|
791
|
+
,.query_string= ""
|
|
792
|
+
,.fragment= ""
|
|
793
|
+
,.request_path= "/"
|
|
794
|
+
,.request_url= "/"
|
|
795
|
+
,.num_headers= 3
|
|
796
|
+
,.upgrade= 0
|
|
797
|
+
,.headers= { { "Host", "www.example.com" }
|
|
798
|
+
, { "Content-Type", "application/x-www-form-urlencoded" }
|
|
799
|
+
, { "Content-Length", "4" }
|
|
800
|
+
}
|
|
801
|
+
,.body= "q=42"
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/* see https://github.com/ry/http-parser/issues/47 */
|
|
805
|
+
#define EAT_TRAILING_CRLF_WITH_CONNECTION_CLOSE 29
|
|
806
|
+
, {.name = "eat CRLF between requests even if \"Connection: close\" is set"
|
|
807
|
+
,.raw= "POST / HTTP/1.1\r\n"
|
|
808
|
+
"Host: www.example.com\r\n"
|
|
809
|
+
"Content-Type: application/x-www-form-urlencoded\r\n"
|
|
810
|
+
"Content-Length: 4\r\n"
|
|
811
|
+
"Connection: close\r\n"
|
|
812
|
+
"\r\n"
|
|
813
|
+
"q=42\r\n" /* note the trailing CRLF */
|
|
814
|
+
,.should_keep_alive= FALSE
|
|
815
|
+
,.message_complete_on_eof= FALSE /* input buffer isn't empty when on_message_complete is called */
|
|
816
|
+
,.http_major= 1
|
|
817
|
+
,.http_minor= 1
|
|
818
|
+
,.method= HTTP_POST
|
|
819
|
+
,.query_string= ""
|
|
820
|
+
,.fragment= ""
|
|
821
|
+
,.request_path= "/"
|
|
822
|
+
,.request_url= "/"
|
|
823
|
+
,.num_headers= 4
|
|
824
|
+
,.upgrade= 0
|
|
825
|
+
,.headers= { { "Host", "www.example.com" }
|
|
826
|
+
, { "Content-Type", "application/x-www-form-urlencoded" }
|
|
827
|
+
, { "Content-Length", "4" }
|
|
828
|
+
, { "Connection", "close" }
|
|
829
|
+
}
|
|
830
|
+
,.body= "q=42"
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
#define PURGE_REQ 30
|
|
834
|
+
, {.name = "PURGE request"
|
|
835
|
+
,.type= HTTP_REQUEST
|
|
836
|
+
,.raw= "PURGE /file.txt HTTP/1.1\r\n"
|
|
837
|
+
"Host: www.example.com\r\n"
|
|
838
|
+
"\r\n"
|
|
839
|
+
,.should_keep_alive= TRUE
|
|
840
|
+
,.message_complete_on_eof= FALSE
|
|
841
|
+
,.http_major= 1
|
|
842
|
+
,.http_minor= 1
|
|
843
|
+
,.method= HTTP_PURGE
|
|
844
|
+
,.query_string= ""
|
|
845
|
+
,.fragment= ""
|
|
846
|
+
,.request_path= "/file.txt"
|
|
847
|
+
,.request_url= "/file.txt"
|
|
848
|
+
,.num_headers= 1
|
|
849
|
+
,.headers= { { "Host", "www.example.com" } }
|
|
850
|
+
,.body= ""
|
|
851
|
+
}
|
|
852
|
+
|
|
585
853
|
, {.name= NULL } /* sentinel */
|
|
586
854
|
};
|
|
587
855
|
|
|
@@ -682,8 +950,8 @@ const struct message responses[] =
|
|
|
682
950
|
, {.name= "404 no headers no body"
|
|
683
951
|
,.type= HTTP_RESPONSE
|
|
684
952
|
,.raw= "HTTP/1.1 404 Not Found\r\n\r\n"
|
|
685
|
-
,.should_keep_alive=
|
|
686
|
-
,.message_complete_on_eof=
|
|
953
|
+
,.should_keep_alive= FALSE
|
|
954
|
+
,.message_complete_on_eof= TRUE
|
|
687
955
|
,.http_major= 1
|
|
688
956
|
,.http_minor= 1
|
|
689
957
|
,.status_code= 404
|
|
@@ -697,8 +965,8 @@ const struct message responses[] =
|
|
|
697
965
|
, {.name= "301 no response phrase"
|
|
698
966
|
,.type= HTTP_RESPONSE
|
|
699
967
|
,.raw= "HTTP/1.1 301\r\n\r\n"
|
|
700
|
-
,.should_keep_alive =
|
|
701
|
-
,.message_complete_on_eof=
|
|
968
|
+
,.should_keep_alive = FALSE
|
|
969
|
+
,.message_complete_on_eof= TRUE
|
|
702
970
|
,.http_major= 1
|
|
703
971
|
,.http_minor= 1
|
|
704
972
|
,.status_code= 301
|
|
@@ -847,40 +1115,7 @@ const struct message responses[] =
|
|
|
847
1115
|
,.body= ""
|
|
848
1116
|
}
|
|
849
1117
|
|
|
850
|
-
#define
|
|
851
|
-
/* Should handle spaces in header fields */
|
|
852
|
-
, {.name= "field space"
|
|
853
|
-
,.type= HTTP_RESPONSE
|
|
854
|
-
,.raw= "HTTP/1.1 200 OK\r\n"
|
|
855
|
-
"Server: Microsoft-IIS/6.0\r\n"
|
|
856
|
-
"X-Powered-By: ASP.NET\r\n"
|
|
857
|
-
"en-US Content-Type: text/xml\r\n" /* this is the problem */
|
|
858
|
-
"Content-Type: text/xml\r\n"
|
|
859
|
-
"Content-Length: 16\r\n"
|
|
860
|
-
"Date: Fri, 23 Jul 2010 18:45:38 GMT\r\n"
|
|
861
|
-
"Connection: keep-alive\r\n"
|
|
862
|
-
"\r\n"
|
|
863
|
-
"<xml>hello</xml>" /* fake body */
|
|
864
|
-
,.should_keep_alive= TRUE
|
|
865
|
-
,.message_complete_on_eof= FALSE
|
|
866
|
-
,.http_major= 1
|
|
867
|
-
,.http_minor= 1
|
|
868
|
-
,.status_code= 200
|
|
869
|
-
,.num_headers= 7
|
|
870
|
-
,.headers=
|
|
871
|
-
{ { "Server", "Microsoft-IIS/6.0" }
|
|
872
|
-
, { "X-Powered-By", "ASP.NET" }
|
|
873
|
-
, { "en-US Content-Type", "text/xml" }
|
|
874
|
-
, { "Content-Type", "text/xml" }
|
|
875
|
-
, { "Content-Length", "16" }
|
|
876
|
-
, { "Date", "Fri, 23 Jul 2010 18:45:38 GMT" }
|
|
877
|
-
, { "Connection", "keep-alive" }
|
|
878
|
-
}
|
|
879
|
-
,.body= "<xml>hello</xml>"
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
#define RES_FIELD_UNDERSCORE 10
|
|
1118
|
+
#define RES_FIELD_UNDERSCORE 9
|
|
884
1119
|
/* Should handle spaces in header fields */
|
|
885
1120
|
, {.name= "field underscore"
|
|
886
1121
|
,.type= HTTP_RESPONSE
|
|
@@ -920,7 +1155,7 @@ const struct message responses[] =
|
|
|
920
1155
|
,.body= ""
|
|
921
1156
|
}
|
|
922
1157
|
|
|
923
|
-
#define NON_ASCII_IN_STATUS_LINE
|
|
1158
|
+
#define NON_ASCII_IN_STATUS_LINE 10
|
|
924
1159
|
/* Should handle non-ASCII in status line */
|
|
925
1160
|
, {.name= "non-ASCII in status line"
|
|
926
1161
|
,.type= HTTP_RESPONSE
|
|
@@ -942,19 +1177,194 @@ const struct message responses[] =
|
|
|
942
1177
|
}
|
|
943
1178
|
,.body= ""
|
|
944
1179
|
}
|
|
945
|
-
|
|
1180
|
+
|
|
1181
|
+
#define HTTP_VERSION_0_9 11
|
|
1182
|
+
/* Should handle HTTP/0.9 */
|
|
1183
|
+
, {.name= "http version 0.9"
|
|
1184
|
+
,.type= HTTP_RESPONSE
|
|
1185
|
+
,.raw= "HTTP/0.9 200 OK\r\n"
|
|
1186
|
+
"\r\n"
|
|
1187
|
+
,.should_keep_alive= FALSE
|
|
1188
|
+
,.message_complete_on_eof= TRUE
|
|
1189
|
+
,.http_major= 0
|
|
1190
|
+
,.http_minor= 9
|
|
1191
|
+
,.status_code= 200
|
|
1192
|
+
,.num_headers= 0
|
|
1193
|
+
,.headers=
|
|
1194
|
+
{}
|
|
1195
|
+
,.body= ""
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
#define NO_CONTENT_LENGTH_NO_TRANSFER_ENCODING_RESPONSE 12
|
|
1199
|
+
/* The client should wait for the server's EOF. That is, when neither
|
|
1200
|
+
* content-length nor transfer-encoding is specified, the end of body
|
|
1201
|
+
* is specified by the EOF.
|
|
1202
|
+
*/
|
|
1203
|
+
, {.name= "neither content-length nor transfer-encoding response"
|
|
1204
|
+
,.type= HTTP_RESPONSE
|
|
1205
|
+
,.raw= "HTTP/1.1 200 OK\r\n"
|
|
1206
|
+
"Content-Type: text/plain\r\n"
|
|
1207
|
+
"\r\n"
|
|
1208
|
+
"hello world"
|
|
1209
|
+
,.should_keep_alive= FALSE
|
|
1210
|
+
,.message_complete_on_eof= TRUE
|
|
1211
|
+
,.http_major= 1
|
|
1212
|
+
,.http_minor= 1
|
|
1213
|
+
,.status_code= 200
|
|
1214
|
+
,.num_headers= 1
|
|
1215
|
+
,.headers=
|
|
1216
|
+
{ { "Content-Type", "text/plain" }
|
|
1217
|
+
}
|
|
1218
|
+
,.body= "hello world"
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
#define NO_BODY_HTTP10_KA_200 13
|
|
1222
|
+
, {.name= "HTTP/1.0 with keep-alive and EOF-terminated 200 status"
|
|
1223
|
+
,.type= HTTP_RESPONSE
|
|
1224
|
+
,.raw= "HTTP/1.0 200 OK\r\n"
|
|
1225
|
+
"Connection: keep-alive\r\n"
|
|
1226
|
+
"\r\n"
|
|
1227
|
+
,.should_keep_alive= FALSE
|
|
1228
|
+
,.message_complete_on_eof= TRUE
|
|
1229
|
+
,.http_major= 1
|
|
1230
|
+
,.http_minor= 0
|
|
1231
|
+
,.status_code= 200
|
|
1232
|
+
,.num_headers= 1
|
|
1233
|
+
,.headers=
|
|
1234
|
+
{ { "Connection", "keep-alive" }
|
|
1235
|
+
}
|
|
1236
|
+
,.body_size= 0
|
|
1237
|
+
,.body= ""
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
#define NO_BODY_HTTP10_KA_204 14
|
|
1241
|
+
, {.name= "HTTP/1.0 with keep-alive and a 204 status"
|
|
1242
|
+
,.type= HTTP_RESPONSE
|
|
1243
|
+
,.raw= "HTTP/1.0 204 No content\r\n"
|
|
1244
|
+
"Connection: keep-alive\r\n"
|
|
1245
|
+
"\r\n"
|
|
1246
|
+
,.should_keep_alive= TRUE
|
|
1247
|
+
,.message_complete_on_eof= FALSE
|
|
1248
|
+
,.http_major= 1
|
|
1249
|
+
,.http_minor= 0
|
|
1250
|
+
,.status_code= 204
|
|
1251
|
+
,.num_headers= 1
|
|
1252
|
+
,.headers=
|
|
1253
|
+
{ { "Connection", "keep-alive" }
|
|
1254
|
+
}
|
|
1255
|
+
,.body_size= 0
|
|
1256
|
+
,.body= ""
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
#define NO_BODY_HTTP11_KA_200 15
|
|
1260
|
+
, {.name= "HTTP/1.1 with an EOF-terminated 200 status"
|
|
1261
|
+
,.type= HTTP_RESPONSE
|
|
1262
|
+
,.raw= "HTTP/1.1 200 OK\r\n"
|
|
1263
|
+
"\r\n"
|
|
1264
|
+
,.should_keep_alive= FALSE
|
|
1265
|
+
,.message_complete_on_eof= TRUE
|
|
1266
|
+
,.http_major= 1
|
|
1267
|
+
,.http_minor= 1
|
|
1268
|
+
,.status_code= 200
|
|
1269
|
+
,.num_headers= 0
|
|
1270
|
+
,.headers={}
|
|
1271
|
+
,.body_size= 0
|
|
1272
|
+
,.body= ""
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
#define NO_BODY_HTTP11_KA_204 16
|
|
1276
|
+
, {.name= "HTTP/1.1 with a 204 status"
|
|
1277
|
+
,.type= HTTP_RESPONSE
|
|
1278
|
+
,.raw= "HTTP/1.1 204 No content\r\n"
|
|
1279
|
+
"\r\n"
|
|
1280
|
+
,.should_keep_alive= TRUE
|
|
1281
|
+
,.message_complete_on_eof= FALSE
|
|
1282
|
+
,.http_major= 1
|
|
1283
|
+
,.http_minor= 1
|
|
1284
|
+
,.status_code= 204
|
|
1285
|
+
,.num_headers= 0
|
|
1286
|
+
,.headers={}
|
|
1287
|
+
,.body_size= 0
|
|
1288
|
+
,.body= ""
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
#define NO_BODY_HTTP11_NOKA_204 17
|
|
1292
|
+
, {.name= "HTTP/1.1 with a 204 status and keep-alive disabled"
|
|
1293
|
+
,.type= HTTP_RESPONSE
|
|
1294
|
+
,.raw= "HTTP/1.1 204 No content\r\n"
|
|
1295
|
+
"Connection: close\r\n"
|
|
1296
|
+
"\r\n"
|
|
1297
|
+
,.should_keep_alive= FALSE
|
|
1298
|
+
,.message_complete_on_eof= FALSE
|
|
1299
|
+
,.http_major= 1
|
|
1300
|
+
,.http_minor= 1
|
|
1301
|
+
,.status_code= 204
|
|
1302
|
+
,.num_headers= 1
|
|
1303
|
+
,.headers=
|
|
1304
|
+
{ { "Connection", "close" }
|
|
1305
|
+
}
|
|
1306
|
+
,.body_size= 0
|
|
1307
|
+
,.body= ""
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
#define NO_BODY_HTTP11_KA_CHUNKED_200 18
|
|
1311
|
+
, {.name= "HTTP/1.1 with chunked endocing and a 200 response"
|
|
1312
|
+
,.type= HTTP_RESPONSE
|
|
1313
|
+
,.raw= "HTTP/1.1 200 OK\r\n"
|
|
1314
|
+
"Transfer-Encoding: chunked\r\n"
|
|
1315
|
+
"\r\n"
|
|
1316
|
+
"0\r\n"
|
|
1317
|
+
"\r\n"
|
|
1318
|
+
,.should_keep_alive= TRUE
|
|
1319
|
+
,.message_complete_on_eof= FALSE
|
|
1320
|
+
,.http_major= 1
|
|
1321
|
+
,.http_minor= 1
|
|
1322
|
+
,.status_code= 200
|
|
1323
|
+
,.num_headers= 1
|
|
1324
|
+
,.headers=
|
|
1325
|
+
{ { "Transfer-Encoding", "chunked" }
|
|
1326
|
+
}
|
|
1327
|
+
,.body_size= 0
|
|
1328
|
+
,.body= ""
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
#if !HTTP_PARSER_STRICT
|
|
1332
|
+
#define SPACE_IN_FIELD_RES 19
|
|
1333
|
+
/* Should handle spaces in header fields */
|
|
1334
|
+
, {.name= "field space"
|
|
1335
|
+
,.type= HTTP_RESPONSE
|
|
1336
|
+
,.raw= "HTTP/1.1 200 OK\r\n"
|
|
1337
|
+
"Server: Microsoft-IIS/6.0\r\n"
|
|
1338
|
+
"X-Powered-By: ASP.NET\r\n"
|
|
1339
|
+
"en-US Content-Type: text/xml\r\n" /* this is the problem */
|
|
1340
|
+
"Content-Type: text/xml\r\n"
|
|
1341
|
+
"Content-Length: 16\r\n"
|
|
1342
|
+
"Date: Fri, 23 Jul 2010 18:45:38 GMT\r\n"
|
|
1343
|
+
"Connection: keep-alive\r\n"
|
|
1344
|
+
"\r\n"
|
|
1345
|
+
"<xml>hello</xml>" /* fake body */
|
|
1346
|
+
,.should_keep_alive= TRUE
|
|
1347
|
+
,.message_complete_on_eof= FALSE
|
|
1348
|
+
,.http_major= 1
|
|
1349
|
+
,.http_minor= 1
|
|
1350
|
+
,.status_code= 200
|
|
1351
|
+
,.num_headers= 7
|
|
1352
|
+
,.headers=
|
|
1353
|
+
{ { "Server", "Microsoft-IIS/6.0" }
|
|
1354
|
+
, { "X-Powered-By", "ASP.NET" }
|
|
1355
|
+
, { "en-US Content-Type", "text/xml" }
|
|
1356
|
+
, { "Content-Type", "text/xml" }
|
|
1357
|
+
, { "Content-Length", "16" }
|
|
1358
|
+
, { "Date", "Fri, 23 Jul 2010 18:45:38 GMT" }
|
|
1359
|
+
, { "Connection", "keep-alive" }
|
|
1360
|
+
}
|
|
1361
|
+
,.body= "<xml>hello</xml>"
|
|
1362
|
+
}
|
|
1363
|
+
#endif /* !HTTP_PARSER_STRICT */
|
|
946
1364
|
|
|
947
1365
|
, {.name= NULL } /* sentinel */
|
|
948
1366
|
};
|
|
949
1367
|
|
|
950
|
-
int
|
|
951
|
-
request_path_cb (http_parser *p, const char *buf, size_t len)
|
|
952
|
-
{
|
|
953
|
-
assert(p == parser);
|
|
954
|
-
strncat(messages[num_messages].request_path, buf, len);
|
|
955
|
-
return 0;
|
|
956
|
-
}
|
|
957
|
-
|
|
958
1368
|
int
|
|
959
1369
|
request_url_cb (http_parser *p, const char *buf, size_t len)
|
|
960
1370
|
{
|
|
@@ -963,22 +1373,6 @@ request_url_cb (http_parser *p, const char *buf, size_t len)
|
|
|
963
1373
|
return 0;
|
|
964
1374
|
}
|
|
965
1375
|
|
|
966
|
-
int
|
|
967
|
-
query_string_cb (http_parser *p, const char *buf, size_t len)
|
|
968
|
-
{
|
|
969
|
-
assert(p == parser);
|
|
970
|
-
strncat(messages[num_messages].query_string, buf, len);
|
|
971
|
-
return 0;
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
int
|
|
975
|
-
fragment_cb (http_parser *p, const char *buf, size_t len)
|
|
976
|
-
{
|
|
977
|
-
assert(p == parser);
|
|
978
|
-
strncat(messages[num_messages].fragment, buf, len);
|
|
979
|
-
return 0;
|
|
980
|
-
}
|
|
981
|
-
|
|
982
1376
|
int
|
|
983
1377
|
header_field_cb (http_parser *p, const char *buf, size_t len)
|
|
984
1378
|
{
|
|
@@ -1068,14 +1462,151 @@ message_complete_cb (http_parser *p)
|
|
|
1068
1462
|
return 0;
|
|
1069
1463
|
}
|
|
1070
1464
|
|
|
1465
|
+
/* These dontcall_* callbacks exist so that we can verify that when we're
|
|
1466
|
+
* paused, no additional callbacks are invoked */
|
|
1467
|
+
int
|
|
1468
|
+
dontcall_message_begin_cb (http_parser *p)
|
|
1469
|
+
{
|
|
1470
|
+
if (p) { } // gcc
|
|
1471
|
+
fprintf(stderr, "\n\n*** on_message_begin() called on paused parser ***\n\n");
|
|
1472
|
+
exit(1);
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
int
|
|
1476
|
+
dontcall_header_field_cb (http_parser *p, const char *buf, size_t len)
|
|
1477
|
+
{
|
|
1478
|
+
if (p || buf || len) { } // gcc
|
|
1479
|
+
fprintf(stderr, "\n\n*** on_header_field() called on paused parser ***\n\n");
|
|
1480
|
+
exit(1);
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
int
|
|
1484
|
+
dontcall_header_value_cb (http_parser *p, const char *buf, size_t len)
|
|
1485
|
+
{
|
|
1486
|
+
if (p || buf || len) { } // gcc
|
|
1487
|
+
fprintf(stderr, "\n\n*** on_header_value() called on paused parser ***\n\n");
|
|
1488
|
+
exit(1);
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
int
|
|
1492
|
+
dontcall_request_url_cb (http_parser *p, const char *buf, size_t len)
|
|
1493
|
+
{
|
|
1494
|
+
if (p || buf || len) { } // gcc
|
|
1495
|
+
fprintf(stderr, "\n\n*** on_request_url() called on paused parser ***\n\n");
|
|
1496
|
+
exit(1);
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
int
|
|
1500
|
+
dontcall_body_cb (http_parser *p, const char *buf, size_t len)
|
|
1501
|
+
{
|
|
1502
|
+
if (p || buf || len) { } // gcc
|
|
1503
|
+
fprintf(stderr, "\n\n*** on_body_cb() called on paused parser ***\n\n");
|
|
1504
|
+
exit(1);
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
int
|
|
1508
|
+
dontcall_headers_complete_cb (http_parser *p)
|
|
1509
|
+
{
|
|
1510
|
+
if (p) { } // gcc
|
|
1511
|
+
fprintf(stderr, "\n\n*** on_headers_complete() called on paused "
|
|
1512
|
+
"parser ***\n\n");
|
|
1513
|
+
exit(1);
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
int
|
|
1517
|
+
dontcall_message_complete_cb (http_parser *p)
|
|
1518
|
+
{
|
|
1519
|
+
if (p) { } // gcc
|
|
1520
|
+
fprintf(stderr, "\n\n*** on_message_complete() called on paused "
|
|
1521
|
+
"parser ***\n\n");
|
|
1522
|
+
exit(1);
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
static http_parser_settings settings_dontcall =
|
|
1526
|
+
{.on_message_begin = dontcall_message_begin_cb
|
|
1527
|
+
,.on_header_field = dontcall_header_field_cb
|
|
1528
|
+
,.on_header_value = dontcall_header_value_cb
|
|
1529
|
+
,.on_url = dontcall_request_url_cb
|
|
1530
|
+
,.on_body = dontcall_body_cb
|
|
1531
|
+
,.on_headers_complete = dontcall_headers_complete_cb
|
|
1532
|
+
,.on_message_complete = dontcall_message_complete_cb
|
|
1533
|
+
};
|
|
1534
|
+
|
|
1535
|
+
/* These pause_* callbacks always pause the parser and just invoke the regular
|
|
1536
|
+
* callback that tracks content. Before returning, we overwrite the parser
|
|
1537
|
+
* settings to point to the _dontcall variety so that we can verify that
|
|
1538
|
+
* the pause actually did, you know, pause. */
|
|
1539
|
+
int
|
|
1540
|
+
pause_message_begin_cb (http_parser *p)
|
|
1541
|
+
{
|
|
1542
|
+
http_parser_pause(p, 1);
|
|
1543
|
+
*current_pause_parser = settings_dontcall;
|
|
1544
|
+
return message_begin_cb(p);
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
int
|
|
1548
|
+
pause_header_field_cb (http_parser *p, const char *buf, size_t len)
|
|
1549
|
+
{
|
|
1550
|
+
http_parser_pause(p, 1);
|
|
1551
|
+
*current_pause_parser = settings_dontcall;
|
|
1552
|
+
return header_field_cb(p, buf, len);
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
int
|
|
1556
|
+
pause_header_value_cb (http_parser *p, const char *buf, size_t len)
|
|
1557
|
+
{
|
|
1558
|
+
http_parser_pause(p, 1);
|
|
1559
|
+
*current_pause_parser = settings_dontcall;
|
|
1560
|
+
return header_value_cb(p, buf, len);
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
int
|
|
1564
|
+
pause_request_url_cb (http_parser *p, const char *buf, size_t len)
|
|
1565
|
+
{
|
|
1566
|
+
http_parser_pause(p, 1);
|
|
1567
|
+
*current_pause_parser = settings_dontcall;
|
|
1568
|
+
return request_url_cb(p, buf, len);
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
int
|
|
1572
|
+
pause_body_cb (http_parser *p, const char *buf, size_t len)
|
|
1573
|
+
{
|
|
1574
|
+
http_parser_pause(p, 1);
|
|
1575
|
+
*current_pause_parser = settings_dontcall;
|
|
1576
|
+
return body_cb(p, buf, len);
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
int
|
|
1580
|
+
pause_headers_complete_cb (http_parser *p)
|
|
1581
|
+
{
|
|
1582
|
+
http_parser_pause(p, 1);
|
|
1583
|
+
*current_pause_parser = settings_dontcall;
|
|
1584
|
+
return headers_complete_cb(p);
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
int
|
|
1588
|
+
pause_message_complete_cb (http_parser *p)
|
|
1589
|
+
{
|
|
1590
|
+
http_parser_pause(p, 1);
|
|
1591
|
+
*current_pause_parser = settings_dontcall;
|
|
1592
|
+
return message_complete_cb(p);
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
static http_parser_settings settings_pause =
|
|
1596
|
+
{.on_message_begin = pause_message_begin_cb
|
|
1597
|
+
,.on_header_field = pause_header_field_cb
|
|
1598
|
+
,.on_header_value = pause_header_value_cb
|
|
1599
|
+
,.on_url = pause_request_url_cb
|
|
1600
|
+
,.on_body = pause_body_cb
|
|
1601
|
+
,.on_headers_complete = pause_headers_complete_cb
|
|
1602
|
+
,.on_message_complete = pause_message_complete_cb
|
|
1603
|
+
};
|
|
1604
|
+
|
|
1071
1605
|
static http_parser_settings settings =
|
|
1072
1606
|
{.on_message_begin = message_begin_cb
|
|
1073
1607
|
,.on_header_field = header_field_cb
|
|
1074
1608
|
,.on_header_value = header_value_cb
|
|
1075
|
-
,.on_path = request_path_cb
|
|
1076
1609
|
,.on_url = request_url_cb
|
|
1077
|
-
,.on_fragment = fragment_cb
|
|
1078
|
-
,.on_query_string = query_string_cb
|
|
1079
1610
|
,.on_body = body_cb
|
|
1080
1611
|
,.on_headers_complete = headers_complete_cb
|
|
1081
1612
|
,.on_message_complete = message_complete_cb
|
|
@@ -1085,10 +1616,7 @@ static http_parser_settings settings_count_body =
|
|
|
1085
1616
|
{.on_message_begin = message_begin_cb
|
|
1086
1617
|
,.on_header_field = header_field_cb
|
|
1087
1618
|
,.on_header_value = header_value_cb
|
|
1088
|
-
,.on_path = request_path_cb
|
|
1089
1619
|
,.on_url = request_url_cb
|
|
1090
|
-
,.on_fragment = fragment_cb
|
|
1091
|
-
,.on_query_string = query_string_cb
|
|
1092
1620
|
,.on_body = count_body_cb
|
|
1093
1621
|
,.on_headers_complete = headers_complete_cb
|
|
1094
1622
|
,.on_message_complete = message_complete_cb
|
|
@@ -1098,10 +1626,7 @@ static http_parser_settings settings_null =
|
|
|
1098
1626
|
{.on_message_begin = 0
|
|
1099
1627
|
,.on_header_field = 0
|
|
1100
1628
|
,.on_header_value = 0
|
|
1101
|
-
,.on_path = 0
|
|
1102
1629
|
,.on_url = 0
|
|
1103
|
-
,.on_fragment = 0
|
|
1104
|
-
,.on_query_string = 0
|
|
1105
1630
|
,.on_body = 0
|
|
1106
1631
|
,.on_headers_complete = 0
|
|
1107
1632
|
,.on_message_complete = 0
|
|
@@ -1146,12 +1671,29 @@ size_t parse_count_body (const char *buf, size_t len)
|
|
|
1146
1671
|
return nparsed;
|
|
1147
1672
|
}
|
|
1148
1673
|
|
|
1674
|
+
size_t parse_pause (const char *buf, size_t len)
|
|
1675
|
+
{
|
|
1676
|
+
size_t nparsed;
|
|
1677
|
+
http_parser_settings s = settings_pause;
|
|
1678
|
+
|
|
1679
|
+
currently_parsing_eof = (len == 0);
|
|
1680
|
+
current_pause_parser = &s;
|
|
1681
|
+
nparsed = http_parser_execute(parser, current_pause_parser, buf, len);
|
|
1682
|
+
return nparsed;
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1149
1685
|
static inline int
|
|
1150
1686
|
check_str_eq (const struct message *m,
|
|
1151
1687
|
const char *prop,
|
|
1152
1688
|
const char *expected,
|
|
1153
1689
|
const char *found) {
|
|
1154
|
-
if (
|
|
1690
|
+
if ((expected == NULL) != (found == NULL)) {
|
|
1691
|
+
printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name);
|
|
1692
|
+
printf("expected %s\n", (expected == NULL) ? "NULL" : expected);
|
|
1693
|
+
printf(" found %s\n", (found == NULL) ? "NULL" : found);
|
|
1694
|
+
return 0;
|
|
1695
|
+
}
|
|
1696
|
+
if (expected != NULL && 0 != strcmp(expected, found)) {
|
|
1155
1697
|
printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name);
|
|
1156
1698
|
printf("expected '%s'\n", expected);
|
|
1157
1699
|
printf(" found '%s'\n", found);
|
|
@@ -1180,6 +1722,20 @@ check_num_eq (const struct message *m,
|
|
|
1180
1722
|
#define MESSAGE_CHECK_NUM_EQ(expected, found, prop) \
|
|
1181
1723
|
if (!check_num_eq(expected, #prop, expected->prop, found->prop)) return 0
|
|
1182
1724
|
|
|
1725
|
+
#define MESSAGE_CHECK_URL_EQ(u, expected, found, prop, fn) \
|
|
1726
|
+
do { \
|
|
1727
|
+
char ubuf[256]; \
|
|
1728
|
+
\
|
|
1729
|
+
if ((u)->field_set & (1 << (fn))) { \
|
|
1730
|
+
memcpy(ubuf, (found)->request_url + (u)->field_data[(fn)].off, \
|
|
1731
|
+
(u)->field_data[(fn)].len); \
|
|
1732
|
+
ubuf[(u)->field_data[(fn)].len] = '\0'; \
|
|
1733
|
+
} else { \
|
|
1734
|
+
ubuf[0] = '\0'; \
|
|
1735
|
+
} \
|
|
1736
|
+
\
|
|
1737
|
+
check_str_eq(expected, #prop, expected->prop, ubuf); \
|
|
1738
|
+
} while(0)
|
|
1183
1739
|
|
|
1184
1740
|
int
|
|
1185
1741
|
message_eq (int index, const struct message *expected)
|
|
@@ -1204,10 +1760,29 @@ message_eq (int index, const struct message *expected)
|
|
|
1204
1760
|
assert(m->message_complete_cb_called);
|
|
1205
1761
|
|
|
1206
1762
|
|
|
1207
|
-
MESSAGE_CHECK_STR_EQ(expected, m, request_path);
|
|
1208
|
-
MESSAGE_CHECK_STR_EQ(expected, m, query_string);
|
|
1209
|
-
MESSAGE_CHECK_STR_EQ(expected, m, fragment);
|
|
1210
1763
|
MESSAGE_CHECK_STR_EQ(expected, m, request_url);
|
|
1764
|
+
|
|
1765
|
+
/* Check URL components; we can't do this w/ CONNECT since it doesn't
|
|
1766
|
+
* send us a well-formed URL.
|
|
1767
|
+
*/
|
|
1768
|
+
if (*m->request_url && m->method != HTTP_CONNECT) {
|
|
1769
|
+
struct http_parser_url u;
|
|
1770
|
+
|
|
1771
|
+
if (http_parser_parse_url(m->request_url, strlen(m->request_url), 0, &u)) {
|
|
1772
|
+
fprintf(stderr, "\n\n*** failed to parse URL %s ***\n\n",
|
|
1773
|
+
m->request_url);
|
|
1774
|
+
exit(1);
|
|
1775
|
+
}
|
|
1776
|
+
|
|
1777
|
+
m->port = (u.field_set & (1 << UF_PORT)) ?
|
|
1778
|
+
u.port : 0;
|
|
1779
|
+
|
|
1780
|
+
MESSAGE_CHECK_URL_EQ(&u, expected, m, query_string, UF_QUERY);
|
|
1781
|
+
MESSAGE_CHECK_URL_EQ(&u, expected, m, fragment, UF_FRAGMENT);
|
|
1782
|
+
MESSAGE_CHECK_URL_EQ(&u, expected, m, request_path, UF_PATH);
|
|
1783
|
+
MESSAGE_CHECK_NUM_EQ(expected, m, port);
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1211
1786
|
if (expected->body_size) {
|
|
1212
1787
|
MESSAGE_CHECK_NUM_EQ(expected, m, body_size);
|
|
1213
1788
|
} else {
|
|
@@ -1224,13 +1799,81 @@ message_eq (int index, const struct message *expected)
|
|
|
1224
1799
|
if (!r) return 0;
|
|
1225
1800
|
}
|
|
1226
1801
|
|
|
1802
|
+
MESSAGE_CHECK_STR_EQ(expected, m, upgrade);
|
|
1803
|
+
|
|
1227
1804
|
return 1;
|
|
1228
1805
|
}
|
|
1229
1806
|
|
|
1807
|
+
/* Given a sequence of varargs messages, return the number of them that the
|
|
1808
|
+
* parser should successfully parse, taking into account that upgraded
|
|
1809
|
+
* messages prevent all subsequent messages from being parsed.
|
|
1810
|
+
*/
|
|
1811
|
+
size_t
|
|
1812
|
+
count_parsed_messages(const size_t nmsgs, ...) {
|
|
1813
|
+
size_t i;
|
|
1814
|
+
va_list ap;
|
|
1815
|
+
|
|
1816
|
+
va_start(ap, nmsgs);
|
|
1817
|
+
|
|
1818
|
+
for (i = 0; i < nmsgs; i++) {
|
|
1819
|
+
struct message *m = va_arg(ap, struct message *);
|
|
1820
|
+
|
|
1821
|
+
if (m->upgrade) {
|
|
1822
|
+
va_end(ap);
|
|
1823
|
+
return i + 1;
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
va_end(ap);
|
|
1828
|
+
return nmsgs;
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
/* Given a sequence of bytes and the number of these that we were able to
|
|
1832
|
+
* parse, verify that upgrade bodies are correct.
|
|
1833
|
+
*/
|
|
1834
|
+
void
|
|
1835
|
+
upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) {
|
|
1836
|
+
va_list ap;
|
|
1837
|
+
size_t i;
|
|
1838
|
+
size_t off = 0;
|
|
1839
|
+
|
|
1840
|
+
va_start(ap, nmsgs);
|
|
1841
|
+
|
|
1842
|
+
for (i = 0; i < nmsgs; i++) {
|
|
1843
|
+
struct message *m = va_arg(ap, struct message *);
|
|
1844
|
+
|
|
1845
|
+
off += strlen(m->raw);
|
|
1846
|
+
|
|
1847
|
+
if (m->upgrade) {
|
|
1848
|
+
off -= strlen(m->upgrade);
|
|
1849
|
+
|
|
1850
|
+
/* Check the portion of the response after its specified upgrade */
|
|
1851
|
+
if (!check_str_eq(m, "upgrade", body + off, body + nread)) {
|
|
1852
|
+
exit(1);
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
/* Fix up the response so that message_eq() will verify the beginning
|
|
1856
|
+
* of the upgrade */
|
|
1857
|
+
*(body + nread + strlen(m->upgrade)) = '\0';
|
|
1858
|
+
messages[num_messages -1 ].upgrade = body + nread;
|
|
1859
|
+
|
|
1860
|
+
va_end(ap);
|
|
1861
|
+
return;
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
va_end(ap);
|
|
1866
|
+
printf("\n\n*** Error: expected a message with upgrade ***\n");
|
|
1867
|
+
|
|
1868
|
+
exit(1);
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1230
1871
|
static void
|
|
1231
1872
|
print_error (const char *raw, size_t error_location)
|
|
1232
1873
|
{
|
|
1233
|
-
fprintf(stderr, "\n***
|
|
1874
|
+
fprintf(stderr, "\n*** %s:%d -- %s ***\n\n",
|
|
1875
|
+
"http_parser.c", HTTP_PARSER_ERRNO_LINE(parser),
|
|
1876
|
+
http_errno_description(HTTP_PARSER_ERRNO(parser)));
|
|
1234
1877
|
|
|
1235
1878
|
int this_line = 0, char_len = 0;
|
|
1236
1879
|
size_t i, j, len = strlen(raw), error_location_line = 0;
|
|
@@ -1268,6 +1911,218 @@ print_error (const char *raw, size_t error_location)
|
|
|
1268
1911
|
fprintf(stderr, "^\n\nerror location: %u\n", (unsigned int)error_location);
|
|
1269
1912
|
}
|
|
1270
1913
|
|
|
1914
|
+
void
|
|
1915
|
+
test_preserve_data (void)
|
|
1916
|
+
{
|
|
1917
|
+
char my_data[] = "application-specific data";
|
|
1918
|
+
http_parser parser;
|
|
1919
|
+
parser.data = my_data;
|
|
1920
|
+
http_parser_init(&parser, HTTP_REQUEST);
|
|
1921
|
+
if (parser.data != my_data) {
|
|
1922
|
+
printf("\n*** parser.data not preserved accross http_parser_init ***\n\n");
|
|
1923
|
+
exit(1);
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
struct url_test {
|
|
1928
|
+
const char *name;
|
|
1929
|
+
const char *url;
|
|
1930
|
+
int is_connect;
|
|
1931
|
+
struct http_parser_url u;
|
|
1932
|
+
int rv;
|
|
1933
|
+
};
|
|
1934
|
+
|
|
1935
|
+
const struct url_test url_tests[] =
|
|
1936
|
+
{ {.name="proxy request"
|
|
1937
|
+
,.url="http://hostname/"
|
|
1938
|
+
,.is_connect=0
|
|
1939
|
+
,.u=
|
|
1940
|
+
{.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH)
|
|
1941
|
+
,.port=0
|
|
1942
|
+
,.field_data=
|
|
1943
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
|
1944
|
+
,{ 7, 8 } /* UF_HOST */
|
|
1945
|
+
,{ 0, 0 } /* UF_PORT */
|
|
1946
|
+
,{ 15, 1 } /* UF_PATH */
|
|
1947
|
+
,{ 0, 0 } /* UF_QUERY */
|
|
1948
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
,.rv=0
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
, {.name="CONNECT request"
|
|
1955
|
+
,.url="hostname:443"
|
|
1956
|
+
,.is_connect=1
|
|
1957
|
+
,.u=
|
|
1958
|
+
{.field_set=(1 << UF_HOST) | (1 << UF_PORT)
|
|
1959
|
+
,.port=443
|
|
1960
|
+
,.field_data=
|
|
1961
|
+
{{ 0, 0 } /* UF_SCHEMA */
|
|
1962
|
+
,{ 0, 8 } /* UF_HOST */
|
|
1963
|
+
,{ 9, 3 } /* UF_PORT */
|
|
1964
|
+
,{ 0, 0 } /* UF_PATH */
|
|
1965
|
+
,{ 0, 0 } /* UF_QUERY */
|
|
1966
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
,.rv=0
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1972
|
+
, {.name="proxy ipv6 request"
|
|
1973
|
+
,.url="http://[1:2::3:4]/"
|
|
1974
|
+
,.is_connect=0
|
|
1975
|
+
,.u=
|
|
1976
|
+
{.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH)
|
|
1977
|
+
,.port=0
|
|
1978
|
+
,.field_data=
|
|
1979
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
|
1980
|
+
,{ 8, 8 } /* UF_HOST */
|
|
1981
|
+
,{ 0, 0 } /* UF_PORT */
|
|
1982
|
+
,{ 17, 1 } /* UF_PATH */
|
|
1983
|
+
,{ 0, 0 } /* UF_QUERY */
|
|
1984
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
,.rv=0
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
, {.name="CONNECT ipv6 address"
|
|
1991
|
+
,.url="[1:2::3:4]:443"
|
|
1992
|
+
,.is_connect=1
|
|
1993
|
+
,.u=
|
|
1994
|
+
{.field_set=(1 << UF_HOST) | (1 << UF_PORT)
|
|
1995
|
+
,.port=443
|
|
1996
|
+
,.field_data=
|
|
1997
|
+
{{ 0, 0 } /* UF_SCHEMA */
|
|
1998
|
+
,{ 1, 8 } /* UF_HOST */
|
|
1999
|
+
,{ 11, 3 } /* UF_PORT */
|
|
2000
|
+
,{ 0, 0 } /* UF_PATH */
|
|
2001
|
+
,{ 0, 0 } /* UF_QUERY */
|
|
2002
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
,.rv=0
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
, {.name="extra ? in query string"
|
|
2009
|
+
,.url="http://a.tbcdn.cn/p/fp/2010c/??fp-header-min.css,fp-base-min.css,fp-channel-min.css,fp-product-min.css,fp-mall-min.css,fp-category-min.css,fp-sub-min.css,fp-gdp4p-min.css,fp-css3-min.css,fp-misc-min.css?t=20101022.css"
|
|
2010
|
+
,.is_connect=0
|
|
2011
|
+
,.u=
|
|
2012
|
+
{.field_set=(1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_QUERY)
|
|
2013
|
+
,.port=0
|
|
2014
|
+
,.field_data=
|
|
2015
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
|
2016
|
+
,{ 7, 10 } /* UF_HOST */
|
|
2017
|
+
,{ 0, 0 } /* UF_PORT */
|
|
2018
|
+
,{ 17, 12 } /* UF_PATH */
|
|
2019
|
+
,{ 30,187 } /* UF_QUERY */
|
|
2020
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
,.rv=0
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
, {.name="proxy empty host"
|
|
2027
|
+
,.url="http://:443/"
|
|
2028
|
+
,.is_connect=0
|
|
2029
|
+
,.rv=1
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2032
|
+
, {.name="proxy empty port"
|
|
2033
|
+
,.url="http://hostname:/"
|
|
2034
|
+
,.is_connect=0
|
|
2035
|
+
,.rv=1
|
|
2036
|
+
}
|
|
2037
|
+
|
|
2038
|
+
, {.name="CONNECT empty host"
|
|
2039
|
+
,.url=":443"
|
|
2040
|
+
,.is_connect=1
|
|
2041
|
+
,.rv=1
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
, {.name="CONNECT empty port"
|
|
2045
|
+
,.url="hostname:"
|
|
2046
|
+
,.is_connect=1
|
|
2047
|
+
,.rv=1
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
, {.name="CONNECT with extra bits"
|
|
2051
|
+
,.url="hostname:443/"
|
|
2052
|
+
,.is_connect=1
|
|
2053
|
+
,.rv=1
|
|
2054
|
+
}
|
|
2055
|
+
};
|
|
2056
|
+
|
|
2057
|
+
void
|
|
2058
|
+
dump_url (const char *url, const struct http_parser_url *u)
|
|
2059
|
+
{
|
|
2060
|
+
char part[512];
|
|
2061
|
+
unsigned int i;
|
|
2062
|
+
|
|
2063
|
+
printf("\tfield_set: 0x%x, port: %u\n", u->field_set, u->port);
|
|
2064
|
+
for (i = 0; i < UF_MAX; i++) {
|
|
2065
|
+
if ((u->field_set & (1 << i)) == 0) {
|
|
2066
|
+
printf("\tfield_data[%u]: unset\n", i);
|
|
2067
|
+
continue;
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
memcpy(part, url + u->field_data[i].off, u->field_data[i].len);
|
|
2071
|
+
part[u->field_data[i].len] = '\0';
|
|
2072
|
+
|
|
2073
|
+
printf("\tfield_data[%u]: off: %u len: %u part: \"%s\"\n",
|
|
2074
|
+
i,
|
|
2075
|
+
u->field_data[i].off,
|
|
2076
|
+
u->field_data[i].len,
|
|
2077
|
+
part);
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
void
|
|
2082
|
+
test_parse_url (void)
|
|
2083
|
+
{
|
|
2084
|
+
struct http_parser_url u;
|
|
2085
|
+
const struct url_test *test;
|
|
2086
|
+
unsigned int i;
|
|
2087
|
+
int rv;
|
|
2088
|
+
|
|
2089
|
+
for (i = 0; i < (sizeof(url_tests) / sizeof(url_tests[0])); i++) {
|
|
2090
|
+
test = &url_tests[i];
|
|
2091
|
+
memset(&u, 0, sizeof(u));
|
|
2092
|
+
|
|
2093
|
+
rv = http_parser_parse_url(test->url,
|
|
2094
|
+
strlen(test->url),
|
|
2095
|
+
test->is_connect,
|
|
2096
|
+
&u);
|
|
2097
|
+
|
|
2098
|
+
if (test->rv == 0) {
|
|
2099
|
+
if (rv != 0) {
|
|
2100
|
+
printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, "
|
|
2101
|
+
"unexpected rv %d ***\n\n", test->url, test->name, rv);
|
|
2102
|
+
exit(1);
|
|
2103
|
+
}
|
|
2104
|
+
|
|
2105
|
+
if (memcmp(&u, &test->u, sizeof(u)) != 0) {
|
|
2106
|
+
printf("\n*** http_parser_parse_url(\"%s\") \"%s\" failed ***\n",
|
|
2107
|
+
test->url, test->name);
|
|
2108
|
+
|
|
2109
|
+
printf("target http_parser_url:\n");
|
|
2110
|
+
dump_url(test->url, &test->u);
|
|
2111
|
+
printf("result http_parser_url:\n");
|
|
2112
|
+
dump_url(test->url, &u);
|
|
2113
|
+
|
|
2114
|
+
exit(1);
|
|
2115
|
+
}
|
|
2116
|
+
} else {
|
|
2117
|
+
/* test->rv != 0 */
|
|
2118
|
+
if (rv == 0) {
|
|
2119
|
+
printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, "
|
|
2120
|
+
"unexpected rv %d ***\n\n", test->url, test->name, rv);
|
|
2121
|
+
exit(1);
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
1271
2126
|
|
|
1272
2127
|
void
|
|
1273
2128
|
test_message (const struct message *message)
|
|
@@ -1285,7 +2140,10 @@ test_message (const struct message *message)
|
|
|
1285
2140
|
if (msg1len) {
|
|
1286
2141
|
read = parse(msg1, msg1len);
|
|
1287
2142
|
|
|
1288
|
-
if (message->upgrade && parser->upgrade)
|
|
2143
|
+
if (message->upgrade && parser->upgrade) {
|
|
2144
|
+
messages[num_messages - 1].upgrade = msg1 + read;
|
|
2145
|
+
goto test;
|
|
2146
|
+
}
|
|
1289
2147
|
|
|
1290
2148
|
if (read != msg1len) {
|
|
1291
2149
|
print_error(msg1, read);
|
|
@@ -1296,7 +2154,10 @@ test_message (const struct message *message)
|
|
|
1296
2154
|
|
|
1297
2155
|
read = parse(msg2, msg2len);
|
|
1298
2156
|
|
|
1299
|
-
if (message->upgrade && parser->upgrade)
|
|
2157
|
+
if (message->upgrade && parser->upgrade) {
|
|
2158
|
+
messages[num_messages - 1].upgrade = msg2 + read;
|
|
2159
|
+
goto test;
|
|
2160
|
+
}
|
|
1300
2161
|
|
|
1301
2162
|
if (read != msg2len) {
|
|
1302
2163
|
print_error(msg2, read);
|
|
@@ -1305,8 +2166,6 @@ test_message (const struct message *message)
|
|
|
1305
2166
|
|
|
1306
2167
|
read = parse(NULL, 0);
|
|
1307
2168
|
|
|
1308
|
-
if (message->upgrade && parser->upgrade) goto test;
|
|
1309
|
-
|
|
1310
2169
|
if (read != 0) {
|
|
1311
2170
|
print_error(message->raw, read);
|
|
1312
2171
|
exit(1);
|
|
@@ -1362,21 +2221,32 @@ test_message_count_body (const struct message *message)
|
|
|
1362
2221
|
}
|
|
1363
2222
|
|
|
1364
2223
|
void
|
|
1365
|
-
test_simple (const char *buf,
|
|
2224
|
+
test_simple (const char *buf, enum http_errno err_expected)
|
|
1366
2225
|
{
|
|
1367
2226
|
parser_init(HTTP_REQUEST);
|
|
1368
2227
|
|
|
1369
2228
|
size_t parsed;
|
|
1370
2229
|
int pass;
|
|
2230
|
+
enum http_errno err;
|
|
2231
|
+
|
|
1371
2232
|
parsed = parse(buf, strlen(buf));
|
|
1372
2233
|
pass = (parsed == strlen(buf));
|
|
2234
|
+
err = HTTP_PARSER_ERRNO(parser);
|
|
1373
2235
|
parsed = parse(NULL, 0);
|
|
1374
2236
|
pass &= (parsed == 0);
|
|
1375
2237
|
|
|
1376
2238
|
parser_free();
|
|
1377
2239
|
|
|
1378
|
-
|
|
1379
|
-
|
|
2240
|
+
/* In strict mode, allow us to pass with an unexpected HPE_STRICT as
|
|
2241
|
+
* long as the caller isn't expecting success.
|
|
2242
|
+
*/
|
|
2243
|
+
#if HTTP_PARSER_STRICT
|
|
2244
|
+
if (err_expected != err && err_expected != HPE_OK && err != HPE_STRICT) {
|
|
2245
|
+
#else
|
|
2246
|
+
if (err_expected != err) {
|
|
2247
|
+
#endif
|
|
2248
|
+
fprintf(stderr, "\n*** test_simple expected %s, but saw %s ***\n\n%s\n",
|
|
2249
|
+
http_errno_name(err_expected), http_errno_name(err), buf);
|
|
1380
2250
|
exit(1);
|
|
1381
2251
|
}
|
|
1382
2252
|
}
|
|
@@ -1393,10 +2263,14 @@ test_header_overflow_error (int req)
|
|
|
1393
2263
|
assert(parsed == strlen(buf));
|
|
1394
2264
|
|
|
1395
2265
|
buf = "header-key: header-value\r\n";
|
|
2266
|
+
size_t buflen = strlen(buf);
|
|
2267
|
+
|
|
1396
2268
|
int i;
|
|
1397
2269
|
for (i = 0; i < 10000; i++) {
|
|
1398
|
-
|
|
2270
|
+
parsed = http_parser_execute(&parser, &settings_null, buf, buflen);
|
|
2271
|
+
if (parsed != buflen) {
|
|
1399
2272
|
//fprintf(stderr, "error found on iter %d\n", i);
|
|
2273
|
+
assert(HTTP_PARSER_ERRNO(&parser) == HPE_HEADER_OVERFLOW);
|
|
1400
2274
|
return;
|
|
1401
2275
|
}
|
|
1402
2276
|
}
|
|
@@ -1405,6 +2279,53 @@ test_header_overflow_error (int req)
|
|
|
1405
2279
|
exit(1);
|
|
1406
2280
|
}
|
|
1407
2281
|
|
|
2282
|
+
static void
|
|
2283
|
+
test_content_length_overflow (const char *buf, size_t buflen, int expect_ok)
|
|
2284
|
+
{
|
|
2285
|
+
http_parser parser;
|
|
2286
|
+
http_parser_init(&parser, HTTP_RESPONSE);
|
|
2287
|
+
http_parser_execute(&parser, &settings_null, buf, buflen);
|
|
2288
|
+
|
|
2289
|
+
if (expect_ok)
|
|
2290
|
+
assert(HTTP_PARSER_ERRNO(&parser) == HPE_OK);
|
|
2291
|
+
else
|
|
2292
|
+
assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_CONTENT_LENGTH);
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2295
|
+
void
|
|
2296
|
+
test_header_content_length_overflow_error (void)
|
|
2297
|
+
{
|
|
2298
|
+
#define X(size) \
|
|
2299
|
+
"HTTP/1.1 200 OK\r\n" \
|
|
2300
|
+
"Content-Length: " #size "\r\n" \
|
|
2301
|
+
"\r\n"
|
|
2302
|
+
const char a[] = X(18446744073709551614); /* 2^64-2 */
|
|
2303
|
+
const char b[] = X(18446744073709551615); /* 2^64-1 */
|
|
2304
|
+
const char c[] = X(18446744073709551616); /* 2^64 */
|
|
2305
|
+
#undef X
|
|
2306
|
+
test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */
|
|
2307
|
+
test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */
|
|
2308
|
+
test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
void
|
|
2312
|
+
test_chunk_content_length_overflow_error (void)
|
|
2313
|
+
{
|
|
2314
|
+
#define X(size) \
|
|
2315
|
+
"HTTP/1.1 200 OK\r\n" \
|
|
2316
|
+
"Transfer-Encoding: chunked\r\n" \
|
|
2317
|
+
"\r\n" \
|
|
2318
|
+
#size "\r\n" \
|
|
2319
|
+
"..."
|
|
2320
|
+
const char a[] = X(FFFFFFFFFFFFFFFE); /* 2^64-2 */
|
|
2321
|
+
const char b[] = X(FFFFFFFFFFFFFFFF); /* 2^64-1 */
|
|
2322
|
+
const char c[] = X(10000000000000000); /* 2^64 */
|
|
2323
|
+
#undef X
|
|
2324
|
+
test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */
|
|
2325
|
+
test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */
|
|
2326
|
+
test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */
|
|
2327
|
+
}
|
|
2328
|
+
|
|
1408
2329
|
void
|
|
1409
2330
|
test_no_overflow_long_body (int req, size_t length)
|
|
1410
2331
|
{
|
|
@@ -1441,12 +2362,7 @@ test_no_overflow_long_body (int req, size_t length)
|
|
|
1441
2362
|
void
|
|
1442
2363
|
test_multiple3 (const struct message *r1, const struct message *r2, const struct message *r3)
|
|
1443
2364
|
{
|
|
1444
|
-
int message_count =
|
|
1445
|
-
if (!r1->upgrade) {
|
|
1446
|
-
message_count++;
|
|
1447
|
-
if (!r2->upgrade) message_count++;
|
|
1448
|
-
}
|
|
1449
|
-
int has_upgrade = (message_count < 3 || r3->upgrade);
|
|
2365
|
+
int message_count = count_parsed_messages(3, r1, r2, r3);
|
|
1450
2366
|
|
|
1451
2367
|
char total[ strlen(r1->raw)
|
|
1452
2368
|
+ strlen(r2->raw)
|
|
@@ -1465,7 +2381,10 @@ test_multiple3 (const struct message *r1, const struct message *r2, const struct
|
|
|
1465
2381
|
|
|
1466
2382
|
read = parse(total, strlen(total));
|
|
1467
2383
|
|
|
1468
|
-
if (
|
|
2384
|
+
if (parser->upgrade) {
|
|
2385
|
+
upgrade_message_fix(total, read, 3, r1, r2, r3);
|
|
2386
|
+
goto test;
|
|
2387
|
+
}
|
|
1469
2388
|
|
|
1470
2389
|
if (read != strlen(total)) {
|
|
1471
2390
|
print_error(total, read);
|
|
@@ -1474,8 +2393,6 @@ test_multiple3 (const struct message *r1, const struct message *r2, const struct
|
|
|
1474
2393
|
|
|
1475
2394
|
read = parse(NULL, 0);
|
|
1476
2395
|
|
|
1477
|
-
if (has_upgrade && parser->upgrade) goto test;
|
|
1478
|
-
|
|
1479
2396
|
if (read != 0) {
|
|
1480
2397
|
print_error(total, read);
|
|
1481
2398
|
exit(1);
|
|
@@ -1489,12 +2406,8 @@ test:
|
|
|
1489
2406
|
}
|
|
1490
2407
|
|
|
1491
2408
|
if (!message_eq(0, r1)) exit(1);
|
|
1492
|
-
if (message_count > 1)
|
|
1493
|
-
|
|
1494
|
-
if (message_count > 2) {
|
|
1495
|
-
if (!message_eq(2, r3)) exit(1);
|
|
1496
|
-
}
|
|
1497
|
-
}
|
|
2409
|
+
if (message_count > 1 && !message_eq(1, r2)) exit(1);
|
|
2410
|
+
if (message_count > 2 && !message_eq(2, r3)) exit(1);
|
|
1498
2411
|
|
|
1499
2412
|
parser_free();
|
|
1500
2413
|
}
|
|
@@ -1523,6 +2436,7 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
|
|
|
1523
2436
|
int ops = 0 ;
|
|
1524
2437
|
|
|
1525
2438
|
size_t buf1_len, buf2_len, buf3_len;
|
|
2439
|
+
int message_count = count_parsed_messages(3, r1, r2, r3);
|
|
1526
2440
|
|
|
1527
2441
|
int i,j,type_both;
|
|
1528
2442
|
for (type_both = 0; type_both < 2; type_both ++ ) {
|
|
@@ -1551,27 +2465,27 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
|
|
|
1551
2465
|
|
|
1552
2466
|
read = parse(buf1, buf1_len);
|
|
1553
2467
|
|
|
1554
|
-
if (
|
|
2468
|
+
if (parser->upgrade) goto test;
|
|
1555
2469
|
|
|
1556
2470
|
if (read != buf1_len) {
|
|
1557
2471
|
print_error(buf1, read);
|
|
1558
2472
|
goto error;
|
|
1559
2473
|
}
|
|
1560
2474
|
|
|
1561
|
-
read
|
|
2475
|
+
read += parse(buf2, buf2_len);
|
|
1562
2476
|
|
|
1563
|
-
if (
|
|
2477
|
+
if (parser->upgrade) goto test;
|
|
1564
2478
|
|
|
1565
|
-
if (read != buf2_len) {
|
|
2479
|
+
if (read != buf1_len + buf2_len) {
|
|
1566
2480
|
print_error(buf2, read);
|
|
1567
2481
|
goto error;
|
|
1568
2482
|
}
|
|
1569
2483
|
|
|
1570
|
-
read
|
|
2484
|
+
read += parse(buf3, buf3_len);
|
|
1571
2485
|
|
|
1572
|
-
if (
|
|
2486
|
+
if (parser->upgrade) goto test;
|
|
1573
2487
|
|
|
1574
|
-
if (read != buf3_len) {
|
|
2488
|
+
if (read != buf1_len + buf2_len + buf3_len) {
|
|
1575
2489
|
print_error(buf3, read);
|
|
1576
2490
|
goto error;
|
|
1577
2491
|
}
|
|
@@ -1579,9 +2493,13 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
|
|
|
1579
2493
|
parse(NULL, 0);
|
|
1580
2494
|
|
|
1581
2495
|
test:
|
|
2496
|
+
if (parser->upgrade) {
|
|
2497
|
+
upgrade_message_fix(total, read, 3, r1, r2, r3);
|
|
2498
|
+
}
|
|
1582
2499
|
|
|
1583
|
-
if (
|
|
1584
|
-
fprintf(stderr, "\n\nParser didn't see
|
|
2500
|
+
if (message_count != num_messages) {
|
|
2501
|
+
fprintf(stderr, "\n\nParser didn't see %d messages only %d\n",
|
|
2502
|
+
message_count, num_messages);
|
|
1585
2503
|
goto error;
|
|
1586
2504
|
}
|
|
1587
2505
|
|
|
@@ -1590,12 +2508,12 @@ test:
|
|
|
1590
2508
|
goto error;
|
|
1591
2509
|
}
|
|
1592
2510
|
|
|
1593
|
-
if (!message_eq(1, r2)) {
|
|
2511
|
+
if (message_count > 1 && !message_eq(1, r2)) {
|
|
1594
2512
|
fprintf(stderr, "\n\nError matching messages[1] in test_scan.\n");
|
|
1595
2513
|
goto error;
|
|
1596
2514
|
}
|
|
1597
2515
|
|
|
1598
|
-
if (!message_eq(2, r3)) {
|
|
2516
|
+
if (message_count > 2 && !message_eq(2, r3)) {
|
|
1599
2517
|
fprintf(stderr, "\n\nError matching messages[2] in test_scan.\n");
|
|
1600
2518
|
goto error;
|
|
1601
2519
|
}
|
|
@@ -1646,6 +2564,58 @@ create_large_chunked_message (int body_size_in_kb, const char* headers)
|
|
|
1646
2564
|
return buf;
|
|
1647
2565
|
}
|
|
1648
2566
|
|
|
2567
|
+
/* Verify that we can pause parsing at any of the bytes in the
|
|
2568
|
+
* message and still get the result that we're expecting. */
|
|
2569
|
+
void
|
|
2570
|
+
test_message_pause (const struct message *msg)
|
|
2571
|
+
{
|
|
2572
|
+
char *buf = (char*) msg->raw;
|
|
2573
|
+
size_t buflen = strlen(msg->raw);
|
|
2574
|
+
size_t nread;
|
|
2575
|
+
|
|
2576
|
+
parser_init(msg->type);
|
|
2577
|
+
|
|
2578
|
+
do {
|
|
2579
|
+
nread = parse_pause(buf, buflen);
|
|
2580
|
+
|
|
2581
|
+
// We can only set the upgrade buffer once we've gotten our message
|
|
2582
|
+
// completion callback.
|
|
2583
|
+
if (messages[0].message_complete_cb_called &&
|
|
2584
|
+
msg->upgrade &&
|
|
2585
|
+
parser->upgrade) {
|
|
2586
|
+
messages[0].upgrade = buf + nread;
|
|
2587
|
+
goto test;
|
|
2588
|
+
}
|
|
2589
|
+
|
|
2590
|
+
if (nread < buflen) {
|
|
2591
|
+
|
|
2592
|
+
// Not much do to if we failed a strict-mode check
|
|
2593
|
+
if (HTTP_PARSER_ERRNO(parser) == HPE_STRICT) {
|
|
2594
|
+
parser_free();
|
|
2595
|
+
return;
|
|
2596
|
+
}
|
|
2597
|
+
|
|
2598
|
+
assert (HTTP_PARSER_ERRNO(parser) == HPE_PAUSED);
|
|
2599
|
+
}
|
|
2600
|
+
|
|
2601
|
+
buf += nread;
|
|
2602
|
+
buflen -= nread;
|
|
2603
|
+
http_parser_pause(parser, 0);
|
|
2604
|
+
} while (buflen > 0);
|
|
2605
|
+
|
|
2606
|
+
nread = parse_pause(NULL, 0);
|
|
2607
|
+
assert (nread == 0);
|
|
2608
|
+
|
|
2609
|
+
test:
|
|
2610
|
+
if (num_messages != 1) {
|
|
2611
|
+
printf("\n*** num_messages != 1 after testing '%s' ***\n\n", msg->name);
|
|
2612
|
+
exit(1);
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2615
|
+
if(!message_eq(0, msg)) exit(1);
|
|
2616
|
+
|
|
2617
|
+
parser_free();
|
|
2618
|
+
}
|
|
1649
2619
|
|
|
1650
2620
|
int
|
|
1651
2621
|
main (void)
|
|
@@ -1660,6 +2630,10 @@ main (void)
|
|
|
1660
2630
|
for (request_count = 0; requests[request_count].name; request_count++);
|
|
1661
2631
|
for (response_count = 0; responses[response_count].name; response_count++);
|
|
1662
2632
|
|
|
2633
|
+
//// API
|
|
2634
|
+
test_preserve_data();
|
|
2635
|
+
test_parse_url();
|
|
2636
|
+
|
|
1663
2637
|
//// OVERFLOW CONDITIONS
|
|
1664
2638
|
|
|
1665
2639
|
test_header_overflow_error(HTTP_REQUEST);
|
|
@@ -1670,12 +2644,19 @@ main (void)
|
|
|
1670
2644
|
test_no_overflow_long_body(HTTP_RESPONSE, 1000);
|
|
1671
2645
|
test_no_overflow_long_body(HTTP_RESPONSE, 100000);
|
|
1672
2646
|
|
|
2647
|
+
test_header_content_length_overflow_error();
|
|
2648
|
+
test_chunk_content_length_overflow_error();
|
|
2649
|
+
|
|
1673
2650
|
//// RESPONSES
|
|
1674
2651
|
|
|
1675
2652
|
for (i = 0; i < response_count; i++) {
|
|
1676
2653
|
test_message(&responses[i]);
|
|
1677
2654
|
}
|
|
1678
2655
|
|
|
2656
|
+
for (i = 0; i < response_count; i++) {
|
|
2657
|
+
test_message_pause(&responses[i]);
|
|
2658
|
+
}
|
|
2659
|
+
|
|
1679
2660
|
for (i = 0; i < response_count; i++) {
|
|
1680
2661
|
if (!responses[i].should_keep_alive) continue;
|
|
1681
2662
|
for (j = 0; j < response_count; j++) {
|
|
@@ -1720,7 +2701,7 @@ main (void)
|
|
|
1720
2701
|
|
|
1721
2702
|
printf("response scan 1/2 ");
|
|
1722
2703
|
test_scan( &responses[TRAILING_SPACE_ON_CHUNKED_BODY]
|
|
1723
|
-
, &responses[
|
|
2704
|
+
, &responses[NO_BODY_HTTP10_KA_204]
|
|
1724
2705
|
, &responses[NO_REASON_PHRASE]
|
|
1725
2706
|
);
|
|
1726
2707
|
|
|
@@ -1735,13 +2716,21 @@ main (void)
|
|
|
1735
2716
|
|
|
1736
2717
|
/// REQUESTS
|
|
1737
2718
|
|
|
2719
|
+
test_simple("hello world", HPE_INVALID_METHOD);
|
|
2720
|
+
test_simple("GET / HTP/1.1\r\n\r\n", HPE_INVALID_VERSION);
|
|
1738
2721
|
|
|
1739
|
-
test_simple("hello world", 0);
|
|
1740
|
-
test_simple("GET / HTP/1.1\r\n\r\n", 0);
|
|
1741
2722
|
|
|
1742
|
-
test_simple("ASDF / HTTP/1.1\r\n\r\n",
|
|
1743
|
-
test_simple("PROPPATCHA / HTTP/1.1\r\n\r\n",
|
|
1744
|
-
test_simple("GETA / HTTP/1.1\r\n\r\n",
|
|
2723
|
+
test_simple("ASDF / HTTP/1.1\r\n\r\n", HPE_INVALID_METHOD);
|
|
2724
|
+
test_simple("PROPPATCHA / HTTP/1.1\r\n\r\n", HPE_INVALID_METHOD);
|
|
2725
|
+
test_simple("GETA / HTTP/1.1\r\n\r\n", HPE_INVALID_METHOD);
|
|
2726
|
+
|
|
2727
|
+
// Well-formed but incomplete
|
|
2728
|
+
test_simple("GET / HTTP/1.1\r\n"
|
|
2729
|
+
"Content-Type: text/plain\r\n"
|
|
2730
|
+
"Content-Length: 6\r\n"
|
|
2731
|
+
"\r\n"
|
|
2732
|
+
"fooba",
|
|
2733
|
+
HPE_OK);
|
|
1745
2734
|
|
|
1746
2735
|
static const char *all_methods[] = {
|
|
1747
2736
|
"DELETE",
|
|
@@ -1759,12 +2748,31 @@ main (void)
|
|
|
1759
2748
|
"PROPFIND",
|
|
1760
2749
|
"PROPPATCH",
|
|
1761
2750
|
"UNLOCK",
|
|
2751
|
+
"REPORT",
|
|
2752
|
+
"MKACTIVITY",
|
|
2753
|
+
"CHECKOUT",
|
|
2754
|
+
"MERGE",
|
|
2755
|
+
"M-SEARCH",
|
|
2756
|
+
"NOTIFY",
|
|
2757
|
+
"SUBSCRIBE",
|
|
2758
|
+
"UNSUBSCRIBE",
|
|
2759
|
+
"PATCH",
|
|
1762
2760
|
0 };
|
|
1763
2761
|
const char **this_method;
|
|
1764
2762
|
for (this_method = all_methods; *this_method; this_method++) {
|
|
1765
2763
|
char buf[200];
|
|
1766
2764
|
sprintf(buf, "%s / HTTP/1.1\r\n\r\n", *this_method);
|
|
1767
|
-
test_simple(buf,
|
|
2765
|
+
test_simple(buf, HPE_OK);
|
|
2766
|
+
}
|
|
2767
|
+
|
|
2768
|
+
static const char *bad_methods[] = {
|
|
2769
|
+
"C******",
|
|
2770
|
+
"M****",
|
|
2771
|
+
0 };
|
|
2772
|
+
for (this_method = bad_methods; *this_method; this_method++) {
|
|
2773
|
+
char buf[200];
|
|
2774
|
+
sprintf(buf, "%s / HTTP/1.1\r\n\r\n", *this_method);
|
|
2775
|
+
test_simple(buf, HPE_UNKNOWN);
|
|
1768
2776
|
}
|
|
1769
2777
|
|
|
1770
2778
|
const char *dumbfuck2 =
|
|
@@ -1802,7 +2810,7 @@ main (void)
|
|
|
1802
2810
|
"\tRA==\r\n"
|
|
1803
2811
|
"\t-----END CERTIFICATE-----\r\n"
|
|
1804
2812
|
"\r\n";
|
|
1805
|
-
test_simple(dumbfuck2,
|
|
2813
|
+
test_simple(dumbfuck2, HPE_OK);
|
|
1806
2814
|
|
|
1807
2815
|
#if 0
|
|
1808
2816
|
// NOTE(Wed Nov 18 11:57:27 CET 2009) this seems okay. we just read body
|
|
@@ -1824,7 +2832,9 @@ main (void)
|
|
|
1824
2832
|
test_message(&requests[i]);
|
|
1825
2833
|
}
|
|
1826
2834
|
|
|
1827
|
-
|
|
2835
|
+
for (i = 0; i < request_count; i++) {
|
|
2836
|
+
test_message_pause(&requests[i]);
|
|
2837
|
+
}
|
|
1828
2838
|
|
|
1829
2839
|
for (i = 0; i < request_count; i++) {
|
|
1830
2840
|
if (!requests[i].should_keep_alive) continue;
|