>From e8cb3e0af8cd9e9621d3307aaab000cf5d7ee879 Mon Sep 17 00:00:00 2001 From: Tomash Brechko Date: Sat, 19 Jul 2008 11:30:58 +0400 Subject: [PATCH] Add memcached_gzip_flag config parameter and memcached_namespace config variable. Note that 'if (clcf->gzip_vary)' part may be obsolete, it seems corresponding code has been removed from gzip module. --- .../src/http/modules/ngx_http_memcached_module.c | 128 +++++++++++++++++-- server/src/http/ngx_http_variables.c | 15 +++ 2 files changed, 129 insertions(+), 14 deletions(-) diff --git a/server/src/http/modules/ngx_http_memcached_module.c b/server/src/http/modules/ngx_http_memcached_module.c index 64592f3..3e3289e 100644 --- a/server/src/http/modules/ngx_http_memcached_module.c +++ b/server/src/http/modules/ngx_http_memcached_module.c @@ -13,6 +13,8 @@ typedef struct { ngx_http_upstream_conf_t upstream; ngx_int_t index; + ngx_uint_t gzip_flag; + ngx_int_t ns_index; } ngx_http_memcached_loc_conf_t; @@ -99,6 +101,14 @@ static ngx_command_t ngx_http_memcached_commands[] = { offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream), &ngx_http_memcached_next_upstream_masks }, + { ngx_string("memcached_gzip_flag"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_memcached_loc_conf_t, gzip_flag), + NULL }, + { ngx_string("memcached_upstream_max_fails"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_http_memcached_upstream_max_fails_unsupported, @@ -149,6 +159,7 @@ ngx_module_t ngx_http_memcached_module = { static ngx_str_t ngx_http_memcached_key = ngx_string("memcached_key"); +static ngx_str_t ngx_http_memcached_ns = ngx_string("memcached_namespace"); #define NGX_HTTP_MEMCACHED_END (sizeof(ngx_http_memcached_end) - 1) @@ -228,11 +239,11 @@ static ngx_int_t ngx_http_memcached_create_request(ngx_http_request_t *r) { size_t len; - uintptr_t escape; + uintptr_t escape, ns_escape = 0; ngx_buf_t *b; ngx_chain_t *cl; ngx_http_memcached_ctx_t *ctx; - ngx_http_variable_value_t *vv; + ngx_http_variable_value_t *vv, *ns_vv; ngx_http_memcached_loc_conf_t *mlcf; mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module); @@ -247,7 +258,15 @@ ngx_http_memcached_create_request(ngx_http_request_t *r) escape = 2 * ngx_escape_uri(NULL, vv->data, vv->len, NGX_ESCAPE_MEMCACHED); - len = sizeof("get ") - 1 + vv->len + escape + sizeof(CRLF) - 1; + ns_vv = ngx_http_get_indexed_variable(r, mlcf->ns_index); + + if (ns_vv != NULL && !ns_vv->not_found && ns_vv->len != 0) { + ns_escape = 2 * ngx_escape_uri(NULL, ns_vv->data, + ns_vv->len, NGX_ESCAPE_MEMCACHED); + } + + len = sizeof("get ") - 1 + ns_vv->len + ns_escape + + vv->len + escape + sizeof(CRLF) - 1; b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { @@ -270,6 +289,16 @@ ngx_http_memcached_create_request(ngx_http_request_t *r) ctx->key.data = b->last; + if (ns_vv != NULL && !ns_vv->not_found && ns_vv->len != 0) { + if (ns_escape == 0) { + b->last = ngx_copy(b->last, ns_vv->data, ns_vv->len); + } else { + b->last = (u_char *) ngx_escape_uri(b->last, ns_vv->data, + ns_vv->len, + NGX_ESCAPE_MEMCACHED); + } + } + if (escape == 0) { b->last = ngx_copy(b->last, vv->data, vv->len); @@ -299,10 +328,14 @@ ngx_http_memcached_reinit_request(ngx_http_request_t *r) static ngx_int_t ngx_http_memcached_process_header(ngx_http_request_t *r) { - u_char *p, *len; + u_char *p, *beg; ngx_str_t line; ngx_http_upstream_t *u; ngx_http_memcached_ctx_t *ctx; + ngx_http_memcached_loc_conf_t *mlcf; + uint32_t flags; + ngx_table_elt_t *h; + ngx_http_core_loc_conf_t *clcf; u = r->upstream; @@ -347,23 +380,21 @@ found: goto no_valid; } - /* skip flags */ + beg = p; - while (*p) { - if (*p++ == ' ') { - goto length; - } - } + while (*p && *p++ != ' ') { /* void */ } - goto no_valid; + if (! *p) { + goto no_valid; + } - length: + flags = ngx_atoof(beg, p - beg - 1); - len = p; + beg = p; while (*p && *p++ != CR) { /* void */ } - r->headers_out.content_length_n = ngx_atoof(len, p - len - 1); + r->headers_out.content_length_n = ngx_atoof(beg, p - beg - 1); if (r->headers_out.content_length_n == -1) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "memcached sent invalid length in response \"%V\" " @@ -372,6 +403,59 @@ found: return NGX_HTTP_UPSTREAM_INVALID_HEADER; } + mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module); + + if (flags & mlcf->gzip_flag) { +#if (NGX_HTTP_GZIP) + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (ngx_http_gzip_ok(r) == NGX_OK) { + h = ngx_list_push(&r->headers_out.headers); + if (h == NULL) { + return NGX_ERROR; + } + + h->hash = 1; + h->key.len = sizeof("Content-Encoding") - 1; + h->key.data = (u_char *) "Content-Encoding"; + h->value.len = sizeof("gzip") - 1; + h->value.data = (u_char *) "gzip"; + + r->headers_out.content_encoding = h; + + if (clcf->gzip_vary) { + h = ngx_list_push(&r->headers_out.headers); + if (h == NULL) { + return NGX_ERROR; + } + + h->hash = 1; + h->key.len = sizeof("Vary") - 1; + h->key.data = (u_char *) "Vary"; + h->value.len = sizeof("Accept-Encoding") - 1; + h->value.data = (u_char *) "Accept-Encoding"; + } + } else { + if (clcf->gunzip) { + r->gunzip = 1; + } else { +#endif + /* + * If the client can't accept compressed data, and + * automatic decompression is not enabled, we + * return 404 in the hope that the next upstream + * will return uncompressed data. + */ + u->headers_in.status_n = 404; + u->state->status = 404; + + return NGX_OK; +#if (NGX_HTTP_GZIP) + } + } +#endif + } + u->headers_in.status_n = 200; u->state->status = 200; u->buffer.pos = p + 1; @@ -533,6 +617,8 @@ ngx_http_memcached_create_loc_conf(ngx_conf_t *cf) conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; + conf->gzip_flag = NGX_CONF_UNSET_UINT; + /* the hardcoded values */ conf->upstream.cyclic_temp_file = 0; conf->upstream.buffering = 0; @@ -548,6 +634,7 @@ ngx_http_memcached_create_loc_conf(ngx_conf_t *cf) conf->upstream.pass_request_body = 0; conf->index = NGX_CONF_UNSET; + conf->ns_index = NGX_CONF_UNSET; return conf; } @@ -578,6 +665,9 @@ ngx_http_memcached_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) |NGX_HTTP_UPSTREAM_FT_ERROR |NGX_HTTP_UPSTREAM_FT_TIMEOUT)); + ngx_conf_merge_uint_value(conf->gzip_flag, + prev->gzip_flag, 0); + if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) { conf->upstream.next_upstream = NGX_CONF_BITMASK_SET |NGX_HTTP_UPSTREAM_FT_OFF; @@ -592,6 +682,10 @@ ngx_http_memcached_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) conf->index = prev->index; } + if (conf->ns_index == NGX_CONF_UNSET) { + conf->ns_index = prev->ns_index; + } + return NGX_CONF_OK; } @@ -638,6 +732,12 @@ ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } + lcf->ns_index = ngx_http_get_variable_index(cf, &ngx_http_memcached_ns); + + if (lcf->ns_index == NGX_ERROR) { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; } diff --git a/server/src/http/ngx_http_variables.c b/server/src/http/ngx_http_variables.c index e014170..f561a27 100644 --- a/server/src/http/ngx_http_variables.c +++ b/server/src/http/ngx_http_variables.c @@ -1335,6 +1335,15 @@ ngx_http_variables_add_core_vars(ngx_conf_t *cf) } +static ngx_int_t +ngx_http_optional_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + *v = ngx_http_variable_null_value; + return NGX_OK; +} + + ngx_int_t ngx_http_variables_init_vars(ngx_conf_t *cf) { @@ -1396,6 +1405,12 @@ ngx_http_variables_init_vars(ngx_conf_t *cf) continue; } + if (ngx_strncmp(v[i].name.data, "memcached_namespace", 19) == 0) { + v[i].get_handler = ngx_http_optional_variable; + + continue; + } + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "unknown \"%V\" variable", &v[i].name); -- 1.5.5.1.116.ge4b9c