summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorValentin Bartenev <vbart@nginx.com>2018-01-15 20:49:59 +0300
committerValentin Bartenev <vbart@nginx.com>2018-01-15 20:49:59 +0300
commit3fb140d6d2f8bf0344e7c311923178db808cb437 (patch)
tree139b1cf0d91895682beb6818136ab2ee6e4831ea
parent819b43fc2da414c9132c6061eabf063ae08c36dc (diff)
downloadunit-3fb140d6d2f8bf0344e7c311923178db808cb437.tar.gz
unit-3fb140d6d2f8bf0344e7c311923178db808cb437.tar.bz2
HTTP parser: improved error reporting.
Diffstat (limited to '')
-rw-r--r--src/nxt_h1proto.c27
-rw-r--r--src/nxt_http_parse.c36
-rw-r--r--src/nxt_http_parse.h6
-rw-r--r--src/test/nxt_http_parse_test.c22
4 files changed, 59 insertions, 32 deletions
diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c
index c3a100a4..5623c019 100644
--- a/src/nxt_h1proto.c
+++ b/src/nxt_h1proto.c
@@ -190,6 +190,7 @@ nxt_h1p_header_parse(nxt_task_t *task, void *obj, void *data)
nxt_buf_t *in, *b;
nxt_conn_t *c;
nxt_h1proto_t *h1p;
+ nxt_http_status_t status;
nxt_http_request_t *r;
nxt_socket_conf_joint_t *joint;
@@ -264,7 +265,13 @@ nxt_h1p_header_parse(nxt_task_t *task, void *obj, void *data)
return;
}
- } else if (ret == NXT_AGAIN) {
+ /* ret == NXT_ERROR */
+
+ nxt_http_request_error(task, r, NXT_HTTP_BAD_REQUEST);
+ return;
+ }
+
+ if (ret == NXT_AGAIN) {
in = c->read;
if (nxt_buf_mem_free_size(&in->mem) == 0) {
@@ -298,9 +305,23 @@ nxt_h1p_header_parse(nxt_task_t *task, void *obj, void *data)
return;
}
- /* ret == NXT_ERROR */
+ switch (ret) {
- nxt_http_request_error(task, r, NXT_HTTP_BAD_REQUEST);
+ case NXT_HTTP_PARSE_INVALID:
+ status = NXT_HTTP_BAD_REQUEST;
+ break;
+
+ case NXT_HTTP_PARSE_TOO_LARGE_FIELD:
+ status = NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE;
+ break;
+
+ default:
+ case NXT_ERROR:
+ status = NXT_HTTP_INTERNAL_SERVER_ERROR;
+ break;
+ }
+
+ nxt_http_request_error(task, r, status);
return;
fail:
diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c
index 65eed934..0a63ab1a 100644
--- a/src/nxt_http_parse.c
+++ b/src/nxt_http_parse.c
@@ -231,7 +231,7 @@ nxt_http_parse_request_line(nxt_http_request_parse_t *rp, u_char **pos,
continue;
}
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_INVALID;
}
p++;
@@ -306,7 +306,7 @@ nxt_http_parse_request_line(nxt_http_request_parse_t *rp, u_char **pos,
return NXT_AGAIN;
case NXT_HTTP_TARGET_BAD:
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_INVALID;
}
nxt_unreachable();
@@ -332,7 +332,7 @@ rest_of_target:
return NXT_AGAIN;
case NXT_HTTP_TARGET_BAD:
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_INVALID;
default:
continue;
@@ -407,7 +407,7 @@ space_after_target:
}
if (nxt_slow_path(*p != '\n')) {
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_INVALID;
}
*pos = p + 1;
@@ -492,7 +492,7 @@ nxt_http_parse_unusual_target(nxt_http_request_parse_t *rp, u_char **pos,
/* TODO */
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_INVALID;
}
@@ -555,7 +555,7 @@ nxt_http_parse_field_name(nxt_http_request_parse_t *rp, u_char **pos,
len = p - *pos;
if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_NAME)) {
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_TOO_LARGE_FIELD;
}
rp->field_hash = hash;
@@ -569,13 +569,13 @@ name_end:
if (nxt_fast_path(*p == ':')) {
if (nxt_slow_path(p == *pos)) {
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_INVALID;
}
len = p - *pos;
if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_NAME)) {
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_TOO_LARGE_FIELD;
}
rp->field_hash = hash;
@@ -589,7 +589,7 @@ name_end:
}
if (nxt_slow_path(p != *pos)) {
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_INVALID;
}
return nxt_http_parse_field_end(rp, pos, end);
@@ -630,7 +630,7 @@ nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos,
len = p - *pos;
if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_VALUE)) {
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_TOO_LARGE_FIELD;
}
rp->field_value.length = len;
@@ -645,7 +645,7 @@ nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos,
}
if (ch == '\0') {
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_INVALID;
}
}
@@ -658,7 +658,7 @@ nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos,
len = p - *pos;
if (nxt_slow_path(len > NXT_HTTP_MAX_FIELD_VALUE)) {
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_TOO_LARGE_FIELD;
}
rp->field_value.length = len;
@@ -784,7 +784,7 @@ nxt_http_parse_field_end(nxt_http_request_parse_t *rp, u_char **pos,
return NXT_DONE;
}
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_INVALID;
}
@@ -976,7 +976,7 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp)
u -= 5;
for ( ;; ) {
if (u < rp->path.start) {
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_INVALID;
}
if (*u == '/') {
u++;
@@ -1022,7 +1022,7 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp)
continue;
}
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_INVALID;
case sw_quoted_second:
if (ch >= '0' && ch <= '9') {
@@ -1034,7 +1034,7 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp)
continue;
} else if (ch == '\0') {
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_INVALID;
}
state = saved_state;
@@ -1058,12 +1058,12 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp)
goto again;
}
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_INVALID;
}
}
if (state >= sw_quoted) {
- return NXT_ERROR;
+ return NXT_HTTP_PARSE_INVALID;
}
args:
diff --git a/src/nxt_http_parse.h b/src/nxt_http_parse.h
index 293c4d0e..0a0ca340 100644
--- a/src/nxt_http_parse.h
+++ b/src/nxt_http_parse.h
@@ -8,6 +8,12 @@
#define _NXT_HTTP_PARSER_H_INCLUDED_
+typedef enum {
+ NXT_HTTP_PARSE_INVALID = 1,
+ NXT_HTTP_PARSE_TOO_LARGE_FIELD,
+} nxt_http_parse_error_t;
+
+
typedef struct nxt_http_request_parse_s nxt_http_request_parse_t;
typedef struct nxt_http_field_s nxt_http_field_t;
typedef struct nxt_http_fields_hash_s nxt_http_fields_hash_t;
diff --git a/src/test/nxt_http_parse_test.c b/src/test/nxt_http_parse_test.c
index bd577e10..637e9298 100644
--- a/src/test/nxt_http_parse_test.c
+++ b/src/test/nxt_http_parse_test.c
@@ -101,27 +101,27 @@ static nxt_http_parse_test_case_t nxt_http_test_cases[] = {
},
{
nxt_string("GEt / HTTP/1.0\r\n\r\n"),
- NXT_ERROR,
+ NXT_HTTP_PARSE_INVALID,
NULL, { NULL }
},
{
nxt_string("GET /\0 HTTP/1.0\r\n\r\n"),
- NXT_ERROR,
+ NXT_HTTP_PARSE_INVALID,
NULL, { NULL }
},
{
nxt_string("GET /\r HTTP/1.0\r\n\r\n"),
- NXT_ERROR,
+ NXT_HTTP_PARSE_INVALID,
NULL, { NULL }
},
{
nxt_string("GET /\n HTTP/1.0\r\n\r\n"),
- NXT_ERROR,
+ NXT_HTTP_PARSE_INVALID,
NULL, { NULL }
},
{
nxt_string("GET / HTTP/1.0\r\r\n"),
- NXT_ERROR,
+ NXT_HTTP_PARSE_INVALID,
NULL, { NULL }
},
{
@@ -230,13 +230,13 @@ static nxt_http_parse_test_case_t nxt_http_test_cases[] = {
{
nxt_string("GET / HTTP/1.1\r\n"
"Host example.com\r\n\r\n"),
- NXT_ERROR,
+ NXT_HTTP_PARSE_INVALID,
NULL, { NULL }
},
{
nxt_string("GET / HTTP/1.1\r\n"
":Host: example.com\r\n\r\n"),
- NXT_ERROR,
+ NXT_HTTP_PARSE_INVALID,
NULL, { NULL }
},
{
@@ -248,25 +248,25 @@ static nxt_http_parse_test_case_t nxt_http_test_cases[] = {
{
nxt_string("GET / HTTP/1.1\r\n"
"Ho\0st: example.com\r\n\r\n"),
- NXT_ERROR,
+ NXT_HTTP_PARSE_INVALID,
NULL, { NULL }
},
{
nxt_string("GET / HTTP/1.1\r\n"
"Ho\rst: example.com\r\n\r\n"),
- NXT_ERROR,
+ NXT_HTTP_PARSE_INVALID,
NULL, { NULL }
},
{
nxt_string("GET / HTTP/1.1\r\n"
"Host: exa\0mple.com\r\n\r\n"),
- NXT_ERROR,
+ NXT_HTTP_PARSE_INVALID,
NULL, { NULL }
},
{
nxt_string("GET / HTTP/1.1\r\n"
"Host: exa\rmple.com\r\n\r\n"),
- NXT_ERROR,
+ NXT_HTTP_PARSE_INVALID,
NULL, { NULL }
},
{