diff options
author | Igor Sysoev <igor@sysoev.ru> | 2019-04-10 13:47:34 +0300 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2019-04-10 13:47:34 +0300 |
commit | 8339b1515816ec8d3661514dc3edb73874580977 (patch) | |
tree | de9b77da32ed2145a5d8285f9273e829e235d871 | |
parent | ac7e65a722d38786c63716c026ab588e3d205a25 (diff) | |
download | unit-8339b1515816ec8d3661514dc3edb73874580977.tar.gz unit-8339b1515816ec8d3661514dc3edb73874580977.tar.bz2 |
Added support for wildcards in the middle of match patterns.
Diffstat (limited to '')
-rw-r--r-- | src/nxt_conf_validation.c | 27 | ||||
-rw-r--r-- | src/nxt_http_route.c | 126 |
2 files changed, 129 insertions, 24 deletions
diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index ee87b0f6..e2e1b89e 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -741,6 +741,12 @@ nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt, nxt_str_t pattern; nxt_uint_t i, first, last; + enum { + sw_none, + sw_side, + sw_middle + } state; + if (nxt_conf_type(value) != NXT_CONF_STRING) { return nxt_conf_vldt_error(vldt, "The \"match\" patterns must be strings."); @@ -754,17 +760,32 @@ nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt, first = (pattern.start[0] == '!'); last = pattern.length - 1; + state = sw_none; for (i = first; i != pattern.length; i++) { + ch = pattern.start[i]; if (ch != '*') { continue; } - if (i != first && i != last) { - return nxt_conf_vldt_error(vldt, "The \"match\" patterns can only " - "contain \"*\" markers at the sides."); + switch (state) { + case sw_none: + state = (i == first) ? sw_side : sw_middle; + break; + + case sw_side: + if (i == last) { + break; + } + + /* Fall through. */ + + case sw_middle: + return nxt_conf_vldt_error(vldt, "The \"match\" patterns can " + "either contain \"*\" markers at " + "the sides or only one in the middle."); } } diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index 133c39ab..f1076b88 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -21,6 +21,7 @@ typedef enum { typedef enum { NXT_HTTP_ROUTE_PATTERN_EXACT = 0, NXT_HTTP_ROUTE_PATTERN_BEGIN, + NXT_HTTP_ROUTE_PATTERN_MIDDLE, NXT_HTTP_ROUTE_PATTERN_END, NXT_HTTP_ROUTE_PATTERN_SUBSTRING, } nxt_http_route_pattern_type_t; @@ -41,7 +42,10 @@ typedef struct { typedef struct { - nxt_str_t test; + u_char *start1; + u_char *start2; + uint32_t length1; + uint32_t length2; uint32_t min_length; nxt_http_route_pattern_type_t type:8; @@ -90,6 +94,8 @@ static int nxt_http_pattern_compare(const void *one, const void *two); static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern, nxt_http_route_pattern_case_t pattern_case); +static u_char *nxt_http_route_pattern_copy(nxt_mp_t *mp, nxt_str_t *test, + nxt_http_route_pattern_case_t pattern_case); static void nxt_http_route_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_http_route_t *route); @@ -107,6 +113,8 @@ static nxt_bool_t nxt_http_route_rule(nxt_http_request_t *r, nxt_http_route_rule_t *rule); static nxt_bool_t nxt_http_route_pattern(nxt_http_request_t *r, nxt_http_route_pattern_t *pattern, u_char *start, size_t length); +static nxt_bool_t nxt_http_route_memcmp(u_char *start, u_char *test, + size_t length, nxt_bool_t case_sensitive); nxt_http_routes_t * @@ -407,8 +415,12 @@ nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, { u_char *start; nxt_str_t test; + nxt_uint_t n, length; nxt_http_route_pattern_type_t type; + /* Suppress warning about uninitialized variable. */ + length = 0; + type = NXT_HTTP_ROUTE_PATTERN_EXACT; nxt_conf_get_string(cv, &test); @@ -448,37 +460,79 @@ nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, } else if (test.start[test.length - 1] == '*') { test.length--; type = NXT_HTTP_ROUTE_PATTERN_BEGIN; + + } else { + length = test.length - 1; + + for (n = 1; n < length; n++) { + if (test.start[n] == '*') { + test.length = n; + type = NXT_HTTP_ROUTE_PATTERN_MIDDLE; + break; + } + } } } } pattern->type = type; pattern->min_length = test.length; - pattern->test.length = test.length; + pattern->length1 = test.length; - start = nxt_mp_nget(mp, test.length); + start = nxt_http_route_pattern_copy(mp, &test, pattern_case); if (nxt_slow_path(start == NULL)) { return NXT_ERROR; } - pattern->test.start = start; + pattern->start1 = start; + + if (type == NXT_HTTP_ROUTE_PATTERN_MIDDLE) { + length -= test.length; + pattern->length2 = length; + pattern->min_length += length; + + test.start = &test.start[test.length + 1]; + test.length = length; + + start = nxt_http_route_pattern_copy(mp, &test, pattern_case); + if (nxt_slow_path(start == NULL)) { + return NXT_ERROR; + } + + pattern->start2 = start; + } + + return NXT_OK; +} + + +static u_char * +nxt_http_route_pattern_copy(nxt_mp_t *mp, nxt_str_t *test, + nxt_http_route_pattern_case_t pattern_case) +{ + u_char *start; + + start = nxt_mp_nget(mp, test->length); + if (nxt_slow_path(start == NULL)) { + return start; + } switch (pattern_case) { case NXT_HTTP_ROUTE_PATTERN_UPCASE: - nxt_memcpy_upcase(start, test.start, test.length); + nxt_memcpy_upcase(start, test->start, test->length); break; case NXT_HTTP_ROUTE_PATTERN_LOWCASE: - nxt_memcpy_lowcase(start, test.start, test.length); + nxt_memcpy_lowcase(start, test->start, test->length); break; case NXT_HTTP_ROUTE_PATTERN_NOCASE: - nxt_memcpy(start, test.start, test.length); + nxt_memcpy(start, test->start, test->length); break; } - return NXT_OK; + return start; } @@ -805,18 +859,21 @@ static nxt_bool_t nxt_http_route_pattern(nxt_http_request_t *r, nxt_http_route_pattern_t *pattern, u_char *start, size_t length) { - nxt_str_t *test; + u_char *p, *end, *test; + size_t test_length; + nxt_bool_t ret; if (length < pattern->min_length) { return 0; } - test = &pattern->test; + test = pattern->start1; + test_length = pattern->length1; switch (pattern->type) { case NXT_HTTP_ROUTE_PATTERN_EXACT: - if (length != test->length) { + if (length != test_length) { return 0; } @@ -825,25 +882,52 @@ nxt_http_route_pattern(nxt_http_request_t *r, nxt_http_route_pattern_t *pattern, case NXT_HTTP_ROUTE_PATTERN_BEGIN: break; + case NXT_HTTP_ROUTE_PATTERN_MIDDLE: + ret = nxt_http_route_memcmp(start, test, test_length, + pattern->case_sensitive); + if (!ret) { + return ret; + } + + test = pattern->start2; + test_length = pattern->length2; + + /* Fall through. */ + case NXT_HTTP_ROUTE_PATTERN_END: - start += length - test->length; + start += length - test_length; break; case NXT_HTTP_ROUTE_PATTERN_SUBSTRING: + end = start + length; + if (pattern->case_sensitive) { - return (nxt_memstrn(start, start + length, - (char *) test->start, test->length) - != NULL); + p = nxt_memstrn(start, end, (char *) test, test_length); + + } else { + p = nxt_memcasestrn(start, end, (char *) test, test_length); } - return (nxt_memcasestrn(start, start + length, - (char *) test->start, test->length) - != NULL); + return (p != NULL); } - if (pattern->case_sensitive) { - return (nxt_memcmp(start, test->start, test->length) == 0); + return nxt_http_route_memcmp(start, test, test_length, + pattern->case_sensitive); +} + + +static nxt_bool_t +nxt_http_route_memcmp(u_char *start, u_char *test, size_t test_length, + nxt_bool_t case_sensitive) +{ + nxt_int_t n; + + if (case_sensitive) { + n = nxt_memcmp(start, test, test_length); + + } else { + n = nxt_memcasecmp(start, test, test_length); } - return (nxt_memcasecmp(start, test->start, test->length) == 0); + return (n == 0); } |