http_parser.rb 0.6.0.beta.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- 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 +86 -52
- 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/ext/ruby_http_parser/vendor/http-parser-java/http_parser.c +271 -154
- data/ext/ruby_http_parser/vendor/http-parser-java/http_parser.h +48 -61
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPMethod.java +5 -3
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserSettings.java +37 -104
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPParser.java +116 -101
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/ParserSettings.java +9 -5
- data/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Message.java +1 -1
- data/ext/ruby_http_parser/vendor/http-parser-java/test.c +579 -153
- data/http_parser.rb.gemspec +14 -9
- data/spec/parser_spec.rb +177 -99
- data/spec/support/requests.json +2 -2
- data/spec/support/responses.json +20 -0
- data/tasks/spec.rake +1 -1
- metadata +131 -162
- data/Gemfile.lock +0 -39
- data/ext/ruby_http_parser/vendor/http-parser/CONTRIBUTIONS +0 -4
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPHeadersCompleteCallback.java +0 -13
- data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPHeadersCompleteCallback.java +0 -12
data/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/ParserSettings.java
CHANGED
@@ -2,15 +2,16 @@ package http_parser.lolevel;
|
|
2
2
|
import java.nio.ByteBuffer;
|
3
3
|
import http_parser.HTTPException;
|
4
4
|
public class ParserSettings {
|
5
|
-
|
5
|
+
|
6
6
|
public HTTPCallback on_message_begin;
|
7
7
|
public HTTPDataCallback on_path;
|
8
8
|
public HTTPDataCallback on_query_string;
|
9
9
|
public HTTPDataCallback on_url;
|
10
10
|
public HTTPDataCallback on_fragment;
|
11
|
+
public HTTPCallback on_status_complete;
|
11
12
|
public HTTPDataCallback on_header_field;
|
12
13
|
public HTTPDataCallback on_header_value;
|
13
|
-
public
|
14
|
+
public HTTPCallback on_headers_complete;
|
14
15
|
public HTTPDataCallback on_body;
|
15
16
|
public HTTPCallback on_message_complete;
|
16
17
|
public HTTPErrorCallback on_error;
|
@@ -22,7 +23,7 @@ public class ParserSettings {
|
|
22
23
|
void call_on_message_complete (HTTPParser p) {
|
23
24
|
call_on(on_message_complete, p);
|
24
25
|
}
|
25
|
-
|
26
|
+
|
26
27
|
// this one is a little bit different:
|
27
28
|
// the current `position` of the buffer is the location of the
|
28
29
|
// error, `ini_pos` indicates where the position of
|
@@ -35,7 +36,7 @@ public class ParserSettings {
|
|
35
36
|
on_error.cb(p, mes, buf, ini_pos);
|
36
37
|
return;
|
37
38
|
}
|
38
|
-
// if on_error gets called it MUST throw an exception, else the parser
|
39
|
+
// if on_error gets called it MUST throw an exception, else the parser
|
39
40
|
// will attempt to continue parsing, which it can't because it's
|
40
41
|
// in an invalid state.
|
41
42
|
throw new HTTPException(mes);
|
@@ -50,6 +51,9 @@ public class ParserSettings {
|
|
50
51
|
void call_on_fragment (HTTPParser p, ByteBuffer buf, int pos, int len) {
|
51
52
|
call_on(on_fragment, p, buf, pos, len);
|
52
53
|
}
|
54
|
+
void call_on_status_complete(HTTPParser p) {
|
55
|
+
call_on(on_status_complete, p);
|
56
|
+
}
|
53
57
|
void call_on_path (HTTPParser p, ByteBuffer buf, int pos, int len) {
|
54
58
|
call_on(on_path, p, buf, pos, len);
|
55
59
|
}
|
@@ -64,7 +68,7 @@ public class ParserSettings {
|
|
64
68
|
}
|
65
69
|
void call_on_headers_complete(HTTPParser p) {
|
66
70
|
call_on(on_headers_complete, p);
|
67
|
-
}
|
71
|
+
}
|
68
72
|
void call_on (HTTPCallback cb, HTTPParser p) {
|
69
73
|
// cf. CALLBACK2 macro
|
70
74
|
if (null != cb) {
|
@@ -228,7 +228,7 @@ public class Message {
|
|
228
228
|
return 0;
|
229
229
|
}
|
230
230
|
};
|
231
|
-
s.on_headers_complete = new
|
231
|
+
s.on_headers_complete = new HTTPCallback() {
|
232
232
|
public int cb (HTTPParser p) {
|
233
233
|
headers_complete_called = true;
|
234
234
|
String parsed_path = null;
|
@@ -32,7 +32,7 @@
|
|
32
32
|
#define FALSE 0
|
33
33
|
|
34
34
|
#define MAX_HEADERS 13
|
35
|
-
#define MAX_ELEMENT_SIZE
|
35
|
+
#define MAX_ELEMENT_SIZE 2048
|
36
36
|
|
37
37
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
38
38
|
|
@@ -50,6 +50,8 @@ struct message {
|
|
50
50
|
char query_string[MAX_ELEMENT_SIZE];
|
51
51
|
char body[MAX_ELEMENT_SIZE];
|
52
52
|
size_t body_size;
|
53
|
+
const char *host;
|
54
|
+
const char *userinfo;
|
53
55
|
uint16_t port;
|
54
56
|
int num_headers;
|
55
57
|
enum { NONE=0, FIELD, VALUE } last_header_element;
|
@@ -65,6 +67,7 @@ struct message {
|
|
65
67
|
int headers_complete_cb_called;
|
66
68
|
int message_complete_cb_called;
|
67
69
|
int message_complete_on_eof;
|
70
|
+
int body_is_final;
|
68
71
|
};
|
69
72
|
|
70
73
|
static int currently_parsing_eof;
|
@@ -587,7 +590,7 @@ const struct message requests[] =
|
|
587
590
|
,.body= ""
|
588
591
|
}
|
589
592
|
|
590
|
-
#define LINE_FOLDING_IN_HEADER
|
593
|
+
#define LINE_FOLDING_IN_HEADER 21
|
591
594
|
, {.name= "line folding in header value"
|
592
595
|
,.type= HTTP_REQUEST
|
593
596
|
,.raw= "GET / HTTP/1.1\r\n"
|
@@ -616,7 +619,7 @@ const struct message requests[] =
|
|
616
619
|
}
|
617
620
|
|
618
621
|
|
619
|
-
#define QUERY_TERMINATED_HOST
|
622
|
+
#define QUERY_TERMINATED_HOST 22
|
620
623
|
, {.name= "host terminated by a query string"
|
621
624
|
,.type= HTTP_REQUEST
|
622
625
|
,.raw= "GET http://hypnotoad.org?hail=all HTTP/1.1\r\n"
|
@@ -630,12 +633,13 @@ const struct message requests[] =
|
|
630
633
|
,.fragment= ""
|
631
634
|
,.request_path= ""
|
632
635
|
,.request_url= "http://hypnotoad.org?hail=all"
|
636
|
+
,.host= "hypnotoad.org"
|
633
637
|
,.num_headers= 0
|
634
638
|
,.headers= { }
|
635
639
|
,.body= ""
|
636
640
|
}
|
637
641
|
|
638
|
-
#define QUERY_TERMINATED_HOSTPORT
|
642
|
+
#define QUERY_TERMINATED_HOSTPORT 23
|
639
643
|
, {.name= "host:port terminated by a query string"
|
640
644
|
,.type= HTTP_REQUEST
|
641
645
|
,.raw= "GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n"
|
@@ -649,13 +653,14 @@ const struct message requests[] =
|
|
649
653
|
,.fragment= ""
|
650
654
|
,.request_path= ""
|
651
655
|
,.request_url= "http://hypnotoad.org:1234?hail=all"
|
656
|
+
,.host= "hypnotoad.org"
|
652
657
|
,.port= 1234
|
653
658
|
,.num_headers= 0
|
654
659
|
,.headers= { }
|
655
660
|
,.body= ""
|
656
661
|
}
|
657
662
|
|
658
|
-
#define SPACE_TERMINATED_HOSTPORT
|
663
|
+
#define SPACE_TERMINATED_HOSTPORT 24
|
659
664
|
, {.name= "host:port terminated by a space"
|
660
665
|
,.type= HTTP_REQUEST
|
661
666
|
,.raw= "GET http://hypnotoad.org:1234 HTTP/1.1\r\n"
|
@@ -669,13 +674,14 @@ const struct message requests[] =
|
|
669
674
|
,.fragment= ""
|
670
675
|
,.request_path= ""
|
671
676
|
,.request_url= "http://hypnotoad.org:1234"
|
677
|
+
,.host= "hypnotoad.org"
|
672
678
|
,.port= 1234
|
673
679
|
,.num_headers= 0
|
674
680
|
,.headers= { }
|
675
681
|
,.body= ""
|
676
682
|
}
|
677
683
|
|
678
|
-
#define PATCH_REQ
|
684
|
+
#define PATCH_REQ 25
|
679
685
|
, {.name = "PATCH request"
|
680
686
|
,.type= HTTP_REQUEST
|
681
687
|
,.raw= "PATCH /file.txt HTTP/1.1\r\n"
|
@@ -703,7 +709,7 @@ const struct message requests[] =
|
|
703
709
|
,.body= "cccccccccc"
|
704
710
|
}
|
705
711
|
|
706
|
-
#define CONNECT_CAPS_REQUEST
|
712
|
+
#define CONNECT_CAPS_REQUEST 26
|
707
713
|
, {.name = "connect caps request"
|
708
714
|
,.type= HTTP_REQUEST
|
709
715
|
,.raw= "CONNECT HOME0.NETSCAPE.COM:443 HTTP/1.0\r\n"
|
@@ -728,7 +734,7 @@ const struct message requests[] =
|
|
728
734
|
}
|
729
735
|
|
730
736
|
#if !HTTP_PARSER_STRICT
|
731
|
-
#define UTF8_PATH_REQ
|
737
|
+
#define UTF8_PATH_REQ 27
|
732
738
|
, {.name= "utf-8 path request"
|
733
739
|
,.type= HTTP_REQUEST
|
734
740
|
,.raw= "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\n"
|
@@ -749,7 +755,7 @@ const struct message requests[] =
|
|
749
755
|
,.body= ""
|
750
756
|
}
|
751
757
|
|
752
|
-
#define HOSTNAME_UNDERSCORE
|
758
|
+
#define HOSTNAME_UNDERSCORE 28
|
753
759
|
, {.name = "hostname underscore"
|
754
760
|
,.type= HTTP_REQUEST
|
755
761
|
,.raw= "CONNECT home_0.netscape.com:443 HTTP/1.0\r\n"
|
@@ -775,7 +781,7 @@ const struct message requests[] =
|
|
775
781
|
#endif /* !HTTP_PARSER_STRICT */
|
776
782
|
|
777
783
|
/* see https://github.com/ry/http-parser/issues/47 */
|
778
|
-
#define EAT_TRAILING_CRLF_NO_CONNECTION_CLOSE
|
784
|
+
#define EAT_TRAILING_CRLF_NO_CONNECTION_CLOSE 29
|
779
785
|
, {.name = "eat CRLF between requests, no \"Connection: close\" header"
|
780
786
|
,.raw= "POST / HTTP/1.1\r\n"
|
781
787
|
"Host: www.example.com\r\n"
|
@@ -802,7 +808,7 @@ const struct message requests[] =
|
|
802
808
|
}
|
803
809
|
|
804
810
|
/* see https://github.com/ry/http-parser/issues/47 */
|
805
|
-
#define EAT_TRAILING_CRLF_WITH_CONNECTION_CLOSE
|
811
|
+
#define EAT_TRAILING_CRLF_WITH_CONNECTION_CLOSE 30
|
806
812
|
, {.name = "eat CRLF between requests even if \"Connection: close\" is set"
|
807
813
|
,.raw= "POST / HTTP/1.1\r\n"
|
808
814
|
"Host: www.example.com\r\n"
|
@@ -830,7 +836,7 @@ const struct message requests[] =
|
|
830
836
|
,.body= "q=42"
|
831
837
|
}
|
832
838
|
|
833
|
-
#define PURGE_REQ
|
839
|
+
#define PURGE_REQ 31
|
834
840
|
, {.name = "PURGE request"
|
835
841
|
,.type= HTTP_REQUEST
|
836
842
|
,.raw= "PURGE /file.txt HTTP/1.1\r\n"
|
@@ -850,6 +856,48 @@ const struct message requests[] =
|
|
850
856
|
,.body= ""
|
851
857
|
}
|
852
858
|
|
859
|
+
#define SEARCH_REQ 32
|
860
|
+
, {.name = "SEARCH request"
|
861
|
+
,.type= HTTP_REQUEST
|
862
|
+
,.raw= "SEARCH / HTTP/1.1\r\n"
|
863
|
+
"Host: www.example.com\r\n"
|
864
|
+
"\r\n"
|
865
|
+
,.should_keep_alive= TRUE
|
866
|
+
,.message_complete_on_eof= FALSE
|
867
|
+
,.http_major= 1
|
868
|
+
,.http_minor= 1
|
869
|
+
,.method= HTTP_SEARCH
|
870
|
+
,.query_string= ""
|
871
|
+
,.fragment= ""
|
872
|
+
,.request_path= "/"
|
873
|
+
,.request_url= "/"
|
874
|
+
,.num_headers= 1
|
875
|
+
,.headers= { { "Host", "www.example.com" } }
|
876
|
+
,.body= ""
|
877
|
+
}
|
878
|
+
|
879
|
+
#define PROXY_WITH_BASIC_AUTH 33
|
880
|
+
, {.name= "host:port and basic_auth"
|
881
|
+
,.type= HTTP_REQUEST
|
882
|
+
,.raw= "GET http://a%12:b!&*$@hypnotoad.org:1234/toto HTTP/1.1\r\n"
|
883
|
+
"\r\n"
|
884
|
+
,.should_keep_alive= TRUE
|
885
|
+
,.message_complete_on_eof= FALSE
|
886
|
+
,.http_major= 1
|
887
|
+
,.http_minor= 1
|
888
|
+
,.method= HTTP_GET
|
889
|
+
,.fragment= ""
|
890
|
+
,.request_path= "/toto"
|
891
|
+
,.request_url= "http://a%12:b!&*$@hypnotoad.org:1234/toto"
|
892
|
+
,.host= "hypnotoad.org"
|
893
|
+
,.userinfo= "a%12:b!&*$"
|
894
|
+
,.port= 1234
|
895
|
+
,.num_headers= 0
|
896
|
+
,.headers= { }
|
897
|
+
,.body= ""
|
898
|
+
}
|
899
|
+
|
900
|
+
|
853
901
|
, {.name= NULL } /* sentinel */
|
854
902
|
};
|
855
903
|
|
@@ -1365,11 +1413,88 @@ const struct message responses[] =
|
|
1365
1413
|
, {.name= NULL } /* sentinel */
|
1366
1414
|
};
|
1367
1415
|
|
1416
|
+
/* strnlen() is a POSIX.2008 addition. Can't rely on it being available so
|
1417
|
+
* define it ourselves.
|
1418
|
+
*/
|
1419
|
+
size_t
|
1420
|
+
strnlen(const char *s, size_t maxlen)
|
1421
|
+
{
|
1422
|
+
const char *p;
|
1423
|
+
|
1424
|
+
p = memchr(s, '\0', maxlen);
|
1425
|
+
if (p == NULL)
|
1426
|
+
return maxlen;
|
1427
|
+
|
1428
|
+
return p - s;
|
1429
|
+
}
|
1430
|
+
|
1431
|
+
size_t
|
1432
|
+
strlncat(char *dst, size_t len, const char *src, size_t n)
|
1433
|
+
{
|
1434
|
+
size_t slen;
|
1435
|
+
size_t dlen;
|
1436
|
+
size_t rlen;
|
1437
|
+
size_t ncpy;
|
1438
|
+
|
1439
|
+
slen = strnlen(src, n);
|
1440
|
+
dlen = strnlen(dst, len);
|
1441
|
+
|
1442
|
+
if (dlen < len) {
|
1443
|
+
rlen = len - dlen;
|
1444
|
+
ncpy = slen < rlen ? slen : (rlen - 1);
|
1445
|
+
memcpy(dst + dlen, src, ncpy);
|
1446
|
+
dst[dlen + ncpy] = '\0';
|
1447
|
+
}
|
1448
|
+
|
1449
|
+
assert(len > slen + dlen);
|
1450
|
+
return slen + dlen;
|
1451
|
+
}
|
1452
|
+
|
1453
|
+
size_t
|
1454
|
+
strlcat(char *dst, const char *src, size_t len)
|
1455
|
+
{
|
1456
|
+
return strlncat(dst, len, src, (size_t) -1);
|
1457
|
+
}
|
1458
|
+
|
1459
|
+
size_t
|
1460
|
+
strlncpy(char *dst, size_t len, const char *src, size_t n)
|
1461
|
+
{
|
1462
|
+
size_t slen;
|
1463
|
+
size_t ncpy;
|
1464
|
+
|
1465
|
+
slen = strnlen(src, n);
|
1466
|
+
|
1467
|
+
if (len > 0) {
|
1468
|
+
ncpy = slen < len ? slen : (len - 1);
|
1469
|
+
memcpy(dst, src, ncpy);
|
1470
|
+
dst[ncpy] = '\0';
|
1471
|
+
}
|
1472
|
+
|
1473
|
+
assert(len > slen);
|
1474
|
+
return slen;
|
1475
|
+
}
|
1476
|
+
|
1477
|
+
size_t
|
1478
|
+
strlcpy(char *dst, const char *src, size_t len)
|
1479
|
+
{
|
1480
|
+
return strlncpy(dst, len, src, (size_t) -1);
|
1481
|
+
}
|
1482
|
+
|
1368
1483
|
int
|
1369
1484
|
request_url_cb (http_parser *p, const char *buf, size_t len)
|
1370
1485
|
{
|
1371
1486
|
assert(p == parser);
|
1372
|
-
|
1487
|
+
strlncat(messages[num_messages].request_url,
|
1488
|
+
sizeof(messages[num_messages].request_url),
|
1489
|
+
buf,
|
1490
|
+
len);
|
1491
|
+
return 0;
|
1492
|
+
}
|
1493
|
+
|
1494
|
+
int
|
1495
|
+
status_complete_cb (http_parser *p) {
|
1496
|
+
assert(p == parser);
|
1497
|
+
p->data++;
|
1373
1498
|
return 0;
|
1374
1499
|
}
|
1375
1500
|
|
@@ -1382,7 +1507,10 @@ header_field_cb (http_parser *p, const char *buf, size_t len)
|
|
1382
1507
|
if (m->last_header_element != FIELD)
|
1383
1508
|
m->num_headers++;
|
1384
1509
|
|
1385
|
-
|
1510
|
+
strlncat(m->headers[m->num_headers-1][0],
|
1511
|
+
sizeof(m->headers[m->num_headers-1][0]),
|
1512
|
+
buf,
|
1513
|
+
len);
|
1386
1514
|
|
1387
1515
|
m->last_header_element = FIELD;
|
1388
1516
|
|
@@ -1395,19 +1523,39 @@ header_value_cb (http_parser *p, const char *buf, size_t len)
|
|
1395
1523
|
assert(p == parser);
|
1396
1524
|
struct message *m = &messages[num_messages];
|
1397
1525
|
|
1398
|
-
|
1526
|
+
strlncat(m->headers[m->num_headers-1][1],
|
1527
|
+
sizeof(m->headers[m->num_headers-1][1]),
|
1528
|
+
buf,
|
1529
|
+
len);
|
1399
1530
|
|
1400
1531
|
m->last_header_element = VALUE;
|
1401
1532
|
|
1402
1533
|
return 0;
|
1403
1534
|
}
|
1404
1535
|
|
1536
|
+
void
|
1537
|
+
check_body_is_final (const http_parser *p)
|
1538
|
+
{
|
1539
|
+
if (messages[num_messages].body_is_final) {
|
1540
|
+
fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 "
|
1541
|
+
"on last on_body callback call "
|
1542
|
+
"but it doesn't! ***\n\n");
|
1543
|
+
assert(0);
|
1544
|
+
abort();
|
1545
|
+
}
|
1546
|
+
messages[num_messages].body_is_final = http_body_is_final(p);
|
1547
|
+
}
|
1548
|
+
|
1405
1549
|
int
|
1406
1550
|
body_cb (http_parser *p, const char *buf, size_t len)
|
1407
1551
|
{
|
1408
1552
|
assert(p == parser);
|
1409
|
-
|
1553
|
+
strlncat(messages[num_messages].body,
|
1554
|
+
sizeof(messages[num_messages].body),
|
1555
|
+
buf,
|
1556
|
+
len);
|
1410
1557
|
messages[num_messages].body_size += len;
|
1558
|
+
check_body_is_final(p);
|
1411
1559
|
// printf("body_cb: '%s'\n", requests[num_messages].body);
|
1412
1560
|
return 0;
|
1413
1561
|
}
|
@@ -1418,6 +1566,7 @@ count_body_cb (http_parser *p, const char *buf, size_t len)
|
|
1418
1566
|
assert(p == parser);
|
1419
1567
|
assert(buf);
|
1420
1568
|
messages[num_messages].body_size += len;
|
1569
|
+
check_body_is_final(p);
|
1421
1570
|
return 0;
|
1422
1571
|
}
|
1423
1572
|
|
@@ -1454,6 +1603,18 @@ message_complete_cb (http_parser *p)
|
|
1454
1603
|
assert(0);
|
1455
1604
|
abort();
|
1456
1605
|
}
|
1606
|
+
|
1607
|
+
if (messages[num_messages].body_size &&
|
1608
|
+
http_body_is_final(p) &&
|
1609
|
+
!messages[num_messages].body_is_final)
|
1610
|
+
{
|
1611
|
+
fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 "
|
1612
|
+
"on last on_body callback call "
|
1613
|
+
"but it doesn't! ***\n\n");
|
1614
|
+
assert(0);
|
1615
|
+
abort();
|
1616
|
+
}
|
1617
|
+
|
1457
1618
|
messages[num_messages].message_complete_cb_called = TRUE;
|
1458
1619
|
|
1459
1620
|
messages[num_messages].message_complete_on_eof = currently_parsing_eof;
|
@@ -1774,6 +1935,14 @@ message_eq (int index, const struct message *expected)
|
|
1774
1935
|
abort();
|
1775
1936
|
}
|
1776
1937
|
|
1938
|
+
if (expected->host) {
|
1939
|
+
MESSAGE_CHECK_URL_EQ(&u, expected, m, host, UF_HOST);
|
1940
|
+
}
|
1941
|
+
|
1942
|
+
if (expected->userinfo) {
|
1943
|
+
MESSAGE_CHECK_URL_EQ(&u, expected, m, userinfo, UF_USERINFO);
|
1944
|
+
}
|
1945
|
+
|
1777
1946
|
m->port = (u.field_set & (1 << UF_PORT)) ?
|
1778
1947
|
u.port : 0;
|
1779
1948
|
|
@@ -1836,7 +2005,7 @@ upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) {
|
|
1836
2005
|
va_list ap;
|
1837
2006
|
size_t i;
|
1838
2007
|
size_t off = 0;
|
1839
|
-
|
2008
|
+
|
1840
2009
|
va_start(ap, nmsgs);
|
1841
2010
|
|
1842
2011
|
for (i = 0; i < nmsgs; i++) {
|
@@ -1871,8 +2040,7 @@ upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) {
|
|
1871
2040
|
static void
|
1872
2041
|
print_error (const char *raw, size_t error_location)
|
1873
2042
|
{
|
1874
|
-
fprintf(stderr, "\n*** %s
|
1875
|
-
"http_parser.c", HTTP_PARSER_ERRNO_LINE(parser),
|
2043
|
+
fprintf(stderr, "\n*** %s ***\n\n",
|
1876
2044
|
http_errno_description(HTTP_PARSER_ERRNO(parser)));
|
1877
2045
|
|
1878
2046
|
int this_line = 0, char_len = 0;
|
@@ -1946,6 +2114,26 @@ const struct url_test url_tests[] =
|
|
1946
2114
|
,{ 15, 1 } /* UF_PATH */
|
1947
2115
|
,{ 0, 0 } /* UF_QUERY */
|
1948
2116
|
,{ 0, 0 } /* UF_FRAGMENT */
|
2117
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2118
|
+
}
|
2119
|
+
}
|
2120
|
+
,.rv=0
|
2121
|
+
}
|
2122
|
+
|
2123
|
+
, {.name="proxy request with port"
|
2124
|
+
,.url="http://hostname:444/"
|
2125
|
+
,.is_connect=0
|
2126
|
+
,.u=
|
2127
|
+
{.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PORT) | (1 << UF_PATH)
|
2128
|
+
,.port=444
|
2129
|
+
,.field_data=
|
2130
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2131
|
+
,{ 7, 8 } /* UF_HOST */
|
2132
|
+
,{ 16, 3 } /* UF_PORT */
|
2133
|
+
,{ 19, 1 } /* UF_PATH */
|
2134
|
+
,{ 0, 0 } /* UF_QUERY */
|
2135
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2136
|
+
,{ 0, 0 } /* UF_USERINFO */
|
1949
2137
|
}
|
1950
2138
|
}
|
1951
2139
|
,.rv=0
|
@@ -1964,11 +2152,18 @@ const struct url_test url_tests[] =
|
|
1964
2152
|
,{ 0, 0 } /* UF_PATH */
|
1965
2153
|
,{ 0, 0 } /* UF_QUERY */
|
1966
2154
|
,{ 0, 0 } /* UF_FRAGMENT */
|
2155
|
+
,{ 0, 0 } /* UF_USERINFO */
|
1967
2156
|
}
|
1968
2157
|
}
|
1969
2158
|
,.rv=0
|
1970
2159
|
}
|
1971
2160
|
|
2161
|
+
, {.name="CONNECT request but not connect"
|
2162
|
+
,.url="hostname:443"
|
2163
|
+
,.is_connect=0
|
2164
|
+
,.rv=1
|
2165
|
+
}
|
2166
|
+
|
1972
2167
|
, {.name="proxy ipv6 request"
|
1973
2168
|
,.url="http://[1:2::3:4]/"
|
1974
2169
|
,.is_connect=0
|
@@ -1982,6 +2177,26 @@ const struct url_test url_tests[] =
|
|
1982
2177
|
,{ 17, 1 } /* UF_PATH */
|
1983
2178
|
,{ 0, 0 } /* UF_QUERY */
|
1984
2179
|
,{ 0, 0 } /* UF_FRAGMENT */
|
2180
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2181
|
+
}
|
2182
|
+
}
|
2183
|
+
,.rv=0
|
2184
|
+
}
|
2185
|
+
|
2186
|
+
, {.name="proxy ipv6 request with port"
|
2187
|
+
,.url="http://[1:2::3:4]:67/"
|
2188
|
+
,.is_connect=0
|
2189
|
+
,.u=
|
2190
|
+
{.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PORT) | (1 << UF_PATH)
|
2191
|
+
,.port=67
|
2192
|
+
,.field_data=
|
2193
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2194
|
+
,{ 8, 8 } /* UF_HOST */
|
2195
|
+
,{ 18, 2 } /* UF_PORT */
|
2196
|
+
,{ 20, 1 } /* UF_PATH */
|
2197
|
+
,{ 0, 0 } /* UF_QUERY */
|
2198
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2199
|
+
,{ 0, 0 } /* UF_USERINFO */
|
1985
2200
|
}
|
1986
2201
|
}
|
1987
2202
|
,.rv=0
|
@@ -2000,13 +2215,35 @@ const struct url_test url_tests[] =
|
|
2000
2215
|
,{ 0, 0 } /* UF_PATH */
|
2001
2216
|
,{ 0, 0 } /* UF_QUERY */
|
2002
2217
|
,{ 0, 0 } /* UF_FRAGMENT */
|
2218
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2219
|
+
}
|
2220
|
+
}
|
2221
|
+
,.rv=0
|
2222
|
+
}
|
2223
|
+
|
2224
|
+
, {.name="ipv4 in ipv6 address"
|
2225
|
+
,.url="http://[2001:0000:0000:0000:0000:0000:1.9.1.1]/"
|
2226
|
+
,.is_connect=0
|
2227
|
+
,.u=
|
2228
|
+
{.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH)
|
2229
|
+
,.port=0
|
2230
|
+
,.field_data=
|
2231
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2232
|
+
,{ 8, 37 } /* UF_HOST */
|
2233
|
+
,{ 0, 0 } /* UF_PORT */
|
2234
|
+
,{ 46, 1 } /* UF_PATH */
|
2235
|
+
,{ 0, 0 } /* UF_QUERY */
|
2236
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2237
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2003
2238
|
}
|
2004
2239
|
}
|
2005
2240
|
,.rv=0
|
2006
2241
|
}
|
2007
2242
|
|
2008
2243
|
, {.name="extra ? in query string"
|
2009
|
-
,.url="http://a.tbcdn.cn/p/fp/2010c/??fp-header-min.css,fp-base-min.css,
|
2244
|
+
,.url="http://a.tbcdn.cn/p/fp/2010c/??fp-header-min.css,fp-base-min.css,"
|
2245
|
+
"fp-channel-min.css,fp-product-min.css,fp-mall-min.css,fp-category-min.css,"
|
2246
|
+
"fp-sub-min.css,fp-gdp4p-min.css,fp-css3-min.css,fp-misc-min.css?t=20101022.css"
|
2010
2247
|
,.is_connect=0
|
2011
2248
|
,.u=
|
2012
2249
|
{.field_set=(1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_QUERY)
|
@@ -2018,11 +2255,118 @@ const struct url_test url_tests[] =
|
|
2018
2255
|
,{ 17, 12 } /* UF_PATH */
|
2019
2256
|
,{ 30,187 } /* UF_QUERY */
|
2020
2257
|
,{ 0, 0 } /* UF_FRAGMENT */
|
2258
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2259
|
+
}
|
2260
|
+
}
|
2261
|
+
,.rv=0
|
2262
|
+
}
|
2263
|
+
|
2264
|
+
, {.name="space URL encoded"
|
2265
|
+
,.url="/toto.html?toto=a%20b"
|
2266
|
+
,.is_connect=0
|
2267
|
+
,.u=
|
2268
|
+
{.field_set= (1<<UF_PATH) | (1<<UF_QUERY)
|
2269
|
+
,.port=0
|
2270
|
+
,.field_data=
|
2271
|
+
{{ 0, 0 } /* UF_SCHEMA */
|
2272
|
+
,{ 0, 0 } /* UF_HOST */
|
2273
|
+
,{ 0, 0 } /* UF_PORT */
|
2274
|
+
,{ 0, 10 } /* UF_PATH */
|
2275
|
+
,{ 11, 10 } /* UF_QUERY */
|
2276
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2277
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2278
|
+
}
|
2279
|
+
}
|
2280
|
+
,.rv=0
|
2281
|
+
}
|
2282
|
+
|
2283
|
+
|
2284
|
+
, {.name="URL fragment"
|
2285
|
+
,.url="/toto.html#titi"
|
2286
|
+
,.is_connect=0
|
2287
|
+
,.u=
|
2288
|
+
{.field_set= (1<<UF_PATH) | (1<<UF_FRAGMENT)
|
2289
|
+
,.port=0
|
2290
|
+
,.field_data=
|
2291
|
+
{{ 0, 0 } /* UF_SCHEMA */
|
2292
|
+
,{ 0, 0 } /* UF_HOST */
|
2293
|
+
,{ 0, 0 } /* UF_PORT */
|
2294
|
+
,{ 0, 10 } /* UF_PATH */
|
2295
|
+
,{ 0, 0 } /* UF_QUERY */
|
2296
|
+
,{ 11, 4 } /* UF_FRAGMENT */
|
2297
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2298
|
+
}
|
2299
|
+
}
|
2300
|
+
,.rv=0
|
2301
|
+
}
|
2302
|
+
|
2303
|
+
, {.name="complex URL fragment"
|
2304
|
+
,.url="http://www.webmasterworld.com/r.cgi?f=21&d=8405&url="
|
2305
|
+
"http://www.example.com/index.html?foo=bar&hello=world#midpage"
|
2306
|
+
,.is_connect=0
|
2307
|
+
,.u=
|
2308
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_QUERY) |\
|
2309
|
+
(1<<UF_FRAGMENT)
|
2310
|
+
,.port=0
|
2311
|
+
,.field_data=
|
2312
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2313
|
+
,{ 7, 22 } /* UF_HOST */
|
2314
|
+
,{ 0, 0 } /* UF_PORT */
|
2315
|
+
,{ 29, 6 } /* UF_PATH */
|
2316
|
+
,{ 36, 69 } /* UF_QUERY */
|
2317
|
+
,{106, 7 } /* UF_FRAGMENT */
|
2318
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2021
2319
|
}
|
2022
2320
|
}
|
2023
2321
|
,.rv=0
|
2024
2322
|
}
|
2025
2323
|
|
2324
|
+
, {.name="complex URL from node js url parser doc"
|
2325
|
+
,.url="http://host.com:8080/p/a/t/h?query=string#hash"
|
2326
|
+
,.is_connect=0
|
2327
|
+
,.u=
|
2328
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PORT) | (1<<UF_PATH) |\
|
2329
|
+
(1<<UF_QUERY) | (1<<UF_FRAGMENT)
|
2330
|
+
,.port=8080
|
2331
|
+
,.field_data=
|
2332
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2333
|
+
,{ 7, 8 } /* UF_HOST */
|
2334
|
+
,{ 16, 4 } /* UF_PORT */
|
2335
|
+
,{ 20, 8 } /* UF_PATH */
|
2336
|
+
,{ 29, 12 } /* UF_QUERY */
|
2337
|
+
,{ 42, 4 } /* UF_FRAGMENT */
|
2338
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2339
|
+
}
|
2340
|
+
}
|
2341
|
+
,.rv=0
|
2342
|
+
}
|
2343
|
+
|
2344
|
+
, {.name="complex URL with basic auth from node js url parser doc"
|
2345
|
+
,.url="http://a:b@host.com:8080/p/a/t/h?query=string#hash"
|
2346
|
+
,.is_connect=0
|
2347
|
+
,.u=
|
2348
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PORT) | (1<<UF_PATH) |\
|
2349
|
+
(1<<UF_QUERY) | (1<<UF_FRAGMENT) | (1<<UF_USERINFO)
|
2350
|
+
,.port=8080
|
2351
|
+
,.field_data=
|
2352
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2353
|
+
,{ 11, 8 } /* UF_HOST */
|
2354
|
+
,{ 20, 4 } /* UF_PORT */
|
2355
|
+
,{ 24, 8 } /* UF_PATH */
|
2356
|
+
,{ 33, 12 } /* UF_QUERY */
|
2357
|
+
,{ 46, 4 } /* UF_FRAGMENT */
|
2358
|
+
,{ 7, 3 } /* UF_USERINFO */
|
2359
|
+
}
|
2360
|
+
}
|
2361
|
+
,.rv=0
|
2362
|
+
}
|
2363
|
+
|
2364
|
+
, {.name="double @"
|
2365
|
+
,.url="http://a:b@@hostname:443/"
|
2366
|
+
,.is_connect=0
|
2367
|
+
,.rv=1
|
2368
|
+
}
|
2369
|
+
|
2026
2370
|
, {.name="proxy empty host"
|
2027
2371
|
,.url="http://:443/"
|
2028
2372
|
,.is_connect=0
|
@@ -2035,6 +2379,12 @@ const struct url_test url_tests[] =
|
|
2035
2379
|
,.rv=1
|
2036
2380
|
}
|
2037
2381
|
|
2382
|
+
, {.name="CONNECT with basic auth"
|
2383
|
+
,.url="a:b@hostname:443"
|
2384
|
+
,.is_connect=1
|
2385
|
+
,.rv=1
|
2386
|
+
}
|
2387
|
+
|
2038
2388
|
, {.name="CONNECT empty host"
|
2039
2389
|
,.url=":443"
|
2040
2390
|
,.is_connect=1
|
@@ -2052,12 +2402,189 @@ const struct url_test url_tests[] =
|
|
2052
2402
|
,.is_connect=1
|
2053
2403
|
,.rv=1
|
2054
2404
|
}
|
2405
|
+
|
2406
|
+
, {.name="space in URL"
|
2407
|
+
,.url="/foo bar/"
|
2408
|
+
,.rv=1 /* s_dead */
|
2409
|
+
}
|
2410
|
+
|
2411
|
+
, {.name="proxy basic auth with space url encoded"
|
2412
|
+
,.url="http://a%20:b@host.com/"
|
2413
|
+
,.is_connect=0
|
2414
|
+
,.u=
|
2415
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_USERINFO)
|
2416
|
+
,.port=0
|
2417
|
+
,.field_data=
|
2418
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2419
|
+
,{ 14, 8 } /* UF_HOST */
|
2420
|
+
,{ 0, 0 } /* UF_PORT */
|
2421
|
+
,{ 22, 1 } /* UF_PATH */
|
2422
|
+
,{ 0, 0 } /* UF_QUERY */
|
2423
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2424
|
+
,{ 7, 6 } /* UF_USERINFO */
|
2425
|
+
}
|
2426
|
+
}
|
2427
|
+
,.rv=0
|
2428
|
+
}
|
2429
|
+
|
2430
|
+
, {.name="carriage return in URL"
|
2431
|
+
,.url="/foo\rbar/"
|
2432
|
+
,.rv=1 /* s_dead */
|
2433
|
+
}
|
2434
|
+
|
2435
|
+
, {.name="proxy double : in URL"
|
2436
|
+
,.url="http://hostname::443/"
|
2437
|
+
,.rv=1 /* s_dead */
|
2438
|
+
}
|
2439
|
+
|
2440
|
+
, {.name="proxy basic auth with double :"
|
2441
|
+
,.url="http://a::b@host.com/"
|
2442
|
+
,.is_connect=0
|
2443
|
+
,.u=
|
2444
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_USERINFO)
|
2445
|
+
,.port=0
|
2446
|
+
,.field_data=
|
2447
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2448
|
+
,{ 12, 8 } /* UF_HOST */
|
2449
|
+
,{ 0, 0 } /* UF_PORT */
|
2450
|
+
,{ 20, 1 } /* UF_PATH */
|
2451
|
+
,{ 0, 0 } /* UF_QUERY */
|
2452
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2453
|
+
,{ 7, 4 } /* UF_USERINFO */
|
2454
|
+
}
|
2455
|
+
}
|
2456
|
+
,.rv=0
|
2457
|
+
}
|
2458
|
+
|
2459
|
+
, {.name="line feed in URL"
|
2460
|
+
,.url="/foo\nbar/"
|
2461
|
+
,.rv=1 /* s_dead */
|
2462
|
+
}
|
2463
|
+
|
2464
|
+
, {.name="proxy empty basic auth"
|
2465
|
+
,.url="http://@hostname/fo"
|
2466
|
+
,.u=
|
2467
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH)
|
2468
|
+
,.port=0
|
2469
|
+
,.field_data=
|
2470
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2471
|
+
,{ 8, 8 } /* UF_HOST */
|
2472
|
+
,{ 0, 0 } /* UF_PORT */
|
2473
|
+
,{ 16, 3 } /* UF_PATH */
|
2474
|
+
,{ 0, 0 } /* UF_QUERY */
|
2475
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2476
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2477
|
+
}
|
2478
|
+
}
|
2479
|
+
,.rv=0
|
2480
|
+
}
|
2481
|
+
, {.name="proxy line feed in hostname"
|
2482
|
+
,.url="http://host\name/fo"
|
2483
|
+
,.rv=1 /* s_dead */
|
2484
|
+
}
|
2485
|
+
|
2486
|
+
, {.name="proxy % in hostname"
|
2487
|
+
,.url="http://host%name/fo"
|
2488
|
+
,.rv=1 /* s_dead */
|
2489
|
+
}
|
2490
|
+
|
2491
|
+
, {.name="proxy ; in hostname"
|
2492
|
+
,.url="http://host;ame/fo"
|
2493
|
+
,.rv=1 /* s_dead */
|
2494
|
+
}
|
2495
|
+
|
2496
|
+
, {.name="proxy basic auth with unreservedchars"
|
2497
|
+
,.url="http://a!;-_!=+$@host.com/"
|
2498
|
+
,.is_connect=0
|
2499
|
+
,.u=
|
2500
|
+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_USERINFO)
|
2501
|
+
,.port=0
|
2502
|
+
,.field_data=
|
2503
|
+
{{ 0, 4 } /* UF_SCHEMA */
|
2504
|
+
,{ 17, 8 } /* UF_HOST */
|
2505
|
+
,{ 0, 0 } /* UF_PORT */
|
2506
|
+
,{ 25, 1 } /* UF_PATH */
|
2507
|
+
,{ 0, 0 } /* UF_QUERY */
|
2508
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2509
|
+
,{ 7, 9 } /* UF_USERINFO */
|
2510
|
+
}
|
2511
|
+
}
|
2512
|
+
,.rv=0
|
2513
|
+
}
|
2514
|
+
|
2515
|
+
, {.name="proxy only empty basic auth"
|
2516
|
+
,.url="http://@/fo"
|
2517
|
+
,.rv=1 /* s_dead */
|
2518
|
+
}
|
2519
|
+
|
2520
|
+
, {.name="proxy only basic auth"
|
2521
|
+
,.url="http://toto@/fo"
|
2522
|
+
,.rv=1 /* s_dead */
|
2523
|
+
}
|
2524
|
+
|
2525
|
+
, {.name="proxy emtpy hostname"
|
2526
|
+
,.url="http:///fo"
|
2527
|
+
,.rv=1 /* s_dead */
|
2528
|
+
}
|
2529
|
+
|
2530
|
+
, {.name="proxy = in URL"
|
2531
|
+
,.url="http://host=ame/fo"
|
2532
|
+
,.rv=1 /* s_dead */
|
2533
|
+
}
|
2534
|
+
|
2535
|
+
#if HTTP_PARSER_STRICT
|
2536
|
+
|
2537
|
+
, {.name="tab in URL"
|
2538
|
+
,.url="/foo\tbar/"
|
2539
|
+
,.rv=1 /* s_dead */
|
2540
|
+
}
|
2541
|
+
|
2542
|
+
, {.name="form feed in URL"
|
2543
|
+
,.url="/foo\fbar/"
|
2544
|
+
,.rv=1 /* s_dead */
|
2545
|
+
}
|
2546
|
+
|
2547
|
+
#else /* !HTTP_PARSER_STRICT */
|
2548
|
+
|
2549
|
+
, {.name="tab in URL"
|
2550
|
+
,.url="/foo\tbar/"
|
2551
|
+
,.u=
|
2552
|
+
{.field_set=(1 << UF_PATH)
|
2553
|
+
,.field_data=
|
2554
|
+
{{ 0, 0 } /* UF_SCHEMA */
|
2555
|
+
,{ 0, 0 } /* UF_HOST */
|
2556
|
+
,{ 0, 0 } /* UF_PORT */
|
2557
|
+
,{ 0, 9 } /* UF_PATH */
|
2558
|
+
,{ 0, 0 } /* UF_QUERY */
|
2559
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2560
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2561
|
+
}
|
2562
|
+
}
|
2563
|
+
,.rv=0
|
2564
|
+
}
|
2565
|
+
|
2566
|
+
, {.name="form feed in URL"
|
2567
|
+
,.url="/foo\fbar/"
|
2568
|
+
,.u=
|
2569
|
+
{.field_set=(1 << UF_PATH)
|
2570
|
+
,.field_data=
|
2571
|
+
{{ 0, 0 } /* UF_SCHEMA */
|
2572
|
+
,{ 0, 0 } /* UF_HOST */
|
2573
|
+
,{ 0, 0 } /* UF_PORT */
|
2574
|
+
,{ 0, 9 } /* UF_PATH */
|
2575
|
+
,{ 0, 0 } /* UF_QUERY */
|
2576
|
+
,{ 0, 0 } /* UF_FRAGMENT */
|
2577
|
+
,{ 0, 0 } /* UF_USERINFO */
|
2578
|
+
}
|
2579
|
+
}
|
2580
|
+
,.rv=0
|
2581
|
+
}
|
2582
|
+
#endif
|
2055
2583
|
};
|
2056
2584
|
|
2057
2585
|
void
|
2058
2586
|
dump_url (const char *url, const struct http_parser_url *u)
|
2059
2587
|
{
|
2060
|
-
char part[512];
|
2061
2588
|
unsigned int i;
|
2062
2589
|
|
2063
2590
|
printf("\tfield_set: 0x%x, port: %u\n", u->field_set, u->port);
|
@@ -2067,14 +2594,12 @@ dump_url (const char *url, const struct http_parser_url *u)
|
|
2067
2594
|
continue;
|
2068
2595
|
}
|
2069
2596
|
|
2070
|
-
|
2071
|
-
part[u->field_data[i].len] = '\0';
|
2072
|
-
|
2073
|
-
printf("\tfield_data[%u]: off: %u len: %u part: \"%s\"\n",
|
2597
|
+
printf("\tfield_data[%u]: off: %u len: %u part: \"%.*s\n\"",
|
2074
2598
|
i,
|
2075
2599
|
u->field_data[i].off,
|
2076
2600
|
u->field_data[i].len,
|
2077
|
-
|
2601
|
+
u->field_data[i].len,
|
2602
|
+
url + u->field_data[i].off);
|
2078
2603
|
}
|
2079
2604
|
}
|
2080
2605
|
|
@@ -2124,6 +2649,13 @@ test_parse_url (void)
|
|
2124
2649
|
}
|
2125
2650
|
}
|
2126
2651
|
|
2652
|
+
void
|
2653
|
+
test_method_str (void)
|
2654
|
+
{
|
2655
|
+
assert(0 == strcmp("GET", http_method_str(HTTP_GET)));
|
2656
|
+
assert(0 == strcmp("<unknown>", http_method_str(1337)));
|
2657
|
+
}
|
2658
|
+
|
2127
2659
|
void
|
2128
2660
|
test_message (const struct message *message)
|
2129
2661
|
{
|
@@ -2334,8 +2866,8 @@ test_no_overflow_long_body (int req, size_t length)
|
|
2334
2866
|
size_t parsed;
|
2335
2867
|
size_t i;
|
2336
2868
|
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);
|
2869
|
+
size_t buf1len = sprintf(buf1, "%s\r\nConnection: Keep-Alive\r\nContent-Length: %lu\r\n\r\n",
|
2870
|
+
req ? "POST / HTTP/1.0" : "HTTP/1.0 200 OK", (unsigned long)length);
|
2339
2871
|
parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len);
|
2340
2872
|
if (parsed != buf1len)
|
2341
2873
|
goto err;
|
@@ -2353,9 +2885,9 @@ test_no_overflow_long_body (int req, size_t length)
|
|
2353
2885
|
|
2354
2886
|
err:
|
2355
2887
|
fprintf(stderr,
|
2356
|
-
"\n*** error in test_no_overflow_long_body %s of length %
|
2888
|
+
"\n*** error in test_no_overflow_long_body %s of length %lu ***\n",
|
2357
2889
|
req ? "REQUEST" : "RESPONSE",
|
2358
|
-
length);
|
2890
|
+
(unsigned long)length);
|
2359
2891
|
abort();
|
2360
2892
|
}
|
2361
2893
|
|
@@ -2452,15 +2984,15 @@ test_scan (const struct message *r1, const struct message *r2, const struct mess
|
|
2452
2984
|
parser_init(type_both ? HTTP_BOTH : r1->type);
|
2453
2985
|
|
2454
2986
|
buf1_len = i;
|
2455
|
-
|
2987
|
+
strlncpy(buf1, sizeof(buf1), total, buf1_len);
|
2456
2988
|
buf1[buf1_len] = 0;
|
2457
2989
|
|
2458
2990
|
buf2_len = j - i;
|
2459
|
-
|
2991
|
+
strlncpy(buf2, sizeof(buf1), total+i, buf2_len);
|
2460
2992
|
buf2[buf2_len] = 0;
|
2461
2993
|
|
2462
2994
|
buf3_len = total_len - j;
|
2463
|
-
|
2995
|
+
strlncpy(buf3, sizeof(buf1), total+j, buf3_len);
|
2464
2996
|
buf3[buf3_len] = 0;
|
2465
2997
|
|
2466
2998
|
read = parse(buf1, buf1_len);
|
@@ -2564,119 +3096,18 @@ create_large_chunked_message (int body_size_in_kb, const char* headers)
|
|
2564
3096
|
return buf;
|
2565
3097
|
}
|
2566
3098
|
|
2567
|
-
char *
|
2568
|
-
quote(const char * orig) {
|
2569
|
-
if (!orig) return NULL;
|
2570
|
-
size_t j, i, len = strlen(orig);
|
2571
|
-
char * quoted = malloc(len == 0 ? 1 : len*2); // hm..
|
2572
|
-
bzero(quoted, len == 0 ? 1 : len*2);
|
2573
|
-
for (i=0, j=0; i!=len; ++i) {
|
2574
|
-
switch (orig[i]){
|
2575
|
-
case '\n':
|
2576
|
-
quoted[j++] = '\\';
|
2577
|
-
quoted[j++] = 'n';
|
2578
|
-
break;
|
2579
|
-
case '\r':
|
2580
|
-
quoted[j++] = '\\';
|
2581
|
-
quoted[j++] = 'r';
|
2582
|
-
break;
|
2583
|
-
case '"':
|
2584
|
-
quoted[j++] = '\\';
|
2585
|
-
quoted[j++] = '"';
|
2586
|
-
break;
|
2587
|
-
default :
|
2588
|
-
quoted[j++] = orig[i];
|
2589
|
-
}
|
2590
|
-
}
|
2591
|
-
return quoted;
|
2592
|
-
}
|
2593
|
-
|
2594
|
-
void
|
2595
|
-
dump_message(const struct message * m)
|
2596
|
-
{
|
2597
|
-
int i;
|
2598
|
-
printf("name :%s\n", m->name);
|
2599
|
-
char * bla = quote(m->raw);
|
2600
|
-
printf("raw :\"%s\"\n", bla);
|
2601
|
-
free(bla);
|
2602
|
-
switch (m->type){
|
2603
|
-
case HTTP_REQUEST:
|
2604
|
-
printf("type :HTTP_REQUEST\n");break;
|
2605
|
-
case HTTP_RESPONSE:
|
2606
|
-
printf("type :HTTP_RESPONSE\n"); break;
|
2607
|
-
case HTTP_BOTH:
|
2608
|
-
printf("type :HTTP_BOTH\n");
|
2609
|
-
}
|
2610
|
-
switch (m->method) {
|
2611
|
-
case HTTP_DELETE: printf("method: HTTP_DELETE\n");break;
|
2612
|
-
case HTTP_GET: printf("method: HTTP_GET\n");break;
|
2613
|
-
case HTTP_HEAD: printf("method: HTTP_HEAD\n");break;
|
2614
|
-
case HTTP_POST: printf("method: HTTP_POST\n");break;
|
2615
|
-
case HTTP_PUT: printf("method: HTTP_PUT\n");break;
|
2616
|
-
case HTTP_CONNECT: printf("method: HTTP_CONNECT\n");break;
|
2617
|
-
case HTTP_OPTIONS: printf("method: HTTP_OPTIONS\n");break;
|
2618
|
-
case HTTP_TRACE: printf("method: HTTP_TRACE\n");break;
|
2619
|
-
case HTTP_COPY: printf("method: HTTP_COPY\n");break;
|
2620
|
-
case HTTP_LOCK: printf("method: HTTP_LOCK\n");break;
|
2621
|
-
case HTTP_MKCOL: printf("method: HTTP_MKCOL\n");break;
|
2622
|
-
case HTTP_MOVE: printf("method: HTTP_MOVE\n");break;
|
2623
|
-
case HTTP_PROPFIND: printf("method: HTTP_PROPFIND\n");break;
|
2624
|
-
case HTTP_PROPPATCH: printf("method: HTTP_PROPPATCH\n");break;
|
2625
|
-
case HTTP_UNLOCK: printf("method: HTTP_UNLOCK\n");break;
|
2626
|
-
/* subversion */
|
2627
|
-
case HTTP_REPORT: printf("method: HTTP_REPORT\n"); break;
|
2628
|
-
case HTTP_MKACTIVITY: printf("method: HTTP_MKACTIVITY\n"); break;
|
2629
|
-
case HTTP_CHECKOUT: printf("method: HTTP_CHECKOUT\n"); break;
|
2630
|
-
case HTTP_MERGE: printf("method: HTTP_MERGE\n"); break;
|
2631
|
-
|
2632
|
-
case HTTP_MSEARCH: printf("method: HTTP_MSEARCH\n"); break;
|
2633
|
-
case HTTP_NOTIFY: printf("method: HTTP_NOTIFY\n"); break;
|
2634
|
-
case HTTP_SUBSCRIBE: printf("method: HTTP_SUBSCRIBE\n"); break;
|
2635
|
-
case HTTP_UNSUBSCRIBE: printf("method: HTTP_UNSUBSCRIBE\n"); break;
|
2636
|
-
default:
|
2637
|
-
printf("method: UNKNOWN\n"); break;
|
2638
|
-
break;
|
2639
|
-
}
|
2640
|
-
printf("status_code :%d\n", m->status_code);
|
2641
|
-
printf("request_path:%s\n", m->request_path);
|
2642
|
-
printf("request_url :%s\n", m->request_url);
|
2643
|
-
printf("fragment :%s\n", m->fragment);
|
2644
|
-
printf("query_string:%s\n", m->query_string);
|
2645
|
-
|
2646
|
-
bla = quote(m->body);
|
2647
|
-
printf("body :\"%s\"\n", bla);
|
2648
|
-
free(bla);
|
2649
|
-
printf("body_size :%zu\n", m->body_size);
|
2650
|
-
|
2651
|
-
for (i=0; i!=m->num_headers; ++i){
|
2652
|
-
printf("header_%d :{ \"%s\": \"%s\"}\n", i, m->headers[i][0], m->headers[i][1]);
|
2653
|
-
}
|
2654
|
-
|
2655
|
-
printf("should_keep_alive :%d\n", m->should_keep_alive);
|
2656
|
-
bla = quote(m->upgrade);
|
2657
|
-
if (bla) {
|
2658
|
-
printf("upgrade :\"%s\"\n", bla);
|
2659
|
-
}
|
2660
|
-
free(bla);
|
2661
|
-
printf("http_major :%d\n", m->http_major);
|
2662
|
-
printf("http_minor :%d\n", m->http_minor);
|
2663
|
-
// printf("message_begin_cb_called :%d\n", m->message_begin_cb_called);
|
2664
|
-
// printf("headers_complete_cb_called:%d\n", m->headers_complete_cb_called);
|
2665
|
-
// printf("message_complete_cb_called:%d\n", m->message_complete_cb_called);
|
2666
|
-
// printf("message_complete_on_eof :%d\n", m->message_complete_on_eof);
|
2667
|
-
printf("\n");
|
2668
|
-
}
|
2669
|
-
|
2670
3099
|
void
|
2671
|
-
|
3100
|
+
test_status_complete (void)
|
2672
3101
|
{
|
2673
|
-
|
2674
|
-
|
2675
|
-
|
2676
|
-
|
2677
|
-
|
2678
|
-
|
2679
|
-
|
3102
|
+
parser_init(HTTP_RESPONSE);
|
3103
|
+
parser->data = 0;
|
3104
|
+
http_parser_settings settings = settings_null;
|
3105
|
+
settings.on_status_complete = status_complete_cb;
|
3106
|
+
|
3107
|
+
char *response = "don't mind me, just a simple response";
|
3108
|
+
http_parser_execute(parser, &settings, response, strlen(response));
|
3109
|
+
assert(parser->data == (void*)0); // the status_complete callback was never called
|
3110
|
+
assert(parser->http_errno == HPE_INVALID_CONSTANT); // the errno for an invalid status line
|
2680
3111
|
}
|
2681
3112
|
|
2682
3113
|
/* Verify that we can pause parsing at any of the bytes in the
|
@@ -2730,23 +3161,15 @@ test:
|
|
2730
3161
|
if(!message_eq(0, msg)) abort();
|
2731
3162
|
|
2732
3163
|
parser_free();
|
2733
|
-
|
2734
3164
|
}
|
2735
3165
|
|
2736
3166
|
int
|
2737
|
-
main (
|
3167
|
+
main (void)
|
2738
3168
|
{
|
2739
3169
|
parser = NULL;
|
2740
3170
|
int i, j, k;
|
2741
3171
|
int request_count;
|
2742
3172
|
int response_count;
|
2743
|
-
|
2744
|
-
if (1 != argc) {
|
2745
|
-
if (0 == (strncmp("-dump", argv[1], sizeof("-dump")))) {
|
2746
|
-
dump_messages();
|
2747
|
-
exit(0);
|
2748
|
-
}
|
2749
|
-
}
|
2750
3173
|
|
2751
3174
|
printf("sizeof(http_parser) = %u\n", (unsigned int)sizeof(http_parser));
|
2752
3175
|
|
@@ -2756,6 +3179,7 @@ main (int argc, char * argv[])
|
|
2756
3179
|
//// API
|
2757
3180
|
test_preserve_data();
|
2758
3181
|
test_parse_url();
|
3182
|
+
test_method_str();
|
2759
3183
|
|
2760
3184
|
//// OVERFLOW CONDITIONS
|
2761
3185
|
|
@@ -2993,6 +3417,8 @@ main (int argc, char * argv[])
|
|
2993
3417
|
, &requests[CONNECT_REQUEST]
|
2994
3418
|
);
|
2995
3419
|
|
3420
|
+
test_status_complete();
|
3421
|
+
|
2996
3422
|
puts("requests okay");
|
2997
3423
|
|
2998
3424
|
return 0;
|