diff options
author | Zhidao HONG <z.hong@f5.com> | 2022-05-19 21:18:25 +0800 |
---|---|---|
committer | Zhidao HONG <z.hong@f5.com> | 2022-05-19 21:18:25 +0800 |
commit | 4f16479482f4902aecefdbcd16f3d6e3bf6b67a4 (patch) | |
tree | e90ce2482c204cad5f2f8d026775b77f7a179ad4 /src | |
parent | 0d48fe73c4450901622373e35f6ff3a944ec13d6 (diff) | |
download | unit-4f16479482f4902aecefdbcd16f3d6e3bf6b67a4.tar.gz unit-4f16479482f4902aecefdbcd16f3d6e3bf6b67a4.tar.bz2 |
HTTP: generalized uri encoding.
No functional changes.
Diffstat (limited to 'src')
-rw-r--r-- | src/nxt_http.h | 10 | ||||
-rw-r--r-- | src/nxt_http_request.c | 83 | ||||
-rw-r--r-- | src/nxt_http_route.c | 136 |
3 files changed, 126 insertions, 103 deletions
diff --git a/src/nxt_http.h b/src/nxt_http.h index d299fdd4..37c27325 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -207,6 +207,13 @@ typedef struct { } nxt_http_name_value_t; +typedef enum { + NXT_HTTP_URI_ENCODING_NONE = 0, + NXT_HTTP_URI_ENCODING, + NXT_HTTP_URI_ENCODING_PLUS +} nxt_http_uri_encoding_t; + + typedef struct nxt_http_route_s nxt_http_route_t; typedef struct nxt_http_route_rule_s nxt_http_route_rule_t; typedef struct nxt_http_route_addr_rule_s nxt_http_route_addr_rule_t; @@ -324,6 +331,9 @@ nxt_int_t nxt_http_request_content_length(void *ctx, nxt_http_field_t *field, nxt_array_t *nxt_http_arguments_parse(nxt_http_request_t *r); nxt_array_t *nxt_http_cookies_parse(nxt_http_request_t *r); +int64_t nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name, + nxt_bool_t case_sensitive, uint8_t encoding); + nxt_http_routes_t *nxt_http_routes_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *routes_conf); nxt_http_action_t *nxt_http_action_create(nxt_task_t *task, diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index 04a6f7f3..0eacf627 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -1024,3 +1024,86 @@ nxt_http_cookie(nxt_array_t *array, u_char *name, size_t name_length, return nv; } + + +int64_t +nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name, nxt_bool_t case_sensitive, + uint8_t encoding) +{ + u_char c, *p, *src, *start, *end, plus; + uint8_t d0, d1; + uint32_t hash; + nxt_str_t str; + nxt_uint_t i; + + str.length = name->length; + + str.start = nxt_mp_nget(mp, str.length); + if (nxt_slow_path(str.start == NULL)) { + return -1; + } + + p = str.start; + + hash = NXT_HTTP_FIELD_HASH_INIT; + + if (encoding == NXT_HTTP_URI_ENCODING_NONE) { + for (i = 0; i < name->length; i++) { + c = name->start[i]; + *p++ = c; + + c = case_sensitive ? c : nxt_lowcase(c); + hash = nxt_http_field_hash_char(hash, c); + } + + goto end; + } + + plus = (encoding == NXT_HTTP_URI_ENCODING_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 -1; + } + + d0 = nxt_hex2int[src[1]]; + d1 = nxt_hex2int[src[2]]; + src += 2; + + if (nxt_slow_path((d0 | d1) >= 16)) { + return -1; + } + + c = (d0 << 4) + d1; + *p++ = c; + break; + + case '+': + c = plus; + *p++ = c; + break; + + default: + *p++ = c; + break; + } + + c = case_sensitive ? c : nxt_lowcase(c); + hash = nxt_http_field_hash_char(hash, c); + } + + str.length = p - str.start; + +end: + + *name = str; + + return nxt_http_field_hash_end(hash) & 0xFFFF; +} diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index 9200dc52..f7023997 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -40,13 +40,6 @@ typedef enum { } 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 { nxt_conf_value_t *host; nxt_conf_value_t *uri; @@ -169,29 +162,29 @@ static nxt_http_route_match_t *nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv); 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_bool_t case_sensitive, nxt_http_route_encoding_t encoding); + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding); 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_bool_t case_sensitive, nxt_http_route_encoding_t encoding); + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding); 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_bool_t case_sensitive, nxt_http_route_encoding_t encoding); + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding); 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_http_route_pattern_case_t pattern_case, - nxt_http_route_encoding_t encoding); + nxt_http_uri_encoding_t encoding); 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 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, - nxt_http_route_encoding_t encoding); + nxt_http_uri_encoding_t encoding); static nxt_int_t nxt_http_route_decode_str(nxt_str_t *str, - nxt_http_route_encoding_t encoding); + nxt_http_uri_encoding_t encoding); 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_uri_encoding_t encoding, nxt_http_route_pattern_case_t pattern_case); static nxt_int_t nxt_http_route_resolve(nxt_task_t *task, @@ -457,7 +450,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.scheme != NULL) { rule = nxt_http_route_rule_create(task, mp, mtcf.scheme, 1, NXT_HTTP_ROUTE_PATTERN_NOCASE, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); if (rule == NULL) { return NULL; } @@ -470,7 +463,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.host != NULL) { rule = nxt_http_route_rule_create(task, mp, mtcf.host, 1, NXT_HTTP_ROUTE_PATTERN_LOWCASE, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); if (rule == NULL) { return NULL; } @@ -484,7 +477,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.uri != NULL) { rule = nxt_http_route_rule_create(task, mp, mtcf.uri, 1, NXT_HTTP_ROUTE_PATTERN_NOCASE, - NXT_HTTP_ROUTE_ENCODING_URI); + NXT_HTTP_URI_ENCODING); if (rule == NULL) { return NULL; } @@ -498,7 +491,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.method != NULL) { rule = nxt_http_route_rule_create(task, mp, mtcf.method, 1, NXT_HTTP_ROUTE_PATTERN_UPCASE, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); if (rule == NULL) { return NULL; } @@ -512,7 +505,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.headers != NULL) { table = nxt_http_route_table_create(task, mp, mtcf.headers, NXT_HTTP_ROUTE_HEADER, 0, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); if (table == NULL) { return NULL; } @@ -524,7 +517,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.arguments != NULL) { table = nxt_http_route_table_create(task, mp, mtcf.arguments, NXT_HTTP_ROUTE_ARGUMENT, 1, - NXT_HTTP_ROUTE_ENCODING_URI_PLUS); + NXT_HTTP_URI_ENCODING_PLUS); if (table == NULL) { return NULL; } @@ -536,7 +529,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.cookies != NULL) { table = nxt_http_route_table_create(task, mp, mtcf.cookies, NXT_HTTP_ROUTE_COOKIE, 1, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); if (table == NULL) { return NULL; } @@ -548,7 +541,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, if (mtcf.query != NULL) { rule = nxt_http_route_rule_create(task, mp, mtcf.query, 1, NXT_HTTP_ROUTE_PATTERN_NOCASE, - NXT_HTTP_ROUTE_ENCODING_URI_PLUS); + NXT_HTTP_URI_ENCODING_PLUS); if (rule == NULL) { return NULL; } @@ -690,7 +683,7 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 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_bool_t case_sensitive, nxt_http_route_encoding_t encoding) + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding) { size_t size; uint32_t i, n; @@ -729,7 +722,7 @@ nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp, 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_bool_t case_sensitive, nxt_http_route_encoding_t encoding) + nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding) { size_t size; uint32_t i, n, next; @@ -777,12 +770,9 @@ nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp, 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_bool_t case_sensitive, - nxt_http_route_encoding_t encoding) + nxt_http_uri_encoding_t encoding) { - u_char c, *p, *src, *start, *end, plus; - uint8_t d0, d1; - uint32_t hash; - nxt_uint_t i; + int64_t hash; nxt_http_route_rule_t *rule; rule = nxt_http_route_rule_create(task, mp, rule_cv, case_sensitive, @@ -792,73 +782,14 @@ nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp, return NULL; } - rule->u.name.length = name->length; - - p = nxt_mp_nget(mp, name->length); - if (nxt_slow_path(p == NULL)) { + hash = nxt_http_field_hash(mp, name, case_sensitive, encoding); + if (nxt_slow_path(hash == -1)) { return NULL; } - hash = NXT_HTTP_FIELD_HASH_INIT; - rule->u.name.start = p; - - if (encoding == NXT_HTTP_ROUTE_ENCODING_NONE) { - for (i = 0; i < name->length; i++) { - c = name->start[i]; - *p++ = c; - - c = case_sensitive ? c : nxt_lowcase(c); - hash = nxt_http_field_hash_char(hash, 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); - 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 = hash; + rule->u.name.start = name->start; + rule->u.name.length = name->length; return rule; } @@ -868,7 +799,7 @@ 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_http_route_pattern_case_t pattern_case, - nxt_http_route_encoding_t encoding) + nxt_http_uri_encoding_t encoding) { size_t size; uint32_t i, n; @@ -953,7 +884,7 @@ nxt_http_route_types_rule_create(nxt_task_t *task, nxt_mp_t *mp, { return nxt_http_route_rule_create(task, mp, types, 0, NXT_HTTP_ROUTE_PATTERN_LOWCASE, - NXT_HTTP_ROUTE_ENCODING_NONE); + NXT_HTTP_URI_ENCODING_NONE); } @@ -992,7 +923,7 @@ 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, - nxt_http_route_encoding_t encoding) + nxt_http_uri_encoding_t encoding) { u_char c, *p, *end; nxt_str_t test, tmp; @@ -1188,15 +1119,15 @@ nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, static nxt_int_t -nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding) +nxt_http_route_decode_str(nxt_str_t *str, nxt_http_uri_encoding_t encoding) { u_char *start, *end; switch (encoding) { - case NXT_HTTP_ROUTE_ENCODING_NONE: + case NXT_HTTP_URI_ENCODING_NONE: break; - case NXT_HTTP_ROUTE_ENCODING_URI: + case NXT_HTTP_URI_ENCODING: start = str->start; end = nxt_decode_uri(start, start, str->length); @@ -1207,7 +1138,7 @@ nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding) str->length = end - start; break; - case NXT_HTTP_ROUTE_ENCODING_URI_PLUS: + case NXT_HTTP_URI_ENCODING_PLUS: start = str->start; end = nxt_decode_uri_plus(start, start, str->length); @@ -1228,9 +1159,8 @@ nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding) 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_str_t *test, nxt_http_route_pattern_type_t type, + nxt_http_uri_encoding_t encoding, nxt_http_route_pattern_case_t pattern_case) { u_char *start; |