http_parser.rb 0.6.0.beta.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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;
|