http_parser.rb 0.6.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/.github/workflows/linux.yml +23 -0
- data/.github/workflows/windows.yml +23 -0
- data/.gitignore +5 -4
- data/.gitmodules +2 -2
- data/README.md +2 -2
- data/Rakefile +4 -2
- data/ext/ruby_http_parser/extconf.rb +1 -1
- data/ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java +8 -1
- data/ext/ruby_http_parser/ruby_http_parser.c +53 -7
- data/ext/ruby_http_parser/vendor/http-parser/AUTHORS +37 -1
- data/ext/ruby_http_parser/vendor/http-parser/LICENSE-MIT +1 -5
- data/ext/ruby_http_parser/vendor/http-parser/Makefile +110 -8
- data/ext/ruby_http_parser/vendor/http-parser/README.md +105 -37
- data/ext/ruby_http_parser/vendor/http-parser/bench.c +128 -0
- data/ext/ruby_http_parser/vendor/http-parser/contrib/parsertrace.c +157 -0
- data/ext/ruby_http_parser/vendor/http-parser/contrib/url_parser.c +47 -0
- data/ext/ruby_http_parser/vendor/http-parser/http_parser.c +892 -510
- data/ext/ruby_http_parser/vendor/http-parser/http_parser.gyp +34 -2
- data/ext/ruby_http_parser/vendor/http-parser/http_parser.h +198 -77
- data/ext/ruby_http_parser/vendor/http-parser/test.c +1781 -201
- data/http_parser.rb.gemspec +13 -9
- data/spec/parser_spec.rb +176 -98
- data/spec/support/requests.json +2 -2
- data/spec/support/responses.json +20 -0
- data/tasks/spec.rake +1 -1
- metadata +64 -63
- data/Gemfile.lock +0 -39
- data/ext/ruby_http_parser/vendor/http-parser/CONTRIBUTIONS +0 -4
@@ -26,16 +26,23 @@
|
|
26
26
|
#include <string.h>
|
27
27
|
#include <stdarg.h>
|
28
28
|
|
29
|
+
#if defined(__APPLE__)
|
30
|
+
# undef strlncpy
|
31
|
+
#endif /* defined(__APPLE__) */
|
32
|
+
|
29
33
|
#undef TRUE
|
30
34
|
#define TRUE 1
|
31
35
|
#undef FALSE
|
32
36
|
#define FALSE 0
|
33
37
|
|
34
38
|
#define MAX_HEADERS 13
|
35
|
-
#define MAX_ELEMENT_SIZE
|
39
|
+
#define MAX_ELEMENT_SIZE 2048
|
40
|
+
#define MAX_CHUNKS 16
|
36
41
|
|
37
42
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
38
43
|
|
44
|
+
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
|
45
|
+
|
39
46
|
static http_parser *parser;
|
40
47
|
|
41
48
|
struct message {
|
@@ -44,18 +51,25 @@ struct message {
|
|
44
51
|
enum http_parser_type type;
|
45
52
|
enum http_method method;
|
46
53
|
int status_code;
|
54
|
+
char response_status[MAX_ELEMENT_SIZE];
|
47
55
|
char request_path[MAX_ELEMENT_SIZE];
|
48
56
|
char request_url[MAX_ELEMENT_SIZE];
|
49
57
|
char fragment[MAX_ELEMENT_SIZE];
|
50
58
|
char query_string[MAX_ELEMENT_SIZE];
|
51
59
|
char body[MAX_ELEMENT_SIZE];
|
52
60
|
size_t body_size;
|
61
|
+
const char *host;
|
62
|
+
const char *userinfo;
|
53
63
|
uint16_t port;
|
54
64
|
int num_headers;
|
55
65
|
enum { NONE=0, FIELD, VALUE } last_header_element;
|
56
66
|
char headers [MAX_HEADERS][2][MAX_ELEMENT_SIZE];
|
57
67
|
int should_keep_alive;
|
58
68
|
|
69
|
+
int num_chunks;
|
70
|
+
int num_chunks_complete;
|
71
|
+
int chunk_lengths[MAX_CHUNKS];
|
72
|
+
|
59
73
|
const char *upgrade; // upgraded body
|
60
74
|
|
61
75
|
unsigned short http_major;
|
@@ -64,7 +78,9 @@ struct message {
|
|
64
78
|
int message_begin_cb_called;
|
65
79
|
int headers_complete_cb_called;
|
66
80
|
int message_complete_cb_called;
|
81
|
+
int status_cb_called;
|
67
82
|
int message_complete_on_eof;
|
83
|
+
int body_is_final;
|
68
84
|
};
|
69
85
|
|
70
86
|
static int currently_parsing_eof;
|
@@ -291,6 +307,8 @@ const struct message requests[] =
|
|
291
307
|
{ { "Transfer-Encoding" , "chunked" }
|
292
308
|
}
|
293
309
|
,.body= "all your base are belong to us"
|
310
|
+
,.num_chunks_complete= 2
|
311
|
+
,.chunk_lengths= { 0x1e }
|
294
312
|
}
|
295
313
|
|
296
314
|
#define TWO_CHUNKS_MULT_ZERO_END 9
|
@@ -317,6 +335,8 @@ const struct message requests[] =
|
|
317
335
|
{ { "Transfer-Encoding", "chunked" }
|
318
336
|
}
|
319
337
|
,.body= "hello world"
|
338
|
+
,.num_chunks_complete= 3
|
339
|
+
,.chunk_lengths= { 5, 6 }
|
320
340
|
}
|
321
341
|
|
322
342
|
#define CHUNKED_W_TRAILING_HEADERS 10
|
@@ -347,6 +367,8 @@ const struct message requests[] =
|
|
347
367
|
, { "Content-Type", "text/plain" }
|
348
368
|
}
|
349
369
|
,.body= "hello world"
|
370
|
+
,.num_chunks_complete= 3
|
371
|
+
,.chunk_lengths= { 5, 6 }
|
350
372
|
}
|
351
373
|
|
352
374
|
#define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11
|
@@ -373,6 +395,8 @@ const struct message requests[] =
|
|
373
395
|
{ { "Transfer-Encoding", "chunked" }
|
374
396
|
}
|
375
397
|
,.body= "hello world"
|
398
|
+
,.num_chunks_complete= 3
|
399
|
+
,.chunk_lengths= { 5, 6 }
|
376
400
|
}
|
377
401
|
|
378
402
|
#define WITH_QUOTES 12
|
@@ -587,7 +611,7 @@ const struct message requests[] =
|
|
587
611
|
,.body= ""
|
588
612
|
}
|
589
613
|
|
590
|
-
#define LINE_FOLDING_IN_HEADER
|
614
|
+
#define LINE_FOLDING_IN_HEADER 21
|
591
615
|
, {.name= "line folding in header value"
|
592
616
|
,.type= HTTP_REQUEST
|
593
617
|
,.raw= "GET / HTTP/1.1\r\n"
|
@@ -598,8 +622,14 @@ const struct message requests[] =
|
|
598
622
|
" mno \r\n"
|
599
623
|
"\t \tqrs\r\n"
|
600
624
|
"Line2: \t line2\t\r\n"
|
625
|
+
"Line3:\r\n"
|
626
|
+
" line3\r\n"
|
627
|
+
"Line4: \r\n"
|
628
|
+
" \r\n"
|
629
|
+
"Connection:\r\n"
|
630
|
+
" close\r\n"
|
601
631
|
"\r\n"
|
602
|
-
,.should_keep_alive=
|
632
|
+
,.should_keep_alive= FALSE
|
603
633
|
,.message_complete_on_eof= FALSE
|
604
634
|
,.http_major= 1
|
605
635
|
,.http_minor= 1
|
@@ -608,15 +638,18 @@ const struct message requests[] =
|
|
608
638
|
,.fragment= ""
|
609
639
|
,.request_path= "/"
|
610
640
|
,.request_url= "/"
|
611
|
-
,.num_headers=
|
612
|
-
,.headers= { { "Line1", "
|
641
|
+
,.num_headers= 5
|
642
|
+
,.headers= { { "Line1", "abc\tdef ghi\t\tjkl mno \t \tqrs" }
|
613
643
|
, { "Line2", "line2\t" }
|
644
|
+
, { "Line3", "line3" }
|
645
|
+
, { "Line4", "" }
|
646
|
+
, { "Connection", "close" },
|
614
647
|
}
|
615
648
|
,.body= ""
|
616
649
|
}
|
617
650
|
|
618
651
|
|
619
|
-
#define QUERY_TERMINATED_HOST
|
652
|
+
#define QUERY_TERMINATED_HOST 22
|
620
653
|
, {.name= "host terminated by a query string"
|
621
654
|
,.type= HTTP_REQUEST
|
622
655
|
,.raw= "GET http://hypnotoad.org?hail=all HTTP/1.1\r\n"
|
@@ -630,12 +663,13 @@ const struct message requests[] =
|
|
630
663
|
,.fragment= ""
|
631
664
|
,.request_path= ""
|
632
665
|
,.request_url= "http://hypnotoad.org?hail=all"
|
666
|
+
,.host= "hypnotoad.org"
|
633
667
|
,.num_headers= 0
|
634
668
|
,.headers= { }
|
635
669
|
,.body= ""
|
636
670
|
}
|
637
671
|
|
638
|
-
#define QUERY_TERMINATED_HOSTPORT
|
672
|
+
#define QUERY_TERMINATED_HOSTPORT 23
|
639
673
|
, {.name= "host:port terminated by a query string"
|
640
674
|
,.type= HTTP_REQUEST
|
641
675
|
,.raw= "GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n"
|
@@ -649,13 +683,14 @@ const struct message requests[] =
|
|
649
683
|
,.fragment= ""
|
650
684
|
,.request_path= ""
|
651
685
|
,.request_url= "http://hypnotoad.org:1234?hail=all"
|
686
|
+
,.host= "hypnotoad.org"
|
652
687
|
,.port= 1234
|
653
688
|
,.num_headers= 0
|
654
689
|
,.headers= { }
|
655
690
|
,.body= ""
|
656
691
|
}
|
657
692
|
|
658
|
-
#define SPACE_TERMINATED_HOSTPORT
|
693
|
+
#define SPACE_TERMINATED_HOSTPORT 24
|
659
694
|
, {.name= "host:port terminated by a space"
|
660
695
|
,.type= HTTP_REQUEST
|
661
696
|
,.raw= "GET http://hypnotoad.org:1234 HTTP/1.1\r\n"
|
@@ -669,13 +704,14 @@ const struct message requests[] =
|
|
669
704
|
,.fragment= ""
|
670
705
|
,.request_path= ""
|
671
706
|
,.request_url= "http://hypnotoad.org:1234"
|
707
|
+
,.host= "hypnotoad.org"
|
672
708
|
,.port= 1234
|
673
709
|
,.num_headers= 0
|
674
710
|
,.headers= { }
|
675
711
|
,.body= ""
|
676
712
|
}
|
677
713
|
|
678
|
-
#define PATCH_REQ
|
714
|
+
#define PATCH_REQ 25
|
679
715
|
, {.name = "PATCH request"
|
680
716
|
,.type= HTTP_REQUEST
|
681
717
|
,.raw= "PATCH /file.txt HTTP/1.1\r\n"
|
@@ -703,7 +739,7 @@ const struct message requests[] =
|
|
703
739
|
,.body= "cccccccccc"
|
704
740
|
}
|
705
741
|
|
706
|
-
#define CONNECT_CAPS_REQUEST
|
742
|
+
#define CONNECT_CAPS_REQUEST 26
|
707
743
|
, {.name = "connect caps request"
|
708
744
|
,.type= HTTP_REQUEST
|
709
745
|
,.raw= "CONNECT HOME0.NETSCAPE.COM:443 HTTP/1.0\r\n"
|
@@ -728,7 +764,7 @@ const struct message requests[] =
|
|
728
764
|
}
|
729
765
|
|
730
766
|
#if !HTTP_PARSER_STRICT
|
731
|
-
#define UTF8_PATH_REQ
|
767
|
+
#define UTF8_PATH_REQ 27
|
732
768
|
, {.name= "utf-8 path request"
|
733
769
|
,.type= HTTP_REQUEST
|
734
770
|
,.raw= "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\n"
|
@@ -749,7 +785,7 @@ const struct message requests[] =
|
|
749
785
|
,.body= ""
|
750
786
|
}
|
751
787
|
|
752
|
-
#define HOSTNAME_UNDERSCORE
|
788
|
+
#define HOSTNAME_UNDERSCORE 28
|
753
789
|
, {.name = "hostname underscore"
|
754
790
|
,.type= HTTP_REQUEST
|
755
791
|
,.raw= "CONNECT home_0.netscape.com:443 HTTP/1.0\r\n"
|
@@ -775,7 +811,7 @@ const struct message requests[] =
|
|
775
811
|
#endif /* !HTTP_PARSER_STRICT */
|
776
812
|
|
777
813
|
/* see https://github.com/ry/http-parser/issues/47 */
|
778
|
-
#define EAT_TRAILING_CRLF_NO_CONNECTION_CLOSE
|
814
|
+
#define EAT_TRAILING_CRLF_NO_CONNECTION_CLOSE 29
|
779
815
|
, {.name = "eat CRLF between requests, no \"Connection: close\" header"
|
780
816
|
,.raw= "POST / HTTP/1.1\r\n"
|
781
817
|
"Host: www.example.com\r\n"
|
@@ -802,7 +838,7 @@ const struct message requests[] =
|
|
802
838
|
}
|
803
839
|
|
804
840
|
/* see https://github.com/ry/http-parser/issues/47 */
|
805
|
-
#define EAT_TRAILING_CRLF_WITH_CONNECTION_CLOSE
|
841
|
+
#define EAT_TRAILING_CRLF_WITH_CONNECTION_CLOSE 30
|
806
842
|
, {.name = "eat CRLF between requests even if \"Connection: close\" is set"
|
807
843
|
,.raw= "POST / HTTP/1.1\r\n"
|
808
844
|
"Host: www.example.com\r\n"
|
@@ -830,7 +866,7 @@ const struct message requests[] =
|
|
830
866
|
,.body= "q=42"
|
831
867
|
}
|
832
868
|
|
833
|
-
#define PURGE_REQ
|
869
|
+
#define PURGE_REQ 31
|
834
870
|
, {.name = "PURGE request"
|
835
871
|
,.type= HTTP_REQUEST
|
836
872
|
,.raw= "PURGE /file.txt HTTP/1.1\r\n"
|
@@ -850,7 +886,293 @@ const struct message requests[] =
|
|
850
886
|
,.body= ""
|
851
887
|
}
|
852
888
|
|
853
|
-
|
889
|
+
#define SEARCH_REQ 32
|
890
|
+
, {.name = "SEARCH request"
|
891
|
+
,.type= HTTP_REQUEST
|
892
|
+
,.raw= "SEARCH / HTTP/1.1\r\n"
|
893
|
+
"Host: www.example.com\r\n"
|
894
|
+
"\r\n"
|
895
|
+
,.should_keep_alive= TRUE
|
896
|
+
,.message_complete_on_eof= FALSE
|
897
|
+
,.http_major= 1
|
898
|
+
,.http_minor= 1
|
899
|
+
,.method= HTTP_SEARCH
|
900
|
+
,.query_string= ""
|
901
|
+
,.fragment= ""
|
902
|
+
,.request_path= "/"
|
903
|
+
,.request_url= "/"
|
904
|
+
,.num_headers= 1
|
905
|
+
,.headers= { { "Host", "www.example.com" } }
|
906
|
+
,.body= ""
|
907
|
+
}
|
908
|
+
|
909
|
+
#define PROXY_WITH_BASIC_AUTH 33
|
910
|
+
, {.name= "host:port and basic_auth"
|
911
|
+
,.type= HTTP_REQUEST
|
912
|
+
,.raw= "GET http://a%12:b!&*$@hypnotoad.org:1234/toto HTTP/1.1\r\n"
|
913
|
+
"\r\n"
|
914
|
+
,.should_keep_alive= TRUE
|
915
|
+
,.message_complete_on_eof= FALSE
|
916
|
+
,.http_major= 1
|
917
|
+
,.http_minor= 1
|
918
|
+
,.method= HTTP_GET
|
919
|
+
,.fragment= ""
|
920
|
+
,.request_path= "/toto"
|
921
|
+
,.request_url= "http://a%12:b!&*$@hypnotoad.org:1234/toto"
|
922
|
+
,.host= "hypnotoad.org"
|
923
|
+
,.userinfo= "a%12:b!&*$"
|
924
|
+
,.port= 1234
|
925
|
+
,.num_headers= 0
|
926
|
+
,.headers= { }
|
927
|
+
,.body= ""
|
928
|
+
}
|
929
|
+
|
930
|
+
#define LINE_FOLDING_IN_HEADER_WITH_LF 34
|
931
|
+
, {.name= "line folding in header value"
|
932
|
+
,.type= HTTP_REQUEST
|
933
|
+
,.raw= "GET / HTTP/1.1\n"
|
934
|
+
"Line1: abc\n"
|
935
|
+
"\tdef\n"
|
936
|
+
" ghi\n"
|
937
|
+
"\t\tjkl\n"
|
938
|
+
" mno \n"
|
939
|
+
"\t \tqrs\n"
|
940
|
+
"Line2: \t line2\t\n"
|
941
|
+
"Line3:\n"
|
942
|
+
" line3\n"
|
943
|
+
"Line4: \n"
|
944
|
+
" \n"
|
945
|
+
"Connection:\n"
|
946
|
+
" close\n"
|
947
|
+
"\n"
|
948
|
+
,.should_keep_alive= FALSE
|
949
|
+
,.message_complete_on_eof= FALSE
|
950
|
+
,.http_major= 1
|
951
|
+
,.http_minor= 1
|
952
|
+
,.method= HTTP_GET
|
953
|
+
,.query_string= ""
|
954
|
+
,.fragment= ""
|
955
|
+
,.request_path= "/"
|
956
|
+
,.request_url= "/"
|
957
|
+
,.num_headers= 5
|
958
|
+
,.headers= { { "Line1", "abc\tdef ghi\t\tjkl mno \t \tqrs" }
|
959
|
+
, { "Line2", "line2\t" }
|
960
|
+
, { "Line3", "line3" }
|
961
|
+
, { "Line4", "" }
|
962
|
+
, { "Connection", "close" },
|
963
|
+
}
|
964
|
+
,.body= ""
|
965
|
+
}
|
966
|
+
|
967
|
+
#define CONNECTION_MULTI 35
|
968
|
+
, {.name = "multiple connection header values with folding"
|
969
|
+
,.type= HTTP_REQUEST
|
970
|
+
,.raw= "GET /demo HTTP/1.1\r\n"
|
971
|
+
"Host: example.com\r\n"
|
972
|
+
"Connection: Something,\r\n"
|
973
|
+
" Upgrade, ,Keep-Alive\r\n"
|
974
|
+
"Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"
|
975
|
+
"Sec-WebSocket-Protocol: sample\r\n"
|
976
|
+
"Upgrade: WebSocket\r\n"
|
977
|
+
"Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
|
978
|
+
"Origin: http://example.com\r\n"
|
979
|
+
"\r\n"
|
980
|
+
"Hot diggity dogg"
|
981
|
+
,.should_keep_alive= TRUE
|
982
|
+
,.message_complete_on_eof= FALSE
|
983
|
+
,.http_major= 1
|
984
|
+
,.http_minor= 1
|
985
|
+
,.method= HTTP_GET
|
986
|
+
,.query_string= ""
|
987
|
+
,.fragment= ""
|
988
|
+
,.request_path= "/demo"
|
989
|
+
,.request_url= "/demo"
|
990
|
+
,.num_headers= 7
|
991
|
+
,.upgrade="Hot diggity dogg"
|
992
|
+
,.headers= { { "Host", "example.com" }
|
993
|
+
, { "Connection", "Something, Upgrade, ,Keep-Alive" }
|
994
|
+
, { "Sec-WebSocket-Key2", "12998 5 Y3 1 .P00" }
|
995
|
+
, { "Sec-WebSocket-Protocol", "sample" }
|
996
|
+
, { "Upgrade", "WebSocket" }
|
997
|
+
, { "Sec-WebSocket-Key1", "4 @1 46546xW%0l 1 5" }
|
998
|
+
, { "Origin", "http://example.com" }
|
999
|
+
}
|
1000
|
+
,.body= ""
|
1001
|
+
}
|
1002
|
+
|
1003
|
+
#define CONNECTION_MULTI_LWS 36
|
1004
|
+
, {.name = "multiple connection header values with folding and lws"
|
1005
|
+
,.type= HTTP_REQUEST
|
1006
|
+
,.raw= "GET /demo HTTP/1.1\r\n"
|
1007
|
+
"Connection: keep-alive, upgrade\r\n"
|
1008
|
+
"Upgrade: WebSocket\r\n"
|
1009
|
+
"\r\n"
|
1010
|
+
"Hot diggity dogg"
|
1011
|
+
,.should_keep_alive= TRUE
|
1012
|
+
,.message_complete_on_eof= FALSE
|
1013
|
+
,.http_major= 1
|
1014
|
+
,.http_minor= 1
|
1015
|
+
,.method= HTTP_GET
|
1016
|
+
,.query_string= ""
|
1017
|
+
,.fragment= ""
|
1018
|
+
,.request_path= "/demo"
|
1019
|
+
,.request_url= "/demo"
|
1020
|
+
,.num_headers= 2
|
1021
|
+
,.upgrade="Hot diggity dogg"
|
1022
|
+
,.headers= { { "Connection", "keep-alive, upgrade" }
|
1023
|
+
, { "Upgrade", "WebSocket" }
|
1024
|
+
}
|
1025
|
+
,.body= ""
|
1026
|
+
}
|
1027
|
+
|
1028
|
+
#define CONNECTION_MULTI_LWS_CRLF 37
|
1029
|
+
, {.name = "multiple connection header values with folding and lws"
|
1030
|
+
,.type= HTTP_REQUEST
|
1031
|
+
,.raw= "GET /demo HTTP/1.1\r\n"
|
1032
|
+
"Connection: keep-alive, \r\n upgrade\r\n"
|
1033
|
+
"Upgrade: WebSocket\r\n"
|
1034
|
+
"\r\n"
|
1035
|
+
"Hot diggity dogg"
|
1036
|
+
,.should_keep_alive= TRUE
|
1037
|
+
,.message_complete_on_eof= FALSE
|
1038
|
+
,.http_major= 1
|
1039
|
+
,.http_minor= 1
|
1040
|
+
,.method= HTTP_GET
|
1041
|
+
,.query_string= ""
|
1042
|
+
,.fragment= ""
|
1043
|
+
,.request_path= "/demo"
|
1044
|
+
,.request_url= "/demo"
|
1045
|
+
,.num_headers= 2
|
1046
|
+
,.upgrade="Hot diggity dogg"
|
1047
|
+
,.headers= { { "Connection", "keep-alive, upgrade" }
|
1048
|
+
, { "Upgrade", "WebSocket" }
|
1049
|
+
}
|
1050
|
+
,.body= ""
|
1051
|
+
}
|
1052
|
+
|
1053
|
+
#define UPGRADE_POST_REQUEST 38
|
1054
|
+
, {.name = "upgrade post request"
|
1055
|
+
,.type= HTTP_REQUEST
|
1056
|
+
,.raw= "POST /demo HTTP/1.1\r\n"
|
1057
|
+
"Host: example.com\r\n"
|
1058
|
+
"Connection: Upgrade\r\n"
|
1059
|
+
"Upgrade: HTTP/2.0\r\n"
|
1060
|
+
"Content-Length: 15\r\n"
|
1061
|
+
"\r\n"
|
1062
|
+
"sweet post body"
|
1063
|
+
"Hot diggity dogg"
|
1064
|
+
,.should_keep_alive= TRUE
|
1065
|
+
,.message_complete_on_eof= FALSE
|
1066
|
+
,.http_major= 1
|
1067
|
+
,.http_minor= 1
|
1068
|
+
,.method= HTTP_POST
|
1069
|
+
,.request_path= "/demo"
|
1070
|
+
,.request_url= "/demo"
|
1071
|
+
,.num_headers= 4
|
1072
|
+
,.upgrade="Hot diggity dogg"
|
1073
|
+
,.headers= { { "Host", "example.com" }
|
1074
|
+
, { "Connection", "Upgrade" }
|
1075
|
+
, { "Upgrade", "HTTP/2.0" }
|
1076
|
+
, { "Content-Length", "15" }
|
1077
|
+
}
|
1078
|
+
,.body= "sweet post body"
|
1079
|
+
}
|
1080
|
+
|
1081
|
+
#define CONNECT_WITH_BODY_REQUEST 39
|
1082
|
+
, {.name = "connect with body request"
|
1083
|
+
,.type= HTTP_REQUEST
|
1084
|
+
,.raw= "CONNECT foo.bar.com:443 HTTP/1.0\r\n"
|
1085
|
+
"User-agent: Mozilla/1.1N\r\n"
|
1086
|
+
"Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n"
|
1087
|
+
"Content-Length: 10\r\n"
|
1088
|
+
"\r\n"
|
1089
|
+
"blarfcicle"
|
1090
|
+
,.should_keep_alive= FALSE
|
1091
|
+
,.message_complete_on_eof= FALSE
|
1092
|
+
,.http_major= 1
|
1093
|
+
,.http_minor= 0
|
1094
|
+
,.method= HTTP_CONNECT
|
1095
|
+
,.request_url= "foo.bar.com:443"
|
1096
|
+
,.num_headers= 3
|
1097
|
+
,.upgrade="blarfcicle"
|
1098
|
+
,.headers= { { "User-agent", "Mozilla/1.1N" }
|
1099
|
+
, { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" }
|
1100
|
+
, { "Content-Length", "10" }
|
1101
|
+
}
|
1102
|
+
,.body= ""
|
1103
|
+
}
|
1104
|
+
|
1105
|
+
/* Examples from the Internet draft for LINK/UNLINK methods:
|
1106
|
+
* https://tools.ietf.org/id/draft-snell-link-method-01.html#rfc.section.5
|
1107
|
+
*/
|
1108
|
+
|
1109
|
+
#define LINK_REQUEST 40
|
1110
|
+
, {.name = "link request"
|
1111
|
+
,.type= HTTP_REQUEST
|
1112
|
+
,.raw= "LINK /images/my_dog.jpg HTTP/1.1\r\n"
|
1113
|
+
"Host: example.com\r\n"
|
1114
|
+
"Link: <http://example.com/profiles/joe>; rel=\"tag\"\r\n"
|
1115
|
+
"Link: <http://example.com/profiles/sally>; rel=\"tag\"\r\n"
|
1116
|
+
"\r\n"
|
1117
|
+
,.should_keep_alive= TRUE
|
1118
|
+
,.message_complete_on_eof= FALSE
|
1119
|
+
,.http_major= 1
|
1120
|
+
,.http_minor= 1
|
1121
|
+
,.method= HTTP_LINK
|
1122
|
+
,.request_path= "/images/my_dog.jpg"
|
1123
|
+
,.request_url= "/images/my_dog.jpg"
|
1124
|
+
,.query_string= ""
|
1125
|
+
,.fragment= ""
|
1126
|
+
,.num_headers= 3
|
1127
|
+
,.headers= { { "Host", "example.com" }
|
1128
|
+
, { "Link", "<http://example.com/profiles/joe>; rel=\"tag\"" }
|
1129
|
+
, { "Link", "<http://example.com/profiles/sally>; rel=\"tag\"" }
|
1130
|
+
}
|
1131
|
+
,.body= ""
|
1132
|
+
}
|
1133
|
+
|
1134
|
+
#define UNLINK_REQUEST 41
|
1135
|
+
, {.name = "unlink request"
|
1136
|
+
,.type= HTTP_REQUEST
|
1137
|
+
,.raw= "UNLINK /images/my_dog.jpg HTTP/1.1\r\n"
|
1138
|
+
"Host: example.com\r\n"
|
1139
|
+
"Link: <http://example.com/profiles/sally>; rel=\"tag\"\r\n"
|
1140
|
+
"\r\n"
|
1141
|
+
,.should_keep_alive= TRUE
|
1142
|
+
,.message_complete_on_eof= FALSE
|
1143
|
+
,.http_major= 1
|
1144
|
+
,.http_minor= 1
|
1145
|
+
,.method= HTTP_UNLINK
|
1146
|
+
,.request_path= "/images/my_dog.jpg"
|
1147
|
+
,.request_url= "/images/my_dog.jpg"
|
1148
|
+
,.query_string= ""
|
1149
|
+
,.fragment= ""
|
1150
|
+
,.num_headers= 2
|
1151
|
+
,.headers= { { "Host", "example.com" }
|
1152
|
+
, { "Link", "<http://example.com/profiles/sally>; rel=\"tag\"" }
|
1153
|
+
}
|
1154
|
+
,.body= ""
|
1155
|
+
}
|
1156
|
+
|
1157
|
+
#define SOURCE_REQUEST 42
|
1158
|
+
, {.name = "source request"
|
1159
|
+
,.type= HTTP_REQUEST
|
1160
|
+
,.raw= "SOURCE /music/sweet/music HTTP/1.1\r\n"
|
1161
|
+
"Host: example.com\r\n"
|
1162
|
+
"\r\n"
|
1163
|
+
,.should_keep_alive= TRUE
|
1164
|
+
,.message_complete_on_eof= FALSE
|
1165
|
+
,.http_major= 1
|
1166
|
+
,.http_minor= 1
|
1167
|
+
,.method= HTTP_SOURCE
|
1168
|
+
,.request_path= "/music/sweet/music"
|
1169
|
+
,.request_url= "/music/sweet/music"
|
1170
|
+
,.query_string= ""
|
1171
|
+
,.fragment= ""
|
1172
|
+
,.num_headers= 1
|
1173
|
+
,.headers= { { "Host", "example.com" } }
|
1174
|
+
,.body= ""
|
1175
|
+
}
|
854
1176
|
};
|
855
1177
|
|
856
1178
|
/* * R E S P O N S E S * */
|
@@ -879,6 +1201,7 @@ const struct message responses[] =
|
|
879
1201
|
,.http_major= 1
|
880
1202
|
,.http_minor= 1
|
881
1203
|
,.status_code= 301
|
1204
|
+
,.response_status= "Moved Permanently"
|
882
1205
|
,.num_headers= 8
|
883
1206
|
,.headers=
|
884
1207
|
{ { "Location", "http://www.google.com/" }
|
@@ -927,6 +1250,7 @@ const struct message responses[] =
|
|
927
1250
|
,.http_major= 1
|
928
1251
|
,.http_minor= 1
|
929
1252
|
,.status_code= 200
|
1253
|
+
,.response_status= "OK"
|
930
1254
|
,.num_headers= 5
|
931
1255
|
,.headers=
|
932
1256
|
{ { "Date", "Tue, 04 Aug 2009 07:59:32 GMT" }
|
@@ -955,6 +1279,7 @@ const struct message responses[] =
|
|
955
1279
|
,.http_major= 1
|
956
1280
|
,.http_minor= 1
|
957
1281
|
,.status_code= 404
|
1282
|
+
,.response_status= "Not Found"
|
958
1283
|
,.num_headers= 0
|
959
1284
|
,.headers= {}
|
960
1285
|
,.body_size= 0
|
@@ -970,6 +1295,7 @@ const struct message responses[] =
|
|
970
1295
|
,.http_major= 1
|
971
1296
|
,.http_minor= 1
|
972
1297
|
,.status_code= 301
|
1298
|
+
,.response_status= ""
|
973
1299
|
,.num_headers= 0
|
974
1300
|
,.headers= {}
|
975
1301
|
,.body= ""
|
@@ -995,6 +1321,7 @@ const struct message responses[] =
|
|
995
1321
|
,.http_major= 1
|
996
1322
|
,.http_minor= 1
|
997
1323
|
,.status_code= 200
|
1324
|
+
,.response_status= "OK"
|
998
1325
|
,.num_headers= 2
|
999
1326
|
,.headers=
|
1000
1327
|
{ {"Content-Type", "text/plain" }
|
@@ -1004,7 +1331,8 @@ const struct message responses[] =
|
|
1004
1331
|
,.body =
|
1005
1332
|
"This is the data in the first chunk\r\n"
|
1006
1333
|
"and this is the second one\r\n"
|
1007
|
-
|
1334
|
+
,.num_chunks_complete= 3
|
1335
|
+
,.chunk_lengths= { 0x25, 0x1c }
|
1008
1336
|
}
|
1009
1337
|
|
1010
1338
|
#define NO_CARRIAGE_RET 5
|
@@ -1020,6 +1348,7 @@ const struct message responses[] =
|
|
1020
1348
|
,.http_major= 1
|
1021
1349
|
,.http_minor= 1
|
1022
1350
|
,.status_code= 200
|
1351
|
+
,.response_status= "OK"
|
1023
1352
|
,.num_headers= 2
|
1024
1353
|
,.headers=
|
1025
1354
|
{ {"Content-Type", "text/html; charset=utf-8" }
|
@@ -1043,6 +1372,7 @@ const struct message responses[] =
|
|
1043
1372
|
,.http_major= 1
|
1044
1373
|
,.http_minor= 1
|
1045
1374
|
,.status_code= 200
|
1375
|
+
,.response_status= "OK"
|
1046
1376
|
,.num_headers= 4
|
1047
1377
|
,.headers=
|
1048
1378
|
{ {"Content-Type", "text/html; charset=UTF-8" }
|
@@ -1068,6 +1398,7 @@ const struct message responses[] =
|
|
1068
1398
|
,.http_major= 1
|
1069
1399
|
,.http_minor= 1
|
1070
1400
|
,.status_code= 200
|
1401
|
+
,.response_status= "OK"
|
1071
1402
|
,.num_headers= 4
|
1072
1403
|
,.headers=
|
1073
1404
|
{ {"Server", "DCLK-AdSvr" }
|
@@ -1100,6 +1431,7 @@ const struct message responses[] =
|
|
1100
1431
|
,.http_major= 1
|
1101
1432
|
,.http_minor= 0
|
1102
1433
|
,.status_code= 301
|
1434
|
+
,.response_status= "Moved Permanently"
|
1103
1435
|
,.num_headers= 9
|
1104
1436
|
,.headers=
|
1105
1437
|
{ { "Date", "Thu, 03 Jun 2010 09:56:32 GMT" }
|
@@ -1138,6 +1470,7 @@ const struct message responses[] =
|
|
1138
1470
|
,.http_major= 1
|
1139
1471
|
,.http_minor= 1
|
1140
1472
|
,.status_code= 200
|
1473
|
+
,.response_status= "OK"
|
1141
1474
|
,.num_headers= 11
|
1142
1475
|
,.headers=
|
1143
1476
|
{ { "Date", "Tue, 28 Sep 2010 01:14:13 GMT" }
|
@@ -1153,6 +1486,8 @@ const struct message responses[] =
|
|
1153
1486
|
, { "Connection", "close" }
|
1154
1487
|
}
|
1155
1488
|
,.body= ""
|
1489
|
+
,.num_chunks_complete= 1
|
1490
|
+
,.chunk_lengths= {}
|
1156
1491
|
}
|
1157
1492
|
|
1158
1493
|
#define NON_ASCII_IN_STATUS_LINE 10
|
@@ -1169,6 +1504,7 @@ const struct message responses[] =
|
|
1169
1504
|
,.http_major= 1
|
1170
1505
|
,.http_minor= 1
|
1171
1506
|
,.status_code= 500
|
1507
|
+
,.response_status= "Oriëntatieprobleem"
|
1172
1508
|
,.num_headers= 3
|
1173
1509
|
,.headers=
|
1174
1510
|
{ { "Date", "Fri, 5 Nov 2010 23:07:12 GMT+2" }
|
@@ -1189,6 +1525,7 @@ const struct message responses[] =
|
|
1189
1525
|
,.http_major= 0
|
1190
1526
|
,.http_minor= 9
|
1191
1527
|
,.status_code= 200
|
1528
|
+
,.response_status= "OK"
|
1192
1529
|
,.num_headers= 0
|
1193
1530
|
,.headers=
|
1194
1531
|
{}
|
@@ -1211,6 +1548,7 @@ const struct message responses[] =
|
|
1211
1548
|
,.http_major= 1
|
1212
1549
|
,.http_minor= 1
|
1213
1550
|
,.status_code= 200
|
1551
|
+
,.response_status= "OK"
|
1214
1552
|
,.num_headers= 1
|
1215
1553
|
,.headers=
|
1216
1554
|
{ { "Content-Type", "text/plain" }
|
@@ -1229,6 +1567,7 @@ const struct message responses[] =
|
|
1229
1567
|
,.http_major= 1
|
1230
1568
|
,.http_minor= 0
|
1231
1569
|
,.status_code= 200
|
1570
|
+
,.response_status= "OK"
|
1232
1571
|
,.num_headers= 1
|
1233
1572
|
,.headers=
|
1234
1573
|
{ { "Connection", "keep-alive" }
|
@@ -1248,6 +1587,7 @@ const struct message responses[] =
|
|
1248
1587
|
,.http_major= 1
|
1249
1588
|
,.http_minor= 0
|
1250
1589
|
,.status_code= 204
|
1590
|
+
,.response_status= "No content"
|
1251
1591
|
,.num_headers= 1
|
1252
1592
|
,.headers=
|
1253
1593
|
{ { "Connection", "keep-alive" }
|
@@ -1266,6 +1606,7 @@ const struct message responses[] =
|
|
1266
1606
|
,.http_major= 1
|
1267
1607
|
,.http_minor= 1
|
1268
1608
|
,.status_code= 200
|
1609
|
+
,.response_status= "OK"
|
1269
1610
|
,.num_headers= 0
|
1270
1611
|
,.headers={}
|
1271
1612
|
,.body_size= 0
|
@@ -1282,6 +1623,7 @@ const struct message responses[] =
|
|
1282
1623
|
,.http_major= 1
|
1283
1624
|
,.http_minor= 1
|
1284
1625
|
,.status_code= 204
|
1626
|
+
,.response_status= "No content"
|
1285
1627
|
,.num_headers= 0
|
1286
1628
|
,.headers={}
|
1287
1629
|
,.body_size= 0
|
@@ -1299,6 +1641,7 @@ const struct message responses[] =
|
|
1299
1641
|
,.http_major= 1
|
1300
1642
|
,.http_minor= 1
|
1301
1643
|
,.status_code= 204
|
1644
|
+
,.response_status= "No content"
|
1302
1645
|
,.num_headers= 1
|
1303
1646
|
,.headers=
|
1304
1647
|
{ { "Connection", "close" }
|
@@ -1320,12 +1663,14 @@ const struct message responses[] =
|
|
1320
1663
|
,.http_major= 1
|
1321
1664
|
,.http_minor= 1
|
1322
1665
|
,.status_code= 200
|
1666
|
+
,.response_status= "OK"
|
1323
1667
|
,.num_headers= 1
|
1324
1668
|
,.headers=
|
1325
1669
|
{ { "Transfer-Encoding", "chunked" }
|
1326
1670
|
}
|
1327
1671
|
,.body_size= 0
|
1328
1672
|
,.body= ""
|
1673
|
+
,.num_chunks_complete= 1
|
1329
1674
|
}
|
1330
1675
|
|
1331
1676
|
#if !HTTP_PARSER_STRICT
|
@@ -1348,6 +1693,7 @@ const struct message responses[] =
|
|
1348
1693
|
,.http_major= 1
|
1349
1694
|
,.http_minor= 1
|
1350
1695
|
,.status_code= 200
|
1696
|
+
,.response_status= "OK"
|
1351
1697
|
,.num_headers= 7
|
1352
1698
|
,.headers=
|
1353
1699
|
{ { "Server", "Microsoft-IIS/6.0" }
|
@@ -1362,32 +1708,334 @@ const struct message responses[] =
|
|
1362
1708
|
}
|
1363
1709
|
#endif /* !HTTP_PARSER_STRICT */
|
1364
1710
|
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1711
|
+
#define AMAZON_COM 20
|
1712
|
+
, {.name= "amazon.com"
|
1713
|
+
,.type= HTTP_RESPONSE
|
1714
|
+
,.raw= "HTTP/1.1 301 MovedPermanently\r\n"
|
1715
|
+
"Date: Wed, 15 May 2013 17:06:33 GMT\r\n"
|
1716
|
+
"Server: Server\r\n"
|
1717
|
+
"x-amz-id-1: 0GPHKXSJQ826RK7GZEB2\r\n"
|
1718
|
+
"p3p: policyref=\"http://www.amazon.com/w3c/p3p.xml\",CP=\"CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC \"\r\n"
|
1719
|
+
"x-amz-id-2: STN69VZxIFSz9YJLbz1GDbxpbjG6Qjmmq5E3DxRhOUw+Et0p4hr7c/Q8qNcx4oAD\r\n"
|
1720
|
+
"Location: http://www.amazon.com/Dan-Brown/e/B000AP9DSU/ref=s9_pop_gw_al1?_encoding=UTF8&refinementId=618073011&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0SHYY5BZXN3KR20BNFAY&pf_rd_t=101&pf_rd_p=1263340922&pf_rd_i=507846\r\n"
|
1721
|
+
"Vary: Accept-Encoding,User-Agent\r\n"
|
1722
|
+
"Content-Type: text/html; charset=ISO-8859-1\r\n"
|
1723
|
+
"Transfer-Encoding: chunked\r\n"
|
1724
|
+
"\r\n"
|
1725
|
+
"1\r\n"
|
1726
|
+
"\n\r\n"
|
1727
|
+
"0\r\n"
|
1728
|
+
"\r\n"
|
1729
|
+
,.should_keep_alive= TRUE
|
1730
|
+
,.message_complete_on_eof= FALSE
|
1731
|
+
,.http_major= 1
|
1732
|
+
,.http_minor= 1
|
1733
|
+
,.status_code= 301
|
1734
|
+
,.response_status= "MovedPermanently"
|
1735
|
+
,.num_headers= 9
|
1736
|
+
,.headers= { { "Date", "Wed, 15 May 2013 17:06:33 GMT" }
|
1737
|
+
, { "Server", "Server" }
|
1738
|
+
, { "x-amz-id-1", "0GPHKXSJQ826RK7GZEB2" }
|
1739
|
+
, { "p3p", "policyref=\"http://www.amazon.com/w3c/p3p.xml\",CP=\"CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC \"" }
|
1740
|
+
, { "x-amz-id-2", "STN69VZxIFSz9YJLbz1GDbxpbjG6Qjmmq5E3DxRhOUw+Et0p4hr7c/Q8qNcx4oAD" }
|
1741
|
+
, { "Location", "http://www.amazon.com/Dan-Brown/e/B000AP9DSU/ref=s9_pop_gw_al1?_encoding=UTF8&refinementId=618073011&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=center-2&pf_rd_r=0SHYY5BZXN3KR20BNFAY&pf_rd_t=101&pf_rd_p=1263340922&pf_rd_i=507846" }
|
1742
|
+
, { "Vary", "Accept-Encoding,User-Agent" }
|
1743
|
+
, { "Content-Type", "text/html; charset=ISO-8859-1" }
|
1744
|
+
, { "Transfer-Encoding", "chunked" }
|
1745
|
+
}
|
1746
|
+
,.body= "\n"
|
1747
|
+
,.num_chunks_complete= 2
|
1748
|
+
,.chunk_lengths= { 1 }
|
1749
|
+
}
|
1388
1750
|
|
1389
|
-
|
1390
|
-
|
1751
|
+
#define EMPTY_REASON_PHRASE_AFTER_SPACE 20
|
1752
|
+
, {.name= "empty reason phrase after space"
|
1753
|
+
,.type= HTTP_RESPONSE
|
1754
|
+
,.raw= "HTTP/1.1 200 \r\n"
|
1755
|
+
"\r\n"
|
1756
|
+
,.should_keep_alive= FALSE
|
1757
|
+
,.message_complete_on_eof= TRUE
|
1758
|
+
,.http_major= 1
|
1759
|
+
,.http_minor= 1
|
1760
|
+
,.status_code= 200
|
1761
|
+
,.response_status= ""
|
1762
|
+
,.num_headers= 0
|
1763
|
+
,.headers= {}
|
1764
|
+
,.body= ""
|
1765
|
+
}
|
1766
|
+
|
1767
|
+
#define CONTENT_LENGTH_X 21
|
1768
|
+
, {.name= "Content-Length-X"
|
1769
|
+
,.type= HTTP_RESPONSE
|
1770
|
+
,.raw= "HTTP/1.1 200 OK\r\n"
|
1771
|
+
"Content-Length-X: 0\r\n"
|
1772
|
+
"Transfer-Encoding: chunked\r\n"
|
1773
|
+
"\r\n"
|
1774
|
+
"2\r\n"
|
1775
|
+
"OK\r\n"
|
1776
|
+
"0\r\n"
|
1777
|
+
"\r\n"
|
1778
|
+
,.should_keep_alive= TRUE
|
1779
|
+
,.message_complete_on_eof= FALSE
|
1780
|
+
,.http_major= 1
|
1781
|
+
,.http_minor= 1
|
1782
|
+
,.status_code= 200
|
1783
|
+
,.response_status= "OK"
|
1784
|
+
,.num_headers= 2
|
1785
|
+
,.headers= { { "Content-Length-X", "0" }
|
1786
|
+
, { "Transfer-Encoding", "chunked" }
|
1787
|
+
}
|
1788
|
+
,.body= "OK"
|
1789
|
+
,.num_chunks_complete= 2
|
1790
|
+
,.chunk_lengths= { 2 }
|
1791
|
+
}
|
1792
|
+
|
1793
|
+
#define HTTP_101_RESPONSE_WITH_UPGRADE_HEADER 22
|
1794
|
+
, {.name= "HTTP 101 response with Upgrade header"
|
1795
|
+
,.type= HTTP_RESPONSE
|
1796
|
+
,.raw= "HTTP/1.1 101 Switching Protocols\r\n"
|
1797
|
+
"Connection: upgrade\r\n"
|
1798
|
+
"Upgrade: h2c\r\n"
|
1799
|
+
"\r\n"
|
1800
|
+
"proto"
|
1801
|
+
,.should_keep_alive= TRUE
|
1802
|
+
,.message_complete_on_eof= FALSE
|
1803
|
+
,.http_major= 1
|
1804
|
+
,.http_minor= 1
|
1805
|
+
,.status_code= 101
|
1806
|
+
,.response_status= "Switching Protocols"
|
1807
|
+
,.upgrade= "proto"
|
1808
|
+
,.num_headers= 2
|
1809
|
+
,.headers=
|
1810
|
+
{ { "Connection", "upgrade" }
|
1811
|
+
, { "Upgrade", "h2c" }
|
1812
|
+
}
|
1813
|
+
}
|
1814
|
+
|
1815
|
+
#define HTTP_101_RESPONSE_WITH_UPGRADE_HEADER_AND_CONTENT_LENGTH 23
|
1816
|
+
, {.name= "HTTP 101 response with Upgrade and Content-Length header"
|
1817
|
+
,.type= HTTP_RESPONSE
|
1818
|
+
,.raw= "HTTP/1.1 101 Switching Protocols\r\n"
|
1819
|
+
"Connection: upgrade\r\n"
|
1820
|
+
"Upgrade: h2c\r\n"
|
1821
|
+
"Content-Length: 4\r\n"
|
1822
|
+
"\r\n"
|
1823
|
+
"body"
|
1824
|
+
"proto"
|
1825
|
+
,.should_keep_alive= TRUE
|
1826
|
+
,.message_complete_on_eof= FALSE
|
1827
|
+
,.http_major= 1
|
1828
|
+
,.http_minor= 1
|
1829
|
+
,.status_code= 101
|
1830
|
+
,.response_status= "Switching Protocols"
|
1831
|
+
,.body= "body"
|
1832
|
+
,.upgrade= "proto"
|
1833
|
+
,.num_headers= 3
|
1834
|
+
,.headers=
|
1835
|
+
{ { "Connection", "upgrade" }
|
1836
|
+
, { "Upgrade", "h2c" }
|
1837
|
+
, { "Content-Length", "4" }
|
1838
|
+
}
|
1839
|
+
}
|
1840
|
+
|
1841
|
+
#define HTTP_101_RESPONSE_WITH_UPGRADE_HEADER_AND_TRANSFER_ENCODING 24
|
1842
|
+
, {.name= "HTTP 101 response with Upgrade and Transfer-Encoding header"
|
1843
|
+
,.type= HTTP_RESPONSE
|
1844
|
+
,.raw= "HTTP/1.1 101 Switching Protocols\r\n"
|
1845
|
+
"Connection: upgrade\r\n"
|
1846
|
+
"Upgrade: h2c\r\n"
|
1847
|
+
"Transfer-Encoding: chunked\r\n"
|
1848
|
+
"\r\n"
|
1849
|
+
"2\r\n"
|
1850
|
+
"bo\r\n"
|
1851
|
+
"2\r\n"
|
1852
|
+
"dy\r\n"
|
1853
|
+
"0\r\n"
|
1854
|
+
"\r\n"
|
1855
|
+
"proto"
|
1856
|
+
,.should_keep_alive= TRUE
|
1857
|
+
,.message_complete_on_eof= FALSE
|
1858
|
+
,.http_major= 1
|
1859
|
+
,.http_minor= 1
|
1860
|
+
,.status_code= 101
|
1861
|
+
,.response_status= "Switching Protocols"
|
1862
|
+
,.body= "body"
|
1863
|
+
,.upgrade= "proto"
|
1864
|
+
,.num_headers= 3
|
1865
|
+
,.headers=
|
1866
|
+
{ { "Connection", "upgrade" }
|
1867
|
+
, { "Upgrade", "h2c" }
|
1868
|
+
, { "Transfer-Encoding", "chunked" }
|
1869
|
+
}
|
1870
|
+
,.num_chunks_complete= 3
|
1871
|
+
,.chunk_lengths= { 2, 2 }
|
1872
|
+
}
|
1873
|
+
|
1874
|
+
#define HTTP_200_RESPONSE_WITH_UPGRADE_HEADER 25
|
1875
|
+
, {.name= "HTTP 200 response with Upgrade header"
|
1876
|
+
,.type= HTTP_RESPONSE
|
1877
|
+
,.raw= "HTTP/1.1 200 OK\r\n"
|
1878
|
+
"Connection: upgrade\r\n"
|
1879
|
+
"Upgrade: h2c\r\n"
|
1880
|
+
"\r\n"
|
1881
|
+
"body"
|
1882
|
+
,.should_keep_alive= FALSE
|
1883
|
+
,.message_complete_on_eof= TRUE
|
1884
|
+
,.http_major= 1
|
1885
|
+
,.http_minor= 1
|
1886
|
+
,.status_code= 200
|
1887
|
+
,.response_status= "OK"
|
1888
|
+
,.body= "body"
|
1889
|
+
,.upgrade= NULL
|
1890
|
+
,.num_headers= 2
|
1891
|
+
,.headers=
|
1892
|
+
{ { "Connection", "upgrade" }
|
1893
|
+
, { "Upgrade", "h2c" }
|
1894
|
+
}
|
1895
|
+
}
|
1896
|
+
|
1897
|
+
#define HTTP_200_RESPONSE_WITH_UPGRADE_HEADER_AND_CONTENT_LENGTH 26
|
1898
|
+
, {.name= "HTTP 200 response with Upgrade and Content-Length header"
|
1899
|
+
,.type= HTTP_RESPONSE
|
1900
|
+
,.raw= "HTTP/1.1 200 OK\r\n"
|
1901
|
+
"Connection: upgrade\r\n"
|
1902
|
+
"Upgrade: h2c\r\n"
|
1903
|
+
"Content-Length: 4\r\n"
|
1904
|
+
"\r\n"
|
1905
|
+
"body"
|
1906
|
+
,.should_keep_alive= TRUE
|
1907
|
+
,.message_complete_on_eof= FALSE
|
1908
|
+
,.http_major= 1
|
1909
|
+
,.http_minor= 1
|
1910
|
+
,.status_code= 200
|
1911
|
+
,.response_status= "OK"
|
1912
|
+
,.num_headers= 3
|
1913
|
+
,.body= "body"
|
1914
|
+
,.upgrade= NULL
|
1915
|
+
,.headers=
|
1916
|
+
{ { "Connection", "upgrade" }
|
1917
|
+
, { "Upgrade", "h2c" }
|
1918
|
+
, { "Content-Length", "4" }
|
1919
|
+
}
|
1920
|
+
}
|
1921
|
+
|
1922
|
+
#define HTTP_200_RESPONSE_WITH_UPGRADE_HEADER_AND_TRANSFER_ENCODING 27
|
1923
|
+
, {.name= "HTTP 200 response with Upgrade and Transfer-Encoding header"
|
1924
|
+
,.type= HTTP_RESPONSE
|
1925
|
+
,.raw= "HTTP/1.1 200 OK\r\n"
|
1926
|
+
"Connection: upgrade\r\n"
|
1927
|
+
"Upgrade: h2c\r\n"
|
1928
|
+
"Transfer-Encoding: chunked\r\n"
|
1929
|
+
"\r\n"
|
1930
|
+
"2\r\n"
|
1931
|
+
"bo\r\n"
|
1932
|
+
"2\r\n"
|
1933
|
+
"dy\r\n"
|
1934
|
+
"0\r\n"
|
1935
|
+
"\r\n"
|
1936
|
+
,.should_keep_alive= TRUE
|
1937
|
+
,.message_complete_on_eof= FALSE
|
1938
|
+
,.http_major= 1
|
1939
|
+
,.http_minor= 1
|
1940
|
+
,.status_code= 200
|
1941
|
+
,.response_status= "OK"
|
1942
|
+
,.num_headers= 3
|
1943
|
+
,.body= "body"
|
1944
|
+
,.upgrade= NULL
|
1945
|
+
,.headers=
|
1946
|
+
{ { "Connection", "upgrade" }
|
1947
|
+
, { "Upgrade", "h2c" }
|
1948
|
+
, { "Transfer-Encoding", "chunked" }
|
1949
|
+
}
|
1950
|
+
,.num_chunks_complete= 3
|
1951
|
+
,.chunk_lengths= { 2, 2 }
|
1952
|
+
}
|
1953
|
+
};
|
1954
|
+
|
1955
|
+
/* strnlen() is a POSIX.2008 addition. Can't rely on it being available so
|
1956
|
+
* define it ourselves.
|
1957
|
+
*/
|
1958
|
+
size_t
|
1959
|
+
strnlen(const char *s, size_t maxlen)
|
1960
|
+
{
|
1961
|
+
const char *p;
|
1962
|
+
|
1963
|
+
p = memchr(s, '\0', maxlen);
|
1964
|
+
if (p == NULL)
|
1965
|
+
return maxlen;
|
1966
|
+
|
1967
|
+
return p - s;
|
1968
|
+
}
|
1969
|
+
|
1970
|
+
size_t
|
1971
|
+
strlncat(char *dst, size_t len, const char *src, size_t n)
|
1972
|
+
{
|
1973
|
+
size_t slen;
|
1974
|
+
size_t dlen;
|
1975
|
+
size_t rlen;
|
1976
|
+
size_t ncpy;
|
1977
|
+
|
1978
|
+
slen = strnlen(src, n);
|
1979
|
+
dlen = strnlen(dst, len);
|
1980
|
+
|
1981
|
+
if (dlen < len) {
|
1982
|
+
rlen = len - dlen;
|
1983
|
+
ncpy = slen < rlen ? slen : (rlen - 1);
|
1984
|
+
memcpy(dst + dlen, src, ncpy);
|
1985
|
+
dst[dlen + ncpy] = '\0';
|
1986
|
+
}
|
1987
|
+
|
1988
|
+
assert(len > slen + dlen);
|
1989
|
+
return slen + dlen;
|
1990
|
+
}
|
1991
|
+
|
1992
|
+
size_t
|
1993
|
+
strlncpy(char *dst, size_t len, const char *src, size_t n)
|
1994
|
+
{
|
1995
|
+
size_t slen;
|
1996
|
+
size_t ncpy;
|
1997
|
+
|
1998
|
+
slen = strnlen(src, n);
|
1999
|
+
|
2000
|
+
if (len > 0) {
|
2001
|
+
ncpy = slen < len ? slen : (len - 1);
|
2002
|
+
memcpy(dst, src, ncpy);
|
2003
|
+
dst[ncpy] = '\0';
|
2004
|
+
}
|
2005
|
+
|
2006
|
+
assert(len > slen);
|
2007
|
+
return slen;
|
2008
|
+
}
|
2009
|
+
|
2010
|
+
int
|
2011
|
+
request_url_cb (http_parser *p, const char *buf, size_t len)
|
2012
|
+
{
|
2013
|
+
assert(p == parser);
|
2014
|
+
strlncat(messages[num_messages].request_url,
|
2015
|
+
sizeof(messages[num_messages].request_url),
|
2016
|
+
buf,
|
2017
|
+
len);
|
2018
|
+
return 0;
|
2019
|
+
}
|
2020
|
+
|
2021
|
+
int
|
2022
|
+
header_field_cb (http_parser *p, const char *buf, size_t len)
|
2023
|
+
{
|
2024
|
+
assert(p == parser);
|
2025
|
+
struct message *m = &messages[num_messages];
|
2026
|
+
|
2027
|
+
if (m->last_header_element != FIELD)
|
2028
|
+
m->num_headers++;
|
2029
|
+
|
2030
|
+
strlncat(m->headers[m->num_headers-1][0],
|
2031
|
+
sizeof(m->headers[m->num_headers-1][0]),
|
2032
|
+
buf,
|
2033
|
+
len);
|
2034
|
+
|
2035
|
+
m->last_header_element = FIELD;
|
2036
|
+
|
2037
|
+
return 0;
|
2038
|
+
}
|
1391
2039
|
|
1392
2040
|
int
|
1393
2041
|
header_value_cb (http_parser *p, const char *buf, size_t len)
|
@@ -1395,19 +2043,39 @@ header_value_cb (http_parser *p, const char *buf, size_t len)
|
|
1395
2043
|
assert(p == parser);
|
1396
2044
|
struct message *m = &messages[num_messages];
|
1397
2045
|
|
1398
|
-
|
2046
|
+
strlncat(m->headers[m->num_headers-1][1],
|
2047
|
+
sizeof(m->headers[m->num_headers-1][1]),
|
2048
|
+
buf,
|
2049
|
+
len);
|
1399
2050
|
|
1400
2051
|
m->last_header_element = VALUE;
|
1401
2052
|
|
1402
2053
|
return 0;
|
1403
2054
|
}
|
1404
2055
|
|
2056
|
+
void
|
2057
|
+
check_body_is_final (const http_parser *p)
|
2058
|
+
{
|
2059
|
+
if (messages[num_messages].body_is_final) {
|
2060
|
+
fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 "
|
2061
|
+
"on last on_body callback call "
|
2062
|
+
"but it doesn't! ***\n\n");
|
2063
|
+
assert(0);
|
2064
|
+
abort();
|
2065
|
+
}
|
2066
|
+
messages[num_messages].body_is_final = http_body_is_final(p);
|
2067
|
+
}
|
2068
|
+
|
1405
2069
|
int
|
1406
2070
|
body_cb (http_parser *p, const char *buf, size_t len)
|
1407
2071
|
{
|
1408
2072
|
assert(p == parser);
|
1409
|
-
|
2073
|
+
strlncat(messages[num_messages].body,
|
2074
|
+
sizeof(messages[num_messages].body),
|
2075
|
+
buf,
|
2076
|
+
len);
|
1410
2077
|
messages[num_messages].body_size += len;
|
2078
|
+
check_body_is_final(p);
|
1411
2079
|
// printf("body_cb: '%s'\n", requests[num_messages].body);
|
1412
2080
|
return 0;
|
1413
2081
|
}
|
@@ -1418,6 +2086,7 @@ count_body_cb (http_parser *p, const char *buf, size_t len)
|
|
1418
2086
|
assert(p == parser);
|
1419
2087
|
assert(buf);
|
1420
2088
|
messages[num_messages].body_size += len;
|
2089
|
+
check_body_is_final(p);
|
1421
2090
|
return 0;
|
1422
2091
|
}
|
1423
2092
|
|
@@ -1452,8 +2121,20 @@ message_complete_cb (http_parser *p)
|
|
1452
2121
|
"value in both on_message_complete and on_headers_complete "
|
1453
2122
|
"but it doesn't! ***\n\n");
|
1454
2123
|
assert(0);
|
1455
|
-
|
2124
|
+
abort();
|
2125
|
+
}
|
2126
|
+
|
2127
|
+
if (messages[num_messages].body_size &&
|
2128
|
+
http_body_is_final(p) &&
|
2129
|
+
!messages[num_messages].body_is_final)
|
2130
|
+
{
|
2131
|
+
fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 "
|
2132
|
+
"on last on_body callback call "
|
2133
|
+
"but it doesn't! ***\n\n");
|
2134
|
+
assert(0);
|
2135
|
+
abort();
|
1456
2136
|
}
|
2137
|
+
|
1457
2138
|
messages[num_messages].message_complete_cb_called = TRUE;
|
1458
2139
|
|
1459
2140
|
messages[num_messages].message_complete_on_eof = currently_parsing_eof;
|
@@ -1462,6 +2143,49 @@ message_complete_cb (http_parser *p)
|
|
1462
2143
|
return 0;
|
1463
2144
|
}
|
1464
2145
|
|
2146
|
+
int
|
2147
|
+
response_status_cb (http_parser *p, const char *buf, size_t len)
|
2148
|
+
{
|
2149
|
+
assert(p == parser);
|
2150
|
+
|
2151
|
+
messages[num_messages].status_cb_called = TRUE;
|
2152
|
+
|
2153
|
+
strlncat(messages[num_messages].response_status,
|
2154
|
+
sizeof(messages[num_messages].response_status),
|
2155
|
+
buf,
|
2156
|
+
len);
|
2157
|
+
return 0;
|
2158
|
+
}
|
2159
|
+
|
2160
|
+
int
|
2161
|
+
chunk_header_cb (http_parser *p)
|
2162
|
+
{
|
2163
|
+
assert(p == parser);
|
2164
|
+
int chunk_idx = messages[num_messages].num_chunks;
|
2165
|
+
messages[num_messages].num_chunks++;
|
2166
|
+
if (chunk_idx < MAX_CHUNKS) {
|
2167
|
+
messages[num_messages].chunk_lengths[chunk_idx] = p->content_length;
|
2168
|
+
}
|
2169
|
+
|
2170
|
+
return 0;
|
2171
|
+
}
|
2172
|
+
|
2173
|
+
int
|
2174
|
+
chunk_complete_cb (http_parser *p)
|
2175
|
+
{
|
2176
|
+
assert(p == parser);
|
2177
|
+
|
2178
|
+
/* Here we want to verify that each chunk_header_cb is matched by a
|
2179
|
+
* chunk_complete_cb, so not only should the total number of calls to
|
2180
|
+
* both callbacks be the same, but they also should be interleaved
|
2181
|
+
* properly */
|
2182
|
+
assert(messages[num_messages].num_chunks ==
|
2183
|
+
messages[num_messages].num_chunks_complete + 1);
|
2184
|
+
|
2185
|
+
messages[num_messages].num_chunks_complete++;
|
2186
|
+
return 0;
|
2187
|
+
}
|
2188
|
+
|
1465
2189
|
/* These dontcall_* callbacks exist so that we can verify that when we're
|
1466
2190
|
* paused, no additional callbacks are invoked */
|
1467
2191
|
int
|
@@ -1469,7 +2193,7 @@ dontcall_message_begin_cb (http_parser *p)
|
|
1469
2193
|
{
|
1470
2194
|
if (p) { } // gcc
|
1471
2195
|
fprintf(stderr, "\n\n*** on_message_begin() called on paused parser ***\n\n");
|
1472
|
-
|
2196
|
+
abort();
|
1473
2197
|
}
|
1474
2198
|
|
1475
2199
|
int
|
@@ -1477,7 +2201,7 @@ dontcall_header_field_cb (http_parser *p, const char *buf, size_t len)
|
|
1477
2201
|
{
|
1478
2202
|
if (p || buf || len) { } // gcc
|
1479
2203
|
fprintf(stderr, "\n\n*** on_header_field() called on paused parser ***\n\n");
|
1480
|
-
|
2204
|
+
abort();
|
1481
2205
|
}
|
1482
2206
|
|
1483
2207
|
int
|
@@ -1485,7 +2209,7 @@ dontcall_header_value_cb (http_parser *p, const char *buf, size_t len)
|
|
1485
2209
|
{
|
1486
2210
|
if (p || buf || len) { } // gcc
|
1487
2211
|
fprintf(stderr, "\n\n*** on_header_value() called on paused parser ***\n\n");
|
1488
|
-
|
2212
|
+
abort();
|
1489
2213
|
}
|
1490
2214
|
|
1491
2215
|
int
|
@@ -1493,7 +2217,7 @@ dontcall_request_url_cb (http_parser *p, const char *buf, size_t len)
|
|
1493
2217
|
{
|
1494
2218
|
if (p || buf || len) { } // gcc
|
1495
2219
|
fprintf(stderr, "\n\n*** on_request_url() called on paused parser ***\n\n");
|
1496
|
-
|
2220
|
+
abort();
|
1497
2221
|
}
|
1498
2222
|
|
1499
2223
|
int
|
@@ -1501,7 +2225,7 @@ dontcall_body_cb (http_parser *p, const char *buf, size_t len)
|
|
1501
2225
|
{
|
1502
2226
|
if (p || buf || len) { } // gcc
|
1503
2227
|
fprintf(stderr, "\n\n*** on_body_cb() called on paused parser ***\n\n");
|
1504
|
-
|
2228
|
+
abort();
|
1505
2229
|
}
|
1506
2230
|
|
1507
2231
|
int
|
@@ -1510,7 +2234,7 @@ dontcall_headers_complete_cb (http_parser *p)
|
|
1510
2234
|
if (p) { } // gcc
|
1511
2235
|
fprintf(stderr, "\n\n*** on_headers_complete() called on paused "
|
1512
2236
|
"parser ***\n\n");
|
1513
|
-
|
2237
|
+
abort();
|
1514
2238
|
}
|
1515
2239
|
|
1516
2240
|
int
|
@@ -1519,6 +2243,31 @@ dontcall_message_complete_cb (http_parser *p)
|
|
1519
2243
|
if (p) { } // gcc
|
1520
2244
|
fprintf(stderr, "\n\n*** on_message_complete() called on paused "
|
1521
2245
|
"parser ***\n\n");
|
2246
|
+
abort();
|
2247
|
+
}
|
2248
|
+
|
2249
|
+
int
|
2250
|
+
dontcall_response_status_cb (http_parser *p, const char *buf, size_t len)
|
2251
|
+
{
|
2252
|
+
if (p || buf || len) { } // gcc
|
2253
|
+
fprintf(stderr, "\n\n*** on_status() called on paused parser ***\n\n");
|
2254
|
+
abort();
|
2255
|
+
}
|
2256
|
+
|
2257
|
+
int
|
2258
|
+
dontcall_chunk_header_cb (http_parser *p)
|
2259
|
+
{
|
2260
|
+
if (p) { } // gcc
|
2261
|
+
fprintf(stderr, "\n\n*** on_chunk_header() called on paused parser ***\n\n");
|
2262
|
+
exit(1);
|
2263
|
+
}
|
2264
|
+
|
2265
|
+
int
|
2266
|
+
dontcall_chunk_complete_cb (http_parser *p)
|
2267
|
+
{
|
2268
|
+
if (p) { } // gcc
|
2269
|
+
fprintf(stderr, "\n\n*** on_chunk_complete() "
|
2270
|
+
"called on paused parser ***\n\n");
|
1522
2271
|
exit(1);
|
1523
2272
|
}
|
1524
2273
|
|
@@ -1527,9 +2276,12 @@ static http_parser_settings settings_dontcall =
|
|
1527
2276
|
,.on_header_field = dontcall_header_field_cb
|
1528
2277
|
,.on_header_value = dontcall_header_value_cb
|
1529
2278
|
,.on_url = dontcall_request_url_cb
|
2279
|
+
,.on_status = dontcall_response_status_cb
|
1530
2280
|
,.on_body = dontcall_body_cb
|
1531
2281
|
,.on_headers_complete = dontcall_headers_complete_cb
|
1532
2282
|
,.on_message_complete = dontcall_message_complete_cb
|
2283
|
+
,.on_chunk_header = dontcall_chunk_header_cb
|
2284
|
+
,.on_chunk_complete = dontcall_chunk_complete_cb
|
1533
2285
|
};
|
1534
2286
|
|
1535
2287
|
/* These pause_* callbacks always pause the parser and just invoke the regular
|
@@ -1592,14 +2344,55 @@ pause_message_complete_cb (http_parser *p)
|
|
1592
2344
|
return message_complete_cb(p);
|
1593
2345
|
}
|
1594
2346
|
|
2347
|
+
int
|
2348
|
+
pause_response_status_cb (http_parser *p, const char *buf, size_t len)
|
2349
|
+
{
|
2350
|
+
http_parser_pause(p, 1);
|
2351
|
+
*current_pause_parser = settings_dontcall;
|
2352
|
+
return response_status_cb(p, buf, len);
|
2353
|
+
}
|
2354
|
+
|
2355
|
+
int
|
2356
|
+
pause_chunk_header_cb (http_parser *p)
|
2357
|
+
{
|
2358
|
+
http_parser_pause(p, 1);
|
2359
|
+
*current_pause_parser = settings_dontcall;
|
2360
|
+
return chunk_header_cb(p);
|
2361
|
+
}
|
2362
|
+
|
2363
|
+
int
|
2364
|
+
pause_chunk_complete_cb (http_parser *p)
|
2365
|
+
{
|
2366
|
+
http_parser_pause(p, 1);
|
2367
|
+
*current_pause_parser = settings_dontcall;
|
2368
|
+
return chunk_complete_cb(p);
|
2369
|
+
}
|
2370
|
+
|
2371
|
+
int
|
2372
|
+
connect_headers_complete_cb (http_parser *p)
|
2373
|
+
{
|
2374
|
+
headers_complete_cb(p);
|
2375
|
+
return 1;
|
2376
|
+
}
|
2377
|
+
|
2378
|
+
int
|
2379
|
+
connect_message_complete_cb (http_parser *p)
|
2380
|
+
{
|
2381
|
+
messages[num_messages].should_keep_alive = http_should_keep_alive(parser);
|
2382
|
+
return message_complete_cb(p);
|
2383
|
+
}
|
2384
|
+
|
1595
2385
|
static http_parser_settings settings_pause =
|
1596
2386
|
{.on_message_begin = pause_message_begin_cb
|
1597
2387
|
,.on_header_field = pause_header_field_cb
|
1598
2388
|
,.on_header_value = pause_header_value_cb
|
1599
2389
|
,.on_url = pause_request_url_cb
|
2390
|
+
,.on_status = pause_response_status_cb
|
1600
2391
|
,.on_body = pause_body_cb
|
1601
2392
|
,.on_headers_complete = pause_headers_complete_cb
|
1602
2393
|
,.on_message_complete = pause_message_complete_cb
|
2394
|
+
,.on_chunk_header = pause_chunk_header_cb
|
2395
|
+
,.on_chunk_complete = pause_chunk_complete_cb
|
1603
2396
|
};
|
1604
2397
|
|
1605
2398
|
static http_parser_settings settings =
|
@@ -1607,9 +2400,12 @@ static http_parser_settings settings =
|
|
1607
2400
|
,.on_header_field = header_field_cb
|
1608
2401
|
,.on_header_value = header_value_cb
|
1609
2402
|
,.on_url = request_url_cb
|
2403
|
+
,.on_status = response_status_cb
|
1610
2404
|
,.on_body = body_cb
|
1611
2405
|
,.on_headers_complete = headers_complete_cb
|
1612
2406
|
,.on_message_complete = message_complete_cb
|
2407
|
+
,.on_chunk_header = chunk_header_cb
|
2408
|
+
,.on_chunk_complete = chunk_complete_cb
|
1613
2409
|
};
|
1614
2410
|
|
1615
2411
|
static http_parser_settings settings_count_body =
|
@@ -1617,9 +2413,25 @@ static http_parser_settings settings_count_body =
|
|
1617
2413
|
,.on_header_field = header_field_cb
|
1618
2414
|
,.on_header_value = header_value_cb
|
1619
2415
|
,.on_url = request_url_cb
|
2416
|
+
,.on_status = response_status_cb
|
1620
2417
|
,.on_body = count_body_cb
|
1621
2418
|
,.on_headers_complete = headers_complete_cb
|
1622
2419
|
,.on_message_complete = message_complete_cb
|
2420
|
+
,.on_chunk_header = chunk_header_cb
|
2421
|
+
,.on_chunk_complete = chunk_complete_cb
|
2422
|
+
};
|
2423
|
+
|
2424
|
+
static http_parser_settings settings_connect =
|
2425
|
+
{.on_message_begin = message_begin_cb
|
2426
|
+
,.on_header_field = header_field_cb
|
2427
|
+
,.on_header_value = header_value_cb
|
2428
|
+
,.on_url = request_url_cb
|
2429
|
+
,.on_status = response_status_cb
|
2430
|
+
,.on_body = dontcall_body_cb
|
2431
|
+
,.on_headers_complete = connect_headers_complete_cb
|
2432
|
+
,.on_message_complete = connect_message_complete_cb
|
2433
|
+
,.on_chunk_header = chunk_header_cb
|
2434
|
+
,.on_chunk_complete = chunk_complete_cb
|
1623
2435
|
};
|
1624
2436
|
|
1625
2437
|
static http_parser_settings settings_null =
|
@@ -1627,9 +2439,12 @@ static http_parser_settings settings_null =
|
|
1627
2439
|
,.on_header_field = 0
|
1628
2440
|
,.on_header_value = 0
|
1629
2441
|
,.on_url = 0
|
2442
|
+
,.on_status = 0
|
1630
2443
|
,.on_body = 0
|
1631
2444
|
,.on_headers_complete = 0
|
1632
2445
|
,.on_message_complete = 0
|
2446
|
+
,.on_chunk_header = 0
|
2447
|
+
,.on_chunk_complete = 0
|
1633
2448
|
};
|
1634
2449
|
|
1635
2450
|
void
|
@@ -1682,6 +2497,14 @@ size_t parse_pause (const char *buf, size_t len)
|
|
1682
2497
|
return nparsed;
|
1683
2498
|
}
|
1684
2499
|
|
2500
|
+
size_t parse_connect (const char *buf, size_t len)
|
2501
|
+
{
|
2502
|
+
size_t nparsed;
|
2503
|
+
currently_parsing_eof = (len == 0);
|
2504
|
+
nparsed = http_parser_execute(parser, &settings_connect, buf, len);
|
2505
|
+
return nparsed;
|
2506
|
+
}
|
2507
|
+
|
1685
2508
|
static inline int
|
1686
2509
|
check_str_eq (const struct message *m,
|
1687
2510
|
const char *prop,
|
@@ -1738,7 +2561,7 @@ do { \
|
|
1738
2561
|
} while(0)
|
1739
2562
|
|
1740
2563
|
int
|
1741
|
-
message_eq (int index, const struct message *expected)
|
2564
|
+
message_eq (int index, int connect, const struct message *expected)
|
1742
2565
|
{
|
1743
2566
|
int i;
|
1744
2567
|
struct message *m = &messages[index];
|
@@ -1750,10 +2573,14 @@ message_eq (int index, const struct message *expected)
|
|
1750
2573
|
MESSAGE_CHECK_NUM_EQ(expected, m, method);
|
1751
2574
|
} else {
|
1752
2575
|
MESSAGE_CHECK_NUM_EQ(expected, m, status_code);
|
2576
|
+
MESSAGE_CHECK_STR_EQ(expected, m, response_status);
|
2577
|
+
assert(m->status_cb_called);
|
1753
2578
|
}
|
1754
2579
|
|
1755
|
-
|
1756
|
-
|
2580
|
+
if (!connect) {
|
2581
|
+
MESSAGE_CHECK_NUM_EQ(expected, m, should_keep_alive);
|
2582
|
+
MESSAGE_CHECK_NUM_EQ(expected, m, message_complete_on_eof);
|
2583
|
+
}
|
1757
2584
|
|
1758
2585
|
assert(m->message_begin_cb_called);
|
1759
2586
|
assert(m->headers_complete_cb_called);
|
@@ -1771,7 +2598,15 @@ message_eq (int index, const struct message *expected)
|
|
1771
2598
|
if (http_parser_parse_url(m->request_url, strlen(m->request_url), 0, &u)) {
|
1772
2599
|
fprintf(stderr, "\n\n*** failed to parse URL %s ***\n\n",
|
1773
2600
|
m->request_url);
|
1774
|
-
|
2601
|
+
abort();
|
2602
|
+
}
|
2603
|
+
|
2604
|
+
if (expected->host) {
|
2605
|
+
MESSAGE_CHECK_URL_EQ(&u, expected, m, host, UF_HOST);
|
2606
|
+
}
|
2607
|
+
|
2608
|
+
if (expected->userinfo) {
|
2609
|
+
MESSAGE_CHECK_URL_EQ(&u, expected, m, userinfo, UF_USERINFO);
|
1775
2610
|
}
|
1776
2611
|
|
1777
2612
|
m->port = (u.field_set & (1 << UF_PORT)) ?
|
@@ -1783,12 +2618,24 @@ message_eq (int index, const struct message *expected)
|
|
1783
2618
|
MESSAGE_CHECK_NUM_EQ(expected, m, port);
|
1784
2619
|
}
|
1785
2620
|
|
1786
|
-
if (
|
2621
|
+
if (connect) {
|
2622
|
+
check_num_eq(m, "body_size", 0, m->body_size);
|
2623
|
+
} else if (expected->body_size) {
|
1787
2624
|
MESSAGE_CHECK_NUM_EQ(expected, m, body_size);
|
1788
2625
|
} else {
|
1789
2626
|
MESSAGE_CHECK_STR_EQ(expected, m, body);
|
1790
2627
|
}
|
1791
2628
|
|
2629
|
+
if (connect) {
|
2630
|
+
check_num_eq(m, "num_chunks_complete", 0, m->num_chunks_complete);
|
2631
|
+
} else {
|
2632
|
+
assert(m->num_chunks == m->num_chunks_complete);
|
2633
|
+
MESSAGE_CHECK_NUM_EQ(expected, m, num_chunks_complete);
|
2634
|
+
for (i = 0; i < m->num_chunks && i < MAX_CHUNKS; i++) {
|
2635
|
+
MESSAGE_CHECK_NUM_EQ(expected, m, chunk_lengths[i]);
|
2636
|
+
}
|
2637
|
+
}
|
2638
|
+
|
1792
2639
|
MESSAGE_CHECK_NUM_EQ(expected, m, num_headers);
|
1793
2640
|
|
1794
2641
|
int r;
|
@@ -1799,7 +2646,9 @@ message_eq (int index, const struct message *expected)
|
|
1799
2646
|
if (!r) return 0;
|
1800
2647
|
}
|
1801
2648
|
|
1802
|
-
|
2649
|
+
if (!connect) {
|
2650
|
+
MESSAGE_CHECK_STR_EQ(expected, m, upgrade);
|
2651
|
+
}
|
1803
2652
|
|
1804
2653
|
return 1;
|
1805
2654
|
}
|
@@ -1836,7 +2685,7 @@ upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) {
|
|
1836
2685
|
va_list ap;
|
1837
2686
|
size_t i;
|
1838
2687
|
size_t off = 0;
|
1839
|
-
|
2688
|
+
|
1840
2689
|
va_start(ap, nmsgs);
|
1841
2690
|
|
1842
2691
|
for (i = 0; i < nmsgs; i++) {
|
@@ -1849,7 +2698,7 @@ upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) {
|
|
1849
2698
|
|
1850
2699
|
/* Check the portion of the response after its specified upgrade */
|
1851
2700
|
if (!check_str_eq(m, "upgrade", body + off, body + nread)) {
|
1852
|
-
|
2701
|
+
abort();
|
1853
2702
|
}
|
1854
2703
|
|
1855
2704
|
/* Fix up the response so that message_eq() will verify the beginning
|
@@ -1865,14 +2714,13 @@ upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) {
|
|
1865
2714
|
va_end(ap);
|
1866
2715
|
printf("\n\n*** Error: expected a message with upgrade ***\n");
|
1867
2716
|
|
1868
|
-
|
2717
|
+
abort();
|
1869
2718
|
}
|
1870
2719
|
|
1871
2720
|
static void
|
1872
2721
|
print_error (const char *raw, size_t error_location)
|
1873
2722
|
{
|
1874
|
-
fprintf(stderr, "\n*** %s
|
1875
|
-
"http_parser.c", HTTP_PARSER_ERRNO_LINE(parser),
|
2723
|
+
fprintf(stderr, "\n*** %s ***\n\n",
|
1876
2724
|
http_errno_description(HTTP_PARSER_ERRNO(parser)));
|
1877
2725
|
|
1878
2726
|
int this_line = 0, char_len = 0;
|
@@ -1886,7 +2734,6 @@ print_error (const char *raw, size_t error_location)
|
|
1886
2734
|
break;
|
1887
2735
|
|
1888
2736
|
case '\n':
|
1889
|
-
char_len = 2;
|
1890
2737
|
fprintf(stderr, "\\n\n");
|
1891
2738
|
|
1892
2739
|
if (this_line) goto print;
|
@@ -1920,7 +2767,7 @@ test_preserve_data (void)
|
|
1920
2767
|
http_parser_init(&parser, HTTP_REQUEST);
|
1921
2768
|
if (parser.data != my_data) {
|
1922
2769
|
printf("\n*** parser.data not preserved accross http_parser_init ***\n\n");
|
1923
|
-
|
2770
|
+
abort();
|
1924
2771
|
}
|
1925
2772
|
}
|
1926
2773
|
|
@@ -1937,127 +2784,539 @@ const struct url_test url_tests[] =
|
|
1937
2784
|
,.url="http://hostname/"
|
1938
2785
|
,.is_connect=0
|
1939
2786
|
,.u=
|
1940
|
-
{.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH)
|
2787
|
+
{.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH)
|
2788
|
+
,.port=0
|
2789
|
+
,.field_data=
|
2790
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2791
|
+
,{ 7, 8 } /* UF_HOST */
|
2792
|
+
,{ 0, 0 } /* UF_PORT */
|
2793
|
+
,{ 15, 1 } /* UF_PATH */
|
2794
|
+
,{ 0, 0 } /* UF_QUERY */
|
2795
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2796
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2797
|
+
}
|
2798
|
+
}
|
2799
|
+
,.rv=0
|
2800
|
+
}
|
2801
|
+
|
2802
|
+
, {.name="proxy request with port"
|
2803
|
+
,.url="http://hostname:444/"
|
2804
|
+
,.is_connect=0
|
2805
|
+
,.u=
|
2806
|
+
{.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PORT) | (1 << UF_PATH)
|
2807
|
+
,.port=444
|
2808
|
+
,.field_data=
|
2809
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2810
|
+
,{ 7, 8 } /* UF_HOST */
|
2811
|
+
,{ 16, 3 } /* UF_PORT */
|
2812
|
+
,{ 19, 1 } /* UF_PATH */
|
2813
|
+
,{ 0, 0 } /* UF_QUERY */
|
2814
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2815
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2816
|
+
}
|
2817
|
+
}
|
2818
|
+
,.rv=0
|
2819
|
+
}
|
2820
|
+
|
2821
|
+
, {.name="CONNECT request"
|
2822
|
+
,.url="hostname:443"
|
2823
|
+
,.is_connect=1
|
2824
|
+
,.u=
|
2825
|
+
{.field_set=(1 << UF_HOST) | (1 << UF_PORT)
|
2826
|
+
,.port=443
|
2827
|
+
,.field_data=
|
2828
|
+
{{ 0, 0 } /* UF_SCHEMA */
|
2829
|
+
,{ 0, 8 } /* UF_HOST */
|
2830
|
+
,{ 9, 3 } /* UF_PORT */
|
2831
|
+
,{ 0, 0 } /* UF_PATH */
|
2832
|
+
,{ 0, 0 } /* UF_QUERY */
|
2833
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2834
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2835
|
+
}
|
2836
|
+
}
|
2837
|
+
,.rv=0
|
2838
|
+
}
|
2839
|
+
|
2840
|
+
, {.name="CONNECT request but not connect"
|
2841
|
+
,.url="hostname:443"
|
2842
|
+
,.is_connect=0
|
2843
|
+
,.rv=1
|
2844
|
+
}
|
2845
|
+
|
2846
|
+
, {.name="proxy ipv6 request"
|
2847
|
+
,.url="http://[1:2::3:4]/"
|
2848
|
+
,.is_connect=0
|
2849
|
+
,.u=
|
2850
|
+
{.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH)
|
2851
|
+
,.port=0
|
2852
|
+
,.field_data=
|
2853
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2854
|
+
,{ 8, 8 } /* UF_HOST */
|
2855
|
+
,{ 0, 0 } /* UF_PORT */
|
2856
|
+
,{ 17, 1 } /* UF_PATH */
|
2857
|
+
,{ 0, 0 } /* UF_QUERY */
|
2858
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2859
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2860
|
+
}
|
2861
|
+
}
|
2862
|
+
,.rv=0
|
2863
|
+
}
|
2864
|
+
|
2865
|
+
, {.name="proxy ipv6 request with port"
|
2866
|
+
,.url="http://[1:2::3:4]:67/"
|
2867
|
+
,.is_connect=0
|
2868
|
+
,.u=
|
2869
|
+
{.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PORT) | (1 << UF_PATH)
|
2870
|
+
,.port=67
|
2871
|
+
,.field_data=
|
2872
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2873
|
+
,{ 8, 8 } /* UF_HOST */
|
2874
|
+
,{ 18, 2 } /* UF_PORT */
|
2875
|
+
,{ 20, 1 } /* UF_PATH */
|
2876
|
+
,{ 0, 0 } /* UF_QUERY */
|
2877
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2878
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2879
|
+
}
|
2880
|
+
}
|
2881
|
+
,.rv=0
|
2882
|
+
}
|
2883
|
+
|
2884
|
+
, {.name="CONNECT ipv6 address"
|
2885
|
+
,.url="[1:2::3:4]:443"
|
2886
|
+
,.is_connect=1
|
2887
|
+
,.u=
|
2888
|
+
{.field_set=(1 << UF_HOST) | (1 << UF_PORT)
|
2889
|
+
,.port=443
|
2890
|
+
,.field_data=
|
2891
|
+
{{ 0, 0 } /* UF_SCHEMA */
|
2892
|
+
,{ 1, 8 } /* UF_HOST */
|
2893
|
+
,{ 11, 3 } /* UF_PORT */
|
2894
|
+
,{ 0, 0 } /* UF_PATH */
|
2895
|
+
,{ 0, 0 } /* UF_QUERY */
|
2896
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2897
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2898
|
+
}
|
2899
|
+
}
|
2900
|
+
,.rv=0
|
2901
|
+
}
|
2902
|
+
|
2903
|
+
, {.name="ipv4 in ipv6 address"
|
2904
|
+
,.url="http://[2001:0000:0000:0000:0000:0000:1.9.1.1]/"
|
2905
|
+
,.is_connect=0
|
2906
|
+
,.u=
|
2907
|
+
{.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH)
|
2908
|
+
,.port=0
|
2909
|
+
,.field_data=
|
2910
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2911
|
+
,{ 8, 37 } /* UF_HOST */
|
2912
|
+
,{ 0, 0 } /* UF_PORT */
|
2913
|
+
,{ 46, 1 } /* UF_PATH */
|
2914
|
+
,{ 0, 0 } /* UF_QUERY */
|
2915
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2916
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2917
|
+
}
|
2918
|
+
}
|
2919
|
+
,.rv=0
|
2920
|
+
}
|
2921
|
+
|
2922
|
+
, {.name="extra ? in query string"
|
2923
|
+
,.url="http://a.tbcdn.cn/p/fp/2010c/??fp-header-min.css,fp-base-min.css,"
|
2924
|
+
"fp-channel-min.css,fp-product-min.css,fp-mall-min.css,fp-category-min.css,"
|
2925
|
+
"fp-sub-min.css,fp-gdp4p-min.css,fp-css3-min.css,fp-misc-min.css?t=20101022.css"
|
2926
|
+
,.is_connect=0
|
2927
|
+
,.u=
|
2928
|
+
{.field_set=(1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_QUERY)
|
2929
|
+
,.port=0
|
2930
|
+
,.field_data=
|
2931
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2932
|
+
,{ 7, 10 } /* UF_HOST */
|
2933
|
+
,{ 0, 0 } /* UF_PORT */
|
2934
|
+
,{ 17, 12 } /* UF_PATH */
|
2935
|
+
,{ 30,187 } /* UF_QUERY */
|
2936
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2937
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2938
|
+
}
|
2939
|
+
}
|
2940
|
+
,.rv=0
|
2941
|
+
}
|
2942
|
+
|
2943
|
+
, {.name="space URL encoded"
|
2944
|
+
,.url="/toto.html?toto=a%20b"
|
2945
|
+
,.is_connect=0
|
2946
|
+
,.u=
|
2947
|
+
{.field_set= (1<<UF_PATH) | (1<<UF_QUERY)
|
2948
|
+
,.port=0
|
2949
|
+
,.field_data=
|
2950
|
+
{{ 0, 0 } /* UF_SCHEMA */
|
2951
|
+
,{ 0, 0 } /* UF_HOST */
|
2952
|
+
,{ 0, 0 } /* UF_PORT */
|
2953
|
+
,{ 0, 10 } /* UF_PATH */
|
2954
|
+
,{ 11, 10 } /* UF_QUERY */
|
2955
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2956
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2957
|
+
}
|
2958
|
+
}
|
2959
|
+
,.rv=0
|
2960
|
+
}
|
2961
|
+
|
2962
|
+
|
2963
|
+
, {.name="URL fragment"
|
2964
|
+
,.url="/toto.html#titi"
|
2965
|
+
,.is_connect=0
|
2966
|
+
,.u=
|
2967
|
+
{.field_set= (1<<UF_PATH) | (1<<UF_FRAGMENT)
|
2968
|
+
,.port=0
|
2969
|
+
,.field_data=
|
2970
|
+
{{ 0, 0 } /* UF_SCHEMA */
|
2971
|
+
,{ 0, 0 } /* UF_HOST */
|
2972
|
+
,{ 0, 0 } /* UF_PORT */
|
2973
|
+
,{ 0, 10 } /* UF_PATH */
|
2974
|
+
,{ 0, 0 } /* UF_QUERY */
|
2975
|
+
,{ 11, 4 } /* UF_FRAGMENT */
|
2976
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2977
|
+
}
|
2978
|
+
}
|
2979
|
+
,.rv=0
|
2980
|
+
}
|
2981
|
+
|
2982
|
+
, {.name="complex URL fragment"
|
2983
|
+
,.url="http://www.webmasterworld.com/r.cgi?f=21&d=8405&url="
|
2984
|
+
"http://www.example.com/index.html?foo=bar&hello=world#midpage"
|
2985
|
+
,.is_connect=0
|
2986
|
+
,.u=
|
2987
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_QUERY) |\
|
2988
|
+
(1<<UF_FRAGMENT)
|
2989
|
+
,.port=0
|
2990
|
+
,.field_data=
|
2991
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2992
|
+
,{ 7, 22 } /* UF_HOST */
|
2993
|
+
,{ 0, 0 } /* UF_PORT */
|
2994
|
+
,{ 29, 6 } /* UF_PATH */
|
2995
|
+
,{ 36, 69 } /* UF_QUERY */
|
2996
|
+
,{106, 7 } /* UF_FRAGMENT */
|
2997
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2998
|
+
}
|
2999
|
+
}
|
3000
|
+
,.rv=0
|
3001
|
+
}
|
3002
|
+
|
3003
|
+
, {.name="complex URL from node js url parser doc"
|
3004
|
+
,.url="http://host.com:8080/p/a/t/h?query=string#hash"
|
3005
|
+
,.is_connect=0
|
3006
|
+
,.u=
|
3007
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PORT) | (1<<UF_PATH) |\
|
3008
|
+
(1<<UF_QUERY) | (1<<UF_FRAGMENT)
|
3009
|
+
,.port=8080
|
3010
|
+
,.field_data=
|
3011
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
3012
|
+
,{ 7, 8 } /* UF_HOST */
|
3013
|
+
,{ 16, 4 } /* UF_PORT */
|
3014
|
+
,{ 20, 8 } /* UF_PATH */
|
3015
|
+
,{ 29, 12 } /* UF_QUERY */
|
3016
|
+
,{ 42, 4 } /* UF_FRAGMENT */
|
3017
|
+
,{ 0, 0 } /* UF_USERINFO */
|
3018
|
+
}
|
3019
|
+
}
|
3020
|
+
,.rv=0
|
3021
|
+
}
|
3022
|
+
|
3023
|
+
, {.name="complex URL with basic auth from node js url parser doc"
|
3024
|
+
,.url="http://a:b@host.com:8080/p/a/t/h?query=string#hash"
|
3025
|
+
,.is_connect=0
|
3026
|
+
,.u=
|
3027
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PORT) | (1<<UF_PATH) |\
|
3028
|
+
(1<<UF_QUERY) | (1<<UF_FRAGMENT) | (1<<UF_USERINFO)
|
3029
|
+
,.port=8080
|
3030
|
+
,.field_data=
|
3031
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
3032
|
+
,{ 11, 8 } /* UF_HOST */
|
3033
|
+
,{ 20, 4 } /* UF_PORT */
|
3034
|
+
,{ 24, 8 } /* UF_PATH */
|
3035
|
+
,{ 33, 12 } /* UF_QUERY */
|
3036
|
+
,{ 46, 4 } /* UF_FRAGMENT */
|
3037
|
+
,{ 7, 3 } /* UF_USERINFO */
|
3038
|
+
}
|
3039
|
+
}
|
3040
|
+
,.rv=0
|
3041
|
+
}
|
3042
|
+
|
3043
|
+
, {.name="double @"
|
3044
|
+
,.url="http://a:b@@hostname:443/"
|
3045
|
+
,.is_connect=0
|
3046
|
+
,.rv=1
|
3047
|
+
}
|
3048
|
+
|
3049
|
+
, {.name="proxy empty host"
|
3050
|
+
,.url="http://:443/"
|
3051
|
+
,.is_connect=0
|
3052
|
+
,.rv=1
|
3053
|
+
}
|
3054
|
+
|
3055
|
+
, {.name="proxy empty port"
|
3056
|
+
,.url="http://hostname:/"
|
3057
|
+
,.is_connect=0
|
3058
|
+
,.rv=1
|
3059
|
+
}
|
3060
|
+
|
3061
|
+
, {.name="CONNECT with basic auth"
|
3062
|
+
,.url="a:b@hostname:443"
|
3063
|
+
,.is_connect=1
|
3064
|
+
,.rv=1
|
3065
|
+
}
|
3066
|
+
|
3067
|
+
, {.name="CONNECT empty host"
|
3068
|
+
,.url=":443"
|
3069
|
+
,.is_connect=1
|
3070
|
+
,.rv=1
|
3071
|
+
}
|
3072
|
+
|
3073
|
+
, {.name="CONNECT empty port"
|
3074
|
+
,.url="hostname:"
|
3075
|
+
,.is_connect=1
|
3076
|
+
,.rv=1
|
3077
|
+
}
|
3078
|
+
|
3079
|
+
, {.name="CONNECT with extra bits"
|
3080
|
+
,.url="hostname:443/"
|
3081
|
+
,.is_connect=1
|
3082
|
+
,.rv=1
|
3083
|
+
}
|
3084
|
+
|
3085
|
+
, {.name="space in URL"
|
3086
|
+
,.url="/foo bar/"
|
3087
|
+
,.rv=1 /* s_dead */
|
3088
|
+
}
|
3089
|
+
|
3090
|
+
, {.name="proxy basic auth with space url encoded"
|
3091
|
+
,.url="http://a%20:b@host.com/"
|
3092
|
+
,.is_connect=0
|
3093
|
+
,.u=
|
3094
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_USERINFO)
|
3095
|
+
,.port=0
|
3096
|
+
,.field_data=
|
3097
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
3098
|
+
,{ 14, 8 } /* UF_HOST */
|
3099
|
+
,{ 0, 0 } /* UF_PORT */
|
3100
|
+
,{ 22, 1 } /* UF_PATH */
|
3101
|
+
,{ 0, 0 } /* UF_QUERY */
|
3102
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
3103
|
+
,{ 7, 6 } /* UF_USERINFO */
|
3104
|
+
}
|
3105
|
+
}
|
3106
|
+
,.rv=0
|
3107
|
+
}
|
3108
|
+
|
3109
|
+
, {.name="carriage return in URL"
|
3110
|
+
,.url="/foo\rbar/"
|
3111
|
+
,.rv=1 /* s_dead */
|
3112
|
+
}
|
3113
|
+
|
3114
|
+
, {.name="proxy double : in URL"
|
3115
|
+
,.url="http://hostname::443/"
|
3116
|
+
,.rv=1 /* s_dead */
|
3117
|
+
}
|
3118
|
+
|
3119
|
+
, {.name="proxy basic auth with double :"
|
3120
|
+
,.url="http://a::b@host.com/"
|
3121
|
+
,.is_connect=0
|
3122
|
+
,.u=
|
3123
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_USERINFO)
|
3124
|
+
,.port=0
|
3125
|
+
,.field_data=
|
3126
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
3127
|
+
,{ 12, 8 } /* UF_HOST */
|
3128
|
+
,{ 0, 0 } /* UF_PORT */
|
3129
|
+
,{ 20, 1 } /* UF_PATH */
|
3130
|
+
,{ 0, 0 } /* UF_QUERY */
|
3131
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
3132
|
+
,{ 7, 4 } /* UF_USERINFO */
|
3133
|
+
}
|
3134
|
+
}
|
3135
|
+
,.rv=0
|
3136
|
+
}
|
3137
|
+
|
3138
|
+
, {.name="line feed in URL"
|
3139
|
+
,.url="/foo\nbar/"
|
3140
|
+
,.rv=1 /* s_dead */
|
3141
|
+
}
|
3142
|
+
|
3143
|
+
, {.name="proxy empty basic auth"
|
3144
|
+
,.url="http://@hostname/fo"
|
3145
|
+
,.u=
|
3146
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH)
|
3147
|
+
,.port=0
|
3148
|
+
,.field_data=
|
3149
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
3150
|
+
,{ 8, 8 } /* UF_HOST */
|
3151
|
+
,{ 0, 0 } /* UF_PORT */
|
3152
|
+
,{ 16, 3 } /* UF_PATH */
|
3153
|
+
,{ 0, 0 } /* UF_QUERY */
|
3154
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
3155
|
+
,{ 0, 0 } /* UF_USERINFO */
|
3156
|
+
}
|
3157
|
+
}
|
3158
|
+
,.rv=0
|
3159
|
+
}
|
3160
|
+
, {.name="proxy line feed in hostname"
|
3161
|
+
,.url="http://host\name/fo"
|
3162
|
+
,.rv=1 /* s_dead */
|
3163
|
+
}
|
3164
|
+
|
3165
|
+
, {.name="proxy % in hostname"
|
3166
|
+
,.url="http://host%name/fo"
|
3167
|
+
,.rv=1 /* s_dead */
|
3168
|
+
}
|
3169
|
+
|
3170
|
+
, {.name="proxy ; in hostname"
|
3171
|
+
,.url="http://host;ame/fo"
|
3172
|
+
,.rv=1 /* s_dead */
|
3173
|
+
}
|
3174
|
+
|
3175
|
+
, {.name="proxy basic auth with unreservedchars"
|
3176
|
+
,.url="http://a!;-_!=+$@host.com/"
|
3177
|
+
,.is_connect=0
|
3178
|
+
,.u=
|
3179
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_USERINFO)
|
1941
3180
|
,.port=0
|
1942
3181
|
,.field_data=
|
1943
3182
|
{{ 0, 4 } /* UF_SCHEMA */
|
1944
|
-
,{
|
3183
|
+
,{ 17, 8 } /* UF_HOST */
|
1945
3184
|
,{ 0, 0 } /* UF_PORT */
|
1946
|
-
,{
|
3185
|
+
,{ 25, 1 } /* UF_PATH */
|
1947
3186
|
,{ 0, 0 } /* UF_QUERY */
|
1948
3187
|
,{ 0, 0 } /* UF_FRAGMENT */
|
3188
|
+
,{ 7, 9 } /* UF_USERINFO */
|
1949
3189
|
}
|
1950
3190
|
}
|
1951
3191
|
,.rv=0
|
1952
3192
|
}
|
1953
3193
|
|
1954
|
-
, {.name="
|
1955
|
-
,.url="
|
1956
|
-
,.
|
3194
|
+
, {.name="proxy only empty basic auth"
|
3195
|
+
,.url="http://@/fo"
|
3196
|
+
,.rv=1 /* s_dead */
|
3197
|
+
}
|
3198
|
+
|
3199
|
+
, {.name="proxy only basic auth"
|
3200
|
+
,.url="http://toto@/fo"
|
3201
|
+
,.rv=1 /* s_dead */
|
3202
|
+
}
|
3203
|
+
|
3204
|
+
, {.name="proxy emtpy hostname"
|
3205
|
+
,.url="http:///fo"
|
3206
|
+
,.rv=1 /* s_dead */
|
3207
|
+
}
|
3208
|
+
|
3209
|
+
, {.name="proxy = in URL"
|
3210
|
+
,.url="http://host=ame/fo"
|
3211
|
+
,.rv=1 /* s_dead */
|
3212
|
+
}
|
3213
|
+
|
3214
|
+
, {.name="ipv6 address with Zone ID"
|
3215
|
+
,.url="http://[fe80::a%25eth0]/"
|
3216
|
+
,.is_connect=0
|
1957
3217
|
,.u=
|
1958
|
-
{.field_set=(1 <<
|
1959
|
-
,.port=
|
3218
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH)
|
3219
|
+
,.port=0
|
1960
3220
|
,.field_data=
|
1961
|
-
{{ 0,
|
1962
|
-
,{
|
1963
|
-
,{
|
1964
|
-
,{
|
3221
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
3222
|
+
,{ 8, 14 } /* UF_HOST */
|
3223
|
+
,{ 0, 0 } /* UF_PORT */
|
3224
|
+
,{ 23, 1 } /* UF_PATH */
|
1965
3225
|
,{ 0, 0 } /* UF_QUERY */
|
1966
3226
|
,{ 0, 0 } /* UF_FRAGMENT */
|
3227
|
+
,{ 0, 0 } /* UF_USERINFO */
|
1967
3228
|
}
|
1968
3229
|
}
|
1969
3230
|
,.rv=0
|
1970
3231
|
}
|
1971
3232
|
|
1972
|
-
, {.name="
|
1973
|
-
,.url="http://[
|
3233
|
+
, {.name="ipv6 address with Zone ID, but '%' is not percent-encoded"
|
3234
|
+
,.url="http://[fe80::a%eth0]/"
|
1974
3235
|
,.is_connect=0
|
1975
3236
|
,.u=
|
1976
|
-
{.field_set=(1
|
3237
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH)
|
1977
3238
|
,.port=0
|
1978
3239
|
,.field_data=
|
1979
3240
|
{{ 0, 4 } /* UF_SCHEMA */
|
1980
|
-
,{ 8,
|
3241
|
+
,{ 8, 12 } /* UF_HOST */
|
1981
3242
|
,{ 0, 0 } /* UF_PORT */
|
1982
|
-
,{
|
3243
|
+
,{ 21, 1 } /* UF_PATH */
|
1983
3244
|
,{ 0, 0 } /* UF_QUERY */
|
1984
3245
|
,{ 0, 0 } /* UF_FRAGMENT */
|
3246
|
+
,{ 0, 0 } /* UF_USERINFO */
|
1985
3247
|
}
|
1986
3248
|
}
|
1987
3249
|
,.rv=0
|
1988
3250
|
}
|
1989
3251
|
|
1990
|
-
, {.name="
|
1991
|
-
,.url="[
|
1992
|
-
,.
|
3252
|
+
, {.name="ipv6 address ending with '%'"
|
3253
|
+
,.url="http://[fe80::a%]/"
|
3254
|
+
,.rv=1 /* s_dead */
|
3255
|
+
}
|
3256
|
+
|
3257
|
+
, {.name="ipv6 address with Zone ID including bad character"
|
3258
|
+
,.url="http://[fe80::a%$HOME]/"
|
3259
|
+
,.rv=1 /* s_dead */
|
3260
|
+
}
|
3261
|
+
|
3262
|
+
, {.name="just ipv6 Zone ID"
|
3263
|
+
,.url="http://[%eth0]/"
|
3264
|
+
,.rv=1 /* s_dead */
|
3265
|
+
}
|
3266
|
+
|
3267
|
+
#if HTTP_PARSER_STRICT
|
3268
|
+
|
3269
|
+
, {.name="tab in URL"
|
3270
|
+
,.url="/foo\tbar/"
|
3271
|
+
,.rv=1 /* s_dead */
|
3272
|
+
}
|
3273
|
+
|
3274
|
+
, {.name="form feed in URL"
|
3275
|
+
,.url="/foo\fbar/"
|
3276
|
+
,.rv=1 /* s_dead */
|
3277
|
+
}
|
3278
|
+
|
3279
|
+
#else /* !HTTP_PARSER_STRICT */
|
3280
|
+
|
3281
|
+
, {.name="tab in URL"
|
3282
|
+
,.url="/foo\tbar/"
|
1993
3283
|
,.u=
|
1994
|
-
{.field_set=(1 <<
|
1995
|
-
,.port=443
|
3284
|
+
{.field_set=(1 << UF_PATH)
|
1996
3285
|
,.field_data=
|
1997
3286
|
{{ 0, 0 } /* UF_SCHEMA */
|
1998
|
-
,{
|
1999
|
-
,{
|
2000
|
-
,{ 0,
|
3287
|
+
,{ 0, 0 } /* UF_HOST */
|
3288
|
+
,{ 0, 0 } /* UF_PORT */
|
3289
|
+
,{ 0, 9 } /* UF_PATH */
|
2001
3290
|
,{ 0, 0 } /* UF_QUERY */
|
2002
3291
|
,{ 0, 0 } /* UF_FRAGMENT */
|
3292
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2003
3293
|
}
|
2004
3294
|
}
|
2005
3295
|
,.rv=0
|
2006
3296
|
}
|
2007
3297
|
|
2008
|
-
, {.name="
|
2009
|
-
,.url="
|
2010
|
-
,.is_connect=0
|
3298
|
+
, {.name="form feed in URL"
|
3299
|
+
,.url="/foo\fbar/"
|
2011
3300
|
,.u=
|
2012
|
-
{.field_set=(1
|
2013
|
-
,.port=0
|
3301
|
+
{.field_set=(1 << UF_PATH)
|
2014
3302
|
,.field_data=
|
2015
|
-
{{ 0,
|
2016
|
-
,{
|
3303
|
+
{{ 0, 0 } /* UF_SCHEMA */
|
3304
|
+
,{ 0, 0 } /* UF_HOST */
|
2017
3305
|
,{ 0, 0 } /* UF_PORT */
|
2018
|
-
,{
|
2019
|
-
,{
|
3306
|
+
,{ 0, 9 } /* UF_PATH */
|
3307
|
+
,{ 0, 0 } /* UF_QUERY */
|
2020
3308
|
,{ 0, 0 } /* UF_FRAGMENT */
|
3309
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2021
3310
|
}
|
2022
3311
|
}
|
2023
3312
|
,.rv=0
|
2024
3313
|
}
|
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
|
-
}
|
3314
|
+
#endif
|
2055
3315
|
};
|
2056
3316
|
|
2057
3317
|
void
|
2058
3318
|
dump_url (const char *url, const struct http_parser_url *u)
|
2059
3319
|
{
|
2060
|
-
char part[512];
|
2061
3320
|
unsigned int i;
|
2062
3321
|
|
2063
3322
|
printf("\tfield_set: 0x%x, port: %u\n", u->field_set, u->port);
|
@@ -2067,14 +3326,12 @@ dump_url (const char *url, const struct http_parser_url *u)
|
|
2067
3326
|
continue;
|
2068
3327
|
}
|
2069
3328
|
|
2070
|
-
|
2071
|
-
part[u->field_data[i].len] = '\0';
|
2072
|
-
|
2073
|
-
printf("\tfield_data[%u]: off: %u len: %u part: \"%s\"\n",
|
3329
|
+
printf("\tfield_data[%u]: off: %u len: %u part: \"%.*s\n\"",
|
2074
3330
|
i,
|
2075
3331
|
u->field_data[i].off,
|
2076
3332
|
u->field_data[i].len,
|
2077
|
-
|
3333
|
+
u->field_data[i].len,
|
3334
|
+
url + u->field_data[i].off);
|
2078
3335
|
}
|
2079
3336
|
}
|
2080
3337
|
|
@@ -2099,7 +3356,7 @@ test_parse_url (void)
|
|
2099
3356
|
if (rv != 0) {
|
2100
3357
|
printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, "
|
2101
3358
|
"unexpected rv %d ***\n\n", test->url, test->name, rv);
|
2102
|
-
|
3359
|
+
abort();
|
2103
3360
|
}
|
2104
3361
|
|
2105
3362
|
if (memcmp(&u, &test->u, sizeof(u)) != 0) {
|
@@ -2111,19 +3368,26 @@ test_parse_url (void)
|
|
2111
3368
|
printf("result http_parser_url:\n");
|
2112
3369
|
dump_url(test->url, &u);
|
2113
3370
|
|
2114
|
-
|
3371
|
+
abort();
|
2115
3372
|
}
|
2116
3373
|
} else {
|
2117
3374
|
/* test->rv != 0 */
|
2118
3375
|
if (rv == 0) {
|
2119
3376
|
printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, "
|
2120
3377
|
"unexpected rv %d ***\n\n", test->url, test->name, rv);
|
2121
|
-
|
3378
|
+
abort();
|
2122
3379
|
}
|
2123
3380
|
}
|
2124
3381
|
}
|
2125
3382
|
}
|
2126
3383
|
|
3384
|
+
void
|
3385
|
+
test_method_str (void)
|
3386
|
+
{
|
3387
|
+
assert(0 == strcmp("GET", http_method_str(HTTP_GET)));
|
3388
|
+
assert(0 == strcmp("<unknown>", http_method_str(1337)));
|
3389
|
+
}
|
3390
|
+
|
2127
3391
|
void
|
2128
3392
|
test_message (const struct message *message)
|
2129
3393
|
{
|
@@ -2140,14 +3404,14 @@ test_message (const struct message *message)
|
|
2140
3404
|
if (msg1len) {
|
2141
3405
|
read = parse(msg1, msg1len);
|
2142
3406
|
|
2143
|
-
if (message->upgrade && parser->upgrade) {
|
3407
|
+
if (message->upgrade && parser->upgrade && num_messages > 0) {
|
2144
3408
|
messages[num_messages - 1].upgrade = msg1 + read;
|
2145
3409
|
goto test;
|
2146
3410
|
}
|
2147
3411
|
|
2148
3412
|
if (read != msg1len) {
|
2149
3413
|
print_error(msg1, read);
|
2150
|
-
|
3414
|
+
abort();
|
2151
3415
|
}
|
2152
3416
|
}
|
2153
3417
|
|
@@ -2161,24 +3425,24 @@ test_message (const struct message *message)
|
|
2161
3425
|
|
2162
3426
|
if (read != msg2len) {
|
2163
3427
|
print_error(msg2, read);
|
2164
|
-
|
3428
|
+
abort();
|
2165
3429
|
}
|
2166
3430
|
|
2167
3431
|
read = parse(NULL, 0);
|
2168
3432
|
|
2169
3433
|
if (read != 0) {
|
2170
3434
|
print_error(message->raw, read);
|
2171
|
-
|
3435
|
+
abort();
|
2172
3436
|
}
|
2173
3437
|
|
2174
3438
|
test:
|
2175
3439
|
|
2176
3440
|
if (num_messages != 1) {
|
2177
3441
|
printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name);
|
2178
|
-
|
3442
|
+
abort();
|
2179
3443
|
}
|
2180
3444
|
|
2181
|
-
if(!message_eq(0, message))
|
3445
|
+
if(!message_eq(0, 0, message)) abort();
|
2182
3446
|
|
2183
3447
|
parser_free();
|
2184
3448
|
}
|
@@ -2199,7 +3463,7 @@ test_message_count_body (const struct message *message)
|
|
2199
3463
|
read = parse_count_body(message->raw + i, toread);
|
2200
3464
|
if (read != toread) {
|
2201
3465
|
print_error(message->raw, read);
|
2202
|
-
|
3466
|
+
abort();
|
2203
3467
|
}
|
2204
3468
|
}
|
2205
3469
|
|
@@ -2207,33 +3471,31 @@ test_message_count_body (const struct message *message)
|
|
2207
3471
|
read = parse_count_body(NULL, 0);
|
2208
3472
|
if (read != 0) {
|
2209
3473
|
print_error(message->raw, read);
|
2210
|
-
|
3474
|
+
abort();
|
2211
3475
|
}
|
2212
3476
|
|
2213
3477
|
if (num_messages != 1) {
|
2214
3478
|
printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name);
|
2215
|
-
|
3479
|
+
abort();
|
2216
3480
|
}
|
2217
3481
|
|
2218
|
-
if(!message_eq(0, message))
|
3482
|
+
if(!message_eq(0, 0, message)) abort();
|
2219
3483
|
|
2220
3484
|
parser_free();
|
2221
3485
|
}
|
2222
3486
|
|
2223
3487
|
void
|
2224
|
-
|
3488
|
+
test_simple_type (const char *buf,
|
3489
|
+
enum http_errno err_expected,
|
3490
|
+
enum http_parser_type type)
|
2225
3491
|
{
|
2226
|
-
parser_init(
|
3492
|
+
parser_init(type);
|
2227
3493
|
|
2228
|
-
size_t parsed;
|
2229
|
-
int pass;
|
2230
3494
|
enum http_errno err;
|
2231
3495
|
|
2232
|
-
|
2233
|
-
pass = (parsed == strlen(buf));
|
3496
|
+
parse(buf, strlen(buf));
|
2234
3497
|
err = HTTP_PARSER_ERRNO(parser);
|
2235
|
-
|
2236
|
-
pass &= (parsed == 0);
|
3498
|
+
parse(NULL, 0);
|
2237
3499
|
|
2238
3500
|
parser_free();
|
2239
3501
|
|
@@ -2247,7 +3509,186 @@ test_simple (const char *buf, enum http_errno err_expected)
|
|
2247
3509
|
#endif
|
2248
3510
|
fprintf(stderr, "\n*** test_simple expected %s, but saw %s ***\n\n%s\n",
|
2249
3511
|
http_errno_name(err_expected), http_errno_name(err), buf);
|
2250
|
-
|
3512
|
+
abort();
|
3513
|
+
}
|
3514
|
+
}
|
3515
|
+
|
3516
|
+
void
|
3517
|
+
test_simple (const char *buf, enum http_errno err_expected)
|
3518
|
+
{
|
3519
|
+
test_simple_type(buf, err_expected, HTTP_REQUEST);
|
3520
|
+
}
|
3521
|
+
|
3522
|
+
void
|
3523
|
+
test_invalid_header_content (int req, const char* str)
|
3524
|
+
{
|
3525
|
+
http_parser parser;
|
3526
|
+
http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
|
3527
|
+
size_t parsed;
|
3528
|
+
const char *buf;
|
3529
|
+
buf = req ?
|
3530
|
+
"GET / HTTP/1.1\r\n" :
|
3531
|
+
"HTTP/1.1 200 OK\r\n";
|
3532
|
+
parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
|
3533
|
+
assert(parsed == strlen(buf));
|
3534
|
+
|
3535
|
+
buf = str;
|
3536
|
+
size_t buflen = strlen(buf);
|
3537
|
+
|
3538
|
+
parsed = http_parser_execute(&parser, &settings_null, buf, buflen);
|
3539
|
+
if (parsed != buflen) {
|
3540
|
+
assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_HEADER_TOKEN);
|
3541
|
+
return;
|
3542
|
+
}
|
3543
|
+
|
3544
|
+
fprintf(stderr,
|
3545
|
+
"\n*** Error expected but none in invalid header content test ***\n");
|
3546
|
+
abort();
|
3547
|
+
}
|
3548
|
+
|
3549
|
+
void
|
3550
|
+
test_invalid_header_field_content_error (int req)
|
3551
|
+
{
|
3552
|
+
test_invalid_header_content(req, "Foo: F\01ailure");
|
3553
|
+
test_invalid_header_content(req, "Foo: B\02ar");
|
3554
|
+
}
|
3555
|
+
|
3556
|
+
void
|
3557
|
+
test_invalid_header_field (int req, const char* str)
|
3558
|
+
{
|
3559
|
+
http_parser parser;
|
3560
|
+
http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
|
3561
|
+
size_t parsed;
|
3562
|
+
const char *buf;
|
3563
|
+
buf = req ?
|
3564
|
+
"GET / HTTP/1.1\r\n" :
|
3565
|
+
"HTTP/1.1 200 OK\r\n";
|
3566
|
+
parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
|
3567
|
+
assert(parsed == strlen(buf));
|
3568
|
+
|
3569
|
+
buf = str;
|
3570
|
+
size_t buflen = strlen(buf);
|
3571
|
+
|
3572
|
+
parsed = http_parser_execute(&parser, &settings_null, buf, buflen);
|
3573
|
+
if (parsed != buflen) {
|
3574
|
+
assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_HEADER_TOKEN);
|
3575
|
+
return;
|
3576
|
+
}
|
3577
|
+
|
3578
|
+
fprintf(stderr,
|
3579
|
+
"\n*** Error expected but none in invalid header token test ***\n");
|
3580
|
+
abort();
|
3581
|
+
}
|
3582
|
+
|
3583
|
+
void
|
3584
|
+
test_invalid_header_field_token_error (int req)
|
3585
|
+
{
|
3586
|
+
test_invalid_header_field(req, "Fo@: Failure");
|
3587
|
+
test_invalid_header_field(req, "Foo\01\test: Bar");
|
3588
|
+
}
|
3589
|
+
|
3590
|
+
void
|
3591
|
+
test_double_content_length_error (int req)
|
3592
|
+
{
|
3593
|
+
http_parser parser;
|
3594
|
+
http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
|
3595
|
+
size_t parsed;
|
3596
|
+
const char *buf;
|
3597
|
+
buf = req ?
|
3598
|
+
"GET / HTTP/1.1\r\n" :
|
3599
|
+
"HTTP/1.1 200 OK\r\n";
|
3600
|
+
parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
|
3601
|
+
assert(parsed == strlen(buf));
|
3602
|
+
|
3603
|
+
buf = "Content-Length: 0\r\nContent-Length: 1\r\n\r\n";
|
3604
|
+
size_t buflen = strlen(buf);
|
3605
|
+
|
3606
|
+
parsed = http_parser_execute(&parser, &settings_null, buf, buflen);
|
3607
|
+
if (parsed != buflen) {
|
3608
|
+
assert(HTTP_PARSER_ERRNO(&parser) == HPE_UNEXPECTED_CONTENT_LENGTH);
|
3609
|
+
return;
|
3610
|
+
}
|
3611
|
+
|
3612
|
+
fprintf(stderr,
|
3613
|
+
"\n*** Error expected but none in double content-length test ***\n");
|
3614
|
+
abort();
|
3615
|
+
}
|
3616
|
+
|
3617
|
+
void
|
3618
|
+
test_chunked_content_length_error (int req)
|
3619
|
+
{
|
3620
|
+
http_parser parser;
|
3621
|
+
http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
|
3622
|
+
size_t parsed;
|
3623
|
+
const char *buf;
|
3624
|
+
buf = req ?
|
3625
|
+
"GET / HTTP/1.1\r\n" :
|
3626
|
+
"HTTP/1.1 200 OK\r\n";
|
3627
|
+
parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
|
3628
|
+
assert(parsed == strlen(buf));
|
3629
|
+
|
3630
|
+
buf = "Transfer-Encoding: chunked\r\nContent-Length: 1\r\n\r\n";
|
3631
|
+
size_t buflen = strlen(buf);
|
3632
|
+
|
3633
|
+
parsed = http_parser_execute(&parser, &settings_null, buf, buflen);
|
3634
|
+
if (parsed != buflen) {
|
3635
|
+
assert(HTTP_PARSER_ERRNO(&parser) == HPE_UNEXPECTED_CONTENT_LENGTH);
|
3636
|
+
return;
|
3637
|
+
}
|
3638
|
+
|
3639
|
+
fprintf(stderr,
|
3640
|
+
"\n*** Error expected but none in chunked content-length test ***\n");
|
3641
|
+
abort();
|
3642
|
+
}
|
3643
|
+
|
3644
|
+
void
|
3645
|
+
test_header_cr_no_lf_error (int req)
|
3646
|
+
{
|
3647
|
+
http_parser parser;
|
3648
|
+
http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
|
3649
|
+
size_t parsed;
|
3650
|
+
const char *buf;
|
3651
|
+
buf = req ?
|
3652
|
+
"GET / HTTP/1.1\r\n" :
|
3653
|
+
"HTTP/1.1 200 OK\r\n";
|
3654
|
+
parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
|
3655
|
+
assert(parsed == strlen(buf));
|
3656
|
+
|
3657
|
+
buf = "Foo: 1\rBar: 1\r\n\r\n";
|
3658
|
+
size_t buflen = strlen(buf);
|
3659
|
+
|
3660
|
+
parsed = http_parser_execute(&parser, &settings_null, buf, buflen);
|
3661
|
+
if (parsed != buflen) {
|
3662
|
+
assert(HTTP_PARSER_ERRNO(&parser) == HPE_LF_EXPECTED);
|
3663
|
+
return;
|
3664
|
+
}
|
3665
|
+
|
3666
|
+
fprintf(stderr,
|
3667
|
+
"\n*** Error expected but none in header whitespace test ***\n");
|
3668
|
+
abort();
|
3669
|
+
}
|
3670
|
+
|
3671
|
+
void
|
3672
|
+
test_no_overflow_parse_url (void)
|
3673
|
+
{
|
3674
|
+
int rv;
|
3675
|
+
struct http_parser_url u;
|
3676
|
+
|
3677
|
+
http_parser_url_init(&u);
|
3678
|
+
rv = http_parser_parse_url("http://example.com:8001", 22, 0, &u);
|
3679
|
+
|
3680
|
+
if (rv != 0) {
|
3681
|
+
fprintf(stderr,
|
3682
|
+
"\n*** test_no_overflow_parse_url invalid return value=%d\n",
|
3683
|
+
rv);
|
3684
|
+
abort();
|
3685
|
+
}
|
3686
|
+
|
3687
|
+
if (u.port != 800) {
|
3688
|
+
fprintf(stderr,
|
3689
|
+
"\n*** test_no_overflow_parse_url invalid port number=%d\n",
|
3690
|
+
u.port);
|
3691
|
+
abort();
|
2251
3692
|
}
|
2252
3693
|
}
|
2253
3694
|
|
@@ -2276,9 +3717,25 @@ test_header_overflow_error (int req)
|
|
2276
3717
|
}
|
2277
3718
|
|
2278
3719
|
fprintf(stderr, "\n*** Error expected but none in header overflow test ***\n");
|
2279
|
-
|
3720
|
+
abort();
|
3721
|
+
}
|
3722
|
+
|
3723
|
+
|
3724
|
+
void
|
3725
|
+
test_header_nread_value ()
|
3726
|
+
{
|
3727
|
+
http_parser parser;
|
3728
|
+
http_parser_init(&parser, HTTP_REQUEST);
|
3729
|
+
size_t parsed;
|
3730
|
+
const char *buf;
|
3731
|
+
buf = "GET / HTTP/1.1\r\nheader: value\nhdr: value\r\n";
|
3732
|
+
parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
|
3733
|
+
assert(parsed == strlen(buf));
|
3734
|
+
|
3735
|
+
assert(parser.nread == strlen(buf));
|
2280
3736
|
}
|
2281
3737
|
|
3738
|
+
|
2282
3739
|
static void
|
2283
3740
|
test_content_length_overflow (const char *buf, size_t buflen, int expect_ok)
|
2284
3741
|
{
|
@@ -2299,7 +3756,7 @@ test_header_content_length_overflow_error (void)
|
|
2299
3756
|
"HTTP/1.1 200 OK\r\n" \
|
2300
3757
|
"Content-Length: " #size "\r\n" \
|
2301
3758
|
"\r\n"
|
2302
|
-
const char a[] = X(
|
3759
|
+
const char a[] = X(1844674407370955160); /* 2^64 / 10 - 1 */
|
2303
3760
|
const char b[] = X(18446744073709551615); /* 2^64-1 */
|
2304
3761
|
const char c[] = X(18446744073709551616); /* 2^64 */
|
2305
3762
|
#undef X
|
@@ -2317,7 +3774,7 @@ test_chunk_content_length_overflow_error (void)
|
|
2317
3774
|
"\r\n" \
|
2318
3775
|
#size "\r\n" \
|
2319
3776
|
"..."
|
2320
|
-
const char a[] = X(
|
3777
|
+
const char a[] = X(FFFFFFFFFFFFFFE); /* 2^64 / 16 - 1 */
|
2321
3778
|
const char b[] = X(FFFFFFFFFFFFFFFF); /* 2^64-1 */
|
2322
3779
|
const char c[] = X(10000000000000000); /* 2^64 */
|
2323
3780
|
#undef X
|
@@ -2334,8 +3791,8 @@ test_no_overflow_long_body (int req, size_t length)
|
|
2334
3791
|
size_t parsed;
|
2335
3792
|
size_t i;
|
2336
3793
|
char buf1[3000];
|
2337
|
-
size_t buf1len = sprintf(buf1, "%s\r\nConnection: Keep-Alive\r\nContent-Length: %
|
2338
|
-
req ? "POST / HTTP/1.0" : "HTTP/1.0 200 OK", length);
|
3794
|
+
size_t buf1len = sprintf(buf1, "%s\r\nConnection: Keep-Alive\r\nContent-Length: %lu\r\n\r\n",
|
3795
|
+
req ? "POST / HTTP/1.0" : "HTTP/1.0 200 OK", (unsigned long)length);
|
2339
3796
|
parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len);
|
2340
3797
|
if (parsed != buf1len)
|
2341
3798
|
goto err;
|
@@ -2353,10 +3810,10 @@ test_no_overflow_long_body (int req, size_t length)
|
|
2353
3810
|
|
2354
3811
|
err:
|
2355
3812
|
fprintf(stderr,
|
2356
|
-
"\n*** error in test_no_overflow_long_body %s of length %
|
3813
|
+
"\n*** error in test_no_overflow_long_body %s of length %lu ***\n",
|
2357
3814
|
req ? "REQUEST" : "RESPONSE",
|
2358
|
-
length);
|
2359
|
-
|
3815
|
+
(unsigned long)length);
|
3816
|
+
abort();
|
2360
3817
|
}
|
2361
3818
|
|
2362
3819
|
void
|
@@ -2388,26 +3845,26 @@ test_multiple3 (const struct message *r1, const struct message *r2, const struct
|
|
2388
3845
|
|
2389
3846
|
if (read != strlen(total)) {
|
2390
3847
|
print_error(total, read);
|
2391
|
-
|
3848
|
+
abort();
|
2392
3849
|
}
|
2393
3850
|
|
2394
3851
|
read = parse(NULL, 0);
|
2395
3852
|
|
2396
3853
|
if (read != 0) {
|
2397
3854
|
print_error(total, read);
|
2398
|
-
|
3855
|
+
abort();
|
2399
3856
|
}
|
2400
3857
|
|
2401
3858
|
test:
|
2402
3859
|
|
2403
3860
|
if (message_count != num_messages) {
|
2404
3861
|
fprintf(stderr, "\n\n*** Parser didn't see 3 messages only %d *** \n", num_messages);
|
2405
|
-
|
3862
|
+
abort();
|
2406
3863
|
}
|
2407
3864
|
|
2408
|
-
if (!message_eq(0, r1))
|
2409
|
-
if (message_count > 1 && !message_eq(1, r2))
|
2410
|
-
if (message_count > 2 && !message_eq(2, r3))
|
3865
|
+
if (!message_eq(0, 0, r1)) abort();
|
3866
|
+
if (message_count > 1 && !message_eq(1, 0, r2)) abort();
|
3867
|
+
if (message_count > 2 && !message_eq(2, 0, r3)) abort();
|
2411
3868
|
|
2412
3869
|
parser_free();
|
2413
3870
|
}
|
@@ -2452,15 +3909,15 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
|
|
2452
3909
|
parser_init(type_both ? HTTP_BOTH : r1->type);
|
2453
3910
|
|
2454
3911
|
buf1_len = i;
|
2455
|
-
|
3912
|
+
strlncpy(buf1, sizeof(buf1), total, buf1_len);
|
2456
3913
|
buf1[buf1_len] = 0;
|
2457
3914
|
|
2458
3915
|
buf2_len = j - i;
|
2459
|
-
|
3916
|
+
strlncpy(buf2, sizeof(buf1), total+i, buf2_len);
|
2460
3917
|
buf2[buf2_len] = 0;
|
2461
3918
|
|
2462
3919
|
buf3_len = total_len - j;
|
2463
|
-
|
3920
|
+
strlncpy(buf3, sizeof(buf1), total+j, buf3_len);
|
2464
3921
|
buf3[buf3_len] = 0;
|
2465
3922
|
|
2466
3923
|
read = parse(buf1, buf1_len);
|
@@ -2503,17 +3960,17 @@ test:
|
|
2503
3960
|
goto error;
|
2504
3961
|
}
|
2505
3962
|
|
2506
|
-
if (!message_eq(0, r1)) {
|
3963
|
+
if (!message_eq(0, 0, r1)) {
|
2507
3964
|
fprintf(stderr, "\n\nError matching messages[0] in test_scan.\n");
|
2508
3965
|
goto error;
|
2509
3966
|
}
|
2510
3967
|
|
2511
|
-
if (message_count > 1 && !message_eq(1, r2)) {
|
3968
|
+
if (message_count > 1 && !message_eq(1, 0, r2)) {
|
2512
3969
|
fprintf(stderr, "\n\nError matching messages[1] in test_scan.\n");
|
2513
3970
|
goto error;
|
2514
3971
|
}
|
2515
3972
|
|
2516
|
-
if (message_count > 2 && !message_eq(2, r3)) {
|
3973
|
+
if (message_count > 2 && !message_eq(2, 0, r3)) {
|
2517
3974
|
fprintf(stderr, "\n\nError matching messages[2] in test_scan.\n");
|
2518
3975
|
goto error;
|
2519
3976
|
}
|
@@ -2530,7 +3987,7 @@ test:
|
|
2530
3987
|
fprintf(stderr, "buf1 (%u) %s\n\n", (unsigned int)buf1_len, buf1);
|
2531
3988
|
fprintf(stderr, "buf2 (%u) %s\n\n", (unsigned int)buf2_len , buf2);
|
2532
3989
|
fprintf(stderr, "buf3 (%u) %s\n", (unsigned int)buf3_len, buf3);
|
2533
|
-
|
3990
|
+
abort();
|
2534
3991
|
}
|
2535
3992
|
|
2536
3993
|
// user required to free the result
|
@@ -2609,10 +4066,31 @@ test_message_pause (const struct message *msg)
|
|
2609
4066
|
test:
|
2610
4067
|
if (num_messages != 1) {
|
2611
4068
|
printf("\n*** num_messages != 1 after testing '%s' ***\n\n", msg->name);
|
2612
|
-
|
4069
|
+
abort();
|
4070
|
+
}
|
4071
|
+
|
4072
|
+
if(!message_eq(0, 0, msg)) abort();
|
4073
|
+
|
4074
|
+
parser_free();
|
4075
|
+
}
|
4076
|
+
|
4077
|
+
/* Verify that body and next message won't be parsed in responses to CONNECT */
|
4078
|
+
void
|
4079
|
+
test_message_connect (const struct message *msg)
|
4080
|
+
{
|
4081
|
+
char *buf = (char*) msg->raw;
|
4082
|
+
size_t buflen = strlen(msg->raw);
|
4083
|
+
|
4084
|
+
parser_init(msg->type);
|
4085
|
+
|
4086
|
+
parse_connect(buf, buflen);
|
4087
|
+
|
4088
|
+
if (num_messages != 1) {
|
4089
|
+
printf("\n*** num_messages != 1 after testing '%s' ***\n\n", msg->name);
|
4090
|
+
abort();
|
2613
4091
|
}
|
2614
4092
|
|
2615
|
-
if(!message_eq(0, msg))
|
4093
|
+
if(!message_eq(0, 1, msg)) abort();
|
2616
4094
|
|
2617
4095
|
parser_free();
|
2618
4096
|
}
|
@@ -2621,20 +4099,30 @@ int
|
|
2621
4099
|
main (void)
|
2622
4100
|
{
|
2623
4101
|
parser = NULL;
|
2624
|
-
|
2625
|
-
|
2626
|
-
|
4102
|
+
unsigned i, j, k;
|
4103
|
+
unsigned long version;
|
4104
|
+
unsigned major;
|
4105
|
+
unsigned minor;
|
4106
|
+
unsigned patch;
|
4107
|
+
|
4108
|
+
version = http_parser_version();
|
4109
|
+
major = (version >> 16) & 255;
|
4110
|
+
minor = (version >> 8) & 255;
|
4111
|
+
patch = version & 255;
|
4112
|
+
printf("http_parser v%u.%u.%u (0x%06lx)\n", major, minor, patch, version);
|
2627
4113
|
|
2628
4114
|
printf("sizeof(http_parser) = %u\n", (unsigned int)sizeof(http_parser));
|
2629
4115
|
|
2630
|
-
for (request_count = 0; requests[request_count].name; request_count++);
|
2631
|
-
for (response_count = 0; responses[response_count].name; response_count++);
|
2632
|
-
|
2633
4116
|
//// API
|
2634
4117
|
test_preserve_data();
|
2635
4118
|
test_parse_url();
|
4119
|
+
test_method_str();
|
4120
|
+
|
4121
|
+
//// NREAD
|
4122
|
+
test_header_nread_value();
|
2636
4123
|
|
2637
4124
|
//// OVERFLOW CONDITIONS
|
4125
|
+
test_no_overflow_parse_url();
|
2638
4126
|
|
2639
4127
|
test_header_overflow_error(HTTP_REQUEST);
|
2640
4128
|
test_no_overflow_long_body(HTTP_REQUEST, 1000);
|
@@ -2647,21 +4135,64 @@ main (void)
|
|
2647
4135
|
test_header_content_length_overflow_error();
|
2648
4136
|
test_chunk_content_length_overflow_error();
|
2649
4137
|
|
4138
|
+
//// HEADER FIELD CONDITIONS
|
4139
|
+
test_double_content_length_error(HTTP_REQUEST);
|
4140
|
+
test_chunked_content_length_error(HTTP_REQUEST);
|
4141
|
+
test_header_cr_no_lf_error(HTTP_REQUEST);
|
4142
|
+
test_invalid_header_field_token_error(HTTP_REQUEST);
|
4143
|
+
test_invalid_header_field_content_error(HTTP_REQUEST);
|
4144
|
+
test_double_content_length_error(HTTP_RESPONSE);
|
4145
|
+
test_chunked_content_length_error(HTTP_RESPONSE);
|
4146
|
+
test_header_cr_no_lf_error(HTTP_RESPONSE);
|
4147
|
+
test_invalid_header_field_token_error(HTTP_RESPONSE);
|
4148
|
+
test_invalid_header_field_content_error(HTTP_RESPONSE);
|
4149
|
+
|
4150
|
+
test_simple_type(
|
4151
|
+
"POST / HTTP/1.1\r\n"
|
4152
|
+
"Content-Length: 42 \r\n" // Note the surrounding whitespace.
|
4153
|
+
"\r\n",
|
4154
|
+
HPE_OK,
|
4155
|
+
HTTP_REQUEST);
|
4156
|
+
|
4157
|
+
test_simple_type(
|
4158
|
+
"POST / HTTP/1.1\r\n"
|
4159
|
+
"Content-Length: 4 2\r\n"
|
4160
|
+
"\r\n",
|
4161
|
+
HPE_INVALID_CONTENT_LENGTH,
|
4162
|
+
HTTP_REQUEST);
|
4163
|
+
|
4164
|
+
test_simple_type(
|
4165
|
+
"POST / HTTP/1.1\r\n"
|
4166
|
+
"Content-Length: 13 37\r\n"
|
4167
|
+
"\r\n",
|
4168
|
+
HPE_INVALID_CONTENT_LENGTH,
|
4169
|
+
HTTP_REQUEST);
|
4170
|
+
|
2650
4171
|
//// RESPONSES
|
2651
4172
|
|
2652
|
-
|
4173
|
+
test_simple_type("HTP/1.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
4174
|
+
test_simple_type("HTTP/01.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
4175
|
+
test_simple_type("HTTP/11.1 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
4176
|
+
test_simple_type("HTTP/1.01 200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
4177
|
+
test_simple_type("HTTP/1.1\t200 OK\r\n\r\n", HPE_INVALID_VERSION, HTTP_RESPONSE);
|
4178
|
+
|
4179
|
+
for (i = 0; i < ARRAY_SIZE(responses); i++) {
|
2653
4180
|
test_message(&responses[i]);
|
2654
4181
|
}
|
2655
4182
|
|
2656
|
-
for (i = 0; i <
|
4183
|
+
for (i = 0; i < ARRAY_SIZE(responses); i++) {
|
2657
4184
|
test_message_pause(&responses[i]);
|
2658
4185
|
}
|
2659
4186
|
|
2660
|
-
for (i = 0; i <
|
4187
|
+
for (i = 0; i < ARRAY_SIZE(responses); i++) {
|
4188
|
+
test_message_connect(&responses[i]);
|
4189
|
+
}
|
4190
|
+
|
4191
|
+
for (i = 0; i < ARRAY_SIZE(responses); i++) {
|
2661
4192
|
if (!responses[i].should_keep_alive) continue;
|
2662
|
-
for (j = 0; j <
|
4193
|
+
for (j = 0; j < ARRAY_SIZE(responses); j++) {
|
2663
4194
|
if (!responses[j].should_keep_alive) continue;
|
2664
|
-
for (k = 0; k <
|
4195
|
+
for (k = 0; k < ARRAY_SIZE(responses); k++) {
|
2665
4196
|
test_multiple3(&responses[i], &responses[j], &responses[k]);
|
2666
4197
|
}
|
2667
4198
|
}
|
@@ -2686,13 +4217,18 @@ main (void)
|
|
2686
4217
|
,.http_major= 1
|
2687
4218
|
,.http_minor= 0
|
2688
4219
|
,.status_code= 200
|
4220
|
+
,.response_status= "OK"
|
2689
4221
|
,.num_headers= 2
|
2690
4222
|
,.headers=
|
2691
4223
|
{ { "Transfer-Encoding", "chunked" }
|
2692
4224
|
, { "Content-Type", "text/plain" }
|
2693
4225
|
}
|
2694
4226
|
,.body_size= 31337*1024
|
4227
|
+
,.num_chunks_complete= 31338
|
2695
4228
|
};
|
4229
|
+
for (i = 0; i < MAX_CHUNKS; i++) {
|
4230
|
+
large_chunked.chunk_lengths[i] = 1024;
|
4231
|
+
}
|
2696
4232
|
test_message_count_body(&large_chunked);
|
2697
4233
|
free(msg);
|
2698
4234
|
}
|
@@ -2716,13 +4252,15 @@ main (void)
|
|
2716
4252
|
|
2717
4253
|
/// REQUESTS
|
2718
4254
|
|
2719
|
-
test_simple("hello world", HPE_INVALID_METHOD);
|
2720
4255
|
test_simple("GET / HTP/1.1\r\n\r\n", HPE_INVALID_VERSION);
|
4256
|
+
test_simple("GET / HTTP/01.1\r\n\r\n", HPE_INVALID_VERSION);
|
4257
|
+
test_simple("GET / HTTP/11.1\r\n\r\n", HPE_INVALID_VERSION);
|
4258
|
+
test_simple("GET / HTTP/1.01\r\n\r\n", HPE_INVALID_VERSION);
|
2721
4259
|
|
2722
|
-
|
2723
|
-
test_simple("
|
2724
|
-
|
2725
|
-
|
4260
|
+
// Extended characters - see nodejs/test/parallel/test-http-headers-obstext.js
|
4261
|
+
test_simple("GET / HTTP/1.1\r\n"
|
4262
|
+
"Test: Düsseldorf\r\n",
|
4263
|
+
HPE_OK);
|
2726
4264
|
|
2727
4265
|
// Well-formed but incomplete
|
2728
4266
|
test_simple("GET / HTTP/1.1\r\n"
|
@@ -2747,7 +4285,12 @@ main (void)
|
|
2747
4285
|
"MOVE",
|
2748
4286
|
"PROPFIND",
|
2749
4287
|
"PROPPATCH",
|
4288
|
+
"SEARCH",
|
2750
4289
|
"UNLOCK",
|
4290
|
+
"BIND",
|
4291
|
+
"REBIND",
|
4292
|
+
"UNBIND",
|
4293
|
+
"ACL",
|
2751
4294
|
"REPORT",
|
2752
4295
|
"MKACTIVITY",
|
2753
4296
|
"CHECKOUT",
|
@@ -2757,6 +4300,10 @@ main (void)
|
|
2757
4300
|
"SUBSCRIBE",
|
2758
4301
|
"UNSUBSCRIBE",
|
2759
4302
|
"PATCH",
|
4303
|
+
"PURGE",
|
4304
|
+
"MKCALENDAR",
|
4305
|
+
"LINK",
|
4306
|
+
"UNLINK",
|
2760
4307
|
0 };
|
2761
4308
|
const char **this_method;
|
2762
4309
|
for (this_method = all_methods; *this_method; this_method++) {
|
@@ -2766,15 +4313,32 @@ main (void)
|
|
2766
4313
|
}
|
2767
4314
|
|
2768
4315
|
static const char *bad_methods[] = {
|
4316
|
+
"ASDF",
|
2769
4317
|
"C******",
|
4318
|
+
"COLA",
|
4319
|
+
"GEM",
|
4320
|
+
"GETA",
|
2770
4321
|
"M****",
|
4322
|
+
"MKCOLA",
|
4323
|
+
"PROPPATCHA",
|
4324
|
+
"PUN",
|
4325
|
+
"PX",
|
4326
|
+
"SA",
|
4327
|
+
"hello world",
|
2771
4328
|
0 };
|
2772
4329
|
for (this_method = bad_methods; *this_method; this_method++) {
|
2773
4330
|
char buf[200];
|
2774
4331
|
sprintf(buf, "%s / HTTP/1.1\r\n\r\n", *this_method);
|
2775
|
-
test_simple(buf,
|
4332
|
+
test_simple(buf, HPE_INVALID_METHOD);
|
2776
4333
|
}
|
2777
4334
|
|
4335
|
+
// illegal header field name line folding
|
4336
|
+
test_simple("GET / HTTP/1.1\r\n"
|
4337
|
+
"name\r\n"
|
4338
|
+
" : value\r\n"
|
4339
|
+
"\r\n",
|
4340
|
+
HPE_INVALID_HEADER_TOKEN);
|
4341
|
+
|
2778
4342
|
const char *dumbfuck2 =
|
2779
4343
|
"GET / HTTP/1.1\r\n"
|
2780
4344
|
"X-SSL-Bullshit: -----BEGIN CERTIFICATE-----\r\n"
|
@@ -2812,6 +4376,22 @@ main (void)
|
|
2812
4376
|
"\r\n";
|
2813
4377
|
test_simple(dumbfuck2, HPE_OK);
|
2814
4378
|
|
4379
|
+
const char *corrupted_connection =
|
4380
|
+
"GET / HTTP/1.1\r\n"
|
4381
|
+
"Host: www.example.com\r\n"
|
4382
|
+
"Connection\r\033\065\325eep-Alive\r\n"
|
4383
|
+
"Accept-Encoding: gzip\r\n"
|
4384
|
+
"\r\n";
|
4385
|
+
test_simple(corrupted_connection, HPE_INVALID_HEADER_TOKEN);
|
4386
|
+
|
4387
|
+
const char *corrupted_header_name =
|
4388
|
+
"GET / HTTP/1.1\r\n"
|
4389
|
+
"Host: www.example.com\r\n"
|
4390
|
+
"X-Some-Header\r\033\065\325eep-Alive\r\n"
|
4391
|
+
"Accept-Encoding: gzip\r\n"
|
4392
|
+
"\r\n";
|
4393
|
+
test_simple(corrupted_header_name, HPE_INVALID_HEADER_TOKEN);
|
4394
|
+
|
2815
4395
|
#if 0
|
2816
4396
|
// NOTE(Wed Nov 18 11:57:27 CET 2009) this seems okay. we just read body
|
2817
4397
|
// until EOF.
|
@@ -2828,19 +4408,19 @@ main (void)
|
|
2828
4408
|
|
2829
4409
|
|
2830
4410
|
/* check to make sure our predefined requests are okay */
|
2831
|
-
for (i = 0; requests
|
4411
|
+
for (i = 0; i < ARRAY_SIZE(requests); i++) {
|
2832
4412
|
test_message(&requests[i]);
|
2833
4413
|
}
|
2834
4414
|
|
2835
|
-
for (i = 0; i <
|
4415
|
+
for (i = 0; i < ARRAY_SIZE(requests); i++) {
|
2836
4416
|
test_message_pause(&requests[i]);
|
2837
4417
|
}
|
2838
4418
|
|
2839
|
-
for (i = 0; i <
|
4419
|
+
for (i = 0; i < ARRAY_SIZE(requests); i++) {
|
2840
4420
|
if (!requests[i].should_keep_alive) continue;
|
2841
|
-
for (j = 0; j <
|
4421
|
+
for (j = 0; j < ARRAY_SIZE(requests); j++) {
|
2842
4422
|
if (!requests[j].should_keep_alive) continue;
|
2843
|
-
for (k = 0; k <
|
4423
|
+
for (k = 0; k < ARRAY_SIZE(requests); k++) {
|
2844
4424
|
test_multiple3(&requests[i], &requests[j], &requests[k]);
|
2845
4425
|
}
|
2846
4426
|
}
|