diff options
Diffstat (limited to 'src/nxt_http_parse.c')
-rw-r--r-- | src/nxt_http_parse.c | 125 |
1 files changed, 71 insertions, 54 deletions
diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c index 8b4bf47c..5b009d96 100644 --- a/src/nxt_http_parse.c +++ b/src/nxt_http_parse.c @@ -47,7 +47,6 @@ typedef enum { NXT_HTTP_TARGET_DOT, /* . */ NXT_HTTP_TARGET_ARGS_MARK, /* ? */ NXT_HTTP_TARGET_QUOTE_MARK, /* % */ - NXT_HTTP_TARGET_PLUS, /* + */ } nxt_http_target_traps_e; @@ -57,7 +56,7 @@ static const uint8_t nxt_http_target_chars[256] nxt_aligned(64) = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* \s ! " # $ % & ' ( ) * + , - . / */ - 1, 0, 0, 2, 0, 8, 0, 0, 0, 0, 0, 9, 0, 0, 6, 5, + 1, 0, 0, 2, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 6, 5, /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, @@ -163,8 +162,9 @@ static nxt_int_t nxt_http_parse_request_line(nxt_http_request_parse_t *rp, u_char **pos, u_char *end) { - u_char *p, ch, *after_slash; + u_char *p, ch, *after_slash, *exten, *args; nxt_int_t rc; + nxt_bool_t rest; nxt_http_ver_t ver; nxt_http_target_traps_e trap; @@ -255,6 +255,11 @@ nxt_http_parse_request_line(nxt_http_request_parse_t *rp, u_char **pos, rp->target_start = p; after_slash = p + 1; + exten = NULL; + args = NULL; + rest = 0; + +continue_target: for ( ;; ) { p++; @@ -269,8 +274,7 @@ nxt_http_parse_request_line(nxt_http_request_parse_t *rp, u_char **pos, } after_slash = p + 1; - - rp->exten_start = NULL; + exten = NULL; continue; case NXT_HTTP_TARGET_DOT: @@ -279,11 +283,11 @@ nxt_http_parse_request_line(nxt_http_request_parse_t *rp, u_char **pos, goto rest_of_target; } - rp->exten_start = p + 1; + exten = p + 1; continue; case NXT_HTTP_TARGET_ARGS_MARK: - rp->args_start = p + 1; + args = p + 1; goto rest_of_target; case NXT_HTTP_TARGET_SPACE: @@ -294,10 +298,6 @@ nxt_http_parse_request_line(nxt_http_request_parse_t *rp, u_char **pos, rp->quoted_target = 1; goto rest_of_target; - case NXT_HTTP_TARGET_PLUS: - rp->plus_in_target = 1; - continue; - case NXT_HTTP_TARGET_HASH: rp->complex_target = 1; goto rest_of_target; @@ -316,6 +316,8 @@ nxt_http_parse_request_line(nxt_http_request_parse_t *rp, u_char **pos, rest_of_target: + rest = 1; + for ( ;; ) { p++; @@ -382,7 +384,12 @@ space_after_target: } rp->space_in_target = 1; - goto rest_of_target; + + if (rest) { + goto rest_of_target; + } + + goto continue_target; } /* " HTTP/1.1\r\n" or " HTTP/1.1\n" */ @@ -396,7 +403,12 @@ space_after_target: } rp->space_in_target = 1; - goto rest_of_target; + + if (rest) { + goto rest_of_target; + } + + goto continue_target; } nxt_memcpy(ver.str, &p[1], 8); @@ -437,20 +449,19 @@ space_after_target: rp->path.start = rp->target_start; - if (rp->args_start != NULL) { - rp->path.length = rp->args_start - rp->target_start - 1; + if (args != NULL) { + rp->path.length = args - rp->target_start - 1; - rp->args.start = rp->args_start; - rp->args.length = rp->target_end - rp->args_start; + rp->args.length = rp->target_end - args; + rp->args.start = args; } else { rp->path.length = rp->target_end - rp->target_start; } - if (rp->exten_start) { - rp->exten.length = rp->path.start + rp->path.length - - rp->exten_start; - rp->exten.start = rp->exten_start; + if (exten != NULL) { + rp->exten.length = (rp->path.start + rp->path.length) - exten; + rp->exten.start = exten; } return nxt_http_parse_field_name(rp, pos, end); @@ -835,7 +846,8 @@ static const uint8_t nxt_http_normal[32] nxt_aligned(32) = { static nxt_int_t nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) { - u_char *p, *u, c, ch, high; + u_char *p, *u, c, ch, high, *exten, *args; + enum { sw_normal = 0, sw_slash, @@ -852,7 +864,6 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) p = rp->target_start; u = nxt_mp_alloc(rp->mem_pool, rp->target_end - p + 1); - if (nxt_slow_path(u == NULL)) { return NXT_ERROR; } @@ -861,8 +872,8 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) rp->path.start = u; high = '\0'; - rp->exten_start = NULL; - rp->args_start = NULL; + exten = NULL; + args = NULL; while (p < rp->target_end) { @@ -881,7 +892,7 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) switch (ch) { case '/': - rp->exten_start = NULL; + exten = NULL; state = sw_slash; *u++ = ch; continue; @@ -890,17 +901,14 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) state = sw_quoted; continue; case '?': - rp->args_start = p; + args = p; goto args; case '#': goto done; case '.': - rp->exten_start = u + 1; + exten = u + 1; *u++ = ch; continue; - case '+': - rp->plus_in_target = 1; - /* Fall through. */ default: *u++ = ch; continue; @@ -928,13 +936,10 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) state = sw_quoted; continue; case '?': - rp->args_start = p; + args = p; goto args; case '#': goto done; - case '+': - rp->plus_in_target = 1; - /* Fall through. */ default: state = sw_normal; *u++ = ch; @@ -965,13 +970,10 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) state = sw_quoted; continue; case '?': - rp->args_start = p; + args = p; goto args; case '#': goto done; - case '+': - rp->plus_in_target = 1; - /* Fall through. */ default: state = sw_normal; *u++ = ch; @@ -1009,13 +1011,10 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) state = sw_quoted; continue; case '?': - rp->args_start = p; + args = p; goto args; case '#': goto done; - case '+': - rp->plus_in_target = 1; - /* Fall through. */ default: state = sw_normal; *u++ = ch; @@ -1046,12 +1045,25 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) if (ch >= '0' && ch <= '9') { ch = (u_char) ((high << 4) + ch - '0'); - if (ch == '%' || ch == '#') { + if (ch == '%') { state = sw_normal; - *u++ = ch; + *u++ = '%'; + + if (rp->encoded_slashes) { + *u++ = '2'; + *u++ = '5'; + } + continue; + } - } else if (ch == '\0') { + if (ch == '#') { + state = sw_normal; + *u++ = '#'; + continue; + } + + if (ch == '\0') { return NXT_HTTP_PARSE_INVALID; } @@ -1067,9 +1079,14 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) state = sw_normal; *u++ = ch; continue; + } - } else if (ch == '+') { - rp->plus_in_target = 1; + if (ch == '/' && rp->encoded_slashes) { + state = sw_normal; + *u++ = '%'; + *u++ = '2'; + *u++ = p[-1]; /* 'f' or 'F' */ + continue; } state = saved_state; @@ -1092,18 +1109,18 @@ args: } } - if (rp->args_start != NULL) { - rp->args.length = p - rp->args_start; - rp->args.start = rp->args_start; + if (args != NULL) { + rp->args.length = p - args; + rp->args.start = args; } done: rp->path.length = u - rp->path.start; - if (rp->exten_start) { - rp->exten.length = u - rp->exten_start; - rp->exten.start = rp->exten_start; + if (exten) { + rp->exten.length = u - exten; + rp->exten.start = exten; } return NXT_OK; |