Router: route patterns multi wildcards support.
This commit is contained in:
@@ -1346,15 +1346,8 @@ static nxt_int_t
|
|||||||
nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt,
|
nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt,
|
||||||
nxt_conf_value_t *value)
|
nxt_conf_value_t *value)
|
||||||
{
|
{
|
||||||
u_char ch;
|
|
||||||
nxt_str_t pattern;
|
nxt_str_t pattern;
|
||||||
nxt_uint_t i, first, last;
|
nxt_uint_t i, first;
|
||||||
|
|
||||||
enum {
|
|
||||||
sw_none,
|
|
||||||
sw_side,
|
|
||||||
sw_middle
|
|
||||||
} state;
|
|
||||||
|
|
||||||
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
||||||
return nxt_conf_vldt_error(vldt, "The \"match\" patterns for \"host\", "
|
return nxt_conf_vldt_error(vldt, "The \"match\" patterns for \"host\", "
|
||||||
@@ -1368,38 +1361,11 @@ nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
first = (pattern.start[0] == '!');
|
first = (pattern.start[0] == '!');
|
||||||
last = pattern.length - 1;
|
|
||||||
state = sw_none;
|
|
||||||
|
|
||||||
for (i = first; i != pattern.length; i++) {
|
for (i = first; i < pattern.length; i++) {
|
||||||
|
if (pattern.start[i] == '*' && pattern.start[i + 1] == '*') {
|
||||||
ch = pattern.start[i];
|
return nxt_conf_vldt_error(vldt, "The \"match\" pattern must "
|
||||||
|
"not contain double \"*\" markers.");
|
||||||
if (ch != '*') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
case sw_none:
|
|
||||||
state = (i == first) ? sw_side : sw_middle;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case sw_side:
|
|
||||||
if (i == last) {
|
|
||||||
if (last - first != 1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nxt_conf_vldt_error(vldt, "The \"match\" pattern must "
|
|
||||||
"not contain double \"*\" markers.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
NXT_HTTP_ROUTE_PATTERN_EXACT = 0,
|
NXT_HTTP_ROUTE_PATTERN_EXACT = 0,
|
||||||
NXT_HTTP_ROUTE_PATTERN_BEGIN,
|
NXT_HTTP_ROUTE_PATTERN_BEGIN,
|
||||||
NXT_HTTP_ROUTE_PATTERN_MIDDLE,
|
|
||||||
NXT_HTTP_ROUTE_PATTERN_END,
|
NXT_HTTP_ROUTE_PATTERN_END,
|
||||||
NXT_HTTP_ROUTE_PATTERN_SUBSTRING,
|
NXT_HTTP_ROUTE_PATTERN_SUBSTRING,
|
||||||
} nxt_http_route_pattern_type_t;
|
} nxt_http_route_pattern_type_t;
|
||||||
@@ -70,13 +69,16 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u_char *start1;
|
u_char *start;
|
||||||
u_char *start2;
|
uint32_t length;
|
||||||
uint32_t length1;
|
|
||||||
uint32_t length2;
|
|
||||||
uint32_t min_length;
|
|
||||||
|
|
||||||
nxt_http_route_pattern_type_t type:8;
|
nxt_http_route_pattern_type_t type:8;
|
||||||
|
} nxt_http_route_pattern_slice_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t min_length;
|
||||||
|
nxt_array_t *pattern_slices;
|
||||||
|
|
||||||
uint8_t case_sensitive; /* 1 bit */
|
uint8_t case_sensitive; /* 1 bit */
|
||||||
uint8_t negative; /* 1 bit */
|
uint8_t negative; /* 1 bit */
|
||||||
uint8_t any; /* 1 bit */
|
uint8_t any; /* 1 bit */
|
||||||
@@ -209,7 +211,10 @@ static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
|
|||||||
nxt_http_route_encoding_t encoding);
|
nxt_http_route_encoding_t encoding);
|
||||||
static nxt_int_t nxt_http_route_decode_str(nxt_str_t *str,
|
static nxt_int_t nxt_http_route_decode_str(nxt_str_t *str,
|
||||||
nxt_http_route_encoding_t encoding);
|
nxt_http_route_encoding_t encoding);
|
||||||
static u_char *nxt_http_route_pattern_copy(nxt_mp_t *mp, nxt_str_t *test,
|
static nxt_int_t nxt_http_route_pattern_slice(nxt_array_t *slices,
|
||||||
|
nxt_str_t *test,
|
||||||
|
nxt_http_route_pattern_type_t type,
|
||||||
|
nxt_http_route_encoding_t encoding,
|
||||||
nxt_http_route_pattern_case_t pattern_case);
|
nxt_http_route_pattern_case_t pattern_case);
|
||||||
|
|
||||||
static nxt_int_t nxt_http_route_resolve(nxt_task_t *task,
|
static nxt_int_t nxt_http_route_resolve(nxt_task_t *task,
|
||||||
@@ -1044,103 +1049,163 @@ nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
|
|||||||
nxt_http_route_pattern_case_t pattern_case,
|
nxt_http_route_pattern_case_t pattern_case,
|
||||||
nxt_http_route_encoding_t encoding)
|
nxt_http_route_encoding_t encoding)
|
||||||
{
|
{
|
||||||
u_char *start;
|
u_char c, *p, *end;
|
||||||
nxt_str_t test, test2;
|
nxt_str_t test, tmp;
|
||||||
nxt_int_t ret;
|
nxt_int_t ret;
|
||||||
nxt_uint_t n, length;
|
nxt_array_t *slices;
|
||||||
nxt_http_route_pattern_type_t type;
|
nxt_http_route_pattern_type_t type;
|
||||||
|
|
||||||
|
nxt_http_route_pattern_slice_t *slice;
|
||||||
|
|
||||||
type = NXT_HTTP_ROUTE_PATTERN_EXACT;
|
type = NXT_HTTP_ROUTE_PATTERN_EXACT;
|
||||||
|
|
||||||
nxt_conf_get_string(cv, &test);
|
nxt_conf_get_string(cv, &test);
|
||||||
|
|
||||||
|
slices = nxt_array_create(mp, 1, sizeof(nxt_http_route_pattern_slice_t));
|
||||||
|
if (nxt_slow_path(slices == NULL)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern->pattern_slices = slices;
|
||||||
|
|
||||||
pattern->negative = 0;
|
pattern->negative = 0;
|
||||||
pattern->any = 1;
|
pattern->any = 1;
|
||||||
pattern->min_length = 0;
|
pattern->min_length = 0;
|
||||||
|
|
||||||
if (test.length != 0) {
|
if (test.length != 0 && test.start[0] == '!') {
|
||||||
|
test.start++;
|
||||||
|
test.length--;
|
||||||
|
|
||||||
if (test.start[0] == '!') {
|
pattern->negative = 1;
|
||||||
test.start++;
|
pattern->any = 0;
|
||||||
test.length--;
|
|
||||||
|
|
||||||
pattern->negative = 1;
|
if (test.length == 0) {
|
||||||
pattern->any = 0;
|
return NXT_OK;
|
||||||
}
|
|
||||||
|
|
||||||
if (test.length != 0) {
|
|
||||||
if (test.start[0] == '*') {
|
|
||||||
test.start++;
|
|
||||||
test.length--;
|
|
||||||
|
|
||||||
if (test.length != 0) {
|
|
||||||
if (test.start[test.length - 1] == '*') {
|
|
||||||
test.length--;
|
|
||||||
type = NXT_HTTP_ROUTE_PATTERN_SUBSTRING;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
type = NXT_HTTP_ROUTE_PATTERN_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
type = NXT_HTTP_ROUTE_PATTERN_BEGIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
} 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] != '*') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
test.length = n;
|
|
||||||
|
|
||||||
test2.start = &test.start[n + 1];
|
|
||||||
test2.length = length - n;
|
|
||||||
|
|
||||||
ret = nxt_http_route_decode_str(&test2, encoding);
|
|
||||||
if (nxt_slow_path(ret != NXT_OK)) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
type = NXT_HTTP_ROUTE_PATTERN_MIDDLE;
|
|
||||||
|
|
||||||
pattern->length2 = test2.length;
|
|
||||||
pattern->min_length += test2.length;
|
|
||||||
|
|
||||||
start = nxt_http_route_pattern_copy(mp, &test2,
|
|
||||||
pattern_case);
|
|
||||||
if (nxt_slow_path(start == NULL)) {
|
|
||||||
return NXT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern->start2 = start;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = nxt_http_route_decode_str(&test, encoding);
|
|
||||||
if (nxt_slow_path(ret != NXT_OK)) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pattern->type = type;
|
if (test.length == 0) {
|
||||||
pattern->min_length += test.length;
|
slice = nxt_array_add(slices);
|
||||||
pattern->length1 = test.length;
|
if (nxt_slow_path(slice == NULL)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
start = nxt_http_route_pattern_copy(mp, &test, pattern_case);
|
slice->type = NXT_HTTP_ROUTE_PATTERN_EXACT;
|
||||||
if (nxt_slow_path(start == NULL)) {
|
slice->start = NULL;
|
||||||
return NXT_ERROR;
|
slice->length = 0;
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
pattern->start1 = start;
|
if (test.start[0] == '*') {
|
||||||
|
/* 'type' is no longer 'EXACT', assume 'END'. */
|
||||||
|
type = NXT_HTTP_ROUTE_PATTERN_END;
|
||||||
|
test.start++;
|
||||||
|
test.length--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == NXT_HTTP_ROUTE_PATTERN_EXACT && test.length != 0) {
|
||||||
|
tmp.start = test.start;
|
||||||
|
|
||||||
|
p = nxt_memchr(test.start, '*', test.length);
|
||||||
|
|
||||||
|
if (p == NULL) {
|
||||||
|
/* No '*' found - EXACT pattern. */
|
||||||
|
tmp.length = test.length;
|
||||||
|
type = NXT_HTTP_ROUTE_PATTERN_EXACT;
|
||||||
|
|
||||||
|
test.start += test.length;
|
||||||
|
test.length = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* '*' found - BEGIN pattern. */
|
||||||
|
tmp.length = p - test.start;
|
||||||
|
type = NXT_HTTP_ROUTE_PATTERN_BEGIN;
|
||||||
|
|
||||||
|
test.start = p + 1;
|
||||||
|
test.length -= tmp.length + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nxt_http_route_pattern_slice(slices, &tmp, type, encoding,
|
||||||
|
pattern_case);
|
||||||
|
if (nxt_slow_path(ret != NXT_OK)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern->min_length += tmp.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
end = test.start + test.length;
|
||||||
|
|
||||||
|
if (test.length != 0 && end[-1] != '*') {
|
||||||
|
p = end - 1;
|
||||||
|
|
||||||
|
while (p != test.start) {
|
||||||
|
c = *p--;
|
||||||
|
|
||||||
|
if (c == '*') {
|
||||||
|
p += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp.start = p;
|
||||||
|
tmp.length = end - p;
|
||||||
|
|
||||||
|
test.length -= tmp.length;
|
||||||
|
end = p;
|
||||||
|
|
||||||
|
ret = nxt_http_route_pattern_slice(slices, &tmp,
|
||||||
|
NXT_HTTP_ROUTE_PATTERN_END,
|
||||||
|
encoding, pattern_case);
|
||||||
|
if (nxt_slow_path(ret != NXT_OK)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern->min_length += tmp.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp.start = test.start;
|
||||||
|
tmp.length = 0;
|
||||||
|
|
||||||
|
p = tmp.start;
|
||||||
|
|
||||||
|
while (p != end) {
|
||||||
|
c = *p++;
|
||||||
|
|
||||||
|
if (c != '*') {
|
||||||
|
tmp.length++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp.length == 0) {
|
||||||
|
tmp.start = p;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nxt_http_route_pattern_slice(slices, &tmp,
|
||||||
|
NXT_HTTP_ROUTE_PATTERN_SUBSTRING,
|
||||||
|
encoding, pattern_case);
|
||||||
|
if (nxt_slow_path(ret != NXT_OK)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern->min_length += tmp.length;
|
||||||
|
|
||||||
|
tmp.start = p;
|
||||||
|
tmp.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp.length != 0) {
|
||||||
|
ret = nxt_http_route_pattern_slice(slices, &tmp,
|
||||||
|
NXT_HTTP_ROUTE_PATTERN_SUBSTRING,
|
||||||
|
encoding, pattern_case);
|
||||||
|
if (nxt_slow_path(ret != NXT_OK)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern->min_length += tmp.length;
|
||||||
|
}
|
||||||
|
|
||||||
return NXT_OK;
|
return NXT_OK;
|
||||||
}
|
}
|
||||||
@@ -1185,15 +1250,25 @@ nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static u_char *
|
static nxt_int_t
|
||||||
nxt_http_route_pattern_copy(nxt_mp_t *mp, nxt_str_t *test,
|
nxt_http_route_pattern_slice(nxt_array_t *slices,
|
||||||
|
nxt_str_t *test,
|
||||||
|
nxt_http_route_pattern_type_t type,
|
||||||
|
nxt_http_route_encoding_t encoding,
|
||||||
nxt_http_route_pattern_case_t pattern_case)
|
nxt_http_route_pattern_case_t pattern_case)
|
||||||
{
|
{
|
||||||
u_char *start;
|
u_char *start;
|
||||||
|
nxt_int_t ret;
|
||||||
|
nxt_http_route_pattern_slice_t *slice;
|
||||||
|
|
||||||
start = nxt_mp_nget(mp, test->length);
|
ret = nxt_http_route_decode_str(test, encoding);
|
||||||
|
if (nxt_slow_path(ret != NXT_OK)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = nxt_mp_nget(slices->mem_pool, test->length);
|
||||||
if (nxt_slow_path(start == NULL)) {
|
if (nxt_slow_path(start == NULL)) {
|
||||||
return start;
|
return NXT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (pattern_case) {
|
switch (pattern_case) {
|
||||||
@@ -1211,7 +1286,16 @@ nxt_http_route_pattern_copy(nxt_mp_t *mp, nxt_str_t *test,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return start;
|
slice = nxt_array_add(slices);
|
||||||
|
if (nxt_slow_path(slices == NULL)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
slice->type = type;
|
||||||
|
slice->start = start;
|
||||||
|
slice->length = test->length;
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2037,9 +2121,11 @@ nxt_http_route_test_argument(nxt_http_request_t *r,
|
|||||||
static nxt_int_t
|
static nxt_int_t
|
||||||
nxt_http_route_scheme(nxt_http_request_t *r, nxt_http_route_rule_t *rule)
|
nxt_http_route_scheme(nxt_http_request_t *r, nxt_http_route_rule_t *rule)
|
||||||
{
|
{
|
||||||
nxt_bool_t tls, https;
|
nxt_bool_t tls, https;
|
||||||
|
nxt_http_route_pattern_slice_t *pattern_slice;
|
||||||
|
|
||||||
https = (rule->pattern[0].length1 == nxt_length("https"));
|
pattern_slice = rule->pattern[0].pattern_slices->elts;
|
||||||
|
https = (pattern_slice->length == nxt_length("https"));
|
||||||
tls = (r->tls != NULL);
|
tls = (r->tls != NULL);
|
||||||
|
|
||||||
return (tls == https);
|
return (tls == https);
|
||||||
@@ -2246,60 +2332,66 @@ static nxt_int_t
|
|||||||
nxt_http_route_pattern(nxt_http_request_t *r, nxt_http_route_pattern_t *pattern,
|
nxt_http_route_pattern(nxt_http_request_t *r, nxt_http_route_pattern_t *pattern,
|
||||||
u_char *start, size_t length)
|
u_char *start, size_t length)
|
||||||
{
|
{
|
||||||
u_char *p, *end, *test;
|
u_char *p, *end, *test;
|
||||||
size_t test_length;
|
size_t test_length;
|
||||||
nxt_int_t ret;
|
uint32_t i;
|
||||||
|
nxt_array_t *pattern_slices;
|
||||||
|
nxt_http_route_pattern_slice_t *pattern_slice;
|
||||||
|
|
||||||
if (length < pattern->min_length) {
|
if (length < pattern->min_length) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
test = pattern->start1;
|
pattern_slices = pattern->pattern_slices;
|
||||||
test_length = pattern->length1;
|
pattern_slice = pattern_slices->elts;
|
||||||
|
|
||||||
switch (pattern->type) {
|
for (i = 0; i < pattern_slices->nelts; i++, pattern_slice++) {
|
||||||
|
test = pattern_slice->start;
|
||||||
|
test_length = pattern_slice->length;
|
||||||
|
|
||||||
|
switch (pattern_slice->type) {
|
||||||
|
case NXT_HTTP_ROUTE_PATTERN_EXACT:
|
||||||
|
return ((length == pattern->min_length) &&
|
||||||
|
nxt_http_route_memcmp(start, test, test_length,
|
||||||
|
pattern->case_sensitive));
|
||||||
|
|
||||||
|
case NXT_HTTP_ROUTE_PATTERN_BEGIN:
|
||||||
|
if (nxt_http_route_memcmp(start, test, test_length,
|
||||||
|
pattern->case_sensitive))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case NXT_HTTP_ROUTE_PATTERN_EXACT:
|
|
||||||
if (length != test_length) {
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case NXT_HTTP_ROUTE_PATTERN_END:
|
||||||
|
p = start + length - test_length;
|
||||||
|
|
||||||
|
if (nxt_http_route_memcmp(p, test, test_length,
|
||||||
|
pattern->case_sensitive))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case NXT_HTTP_ROUTE_PATTERN_SUBSTRING:
|
||||||
|
end = start + length;
|
||||||
|
|
||||||
|
if (pattern->case_sensitive) {
|
||||||
|
p = nxt_memstrn(start, end, (char *) test, test_length);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
p = nxt_memcasestrn(start, end, (char *) test, test_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
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;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NXT_HTTP_ROUTE_PATTERN_SUBSTRING:
|
|
||||||
end = start + length;
|
|
||||||
|
|
||||||
if (pattern->case_sensitive) {
|
|
||||||
p = nxt_memstrn(start, end, (char *) test, test_length);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
p = nxt_memcasestrn(start, end, (char *) test, test_length);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (p != NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nxt_http_route_memcmp(start, test, test_length,
|
return 1;
|
||||||
pattern->case_sensitive);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -115,10 +115,41 @@ class TestRouting(TestApplicationProto):
|
|||||||
|
|
||||||
def test_routes_match_invalid(self):
|
def test_routes_match_invalid(self):
|
||||||
self.route_match_invalid({"method": "**"})
|
self.route_match_invalid({"method": "**"})
|
||||||
self.route_match_invalid({"method": "blah**"})
|
|
||||||
self.route_match_invalid({"host": "*blah*blah"})
|
def test_routes_match_valid(self):
|
||||||
self.route_match_invalid({"host": "blah*blah*blah"})
|
self.route_match({"method": "blah*"})
|
||||||
self.route_match_invalid({"host": "blah*blah*"})
|
self.route_match({"host": "*blah*blah"})
|
||||||
|
self.route_match({"host": "blah*blah*blah"})
|
||||||
|
self.route_match({"host": "blah*blah*"})
|
||||||
|
|
||||||
|
def test_routes_match_empty_exact(self):
|
||||||
|
self.route_match({"uri": ""})
|
||||||
|
self.assertEqual(self.get()['status'], 404)
|
||||||
|
|
||||||
|
self.route_match({"uri": "/"})
|
||||||
|
self.assertEqual(self.get()['status'], 200)
|
||||||
|
self.assertEqual(self.get(url='/blah')['status'], 404)
|
||||||
|
|
||||||
|
def test_routes_match_negative(self):
|
||||||
|
self.route_match({"uri": "!"})
|
||||||
|
self.assertEqual(self.get()['status'], 404)
|
||||||
|
|
||||||
|
self.route_match({"uri": "!/"})
|
||||||
|
self.assertEqual(self.get()['status'], 404)
|
||||||
|
self.assertEqual(self.get(url='/blah')['status'], 200)
|
||||||
|
|
||||||
|
self.route_match({"uri": "!*blah"})
|
||||||
|
self.assertEqual(self.get()['status'], 200)
|
||||||
|
self.assertEqual(self.get(url='/bla')['status'], 200)
|
||||||
|
self.assertEqual(self.get(url='/blah')['status'], 404)
|
||||||
|
self.assertEqual(self.get(url='/blah1')['status'], 200)
|
||||||
|
|
||||||
|
self.route_match({"uri": "!/blah*1*"})
|
||||||
|
self.assertEqual(self.get()['status'], 200)
|
||||||
|
self.assertEqual(self.get(url='/blah')['status'], 200)
|
||||||
|
self.assertEqual(self.get(url='/blah1')['status'], 404)
|
||||||
|
self.assertEqual(self.get(url='/blah12')['status'], 404)
|
||||||
|
self.assertEqual(self.get(url='/blah2')['status'], 200)
|
||||||
|
|
||||||
def test_routes_match_wildcard_middle(self):
|
def test_routes_match_wildcard_middle(self):
|
||||||
self.route_match({"host": "ex*le"})
|
self.route_match({"host": "ex*le"})
|
||||||
@@ -181,6 +212,15 @@ class TestRouting(TestApplicationProto):
|
|||||||
self.assertEqual(self.get(url='/blah')['status'], 200, '/blah')
|
self.assertEqual(self.get(url='/blah')['status'], 200, '/blah')
|
||||||
self.assertEqual(self.get(url='/BLAH')['status'], 404, '/BLAH')
|
self.assertEqual(self.get(url='/BLAH')['status'], 404, '/BLAH')
|
||||||
|
|
||||||
|
def test_routes_match_many_wildcard_substrings_case_sensitive(self):
|
||||||
|
self.route_match({"uri": "*a*B*c*"})
|
||||||
|
|
||||||
|
self.assertEqual(self.get(url='/blah-a-B-c-blah')['status'], 200)
|
||||||
|
self.assertEqual(self.get(url='/a-B-c')['status'], 200)
|
||||||
|
self.assertEqual(self.get(url='/aBc')['status'], 200)
|
||||||
|
self.assertEqual(self.get(url='/aBCaBbc')['status'], 200)
|
||||||
|
self.assertEqual(self.get(url='/ABc')['status'], 404)
|
||||||
|
|
||||||
def test_routes_pass_encode(self):
|
def test_routes_pass_encode(self):
|
||||||
def check_pass(path, name):
|
def check_pass(path, name):
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
@@ -1362,7 +1402,6 @@ class TestRouting(TestApplicationProto):
|
|||||||
self.route_match_invalid({"arguments": ["var"]})
|
self.route_match_invalid({"arguments": ["var"]})
|
||||||
self.route_match_invalid({"arguments": [{"var1": {}}]})
|
self.route_match_invalid({"arguments": [{"var1": {}}]})
|
||||||
self.route_match_invalid({"arguments": {"": "bar"}})
|
self.route_match_invalid({"arguments": {"": "bar"}})
|
||||||
self.route_match_invalid({"arguments": {"foo": "*ba*r"}})
|
|
||||||
self.route_match_invalid({"arguments": {"foo": "%"}})
|
self.route_match_invalid({"arguments": {"foo": "%"}})
|
||||||
self.route_match_invalid({"arguments": {"foo": "%1G"}})
|
self.route_match_invalid({"arguments": {"foo": "%1G"}})
|
||||||
self.route_match_invalid({"arguments": {"%": "bar"}})
|
self.route_match_invalid({"arguments": {"%": "bar"}})
|
||||||
|
|||||||
Reference in New Issue
Block a user