From 9fe8fbaa72451ebdbfa1a30c73a5e4f37f6dc205 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Sun, 20 Jun 2021 11:21:14 -0400 Subject: [PATCH] [multiple] http_method_buf() - http_method_buf() returns (const buffer *) - comment out unused get_http_status_name() - inline func for http_append_method() config processing requires a persistent buffer for method on the off-chance that the config performed a capturing regex match in $HTTP["method"] condition and used it later (e.g. in mod_rewrite) (Prior behavior using r->tmp_buf was undefined in this case) --- src/configfile-glue.c | 7 +-- src/http_cgi.c | 5 +- src/http_kv.c | 116 +++++++++++++++++++++++------------------- src/http_kv.h | 20 ++++++-- src/mod_auth.c | 8 +-- src/mod_proxy.c | 7 ++- src/request.c | 4 +- 7 files changed, 92 insertions(+), 75 deletions(-) diff --git a/src/configfile-glue.c b/src/configfile-glue.c index e0588c92..6bf1fbf7 100644 --- a/src/configfile-glue.c +++ b/src/configfile-glue.c @@ -541,12 +541,7 @@ static cond_result_t config_check_cond_nocache(request_st * const r, const data_ if (NULL == l) l = (buffer *)&empty_string; break; case COMP_HTTP_REQUEST_METHOD: - { - buffer * const tb = r->tmp_buf; - l = tb; - buffer_clear(tb); - http_method_append(tb, r->http_method); - } + l = http_method_buf(r->http_method); break; default: return COND_RESULT_FALSE; diff --git a/src/http_cgi.c b/src/http_cgi.c index a39f5bbc..5044f49e 100644 --- a/src/http_cgi.c +++ b/src/http_cgi.c @@ -220,9 +220,8 @@ http_cgi_headers (request_st * const r, http_cgi_opts * const opts, http_cgi_hea BUF_PTR_LEN(&r->physical.basedir)); } - s = get_http_method_name(r->http_method); - force_assert(s); - rc |= cb(vdata, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s)); + const buffer * const m = http_method_buf(r->http_method); + rc |= cb(vdata, CONST_STR_LEN("REQUEST_METHOD"), BUF_PTR_LEN(m)); s = get_http_version_name(r->http_version); force_assert(s); diff --git a/src/http_kv.c b/src/http_kv.c index 520ec806..673ea1f1 100644 --- a/src/http_kv.c +++ b/src/http_kv.c @@ -25,48 +25,48 @@ static const keyvalue http_versions[] = { { HTTP_VERSION_UNSET, 0, NULL } }; -static const keyvalue http_methods[] = { - { HTTP_METHOD_GET, CONST_LEN_STR("GET") }, - { HTTP_METHOD_HEAD, CONST_LEN_STR("HEAD") }, - { HTTP_METHOD_POST, CONST_LEN_STR("POST") }, - { HTTP_METHOD_PUT, CONST_LEN_STR("PUT") }, - { HTTP_METHOD_DELETE, CONST_LEN_STR("DELETE") }, - { HTTP_METHOD_CONNECT, CONST_LEN_STR("CONNECT") }, - { HTTP_METHOD_OPTIONS, CONST_LEN_STR("OPTIONS") }, - { HTTP_METHOD_TRACE, CONST_LEN_STR("TRACE") }, - { HTTP_METHOD_ACL, CONST_LEN_STR("ACL") }, - { HTTP_METHOD_BASELINE_CONTROL, CONST_LEN_STR("BASELINE-CONTROL") }, - { HTTP_METHOD_BIND, CONST_LEN_STR("BIND") }, - { HTTP_METHOD_CHECKIN, CONST_LEN_STR("CHECKIN") }, - { HTTP_METHOD_CHECKOUT, CONST_LEN_STR("CHECKOUT") }, - { HTTP_METHOD_COPY, CONST_LEN_STR("COPY") }, - { HTTP_METHOD_LABEL, CONST_LEN_STR("LABEL") }, - { HTTP_METHOD_LINK, CONST_LEN_STR("LINK") }, - { HTTP_METHOD_LOCK, CONST_LEN_STR("LOCK") }, - { HTTP_METHOD_MERGE, CONST_LEN_STR("MERGE") }, - { HTTP_METHOD_MKACTIVITY, CONST_LEN_STR("MKACTIVITY") }, - { HTTP_METHOD_MKCALENDAR, CONST_LEN_STR("MKCALENDAR") }, - { HTTP_METHOD_MKCOL, CONST_LEN_STR("MKCOL") }, - { HTTP_METHOD_MKREDIRECTREF, CONST_LEN_STR("MKREDIRECTREF") }, - { HTTP_METHOD_MKWORKSPACE, CONST_LEN_STR("MKWORKSPACE") }, - { HTTP_METHOD_MOVE, CONST_LEN_STR("MOVE") }, - { HTTP_METHOD_ORDERPATCH, CONST_LEN_STR("ORDERPATCH") }, - { HTTP_METHOD_PATCH, CONST_LEN_STR("PATCH") }, - { HTTP_METHOD_PROPFIND, CONST_LEN_STR("PROPFIND") }, - { HTTP_METHOD_PROPPATCH, CONST_LEN_STR("PROPPATCH") }, - { HTTP_METHOD_REBIND, CONST_LEN_STR("REBIND") }, - { HTTP_METHOD_REPORT, CONST_LEN_STR("REPORT") }, - { HTTP_METHOD_SEARCH, CONST_LEN_STR("SEARCH") }, - { HTTP_METHOD_UNBIND, CONST_LEN_STR("UNBIND") }, - { HTTP_METHOD_UNCHECKOUT, CONST_LEN_STR("UNCHECKOUT") }, - { HTTP_METHOD_UNLINK, CONST_LEN_STR("UNLINK") }, - { HTTP_METHOD_UNLOCK, CONST_LEN_STR("UNLOCK") }, - { HTTP_METHOD_UPDATE, CONST_LEN_STR("UPDATE") }, - { HTTP_METHOD_UPDATEREDIRECTREF, CONST_LEN_STR("UPDATEREDIRECTREF") }, - { HTTP_METHOD_VERSION_CONTROL, CONST_LEN_STR("VERSION-CONTROL") }, +static const buffer http_methods[] = { + { CONST_STR_LEN("GET")+1, 0 }, + { CONST_STR_LEN("HEAD")+1, 0 }, + { CONST_STR_LEN("POST")+1, 0 }, + { CONST_STR_LEN("PUT")+1, 0 }, + { CONST_STR_LEN("DELETE")+1, 0 }, + { CONST_STR_LEN("CONNECT")+1, 0 }, + { CONST_STR_LEN("OPTIONS")+1, 0 }, + { CONST_STR_LEN("TRACE")+1, 0 }, + { CONST_STR_LEN("ACL")+1, 0 }, + { CONST_STR_LEN("BASELINE-CONTROL")+1, 0 }, + { CONST_STR_LEN("BIND")+1, 0 }, + { CONST_STR_LEN("CHECKIN")+1, 0 }, + { CONST_STR_LEN("CHECKOUT")+1, 0 }, + { CONST_STR_LEN("COPY")+1, 0 }, + { CONST_STR_LEN("LABEL")+1, 0 }, + { CONST_STR_LEN("LINK")+1, 0 }, + { CONST_STR_LEN("LOCK")+1, 0 }, + { CONST_STR_LEN("MERGE")+1, 0 }, + { CONST_STR_LEN("MKACTIVITY")+1, 0 }, + { CONST_STR_LEN("MKCALENDAR")+1, 0 }, + { CONST_STR_LEN("MKCOL")+1, 0 }, + { CONST_STR_LEN("MKREDIRECTREF")+1, 0 }, + { CONST_STR_LEN("MKWORKSPACE")+1, 0 }, + { CONST_STR_LEN("MOVE")+1, 0 }, + { CONST_STR_LEN("ORDERPATCH")+1, 0 }, + { CONST_STR_LEN("PATCH")+1, 0 }, + { CONST_STR_LEN("PROPFIND")+1, 0 }, + { CONST_STR_LEN("PROPPATCH")+1, 0 }, + { CONST_STR_LEN("REBIND")+1, 0 }, + { CONST_STR_LEN("REPORT")+1, 0 }, + { CONST_STR_LEN("SEARCH")+1, 0 }, + { CONST_STR_LEN("UNBIND")+1, 0 }, + { CONST_STR_LEN("UNCHECKOUT")+1, 0 }, + { CONST_STR_LEN("UNLINK")+1, 0 }, + { CONST_STR_LEN("UNLOCK")+1, 0 }, + { CONST_STR_LEN("UPDATE")+1, 0 }, + { CONST_STR_LEN("UPDATEREDIRECTREF")+1, 0 }, + { CONST_STR_LEN("VERSION-CONTROL")+1, 0 }, - { HTTP_METHOD_PRI, CONST_LEN_STR("PRI") }, - { HTTP_METHOD_UNSET, 0, NULL } + { CONST_STR_LEN("PRI")+1, 0 }, + { "", 0, 0 } }; /* https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml */ @@ -137,6 +137,15 @@ static const keyvalue http_status[] = { }; +const buffer *http_method_buf (http_method_t i) +{ + return ((unsigned int)i < sizeof(http_methods)/sizeof(*http_methods)-2) + ? http_methods+i + : http_methods+i+sizeof(http_methods)/sizeof(*http_methods); + /* HTTP_METHOD_PRI is -2, HTTP_METHOD_UNSET is -1 */ +} + + __attribute_noinline__ __attribute_pure__ static const keyvalue * keyvalue_from_key (const keyvalue *kv, const int k) @@ -147,6 +156,7 @@ static const keyvalue * keyvalue_from_key (const keyvalue *kv, const int k) } +#if 0 /*(unused)*/ __attribute_pure__ static int keyvalue_get_key(const keyvalue *kv, const char * const s, const unsigned int slen) { @@ -155,19 +165,18 @@ static int keyvalue_get_key(const keyvalue *kv, const char * const s, const unsi ++kv; return kv->key; } +#endif const char *get_http_version_name(int i) { return keyvalue_from_key(http_versions, i)->value; } +#if 0 /*(unused)*/ const char *get_http_status_name(int i) { return keyvalue_from_key(http_status, i)->value; } - -const char *get_http_method_name(http_method_t i) { - return keyvalue_from_key(http_methods, i)->value; -} +#endif #if 0 /*(unused)*/ int get_http_version_key(const char *s, size_t slen) { @@ -178,7 +187,16 @@ int get_http_version_key(const char *s, size_t slen) { http_method_t get_http_method_key(const char *s, const size_t slen) { if (slen == 3 && s[0] == 'G' && s[1] == 'E' && s[2] == 'T') return HTTP_METHOD_GET; - return (http_method_t)keyvalue_get_key(http_methods, s, (unsigned int)slen); + const buffer *kv = http_methods; + while (kv->used && (kv->used-1 != slen || 0 != memcmp(kv->ptr, s, slen))) + ++kv; + const uint_fast32_t i = kv - http_methods; + /*(not done: could overload kv->size and store enum in kv->size)*/ + return (i < sizeof(http_methods)/sizeof(*http_methods)-2) + ? (http_method_t)i + : i == sizeof(http_methods)/sizeof(*http_methods)-2 + ? HTTP_METHOD_PRI + : HTTP_METHOD_UNSET; } @@ -197,12 +215,6 @@ void http_status_append(buffer * const b, const int status) { } } -void http_method_append(buffer * const b, const http_method_t method) { - const keyvalue * const kv = keyvalue_from_key(http_methods, method); - if (__builtin_expect( (0 != kv->vlen), 1)) - buffer_append_string_len(b, kv->value, kv->vlen); -} - void http_version_append(buffer * const b, const http_version_t version) { const keyvalue * const kv = keyvalue_from_key(http_versions, version); if (__builtin_expect( (0 != kv->vlen), 1)) diff --git a/src/http_kv.h b/src/http_kv.h index 023055da..ce84f7ea 100644 --- a/src/http_kv.h +++ b/src/http_kv.h @@ -59,14 +59,16 @@ typedef enum { typedef enum { HTTP_VERSION_UNSET = -1, HTTP_VERSION_1_0, HTTP_VERSION_1_1, HTTP_VERSION_2 } http_version_t; +#if 0 /*(unused)*/ __attribute_pure__ const char *get_http_status_name(int i); +#endif __attribute_pure__ const char *get_http_version_name(int i); -__attribute_pure__ -const char *get_http_method_name(http_method_t i); +/*(deprecated)*/ +#define get_http_method_name(i) http_method_buf(i)->ptr #if 0 /*(unused)*/ __attribute_nonnull__ @@ -74,6 +76,9 @@ __attribute_pure__ int get_http_version_key(const char *s, size_t slen); #endif +__attribute_pure__ +const buffer *http_method_buf (http_method_t i); + __attribute_nonnull__ __attribute_pure__ http_method_t get_http_method_key(const char *s, size_t slen); @@ -81,13 +86,18 @@ http_method_t get_http_method_key(const char *s, size_t slen); __attribute_nonnull__ void http_status_append(buffer *b, int status); -__attribute_nonnull__ -void http_method_append(buffer *b, http_method_t method); - __attribute_nonnull__ void http_version_append(buffer *b, http_version_t version); #define http_method_get_or_head(method) ((method) <= HTTP_METHOD_HEAD) #define http_method_get_head_post(method) ((method) <= HTTP_METHOD_POST) +__attribute_nonnull__ +static inline void http_method_append (buffer * const b, const http_method_t method); +static inline void http_method_append (buffer * const b, const http_method_t method) { + const buffer * const kv = http_method_buf(method); + buffer_append_string_len(b, BUF_PTR_LEN(kv)); +} + + #endif diff --git a/src/mod_auth.c b/src/mod_auth.c index 4c97064c..e08d1dc9 100644 --- a/src/mod_auth.c +++ b/src/mod_auth.c @@ -873,7 +873,7 @@ typedef struct http_auth_digest_params_t { static void -mod_auth_digest_mutate (http_auth_info_t * const ai, const http_auth_digest_params_t * const dp, const char * const method) +mod_auth_digest_mutate (http_auth_info_t * const ai, const http_auth_digest_params_t * const dp, const buffer * const method) { force_assert(method); li_md_iov_fn digest_iov = MD5_iov; @@ -911,8 +911,8 @@ mod_auth_digest_mutate (http_auth_info_t * const ai, const http_auth_digest_para } /* calculate H(A2) */ - iov[0].iov_base = method; - iov[0].iov_len = strlen(method); + iov[0].iov_base = method->ptr; + iov[0].iov_len = buffer_clen(method); iov[1].iov_base = ":"; iov[1].iov_len = 1; iov[2].iov_base = dp->ptr[e_uri]; @@ -1410,7 +1410,7 @@ mod_auth_check_digest (request_st * const r, void *p_d, const struct http_auth_r if (__builtin_expect( (HANDLER_GO_ON != rc), 0)) return rc; - mod_auth_digest_mutate(&ai, &dp, get_http_method_name(r->http_method)); + mod_auth_digest_mutate(&ai, &dp, http_method_buf(r->http_method)); if (!ck_memeq_const_time_fixed_len(dp.rdigest, ai.digest, ai.dlen)) { /*ck_memzero(ai.digest, ai.dlen);*//*skip clear since mutated*/ diff --git a/src/mod_proxy.c b/src/mod_proxy.c index 627405b0..4a429fcf 100644 --- a/src/mod_proxy.c +++ b/src/mod_proxy.c @@ -850,8 +850,11 @@ static handler_t proxy_create_env(gw_handler_ctx *gwhctx) { /* build header */ /* request line */ - http_method_append(b, r->http_method); - buffer_append_str2(b, CONST_STR_LEN(" "), BUF_PTR_LEN(&r->target)); + const buffer * const m = http_method_buf(r->http_method); + buffer_append_str3(b, + BUF_PTR_LEN(m), + CONST_STR_LEN(" "), + BUF_PTR_LEN(&r->target)); if (remap_headers) http_header_remap_uri(b, buffer_clen(b) - buffer_clen(&r->target), &hctx->conf.header, 1); diff --git a/src/request.c b/src/request.c index d10774f6..a0ca5cef 100644 --- a/src/request.c +++ b/src/request.c @@ -1278,9 +1278,7 @@ http_request_headers_process_h2 (request_st * const restrict r, const int scheme log_error(r->conf.errh, __FILE__, __LINE__, "request-header:\n:authority: %s\n:method: %s\n:path: %s", r->http_host ? r->http_host->ptr : "", - (HTTP_METHOD_UNSET != r->http_method) - ? get_http_method_name(r->http_method) - : "", + http_method_buf(r->http_method)->ptr, !buffer_is_blank(&r->target) ? r->target.ptr : ""); } }