Router: decode uri and args.
This commit is contained in:
@@ -85,6 +85,16 @@ static nxt_int_t nxt_conf_vldt_routes_member(nxt_conf_validation_t *vldt,
|
|||||||
nxt_str_t *name, nxt_conf_value_t *value);
|
nxt_str_t *name, nxt_conf_value_t *value);
|
||||||
static nxt_int_t nxt_conf_vldt_route(nxt_conf_validation_t *vldt,
|
static nxt_int_t nxt_conf_vldt_route(nxt_conf_validation_t *vldt,
|
||||||
nxt_conf_value_t *value);
|
nxt_conf_value_t *value);
|
||||||
|
static nxt_int_t nxt_conf_vldt_match_encoded_patterns_sets(
|
||||||
|
nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data);
|
||||||
|
static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set(
|
||||||
|
nxt_conf_validation_t *vldt, nxt_conf_value_t *value);
|
||||||
|
static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set_member(
|
||||||
|
nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value);
|
||||||
|
static nxt_int_t nxt_conf_vldt_match_encoded_patterns(
|
||||||
|
nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data);
|
||||||
|
static nxt_int_t nxt_conf_vldt_match_encoded_pattern(
|
||||||
|
nxt_conf_validation_t *vldt, nxt_conf_value_t *value);
|
||||||
static nxt_int_t nxt_conf_vldt_match_patterns(nxt_conf_validation_t *vldt,
|
static nxt_int_t nxt_conf_vldt_match_patterns(nxt_conf_validation_t *vldt,
|
||||||
nxt_conf_value_t *value, void *data);
|
nxt_conf_value_t *value, void *data);
|
||||||
static nxt_int_t nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt,
|
static nxt_int_t nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt,
|
||||||
@@ -343,12 +353,12 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_match_members[] = {
|
|||||||
|
|
||||||
{ nxt_string("uri"),
|
{ nxt_string("uri"),
|
||||||
NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
|
||||||
&nxt_conf_vldt_match_patterns,
|
&nxt_conf_vldt_match_encoded_patterns,
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ nxt_string("arguments"),
|
{ nxt_string("arguments"),
|
||||||
NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY,
|
NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY,
|
||||||
&nxt_conf_vldt_match_patterns_sets,
|
&nxt_conf_vldt_match_encoded_patterns_sets,
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ nxt_string("headers"),
|
{ nxt_string("headers"),
|
||||||
@@ -1379,6 +1389,109 @@ nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static nxt_int_t nxt_conf_vldt_match_encoded_patterns_sets(
|
||||||
|
nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data)
|
||||||
|
{
|
||||||
|
if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
|
||||||
|
return nxt_conf_vldt_array_iterator(vldt, value,
|
||||||
|
&nxt_conf_vldt_match_encoded_patterns_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NXT_CONF_STRING */
|
||||||
|
|
||||||
|
return nxt_conf_vldt_match_encoded_patterns_set(vldt, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set(
|
||||||
|
nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
|
||||||
|
{
|
||||||
|
if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
|
||||||
|
return nxt_conf_vldt_error(vldt, "The \"match\" pattern for "
|
||||||
|
"\"arguments\" must be an object.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return nxt_conf_vldt_object_iterator(vldt, value,
|
||||||
|
&nxt_conf_vldt_match_encoded_patterns_set_member);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static nxt_int_t
|
||||||
|
nxt_conf_vldt_match_encoded_patterns_set_member(nxt_conf_validation_t *vldt,
|
||||||
|
nxt_str_t *name, nxt_conf_value_t *value)
|
||||||
|
{
|
||||||
|
u_char *p, *end;
|
||||||
|
|
||||||
|
if (nxt_slow_path(name->length == 0)) {
|
||||||
|
return nxt_conf_vldt_error(vldt, "The \"match\" pattern objects must "
|
||||||
|
"not contain empty member names.");
|
||||||
|
}
|
||||||
|
|
||||||
|
p = nxt_mp_nget(vldt->pool, name->length);
|
||||||
|
if (nxt_slow_path(p == NULL)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
end = nxt_decode_uri(p, name->start, name->length);
|
||||||
|
if (nxt_slow_path(end == NULL)) {
|
||||||
|
return nxt_conf_vldt_error(vldt, "The \"match\" pattern for "
|
||||||
|
"\"arguments\" is encoded but is invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return nxt_conf_vldt_match_encoded_patterns(vldt, value, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static nxt_int_t
|
||||||
|
nxt_conf_vldt_match_encoded_patterns(nxt_conf_validation_t *vldt,
|
||||||
|
nxt_conf_value_t *value, void *data)
|
||||||
|
{
|
||||||
|
if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
|
||||||
|
return nxt_conf_vldt_array_iterator(vldt, value,
|
||||||
|
&nxt_conf_vldt_match_encoded_pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NXT_CONF_STRING */
|
||||||
|
|
||||||
|
return nxt_conf_vldt_match_encoded_pattern(vldt, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static nxt_int_t
|
||||||
|
nxt_conf_vldt_match_encoded_pattern(nxt_conf_validation_t *vldt,
|
||||||
|
nxt_conf_value_t *value)
|
||||||
|
{
|
||||||
|
u_char *p, *end;
|
||||||
|
nxt_int_t ret;
|
||||||
|
nxt_str_t pattern;
|
||||||
|
|
||||||
|
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
||||||
|
return nxt_conf_vldt_error(vldt, "The \"match\" pattern for \"uri\" "
|
||||||
|
"must be a string.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nxt_conf_vldt_match_pattern(vldt, value);
|
||||||
|
if (nxt_slow_path(ret != NXT_OK)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
nxt_conf_get_string(value, &pattern);
|
||||||
|
|
||||||
|
p = nxt_mp_nget(vldt->pool, pattern.length);
|
||||||
|
if (nxt_slow_path(p == NULL)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
end = nxt_decode_uri(p, pattern.start, pattern.length);
|
||||||
|
if (nxt_slow_path(end == NULL)) {
|
||||||
|
return nxt_conf_vldt_error(vldt, "The \"match\" pattern for \"uri\" "
|
||||||
|
"is encoded but is invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static nxt_int_t
|
static nxt_int_t
|
||||||
nxt_conf_vldt_match_addrs(nxt_conf_validation_t *vldt,
|
nxt_conf_vldt_match_addrs(nxt_conf_validation_t *vldt,
|
||||||
nxt_conf_value_t *value, void *data)
|
nxt_conf_value_t *value, void *data)
|
||||||
|
|||||||
@@ -39,6 +39,13 @@ typedef enum {
|
|||||||
} nxt_http_route_pattern_case_t;
|
} nxt_http_route_pattern_case_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NXT_HTTP_ROUTE_ENCODING_NONE = 0,
|
||||||
|
NXT_HTTP_ROUTE_ENCODING_URI,
|
||||||
|
NXT_HTTP_ROUTE_ENCODING_URI_PLUS
|
||||||
|
} nxt_http_route_encoding_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
nxt_conf_value_t *pass;
|
nxt_conf_value_t *pass;
|
||||||
nxt_conf_value_t *ret;
|
nxt_conf_value_t *ret;
|
||||||
@@ -181,23 +188,27 @@ static nxt_int_t nxt_http_route_action_create(nxt_router_temp_conf_t *tmcf,
|
|||||||
nxt_conf_value_t *cv, nxt_http_action_t *action);
|
nxt_conf_value_t *cv, nxt_http_action_t *action);
|
||||||
static nxt_http_route_table_t *nxt_http_route_table_create(nxt_task_t *task,
|
static nxt_http_route_table_t *nxt_http_route_table_create(nxt_task_t *task,
|
||||||
nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object,
|
nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object,
|
||||||
nxt_bool_t case_sensitive);
|
nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding);
|
||||||
static nxt_http_route_ruleset_t *nxt_http_route_ruleset_create(nxt_task_t *task,
|
static nxt_http_route_ruleset_t *nxt_http_route_ruleset_create(nxt_task_t *task,
|
||||||
nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object,
|
nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object,
|
||||||
nxt_bool_t case_sensitive);
|
nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding);
|
||||||
static nxt_http_route_rule_t *nxt_http_route_rule_name_create(nxt_task_t *task,
|
static nxt_http_route_rule_t *nxt_http_route_rule_name_create(nxt_task_t *task,
|
||||||
nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name,
|
nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name,
|
||||||
nxt_bool_t case_sensitive);
|
nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding);
|
||||||
static nxt_http_route_addr_rule_t *nxt_http_route_addr_rule_create(
|
static nxt_http_route_addr_rule_t *nxt_http_route_addr_rule_create(
|
||||||
nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv);
|
nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv);
|
||||||
static nxt_http_route_rule_t *nxt_http_route_rule_create(nxt_task_t *task,
|
static nxt_http_route_rule_t *nxt_http_route_rule_create(nxt_task_t *task,
|
||||||
nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_bool_t case_sensitive,
|
nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_bool_t case_sensitive,
|
||||||
nxt_http_route_pattern_case_t pattern_case);
|
nxt_http_route_pattern_case_t pattern_case,
|
||||||
|
nxt_http_route_encoding_t encoding);
|
||||||
static int nxt_http_pattern_compare(const void *one, const void *two);
|
static int nxt_http_pattern_compare(const void *one, const void *two);
|
||||||
static int nxt_http_addr_pattern_compare(const void *one, const void *two);
|
static int nxt_http_addr_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,
|
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_conf_value_t *cv, nxt_http_route_pattern_t *pattern,
|
||||||
nxt_http_route_pattern_case_t pattern_case);
|
nxt_http_route_pattern_case_t pattern_case,
|
||||||
|
nxt_http_route_encoding_t encoding);
|
||||||
|
static nxt_int_t nxt_http_route_decode_str(nxt_str_t *str,
|
||||||
|
nxt_http_route_encoding_t encoding);
|
||||||
static u_char *nxt_http_route_pattern_copy(nxt_mp_t *mp, nxt_str_t *test,
|
static u_char *nxt_http_route_pattern_copy(nxt_mp_t *mp, nxt_str_t *test,
|
||||||
nxt_http_route_pattern_case_t pattern_case);
|
nxt_http_route_pattern_case_t pattern_case);
|
||||||
|
|
||||||
@@ -463,7 +474,8 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
|||||||
|
|
||||||
if (mtcf.scheme != NULL) {
|
if (mtcf.scheme != NULL) {
|
||||||
rule = nxt_http_route_rule_create(task, mp, mtcf.scheme, 1,
|
rule = nxt_http_route_rule_create(task, mp, mtcf.scheme, 1,
|
||||||
NXT_HTTP_ROUTE_PATTERN_NOCASE);
|
NXT_HTTP_ROUTE_PATTERN_NOCASE,
|
||||||
|
NXT_HTTP_ROUTE_ENCODING_NONE);
|
||||||
if (rule == NULL) {
|
if (rule == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -475,7 +487,8 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
|||||||
|
|
||||||
if (mtcf.host != NULL) {
|
if (mtcf.host != NULL) {
|
||||||
rule = nxt_http_route_rule_create(task, mp, mtcf.host, 1,
|
rule = nxt_http_route_rule_create(task, mp, mtcf.host, 1,
|
||||||
NXT_HTTP_ROUTE_PATTERN_LOWCASE);
|
NXT_HTTP_ROUTE_PATTERN_LOWCASE,
|
||||||
|
NXT_HTTP_ROUTE_ENCODING_NONE);
|
||||||
if (rule == NULL) {
|
if (rule == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -488,7 +501,8 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
|||||||
|
|
||||||
if (mtcf.uri != NULL) {
|
if (mtcf.uri != NULL) {
|
||||||
rule = nxt_http_route_rule_create(task, mp, mtcf.uri, 1,
|
rule = nxt_http_route_rule_create(task, mp, mtcf.uri, 1,
|
||||||
NXT_HTTP_ROUTE_PATTERN_NOCASE);
|
NXT_HTTP_ROUTE_PATTERN_NOCASE,
|
||||||
|
NXT_HTTP_ROUTE_ENCODING_URI);
|
||||||
if (rule == NULL) {
|
if (rule == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -501,7 +515,8 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
|||||||
|
|
||||||
if (mtcf.method != NULL) {
|
if (mtcf.method != NULL) {
|
||||||
rule = nxt_http_route_rule_create(task, mp, mtcf.method, 1,
|
rule = nxt_http_route_rule_create(task, mp, mtcf.method, 1,
|
||||||
NXT_HTTP_ROUTE_PATTERN_UPCASE);
|
NXT_HTTP_ROUTE_PATTERN_UPCASE,
|
||||||
|
NXT_HTTP_ROUTE_ENCODING_NONE);
|
||||||
if (rule == NULL) {
|
if (rule == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -514,7 +529,8 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
|||||||
|
|
||||||
if (mtcf.headers != NULL) {
|
if (mtcf.headers != NULL) {
|
||||||
table = nxt_http_route_table_create(task, mp, mtcf.headers,
|
table = nxt_http_route_table_create(task, mp, mtcf.headers,
|
||||||
NXT_HTTP_ROUTE_HEADER, 0);
|
NXT_HTTP_ROUTE_HEADER, 0,
|
||||||
|
NXT_HTTP_ROUTE_ENCODING_NONE);
|
||||||
if (table == NULL) {
|
if (table == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -525,7 +541,8 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
|||||||
|
|
||||||
if (mtcf.arguments != NULL) {
|
if (mtcf.arguments != NULL) {
|
||||||
table = nxt_http_route_table_create(task, mp, mtcf.arguments,
|
table = nxt_http_route_table_create(task, mp, mtcf.arguments,
|
||||||
NXT_HTTP_ROUTE_ARGUMENT, 1);
|
NXT_HTTP_ROUTE_ARGUMENT, 1,
|
||||||
|
NXT_HTTP_ROUTE_ENCODING_URI_PLUS);
|
||||||
if (table == NULL) {
|
if (table == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -536,7 +553,8 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
|||||||
|
|
||||||
if (mtcf.cookies != NULL) {
|
if (mtcf.cookies != NULL) {
|
||||||
table = nxt_http_route_table_create(task, mp, mtcf.cookies,
|
table = nxt_http_route_table_create(task, mp, mtcf.cookies,
|
||||||
NXT_HTTP_ROUTE_COOKIE, 1);
|
NXT_HTTP_ROUTE_COOKIE, 1,
|
||||||
|
NXT_HTTP_ROUTE_ENCODING_NONE);
|
||||||
if (table == NULL) {
|
if (table == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -699,7 +717,7 @@ nxt_http_route_action_create(nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv,
|
|||||||
static nxt_http_route_table_t *
|
static nxt_http_route_table_t *
|
||||||
nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp,
|
nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp,
|
||||||
nxt_conf_value_t *table_cv, nxt_http_route_object_t object,
|
nxt_conf_value_t *table_cv, nxt_http_route_object_t object,
|
||||||
nxt_bool_t case_sensitive)
|
nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding)
|
||||||
{
|
{
|
||||||
size_t size;
|
size_t size;
|
||||||
uint32_t i, n;
|
uint32_t i, n;
|
||||||
@@ -722,8 +740,8 @@ nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp,
|
|||||||
table->object = NXT_HTTP_ROUTE_TABLE;
|
table->object = NXT_HTTP_ROUTE_TABLE;
|
||||||
|
|
||||||
if (!array) {
|
if (!array) {
|
||||||
ruleset = nxt_http_route_ruleset_create(task, mp, table_cv,
|
ruleset = nxt_http_route_ruleset_create(task, mp, table_cv, object,
|
||||||
object, case_sensitive);
|
case_sensitive, encoding);
|
||||||
if (nxt_slow_path(ruleset == NULL)) {
|
if (nxt_slow_path(ruleset == NULL)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -736,8 +754,8 @@ nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp,
|
|||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
ruleset_cv = nxt_conf_get_array_element(table_cv, i);
|
ruleset_cv = nxt_conf_get_array_element(table_cv, i);
|
||||||
|
|
||||||
ruleset = nxt_http_route_ruleset_create(task, mp, ruleset_cv,
|
ruleset = nxt_http_route_ruleset_create(task, mp, ruleset_cv, object,
|
||||||
object, case_sensitive);
|
case_sensitive, encoding);
|
||||||
if (nxt_slow_path(ruleset == NULL)) {
|
if (nxt_slow_path(ruleset == NULL)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -752,7 +770,7 @@ nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp,
|
|||||||
static nxt_http_route_ruleset_t *
|
static nxt_http_route_ruleset_t *
|
||||||
nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp,
|
nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp,
|
||||||
nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object,
|
nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object,
|
||||||
nxt_bool_t case_sensitive)
|
nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding)
|
||||||
{
|
{
|
||||||
size_t size;
|
size_t size;
|
||||||
uint32_t i, n, next;
|
uint32_t i, n, next;
|
||||||
@@ -778,7 +796,7 @@ nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp,
|
|||||||
rule_cv = nxt_conf_next_object_member(ruleset_cv, &name, &next);
|
rule_cv = nxt_conf_next_object_member(ruleset_cv, &name, &next);
|
||||||
|
|
||||||
rule = nxt_http_route_rule_name_create(task, mp, rule_cv, &name,
|
rule = nxt_http_route_rule_name_create(task, mp, rule_cv, &name,
|
||||||
case_sensitive);
|
case_sensitive, encoding);
|
||||||
if (nxt_slow_path(rule == NULL)) {
|
if (nxt_slow_path(rule == NULL)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -793,15 +811,18 @@ nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp,
|
|||||||
|
|
||||||
static nxt_http_route_rule_t *
|
static nxt_http_route_rule_t *
|
||||||
nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp,
|
nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp,
|
||||||
nxt_conf_value_t *rule_cv, nxt_str_t *name, nxt_bool_t case_sensitive)
|
nxt_conf_value_t *rule_cv, nxt_str_t *name, nxt_bool_t case_sensitive,
|
||||||
|
nxt_http_route_encoding_t encoding)
|
||||||
{
|
{
|
||||||
u_char c, *p;
|
u_char c, *p, *src, *start, *end, plus;
|
||||||
|
uint8_t d0, d1;
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
nxt_uint_t i;
|
nxt_uint_t i;
|
||||||
nxt_http_route_rule_t *rule;
|
nxt_http_route_rule_t *rule;
|
||||||
|
|
||||||
rule = nxt_http_route_rule_create(task, mp, rule_cv, case_sensitive,
|
rule = nxt_http_route_rule_create(task, mp, rule_cv, case_sensitive,
|
||||||
NXT_HTTP_ROUTE_PATTERN_NOCASE);
|
NXT_HTTP_ROUTE_PATTERN_NOCASE,
|
||||||
|
encoding);
|
||||||
if (nxt_slow_path(rule == NULL)) {
|
if (nxt_slow_path(rule == NULL)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -813,18 +834,65 @@ nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hash = NXT_HTTP_FIELD_HASH_INIT;
|
||||||
rule->u.name.start = p;
|
rule->u.name.start = p;
|
||||||
|
|
||||||
hash = NXT_HTTP_FIELD_HASH_INIT;
|
if (encoding == NXT_HTTP_ROUTE_ENCODING_NONE) {
|
||||||
|
for (i = 0; i < name->length; i++) {
|
||||||
|
c = name->start[i];
|
||||||
|
*p++ = c;
|
||||||
|
|
||||||
for (i = 0; i < name->length; i++) {
|
c = case_sensitive ? c : nxt_lowcase(c);
|
||||||
c = name->start[i];
|
hash = nxt_http_field_hash_char(hash, c);
|
||||||
*p++ = c;
|
}
|
||||||
|
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
plus = (encoding == NXT_HTTP_ROUTE_ENCODING_URI_PLUS) ? ' ' : '+';
|
||||||
|
|
||||||
|
start = name->start;
|
||||||
|
end = start + name->length;
|
||||||
|
|
||||||
|
for (src = start; src < end; src++) {
|
||||||
|
c = *src;
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case '%':
|
||||||
|
if (nxt_slow_path(end - src <= 2)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
d0 = nxt_hex2int[src[1]];
|
||||||
|
d1 = nxt_hex2int[src[2]];
|
||||||
|
src += 2;
|
||||||
|
|
||||||
|
if (nxt_slow_path((d0 | d1) >= 16)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = (d0 << 4) + d1;
|
||||||
|
*p++ = c;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '+':
|
||||||
|
c = plus;
|
||||||
|
*p++ = c;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
*p++ = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
c = case_sensitive ? c : nxt_lowcase(c);
|
c = case_sensitive ? c : nxt_lowcase(c);
|
||||||
hash = nxt_http_field_hash_char(hash, c);
|
hash = nxt_http_field_hash_char(hash, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rule->u.name.length = p - rule->u.name.start;
|
||||||
|
|
||||||
|
end:
|
||||||
|
|
||||||
rule->u.name.hash = nxt_http_field_hash_end(hash) & 0xFFFF;
|
rule->u.name.hash = nxt_http_field_hash_end(hash) & 0xFFFF;
|
||||||
|
|
||||||
return rule;
|
return rule;
|
||||||
@@ -834,7 +902,8 @@ nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp,
|
|||||||
static nxt_http_route_rule_t *
|
static nxt_http_route_rule_t *
|
||||||
nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp,
|
nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp,
|
||||||
nxt_conf_value_t *cv, nxt_bool_t case_sensitive,
|
nxt_conf_value_t *cv, nxt_bool_t case_sensitive,
|
||||||
nxt_http_route_pattern_case_t pattern_case)
|
nxt_http_route_pattern_case_t pattern_case,
|
||||||
|
nxt_http_route_encoding_t encoding)
|
||||||
{
|
{
|
||||||
size_t size;
|
size_t size;
|
||||||
uint32_t i, n;
|
uint32_t i, n;
|
||||||
@@ -860,7 +929,7 @@ nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp,
|
|||||||
if (string) {
|
if (string) {
|
||||||
pattern[0].case_sensitive = case_sensitive;
|
pattern[0].case_sensitive = case_sensitive;
|
||||||
ret = nxt_http_route_pattern_create(task, mp, cv, &pattern[0],
|
ret = nxt_http_route_pattern_create(task, mp, cv, &pattern[0],
|
||||||
pattern_case);
|
pattern_case, encoding);
|
||||||
if (nxt_slow_path(ret != NXT_OK)) {
|
if (nxt_slow_path(ret != NXT_OK)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -875,7 +944,7 @@ nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp,
|
|||||||
value = nxt_conf_get_array_element(cv, i);
|
value = nxt_conf_get_array_element(cv, i);
|
||||||
|
|
||||||
ret = nxt_http_route_pattern_create(task, mp, value, &pattern[i],
|
ret = nxt_http_route_pattern_create(task, mp, value, &pattern[i],
|
||||||
pattern_case);
|
pattern_case, encoding);
|
||||||
if (nxt_slow_path(ret != NXT_OK)) {
|
if (nxt_slow_path(ret != NXT_OK)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -972,10 +1041,12 @@ nxt_http_addr_pattern_compare(const void *one, const void *two)
|
|||||||
static nxt_int_t
|
static nxt_int_t
|
||||||
nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
|
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_conf_value_t *cv, nxt_http_route_pattern_t *pattern,
|
||||||
nxt_http_route_pattern_case_t pattern_case)
|
nxt_http_route_pattern_case_t pattern_case,
|
||||||
|
nxt_http_route_encoding_t encoding)
|
||||||
{
|
{
|
||||||
u_char *start;
|
u_char *start;
|
||||||
nxt_str_t test;
|
nxt_str_t test, test2;
|
||||||
|
nxt_int_t ret;
|
||||||
nxt_uint_t n, length;
|
nxt_uint_t n, length;
|
||||||
nxt_http_route_pattern_type_t type;
|
nxt_http_route_pattern_type_t type;
|
||||||
|
|
||||||
@@ -988,6 +1059,7 @@ nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
|
|||||||
|
|
||||||
pattern->negative = 0;
|
pattern->negative = 0;
|
||||||
pattern->any = 1;
|
pattern->any = 1;
|
||||||
|
pattern->min_length = 0;
|
||||||
|
|
||||||
if (test.length != 0) {
|
if (test.length != 0) {
|
||||||
|
|
||||||
@@ -1000,7 +1072,6 @@ nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (test.length != 0) {
|
if (test.length != 0) {
|
||||||
|
|
||||||
if (test.start[0] == '*') {
|
if (test.start[0] == '*') {
|
||||||
test.start++;
|
test.start++;
|
||||||
test.length--;
|
test.length--;
|
||||||
@@ -1026,18 +1097,45 @@ nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
|
|||||||
length = test.length - 1;
|
length = test.length - 1;
|
||||||
|
|
||||||
for (n = 1; n < length; n++) {
|
for (n = 1; n < length; n++) {
|
||||||
if (test.start[n] == '*') {
|
if (test.start[n] != '*') {
|
||||||
test.length = n;
|
continue;
|
||||||
type = NXT_HTTP_ROUTE_PATTERN_MIDDLE;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
pattern->type = type;
|
||||||
pattern->min_length = test.length;
|
pattern->min_length += test.length;
|
||||||
pattern->length1 = test.length;
|
pattern->length1 = test.length;
|
||||||
|
|
||||||
start = nxt_http_route_pattern_copy(mp, &test, pattern_case);
|
start = nxt_http_route_pattern_copy(mp, &test, pattern_case);
|
||||||
@@ -1047,20 +1145,43 @@ nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
|
|||||||
|
|
||||||
pattern->start1 = start;
|
pattern->start1 = start;
|
||||||
|
|
||||||
if (type == NXT_HTTP_ROUTE_PATTERN_MIDDLE) {
|
return NXT_OK;
|
||||||
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);
|
static nxt_int_t
|
||||||
if (nxt_slow_path(start == NULL)) {
|
nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding)
|
||||||
|
{
|
||||||
|
u_char *start, *end;
|
||||||
|
|
||||||
|
switch (encoding) {
|
||||||
|
case NXT_HTTP_ROUTE_ENCODING_NONE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NXT_HTTP_ROUTE_ENCODING_URI:
|
||||||
|
start = str->start;
|
||||||
|
|
||||||
|
end = nxt_decode_uri(start, start, str->length);
|
||||||
|
if (nxt_slow_path(end == NULL)) {
|
||||||
return NXT_ERROR;
|
return NXT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
pattern->start2 = start;
|
str->length = end - start;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NXT_HTTP_ROUTE_ENCODING_URI_PLUS:
|
||||||
|
start = str->start;
|
||||||
|
|
||||||
|
end = nxt_decode_uri_plus(start, start, str->length);
|
||||||
|
if (nxt_slow_path(end == NULL)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
str->length = end - start;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
nxt_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
return NXT_OK;
|
return NXT_OK;
|
||||||
@@ -1746,7 +1867,8 @@ static nxt_array_t *
|
|||||||
nxt_http_route_arguments_parse(nxt_http_request_t *r)
|
nxt_http_route_arguments_parse(nxt_http_request_t *r)
|
||||||
{
|
{
|
||||||
size_t name_length;
|
size_t name_length;
|
||||||
u_char c, *p, *start, *end, *name;
|
u_char c, *p, *dst, *dst_start, *start, *end, *name;
|
||||||
|
uint8_t d0, d1;
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
nxt_bool_t valid;
|
nxt_bool_t valid;
|
||||||
nxt_array_t *args;
|
nxt_array_t *args;
|
||||||
@@ -1766,39 +1888,81 @@ nxt_http_route_arguments_parse(nxt_http_request_t *r)
|
|||||||
name = NULL;
|
name = NULL;
|
||||||
name_length = 0;
|
name_length = 0;
|
||||||
|
|
||||||
|
dst_start = nxt_mp_nget(r->mem_pool, r->args->length);
|
||||||
|
if (nxt_slow_path(dst_start == NULL)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
start = r->args->start;
|
start = r->args->start;
|
||||||
end = start + r->args->length;
|
end = start + r->args->length;
|
||||||
|
|
||||||
for (p = start; p < end; p++) {
|
for (p = start, dst = dst_start; p < end; p++, dst++) {
|
||||||
c = *p;
|
c = *p;
|
||||||
|
*dst = c;
|
||||||
|
|
||||||
if (c == '=') {
|
switch (c) {
|
||||||
name_length = p - start;
|
case '=':
|
||||||
name = start;
|
if (name != NULL) {
|
||||||
start = p + 1;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
name_length = dst - dst_start;
|
||||||
valid = (name_length != 0);
|
valid = (name_length != 0);
|
||||||
|
name = dst_start;
|
||||||
|
dst_start = dst + 1;
|
||||||
|
|
||||||
} else if (c == '&') {
|
continue;
|
||||||
|
|
||||||
|
case '&':
|
||||||
if (valid) {
|
if (valid) {
|
||||||
nv = nxt_http_route_argument(args, name, name_length, hash,
|
nv = nxt_http_route_argument(args, name, name_length, hash,
|
||||||
start, p);
|
dst_start, dst);
|
||||||
if (nxt_slow_path(nv == NULL)) {
|
if (nxt_slow_path(nv == NULL)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hash = NXT_HTTP_FIELD_HASH_INIT;
|
hash = NXT_HTTP_FIELD_HASH_INIT;
|
||||||
|
name_length = 0;
|
||||||
valid = 1;
|
valid = 1;
|
||||||
name = NULL;
|
name = NULL;
|
||||||
start = p + 1;
|
dst_start = dst + 1;
|
||||||
|
|
||||||
} else if (name == NULL) {
|
continue;
|
||||||
|
|
||||||
|
case '+':
|
||||||
|
c = ' ';
|
||||||
|
*dst = ' ';
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '%':
|
||||||
|
if (nxt_slow_path(end - p <= 2)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
d0 = nxt_hex2int[p[1]];
|
||||||
|
d1 = nxt_hex2int[p[2]];
|
||||||
|
|
||||||
|
if (nxt_slow_path((d0 | d1) >= 16)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += 2;
|
||||||
|
c = (d0 << 4) + d1;
|
||||||
|
*dst = c;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == NULL) {
|
||||||
hash = nxt_http_field_hash_char(hash, c);
|
hash = nxt_http_field_hash_char(hash, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
nv = nxt_http_route_argument(args, name, name_length, hash, start, p);
|
nv = nxt_http_route_argument(args, name, name_length, hash, dst_start,
|
||||||
|
dst);
|
||||||
if (nxt_slow_path(nv == NULL)) {
|
if (nxt_slow_path(nv == NULL)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -475,7 +475,7 @@ nxt_strvers_match(u_char *version, u_char *prefix, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const uint8_t nxt_hex2int[256]
|
const uint8_t nxt_hex2int[256]
|
||||||
nxt_aligned(32) =
|
nxt_aligned(32) =
|
||||||
{
|
{
|
||||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||||
@@ -551,6 +551,47 @@ nxt_decode_uri(u_char *dst, u_char *src, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u_char *
|
||||||
|
nxt_decode_uri_plus(u_char *dst, u_char *src, size_t length)
|
||||||
|
{
|
||||||
|
u_char *end, ch;
|
||||||
|
uint8_t d0, d1;
|
||||||
|
|
||||||
|
nxt_prefetch(&nxt_hex2int['0']);
|
||||||
|
|
||||||
|
end = src + length;
|
||||||
|
|
||||||
|
while (src < end) {
|
||||||
|
ch = *src++;
|
||||||
|
|
||||||
|
switch (ch) {
|
||||||
|
case '%':
|
||||||
|
if (nxt_slow_path(end - src < 2)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
d0 = nxt_hex2int[*src++];
|
||||||
|
d1 = nxt_hex2int[*src++];
|
||||||
|
|
||||||
|
if (nxt_slow_path((d0 | d1) >= 16)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ch = (d0 << 4) + d1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '+':
|
||||||
|
ch = ' ';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dst++ = ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uintptr_t
|
uintptr_t
|
||||||
nxt_encode_uri(u_char *dst, u_char *src, size_t length)
|
nxt_encode_uri(u_char *dst, u_char *src, size_t length)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -174,10 +174,13 @@ NXT_EXPORT nxt_bool_t nxt_strvers_match(u_char *version, u_char *prefix,
|
|||||||
size_t length);
|
size_t length);
|
||||||
|
|
||||||
NXT_EXPORT u_char *nxt_decode_uri(u_char *dst, u_char *src, size_t length);
|
NXT_EXPORT u_char *nxt_decode_uri(u_char *dst, u_char *src, size_t length);
|
||||||
|
NXT_EXPORT u_char *nxt_decode_uri_plus(u_char *dst, u_char *src, size_t length);
|
||||||
NXT_EXPORT uintptr_t nxt_encode_uri(u_char *dst, u_char *src, size_t length);
|
NXT_EXPORT uintptr_t nxt_encode_uri(u_char *dst, u_char *src, size_t length);
|
||||||
NXT_EXPORT uintptr_t nxt_encode_complex_uri(u_char *dst, u_char *src,
|
NXT_EXPORT uintptr_t nxt_encode_complex_uri(u_char *dst, u_char *src,
|
||||||
size_t length);
|
size_t length);
|
||||||
NXT_EXPORT nxt_bool_t nxt_is_complex_uri_encoded(u_char *s, size_t length);
|
NXT_EXPORT nxt_bool_t nxt_is_complex_uri_encoded(u_char *s, size_t length);
|
||||||
|
|
||||||
|
NXT_EXPORT const uint8_t nxt_hex2int[256];
|
||||||
|
|
||||||
|
|
||||||
#endif /* _NXT_STRING_H_INCLUDED_ */
|
#endif /* _NXT_STRING_H_INCLUDED_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user