http-parser 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/ext/Rakefile +2 -2
- data/ext/http-parser/http_parser.c +146 -154
- data/ext/http-parser/http_parser.h +77 -3
- data/lib/http-parser/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b10418834197ee747e8e8b0f731efef8f1f80285f05426292b627edadc7da52a
|
4
|
+
data.tar.gz: 5e159cadc303a5a811754eeac131d56bb5e6f8eff66be4650c049c8fc10a4a2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3fb875b674223383319ab6b02b019acf27964cddec2bb732773d4315f1aac472529b27b1a4edbf8bdbfd5441117c8a274009ad0ace5457082918e42043aa75ef
|
7
|
+
data.tar.gz: 3ada5a0f5e72ff81495e6b97c3ea20d16aa7b536fe6a7425477e73360228e3983c92788663ed3fe76e3c1b194230092f1bbed1274e68cf853bdc583c1d053cda
|
data/ext/Rakefile
CHANGED
@@ -3,6 +3,6 @@ require 'ffi-compiler/compile_task'
|
|
3
3
|
FFI::Compiler::CompileTask.new('http-parser-ext') do |t|
|
4
4
|
t.cflags << "-Wall -Wextra -O3"
|
5
5
|
t.cflags << "-D_GNU_SOURCE=1" if RbConfig::CONFIG["host_os"].downcase =~ /mingw/
|
6
|
-
t.cflags << "-arch x86_64
|
7
|
-
t.ldflags << "-arch x86_64
|
6
|
+
t.cflags << "-arch x86_64" if t.platform.mac?
|
7
|
+
t.ldflags << "-arch x86_64" if t.platform.mac?
|
8
8
|
end
|
@@ -1,7 +1,4 @@
|
|
1
|
-
/*
|
2
|
-
*
|
3
|
-
* Additional changes are licensed under the same terms as NGINX and
|
4
|
-
* copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
1
|
+
/* Copyright Joyent, Inc. and other Node contributors.
|
5
2
|
*
|
6
3
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
4
|
* of this software and associated documentation files (the "Software"), to
|
@@ -25,7 +22,6 @@
|
|
25
22
|
#include <assert.h>
|
26
23
|
#include <stddef.h>
|
27
24
|
#include <ctype.h>
|
28
|
-
#include <stdlib.h>
|
29
25
|
#include <string.h>
|
30
26
|
#include <limits.h>
|
31
27
|
|
@@ -53,6 +49,7 @@
|
|
53
49
|
|
54
50
|
#define SET_ERRNO(e) \
|
55
51
|
do { \
|
52
|
+
parser->nread = nread; \
|
56
53
|
parser->http_errno = (e); \
|
57
54
|
} while(0)
|
58
55
|
|
@@ -60,6 +57,7 @@ do { \
|
|
60
57
|
#define UPDATE_STATE(V) p_state = (enum state) (V);
|
61
58
|
#define RETURN(V) \
|
62
59
|
do { \
|
60
|
+
parser->nread = nread; \
|
63
61
|
parser->state = CURRENT_STATE(); \
|
64
62
|
return (V); \
|
65
63
|
} while (0);
|
@@ -153,8 +151,8 @@ do { \
|
|
153
151
|
*/
|
154
152
|
#define COUNT_HEADER_SIZE(V) \
|
155
153
|
do { \
|
156
|
-
|
157
|
-
if (UNLIKELY(
|
154
|
+
nread += (V); \
|
155
|
+
if (UNLIKELY(nread > (HTTP_MAX_HEADER_SIZE))) { \
|
158
156
|
SET_ERRNO(HPE_HEADER_OVERFLOW); \
|
159
157
|
goto error; \
|
160
158
|
} \
|
@@ -196,7 +194,7 @@ static const char tokens[256] = {
|
|
196
194
|
/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
|
197
195
|
0, 0, 0, 0, 0, 0, 0, 0,
|
198
196
|
/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
|
199
|
-
|
197
|
+
' ', '!', 0, '#', '$', '%', '&', '\'',
|
200
198
|
/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
|
201
199
|
0, 0, '*', '+', 0, '-', '.', 0,
|
202
200
|
/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
|
@@ -286,10 +284,10 @@ enum state
|
|
286
284
|
, s_res_HT
|
287
285
|
, s_res_HTT
|
288
286
|
, s_res_HTTP
|
289
|
-
, s_res_first_http_major
|
290
287
|
, s_res_http_major
|
291
|
-
,
|
288
|
+
, s_res_http_dot
|
292
289
|
, s_res_http_minor
|
290
|
+
, s_res_http_end
|
293
291
|
, s_res_first_status_code
|
294
292
|
, s_res_status_code
|
295
293
|
, s_res_status_start
|
@@ -316,10 +314,10 @@ enum state
|
|
316
314
|
, s_req_http_HT
|
317
315
|
, s_req_http_HTT
|
318
316
|
, s_req_http_HTTP
|
319
|
-
, s_req_first_http_major
|
320
317
|
, s_req_http_major
|
321
|
-
,
|
318
|
+
, s_req_http_dot
|
322
319
|
, s_req_http_minor
|
320
|
+
, s_req_http_end
|
323
321
|
, s_req_line_almost_done
|
324
322
|
|
325
323
|
, s_header_field_start
|
@@ -374,6 +372,8 @@ enum header_states
|
|
374
372
|
|
375
373
|
, h_connection
|
376
374
|
, h_content_length
|
375
|
+
, h_content_length_num
|
376
|
+
, h_content_length_ws
|
377
377
|
, h_transfer_encoding
|
378
378
|
, h_upgrade
|
379
379
|
|
@@ -421,14 +421,14 @@ enum http_host_state
|
|
421
421
|
(c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \
|
422
422
|
(c) == '$' || (c) == ',')
|
423
423
|
|
424
|
-
#define STRICT_TOKEN(c) (tokens[(unsigned char)c])
|
424
|
+
#define STRICT_TOKEN(c) ((c == ' ') ? 0 : tokens[(unsigned char)c])
|
425
425
|
|
426
426
|
#if HTTP_PARSER_STRICT
|
427
|
-
#define TOKEN(c) (
|
427
|
+
#define TOKEN(c) STRICT_TOKEN(c)
|
428
428
|
#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c))
|
429
429
|
#define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
|
430
430
|
#else
|
431
|
-
#define TOKEN(c)
|
431
|
+
#define TOKEN(c) tokens[(unsigned char)c]
|
432
432
|
#define IS_URL_CHAR(c) \
|
433
433
|
(BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
|
434
434
|
#define IS_HOST_CHAR(c) \
|
@@ -542,7 +542,7 @@ parse_url_char(enum state s, const char ch)
|
|
542
542
|
return s_dead;
|
543
543
|
}
|
544
544
|
|
545
|
-
/*
|
545
|
+
/* fall through */
|
546
546
|
case s_req_server_start:
|
547
547
|
case s_req_server:
|
548
548
|
if (ch == '/') {
|
@@ -646,6 +646,7 @@ size_t http_parser_execute (http_parser *parser,
|
|
646
646
|
const char *status_mark = 0;
|
647
647
|
enum state p_state = (enum state) parser->state;
|
648
648
|
const unsigned int lenient = parser->lenient_http_headers;
|
649
|
+
uint32_t nread = parser->nread;
|
649
650
|
|
650
651
|
/* We're in an error state. Don't bother doing anything. */
|
651
652
|
if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
|
@@ -757,21 +758,16 @@ reexecute:
|
|
757
758
|
|
758
759
|
case s_start_res:
|
759
760
|
{
|
761
|
+
if (ch == CR || ch == LF)
|
762
|
+
break;
|
760
763
|
parser->flags = 0;
|
761
764
|
parser->content_length = ULLONG_MAX;
|
762
765
|
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
case CR:
|
769
|
-
case LF:
|
770
|
-
break;
|
771
|
-
|
772
|
-
default:
|
773
|
-
SET_ERRNO(HPE_INVALID_CONSTANT);
|
774
|
-
goto error;
|
766
|
+
if (ch == 'H') {
|
767
|
+
UPDATE_STATE(s_res_H);
|
768
|
+
} else {
|
769
|
+
SET_ERRNO(HPE_INVALID_CONSTANT);
|
770
|
+
goto error;
|
775
771
|
}
|
776
772
|
|
777
773
|
CALLBACK_NOTIFY(message_begin);
|
@@ -795,75 +791,48 @@ reexecute:
|
|
795
791
|
|
796
792
|
case s_res_HTTP:
|
797
793
|
STRICT_CHECK(ch != '/');
|
798
|
-
UPDATE_STATE(
|
794
|
+
UPDATE_STATE(s_res_http_major);
|
799
795
|
break;
|
800
796
|
|
801
|
-
case
|
802
|
-
if (UNLIKELY(ch
|
797
|
+
case s_res_http_major:
|
798
|
+
if (UNLIKELY(!IS_NUM(ch))) {
|
803
799
|
SET_ERRNO(HPE_INVALID_VERSION);
|
804
800
|
goto error;
|
805
801
|
}
|
806
802
|
|
807
803
|
parser->http_major = ch - '0';
|
808
|
-
UPDATE_STATE(
|
804
|
+
UPDATE_STATE(s_res_http_dot);
|
809
805
|
break;
|
810
806
|
|
811
|
-
|
812
|
-
case s_res_http_major:
|
807
|
+
case s_res_http_dot:
|
813
808
|
{
|
814
|
-
if (ch
|
815
|
-
UPDATE_STATE(s_res_first_http_minor);
|
816
|
-
break;
|
817
|
-
}
|
818
|
-
|
819
|
-
if (!IS_NUM(ch)) {
|
820
|
-
SET_ERRNO(HPE_INVALID_VERSION);
|
821
|
-
goto error;
|
822
|
-
}
|
823
|
-
|
824
|
-
parser->http_major *= 10;
|
825
|
-
parser->http_major += ch - '0';
|
826
|
-
|
827
|
-
if (UNLIKELY(parser->http_major > 999)) {
|
809
|
+
if (UNLIKELY(ch != '.')) {
|
828
810
|
SET_ERRNO(HPE_INVALID_VERSION);
|
829
811
|
goto error;
|
830
812
|
}
|
831
813
|
|
814
|
+
UPDATE_STATE(s_res_http_minor);
|
832
815
|
break;
|
833
816
|
}
|
834
817
|
|
835
|
-
|
836
|
-
case s_res_first_http_minor:
|
818
|
+
case s_res_http_minor:
|
837
819
|
if (UNLIKELY(!IS_NUM(ch))) {
|
838
820
|
SET_ERRNO(HPE_INVALID_VERSION);
|
839
821
|
goto error;
|
840
822
|
}
|
841
823
|
|
842
824
|
parser->http_minor = ch - '0';
|
843
|
-
UPDATE_STATE(
|
825
|
+
UPDATE_STATE(s_res_http_end);
|
844
826
|
break;
|
845
827
|
|
846
|
-
|
847
|
-
case s_res_http_minor:
|
828
|
+
case s_res_http_end:
|
848
829
|
{
|
849
|
-
if (ch
|
850
|
-
UPDATE_STATE(s_res_first_status_code);
|
851
|
-
break;
|
852
|
-
}
|
853
|
-
|
854
|
-
if (UNLIKELY(!IS_NUM(ch))) {
|
855
|
-
SET_ERRNO(HPE_INVALID_VERSION);
|
856
|
-
goto error;
|
857
|
-
}
|
858
|
-
|
859
|
-
parser->http_minor *= 10;
|
860
|
-
parser->http_minor += ch - '0';
|
861
|
-
|
862
|
-
if (UNLIKELY(parser->http_minor > 999)) {
|
830
|
+
if (UNLIKELY(ch != ' ')) {
|
863
831
|
SET_ERRNO(HPE_INVALID_VERSION);
|
864
832
|
goto error;
|
865
833
|
}
|
866
834
|
|
835
|
+
UPDATE_STATE(s_res_first_status_code);
|
867
836
|
break;
|
868
837
|
}
|
869
838
|
|
@@ -890,10 +859,9 @@ reexecute:
|
|
890
859
|
UPDATE_STATE(s_res_status_start);
|
891
860
|
break;
|
892
861
|
case CR:
|
893
|
-
UPDATE_STATE(s_res_line_almost_done);
|
894
|
-
break;
|
895
862
|
case LF:
|
896
|
-
UPDATE_STATE(
|
863
|
+
UPDATE_STATE(s_res_status_start);
|
864
|
+
REEXECUTE();
|
897
865
|
break;
|
898
866
|
default:
|
899
867
|
SET_ERRNO(HPE_INVALID_STATUS);
|
@@ -915,19 +883,13 @@ reexecute:
|
|
915
883
|
|
916
884
|
case s_res_status_start:
|
917
885
|
{
|
918
|
-
if (ch == CR) {
|
919
|
-
UPDATE_STATE(s_res_line_almost_done);
|
920
|
-
break;
|
921
|
-
}
|
922
|
-
|
923
|
-
if (ch == LF) {
|
924
|
-
UPDATE_STATE(s_header_field_start);
|
925
|
-
break;
|
926
|
-
}
|
927
|
-
|
928
886
|
MARK(status);
|
929
887
|
UPDATE_STATE(s_res_status);
|
930
888
|
parser->index = 0;
|
889
|
+
|
890
|
+
if (ch == CR || ch == LF)
|
891
|
+
REEXECUTE();
|
892
|
+
|
931
893
|
break;
|
932
894
|
}
|
933
895
|
|
@@ -980,7 +942,7 @@ reexecute:
|
|
980
942
|
/* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */
|
981
943
|
break;
|
982
944
|
case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break;
|
983
|
-
case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break;
|
945
|
+
case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH, SOURCE */ break;
|
984
946
|
case 'T': parser->method = HTTP_TRACE; break;
|
985
947
|
case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break;
|
986
948
|
default:
|
@@ -1007,7 +969,7 @@ reexecute:
|
|
1007
969
|
UPDATE_STATE(s_req_spaces_before_url);
|
1008
970
|
} else if (ch == matcher[parser->index]) {
|
1009
971
|
; /* nada */
|
1010
|
-
} else if (
|
972
|
+
} else if ((ch >= 'A' && ch <= 'Z') || ch == '-') {
|
1011
973
|
|
1012
974
|
switch (parser->method << 16 | parser->index << 8 | ch) {
|
1013
975
|
#define XX(meth, pos, ch, new_meth) \
|
@@ -1016,31 +978,28 @@ reexecute:
|
|
1016
978
|
|
1017
979
|
XX(POST, 1, 'U', PUT)
|
1018
980
|
XX(POST, 1, 'A', PATCH)
|
981
|
+
XX(POST, 1, 'R', PROPFIND)
|
982
|
+
XX(PUT, 2, 'R', PURGE)
|
1019
983
|
XX(CONNECT, 1, 'H', CHECKOUT)
|
1020
984
|
XX(CONNECT, 2, 'P', COPY)
|
1021
985
|
XX(MKCOL, 1, 'O', MOVE)
|
1022
986
|
XX(MKCOL, 1, 'E', MERGE)
|
987
|
+
XX(MKCOL, 1, '-', MSEARCH)
|
1023
988
|
XX(MKCOL, 2, 'A', MKACTIVITY)
|
1024
989
|
XX(MKCOL, 3, 'A', MKCALENDAR)
|
1025
990
|
XX(SUBSCRIBE, 1, 'E', SEARCH)
|
991
|
+
XX(SUBSCRIBE, 1, 'O', SOURCE)
|
1026
992
|
XX(REPORT, 2, 'B', REBIND)
|
1027
|
-
XX(POST, 1, 'R', PROPFIND)
|
1028
993
|
XX(PROPFIND, 4, 'P', PROPPATCH)
|
1029
|
-
XX(PUT, 2, 'R', PURGE)
|
1030
994
|
XX(LOCK, 1, 'I', LINK)
|
1031
995
|
XX(UNLOCK, 2, 'S', UNSUBSCRIBE)
|
1032
996
|
XX(UNLOCK, 2, 'B', UNBIND)
|
1033
997
|
XX(UNLOCK, 3, 'I', UNLINK)
|
1034
998
|
#undef XX
|
1035
|
-
|
1036
999
|
default:
|
1037
1000
|
SET_ERRNO(HPE_INVALID_METHOD);
|
1038
1001
|
goto error;
|
1039
1002
|
}
|
1040
|
-
} else if (ch == '-' &&
|
1041
|
-
parser->index == 1 &&
|
1042
|
-
parser->method == HTTP_MKCOL) {
|
1043
|
-
parser->method = HTTP_MSEARCH;
|
1044
1003
|
} else {
|
1045
1004
|
SET_ERRNO(HPE_INVALID_METHOD);
|
1046
1005
|
goto error;
|
@@ -1153,57 +1112,41 @@ reexecute:
|
|
1153
1112
|
|
1154
1113
|
case s_req_http_HTTP:
|
1155
1114
|
STRICT_CHECK(ch != '/');
|
1156
|
-
UPDATE_STATE(s_req_first_http_major);
|
1157
|
-
break;
|
1158
|
-
|
1159
|
-
/* first digit of major HTTP version */
|
1160
|
-
case s_req_first_http_major:
|
1161
|
-
if (UNLIKELY(ch < '1' || ch > '9')) {
|
1162
|
-
SET_ERRNO(HPE_INVALID_VERSION);
|
1163
|
-
goto error;
|
1164
|
-
}
|
1165
|
-
|
1166
|
-
parser->http_major = ch - '0';
|
1167
1115
|
UPDATE_STATE(s_req_http_major);
|
1168
1116
|
break;
|
1169
1117
|
|
1170
|
-
/* major HTTP version or dot */
|
1171
1118
|
case s_req_http_major:
|
1172
|
-
{
|
1173
|
-
if (ch == '.') {
|
1174
|
-
UPDATE_STATE(s_req_first_http_minor);
|
1175
|
-
break;
|
1176
|
-
}
|
1177
|
-
|
1178
1119
|
if (UNLIKELY(!IS_NUM(ch))) {
|
1179
1120
|
SET_ERRNO(HPE_INVALID_VERSION);
|
1180
1121
|
goto error;
|
1181
1122
|
}
|
1182
1123
|
|
1183
|
-
parser->http_major
|
1184
|
-
|
1124
|
+
parser->http_major = ch - '0';
|
1125
|
+
UPDATE_STATE(s_req_http_dot);
|
1126
|
+
break;
|
1185
1127
|
|
1186
|
-
|
1128
|
+
case s_req_http_dot:
|
1129
|
+
{
|
1130
|
+
if (UNLIKELY(ch != '.')) {
|
1187
1131
|
SET_ERRNO(HPE_INVALID_VERSION);
|
1188
1132
|
goto error;
|
1189
1133
|
}
|
1190
1134
|
|
1135
|
+
UPDATE_STATE(s_req_http_minor);
|
1191
1136
|
break;
|
1192
1137
|
}
|
1193
1138
|
|
1194
|
-
|
1195
|
-
case s_req_first_http_minor:
|
1139
|
+
case s_req_http_minor:
|
1196
1140
|
if (UNLIKELY(!IS_NUM(ch))) {
|
1197
1141
|
SET_ERRNO(HPE_INVALID_VERSION);
|
1198
1142
|
goto error;
|
1199
1143
|
}
|
1200
1144
|
|
1201
1145
|
parser->http_minor = ch - '0';
|
1202
|
-
UPDATE_STATE(
|
1146
|
+
UPDATE_STATE(s_req_http_end);
|
1203
1147
|
break;
|
1204
1148
|
|
1205
|
-
|
1206
|
-
case s_req_http_minor:
|
1149
|
+
case s_req_http_end:
|
1207
1150
|
{
|
1208
1151
|
if (ch == CR) {
|
1209
1152
|
UPDATE_STATE(s_req_line_almost_done);
|
@@ -1215,21 +1158,8 @@ reexecute:
|
|
1215
1158
|
break;
|
1216
1159
|
}
|
1217
1160
|
|
1218
|
-
|
1219
|
-
|
1220
|
-
if (UNLIKELY(!IS_NUM(ch))) {
|
1221
|
-
SET_ERRNO(HPE_INVALID_VERSION);
|
1222
|
-
goto error;
|
1223
|
-
}
|
1224
|
-
|
1225
|
-
parser->http_minor *= 10;
|
1226
|
-
parser->http_minor += ch - '0';
|
1227
|
-
|
1228
|
-
if (UNLIKELY(parser->http_minor > 999)) {
|
1229
|
-
SET_ERRNO(HPE_INVALID_VERSION);
|
1230
|
-
goto error;
|
1231
|
-
}
|
1232
|
-
|
1161
|
+
SET_ERRNO(HPE_INVALID_VERSION);
|
1162
|
+
goto error;
|
1233
1163
|
break;
|
1234
1164
|
}
|
1235
1165
|
|
@@ -1306,8 +1236,14 @@ reexecute:
|
|
1306
1236
|
break;
|
1307
1237
|
|
1308
1238
|
switch (parser->header_state) {
|
1309
|
-
case h_general:
|
1239
|
+
case h_general: {
|
1240
|
+
size_t limit = data + len - p;
|
1241
|
+
limit = MIN(limit, HTTP_MAX_HEADER_SIZE);
|
1242
|
+
while (p+1 < data + limit && TOKEN(p[1])) {
|
1243
|
+
p++;
|
1244
|
+
}
|
1310
1245
|
break;
|
1246
|
+
}
|
1311
1247
|
|
1312
1248
|
case h_C:
|
1313
1249
|
parser->index++;
|
@@ -1407,13 +1343,14 @@ reexecute:
|
|
1407
1343
|
}
|
1408
1344
|
}
|
1409
1345
|
|
1410
|
-
COUNT_HEADER_SIZE(p - start);
|
1411
|
-
|
1412
1346
|
if (p == data + len) {
|
1413
1347
|
--p;
|
1348
|
+
COUNT_HEADER_SIZE(p - start);
|
1414
1349
|
break;
|
1415
1350
|
}
|
1416
1351
|
|
1352
|
+
COUNT_HEADER_SIZE(p - start);
|
1353
|
+
|
1417
1354
|
if (ch == ':') {
|
1418
1355
|
UPDATE_STATE(s_header_value_discard_ws);
|
1419
1356
|
CALLBACK_DATA(header_field);
|
@@ -1437,7 +1374,7 @@ reexecute:
|
|
1437
1374
|
break;
|
1438
1375
|
}
|
1439
1376
|
|
1440
|
-
/*
|
1377
|
+
/* fall through */
|
1441
1378
|
|
1442
1379
|
case s_header_value_start:
|
1443
1380
|
{
|
@@ -1476,6 +1413,7 @@ reexecute:
|
|
1476
1413
|
|
1477
1414
|
parser->flags |= F_CONTENTLENGTH;
|
1478
1415
|
parser->content_length = ch - '0';
|
1416
|
+
parser->header_state = h_content_length_num;
|
1479
1417
|
break;
|
1480
1418
|
|
1481
1419
|
case h_connection:
|
@@ -1553,7 +1491,6 @@ reexecute:
|
|
1553
1491
|
p = data + len;
|
1554
1492
|
}
|
1555
1493
|
--p;
|
1556
|
-
|
1557
1494
|
break;
|
1558
1495
|
}
|
1559
1496
|
|
@@ -1563,10 +1500,18 @@ reexecute:
|
|
1563
1500
|
break;
|
1564
1501
|
|
1565
1502
|
case h_content_length:
|
1503
|
+
if (ch == ' ') break;
|
1504
|
+
h_state = h_content_length_num;
|
1505
|
+
/* fall through */
|
1506
|
+
|
1507
|
+
case h_content_length_num:
|
1566
1508
|
{
|
1567
1509
|
uint64_t t;
|
1568
1510
|
|
1569
|
-
if (ch == ' ')
|
1511
|
+
if (ch == ' ') {
|
1512
|
+
h_state = h_content_length_ws;
|
1513
|
+
break;
|
1514
|
+
}
|
1570
1515
|
|
1571
1516
|
if (UNLIKELY(!IS_NUM(ch))) {
|
1572
1517
|
SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
|
@@ -1589,6 +1534,12 @@ reexecute:
|
|
1589
1534
|
break;
|
1590
1535
|
}
|
1591
1536
|
|
1537
|
+
case h_content_length_ws:
|
1538
|
+
if (ch == ' ') break;
|
1539
|
+
SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
|
1540
|
+
parser->header_state = h_state;
|
1541
|
+
goto error;
|
1542
|
+
|
1592
1543
|
/* Transfer-Encoding: chunked */
|
1593
1544
|
case h_matching_transfer_encoding_chunked:
|
1594
1545
|
parser->index++;
|
@@ -1687,10 +1638,10 @@ reexecute:
|
|
1687
1638
|
}
|
1688
1639
|
parser->header_state = h_state;
|
1689
1640
|
|
1690
|
-
COUNT_HEADER_SIZE(p - start);
|
1691
|
-
|
1692
1641
|
if (p == data + len)
|
1693
1642
|
--p;
|
1643
|
+
|
1644
|
+
COUNT_HEADER_SIZE(p - start);
|
1694
1645
|
break;
|
1695
1646
|
}
|
1696
1647
|
|
@@ -1794,10 +1745,17 @@ reexecute:
|
|
1794
1745
|
UPDATE_STATE(s_headers_done);
|
1795
1746
|
|
1796
1747
|
/* Set this here so that on_headers_complete() callbacks can see it */
|
1797
|
-
parser->
|
1798
|
-
|
1799
|
-
|
1800
|
-
|
1748
|
+
if ((parser->flags & F_UPGRADE) &&
|
1749
|
+
(parser->flags & F_CONNECTION_UPGRADE)) {
|
1750
|
+
/* For responses, "Upgrade: foo" and "Connection: upgrade" are
|
1751
|
+
* mandatory only when it is a 101 Switching Protocols response,
|
1752
|
+
* otherwise it is purely informational, to announce support.
|
1753
|
+
*/
|
1754
|
+
parser->upgrade =
|
1755
|
+
(parser->type == HTTP_REQUEST || parser->status_code == 101);
|
1756
|
+
} else {
|
1757
|
+
parser->upgrade = (parser->method == HTTP_CONNECT);
|
1758
|
+
}
|
1801
1759
|
|
1802
1760
|
/* Here we call the headers_complete callback. This is somewhat
|
1803
1761
|
* different than other callbacks because if the user returns 1, we
|
@@ -1816,6 +1774,7 @@ reexecute:
|
|
1816
1774
|
case 2:
|
1817
1775
|
parser->upgrade = 1;
|
1818
1776
|
|
1777
|
+
/* fall through */
|
1819
1778
|
case 1:
|
1820
1779
|
parser->flags |= F_SKIPBODY;
|
1821
1780
|
break;
|
@@ -1839,6 +1798,7 @@ reexecute:
|
|
1839
1798
|
STRICT_CHECK(ch != LF);
|
1840
1799
|
|
1841
1800
|
parser->nread = 0;
|
1801
|
+
nread = 0;
|
1842
1802
|
|
1843
1803
|
hasBody = parser->flags & F_CHUNKED ||
|
1844
1804
|
(parser->content_length > 0 && parser->content_length != ULLONG_MAX);
|
@@ -1933,7 +1893,7 @@ reexecute:
|
|
1933
1893
|
|
1934
1894
|
case s_chunk_size_start:
|
1935
1895
|
{
|
1936
|
-
assert(
|
1896
|
+
assert(nread == 1);
|
1937
1897
|
assert(parser->flags & F_CHUNKED);
|
1938
1898
|
|
1939
1899
|
unhex_val = unhex[(unsigned char)ch];
|
@@ -2001,6 +1961,7 @@ reexecute:
|
|
2001
1961
|
STRICT_CHECK(ch != LF);
|
2002
1962
|
|
2003
1963
|
parser->nread = 0;
|
1964
|
+
nread = 0;
|
2004
1965
|
|
2005
1966
|
if (parser->content_length == 0) {
|
2006
1967
|
parser->flags |= F_TRAILING;
|
@@ -2047,6 +2008,7 @@ reexecute:
|
|
2047
2008
|
assert(parser->flags & F_CHUNKED);
|
2048
2009
|
STRICT_CHECK(ch != LF);
|
2049
2010
|
parser->nread = 0;
|
2011
|
+
nread = 0;
|
2050
2012
|
UPDATE_STATE(s_chunk_size_start);
|
2051
2013
|
CALLBACK_NOTIFY(chunk_complete);
|
2052
2014
|
break;
|
@@ -2058,7 +2020,7 @@ reexecute:
|
|
2058
2020
|
}
|
2059
2021
|
}
|
2060
2022
|
|
2061
|
-
/* Run callbacks for any marks that we have leftover after we ran
|
2023
|
+
/* Run callbacks for any marks that we have leftover after we ran out of
|
2062
2024
|
* bytes. There should be at most one of these set, so it's OK to invoke
|
2063
2025
|
* them in series (unset marks will not result in callbacks).
|
2064
2026
|
*
|
@@ -2140,6 +2102,16 @@ http_method_str (enum http_method m)
|
|
2140
2102
|
return ELEM_AT(method_strings, m, "<unknown>");
|
2141
2103
|
}
|
2142
2104
|
|
2105
|
+
const char *
|
2106
|
+
http_status_str (enum http_status s)
|
2107
|
+
{
|
2108
|
+
switch (s) {
|
2109
|
+
#define XX(num, name, string) case HTTP_STATUS_##name: return #string;
|
2110
|
+
HTTP_STATUS_MAP(XX)
|
2111
|
+
#undef XX
|
2112
|
+
default: return "<unknown>";
|
2113
|
+
}
|
2114
|
+
}
|
2143
2115
|
|
2144
2116
|
void
|
2145
2117
|
http_parser_init (http_parser *parser, enum http_parser_type t)
|
@@ -2200,7 +2172,7 @@ http_parse_host_char(enum http_host_state s, const char ch) {
|
|
2200
2172
|
return s_http_host;
|
2201
2173
|
}
|
2202
2174
|
|
2203
|
-
/*
|
2175
|
+
/* fall through */
|
2204
2176
|
case s_http_host_v6_end:
|
2205
2177
|
if (ch == ':') {
|
2206
2178
|
return s_http_host_port_start;
|
@@ -2213,7 +2185,7 @@ http_parse_host_char(enum http_host_state s, const char ch) {
|
|
2213
2185
|
return s_http_host_v6_end;
|
2214
2186
|
}
|
2215
2187
|
|
2216
|
-
/*
|
2188
|
+
/* fall through */
|
2217
2189
|
case s_http_host_v6_start:
|
2218
2190
|
if (IS_HEX(ch) || ch == ':' || ch == '.') {
|
2219
2191
|
return s_http_host_v6;
|
@@ -2229,7 +2201,7 @@ http_parse_host_char(enum http_host_state s, const char ch) {
|
|
2229
2201
|
return s_http_host_v6_end;
|
2230
2202
|
}
|
2231
2203
|
|
2232
|
-
/*
|
2204
|
+
/* fall through */
|
2233
2205
|
case s_http_host_v6_zone_start:
|
2234
2206
|
/* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */
|
2235
2207
|
if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' ||
|
@@ -2348,6 +2320,10 @@ http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
|
|
2348
2320
|
enum http_parser_url_fields uf, old_uf;
|
2349
2321
|
int found_at = 0;
|
2350
2322
|
|
2323
|
+
if (buflen == 0) {
|
2324
|
+
return 1;
|
2325
|
+
}
|
2326
|
+
|
2351
2327
|
u->port = u->field_set = 0;
|
2352
2328
|
s = is_connect ? s_req_server_start : s_req_spaces_before_url;
|
2353
2329
|
old_uf = UF_MAX;
|
@@ -2375,7 +2351,7 @@ http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
|
|
2375
2351
|
case s_req_server_with_at:
|
2376
2352
|
found_at = 1;
|
2377
2353
|
|
2378
|
-
/*
|
2354
|
+
/* fall through */
|
2379
2355
|
case s_req_server:
|
2380
2356
|
uf = UF_HOST;
|
2381
2357
|
break;
|
@@ -2429,12 +2405,27 @@ http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
|
|
2429
2405
|
}
|
2430
2406
|
|
2431
2407
|
if (u->field_set & (1 << UF_PORT)) {
|
2432
|
-
|
2433
|
-
|
2434
|
-
|
2435
|
-
|
2436
|
-
|
2437
|
-
|
2408
|
+
uint16_t off;
|
2409
|
+
uint16_t len;
|
2410
|
+
const char* p;
|
2411
|
+
const char* end;
|
2412
|
+
unsigned long v;
|
2413
|
+
|
2414
|
+
off = u->field_data[UF_PORT].off;
|
2415
|
+
len = u->field_data[UF_PORT].len;
|
2416
|
+
end = buf + off + len;
|
2417
|
+
|
2418
|
+
/* NOTE: The characters are already validated and are in the [0-9] range */
|
2419
|
+
assert(off + len <= buflen && "Port number overflow");
|
2420
|
+
v = 0;
|
2421
|
+
for (p = buf + off; p < end; p++) {
|
2422
|
+
v *= 10;
|
2423
|
+
v += *p - '0';
|
2424
|
+
|
2425
|
+
/* Ports have a max value of 2^16 */
|
2426
|
+
if (v > 0xffff) {
|
2427
|
+
return 1;
|
2428
|
+
}
|
2438
2429
|
}
|
2439
2430
|
|
2440
2431
|
u->port = (uint16_t) v;
|
@@ -2451,6 +2442,7 @@ http_parser_pause(http_parser *parser, int paused) {
|
|
2451
2442
|
*/
|
2452
2443
|
if (HTTP_PARSER_ERRNO(parser) == HPE_OK ||
|
2453
2444
|
HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {
|
2445
|
+
uint32_t nread = parser->nread; /* used by the SET_ERRNO macro */
|
2454
2446
|
SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);
|
2455
2447
|
} else {
|
2456
2448
|
assert(0 && "Attempting to pause parser in error state");
|
@@ -26,14 +26,13 @@ extern "C" {
|
|
26
26
|
|
27
27
|
/* Also update SONAME in the Makefile whenever you change these. */
|
28
28
|
#define HTTP_PARSER_VERSION_MAJOR 2
|
29
|
-
#define HTTP_PARSER_VERSION_MINOR
|
29
|
+
#define HTTP_PARSER_VERSION_MINOR 8
|
30
30
|
#define HTTP_PARSER_VERSION_PATCH 1
|
31
31
|
|
32
|
-
#include <
|
32
|
+
#include <stddef.h>
|
33
33
|
#if defined(_WIN32) && !defined(__MINGW32__) && \
|
34
34
|
(!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__)
|
35
35
|
#include <BaseTsd.h>
|
36
|
-
#include <stddef.h>
|
37
36
|
typedef __int8 int8_t;
|
38
37
|
typedef unsigned __int8 uint8_t;
|
39
38
|
typedef __int16 int16_t;
|
@@ -90,6 +89,76 @@ typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
|
|
90
89
|
typedef int (*http_cb) (http_parser*);
|
91
90
|
|
92
91
|
|
92
|
+
/* Status Codes */
|
93
|
+
#define HTTP_STATUS_MAP(XX) \
|
94
|
+
XX(100, CONTINUE, Continue) \
|
95
|
+
XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \
|
96
|
+
XX(102, PROCESSING, Processing) \
|
97
|
+
XX(200, OK, OK) \
|
98
|
+
XX(201, CREATED, Created) \
|
99
|
+
XX(202, ACCEPTED, Accepted) \
|
100
|
+
XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \
|
101
|
+
XX(204, NO_CONTENT, No Content) \
|
102
|
+
XX(205, RESET_CONTENT, Reset Content) \
|
103
|
+
XX(206, PARTIAL_CONTENT, Partial Content) \
|
104
|
+
XX(207, MULTI_STATUS, Multi-Status) \
|
105
|
+
XX(208, ALREADY_REPORTED, Already Reported) \
|
106
|
+
XX(226, IM_USED, IM Used) \
|
107
|
+
XX(300, MULTIPLE_CHOICES, Multiple Choices) \
|
108
|
+
XX(301, MOVED_PERMANENTLY, Moved Permanently) \
|
109
|
+
XX(302, FOUND, Found) \
|
110
|
+
XX(303, SEE_OTHER, See Other) \
|
111
|
+
XX(304, NOT_MODIFIED, Not Modified) \
|
112
|
+
XX(305, USE_PROXY, Use Proxy) \
|
113
|
+
XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \
|
114
|
+
XX(308, PERMANENT_REDIRECT, Permanent Redirect) \
|
115
|
+
XX(400, BAD_REQUEST, Bad Request) \
|
116
|
+
XX(401, UNAUTHORIZED, Unauthorized) \
|
117
|
+
XX(402, PAYMENT_REQUIRED, Payment Required) \
|
118
|
+
XX(403, FORBIDDEN, Forbidden) \
|
119
|
+
XX(404, NOT_FOUND, Not Found) \
|
120
|
+
XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \
|
121
|
+
XX(406, NOT_ACCEPTABLE, Not Acceptable) \
|
122
|
+
XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \
|
123
|
+
XX(408, REQUEST_TIMEOUT, Request Timeout) \
|
124
|
+
XX(409, CONFLICT, Conflict) \
|
125
|
+
XX(410, GONE, Gone) \
|
126
|
+
XX(411, LENGTH_REQUIRED, Length Required) \
|
127
|
+
XX(412, PRECONDITION_FAILED, Precondition Failed) \
|
128
|
+
XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \
|
129
|
+
XX(414, URI_TOO_LONG, URI Too Long) \
|
130
|
+
XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \
|
131
|
+
XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \
|
132
|
+
XX(417, EXPECTATION_FAILED, Expectation Failed) \
|
133
|
+
XX(421, MISDIRECTED_REQUEST, Misdirected Request) \
|
134
|
+
XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \
|
135
|
+
XX(423, LOCKED, Locked) \
|
136
|
+
XX(424, FAILED_DEPENDENCY, Failed Dependency) \
|
137
|
+
XX(426, UPGRADE_REQUIRED, Upgrade Required) \
|
138
|
+
XX(428, PRECONDITION_REQUIRED, Precondition Required) \
|
139
|
+
XX(429, TOO_MANY_REQUESTS, Too Many Requests) \
|
140
|
+
XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \
|
141
|
+
XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \
|
142
|
+
XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \
|
143
|
+
XX(501, NOT_IMPLEMENTED, Not Implemented) \
|
144
|
+
XX(502, BAD_GATEWAY, Bad Gateway) \
|
145
|
+
XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \
|
146
|
+
XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \
|
147
|
+
XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \
|
148
|
+
XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \
|
149
|
+
XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \
|
150
|
+
XX(508, LOOP_DETECTED, Loop Detected) \
|
151
|
+
XX(510, NOT_EXTENDED, Not Extended) \
|
152
|
+
XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \
|
153
|
+
|
154
|
+
enum http_status
|
155
|
+
{
|
156
|
+
#define XX(num, name, string) HTTP_STATUS_##name = num,
|
157
|
+
HTTP_STATUS_MAP(XX)
|
158
|
+
#undef XX
|
159
|
+
};
|
160
|
+
|
161
|
+
|
93
162
|
/* Request Methods */
|
94
163
|
#define HTTP_METHOD_MAP(XX) \
|
95
164
|
XX(0, DELETE, DELETE) \
|
@@ -132,6 +201,8 @@ typedef int (*http_cb) (http_parser*);
|
|
132
201
|
/* RFC-2068, section 19.6.1.2 */ \
|
133
202
|
XX(31, LINK, LINK) \
|
134
203
|
XX(32, UNLINK, UNLINK) \
|
204
|
+
/* icecast */ \
|
205
|
+
XX(33, SOURCE, SOURCE) \
|
135
206
|
|
136
207
|
enum http_method
|
137
208
|
{
|
@@ -336,6 +407,9 @@ int http_should_keep_alive(const http_parser *parser);
|
|
336
407
|
/* Returns a string version of the HTTP method. */
|
337
408
|
const char *http_method_str(enum http_method m);
|
338
409
|
|
410
|
+
/* Returns a string version of the HTTP status code. */
|
411
|
+
const char *http_status_str(enum http_status s);
|
412
|
+
|
339
413
|
/* Return a string name of the given error */
|
340
414
|
const char *http_errno_name(enum http_errno err);
|
341
415
|
|
data/lib/http-parser/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: http-parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen von Takach
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-10-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi-compiler
|
@@ -119,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
119
|
version: '0'
|
120
120
|
requirements: []
|
121
121
|
rubyforge_project:
|
122
|
-
rubygems_version: 2.
|
122
|
+
rubygems_version: 2.7.7
|
123
123
|
signing_key:
|
124
124
|
specification_version: 4
|
125
125
|
summary: Ruby bindings to joyent/http-parser
|