comparison src/http/modules/ngx_http_memcached_module.c @ 4835:a4512d7737f6

Memcached: memcached_gzip_flag directive. This directive allows to test desired flag as returned by memcached and sets Content-Encoding to gzip if one found. This is reimplementation of patch by Tomash Brechko as available on http://openhack.ru/. It should be a bit more correct though (at least I think so). In particular, it doesn't try to detect if we are able to gunzip data, but instead just sets correct Content-Encoding.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 10 Sep 2012 16:43:49 +0000
parents 778ef9c3fd2d
children fd84344f1df7
comparison
equal deleted inserted replaced
4834:ed470a7bf7fd 4835:a4512d7737f6
11 11
12 12
13 typedef struct { 13 typedef struct {
14 ngx_http_upstream_conf_t upstream; 14 ngx_http_upstream_conf_t upstream;
15 ngx_int_t index; 15 ngx_int_t index;
16 ngx_uint_t gzip_flag;
16 } ngx_http_memcached_loc_conf_t; 17 } ngx_http_memcached_loc_conf_t;
17 18
18 19
19 typedef struct { 20 typedef struct {
20 size_t rest; 21 size_t rest;
98 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, 99 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
99 ngx_conf_set_bitmask_slot, 100 ngx_conf_set_bitmask_slot,
100 NGX_HTTP_LOC_CONF_OFFSET, 101 NGX_HTTP_LOC_CONF_OFFSET,
101 offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream), 102 offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream),
102 &ngx_http_memcached_next_upstream_masks }, 103 &ngx_http_memcached_next_upstream_masks },
104
105 { ngx_string("memcached_gzip_flag"),
106 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
107 ngx_conf_set_num_slot,
108 NGX_HTTP_LOC_CONF_OFFSET,
109 offsetof(ngx_http_memcached_loc_conf_t, gzip_flag),
110 NULL },
103 111
104 ngx_null_command 112 ngx_null_command
105 }; 113 };
106 114
107 115
279 287
280 288
281 static ngx_int_t 289 static ngx_int_t
282 ngx_http_memcached_process_header(ngx_http_request_t *r) 290 ngx_http_memcached_process_header(ngx_http_request_t *r)
283 { 291 {
284 u_char *p, *len; 292 u_char *p, *start;
285 ngx_str_t line; 293 ngx_str_t line;
286 ngx_http_upstream_t *u; 294 ngx_uint_t flags;
287 ngx_http_memcached_ctx_t *ctx; 295 ngx_table_elt_t *h;
296 ngx_http_upstream_t *u;
297 ngx_http_memcached_ctx_t *ctx;
298 ngx_http_memcached_loc_conf_t *mlcf;
288 299
289 u = r->upstream; 300 u = r->upstream;
290 301
291 for (p = u->buffer.pos; p < u->buffer.last; p++) { 302 for (p = u->buffer.pos; p < u->buffer.last; p++) {
292 if (*p == LF) { 303 if (*p == LF) {
307 "memcached: \"%V\"", &line); 318 "memcached: \"%V\"", &line);
308 319
309 p = u->buffer.pos; 320 p = u->buffer.pos;
310 321
311 ctx = ngx_http_get_module_ctx(r, ngx_http_memcached_module); 322 ctx = ngx_http_get_module_ctx(r, ngx_http_memcached_module);
323 mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module);
312 324
313 if (ngx_strncmp(p, "VALUE ", sizeof("VALUE ") - 1) == 0) { 325 if (ngx_strncmp(p, "VALUE ", sizeof("VALUE ") - 1) == 0) {
314 326
315 p += sizeof("VALUE ") - 1; 327 p += sizeof("VALUE ") - 1;
316 328
327 339
328 if (*p++ != ' ') { 340 if (*p++ != ' ') {
329 goto no_valid; 341 goto no_valid;
330 } 342 }
331 343
332 /* skip flags */ 344 /* flags */
345
346 start = p;
333 347
334 while (*p) { 348 while (*p) {
335 if (*p++ == ' ') { 349 if (*p++ == ' ') {
336 goto length; 350 if (mlcf->gzip_flag) {
351 goto flags;
352 } else {
353 goto length;
354 }
337 } 355 }
338 } 356 }
339 357
340 goto no_valid; 358 goto no_valid;
341 359
360 flags:
361
362 flags = ngx_atoi(start, p - start - 1);
363
364 if (flags == (ngx_uint_t) NGX_ERROR) {
365 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
366 "memcached sent invalid flags in response \"%V\" "
367 "for key \"%V\"",
368 &line, &ctx->key);
369 return NGX_HTTP_UPSTREAM_INVALID_HEADER;
370 }
371
372 if (flags & mlcf->gzip_flag) {
373 h = ngx_list_push(&r->headers_out.headers);
374 if (h == NULL) {
375 return NGX_ERROR;
376 }
377
378 h->hash = 1;
379 h->key.len = sizeof("Content-Encoding") - 1;
380 h->key.data = (u_char *) "Content-Encoding";
381 h->value.len = sizeof("gzip") - 1;
382 h->value.data = (u_char *) "gzip";
383
384 r->headers_out.content_encoding = h;
385 }
386
342 length: 387 length:
343 388
344 len = p; 389 start = p;
345 390
346 while (*p && *p++ != CR) { /* void */ } 391 while (*p && *p++ != CR) { /* void */ }
347 392
348 u->headers_in.content_length_n = ngx_atoof(len, p - len - 1); 393 u->headers_in.content_length_n = ngx_atoof(start, p - start - 1);
349 if (u->headers_in.content_length_n == -1) { 394 if (u->headers_in.content_length_n == -1) {
350 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 395 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
351 "memcached sent invalid length in response \"%V\" " 396 "memcached sent invalid length in response \"%V\" "
352 "for key \"%V\"", 397 "for key \"%V\"",
353 &line, &ctx->key); 398 &line, &ctx->key);
548 conf->upstream.intercept_404 = 1; 593 conf->upstream.intercept_404 = 1;
549 conf->upstream.pass_request_headers = 0; 594 conf->upstream.pass_request_headers = 0;
550 conf->upstream.pass_request_body = 0; 595 conf->upstream.pass_request_body = 0;
551 596
552 conf->index = NGX_CONF_UNSET; 597 conf->index = NGX_CONF_UNSET;
598 conf->gzip_flag = NGX_CONF_UNSET_UINT;
553 599
554 return conf; 600 return conf;
555 } 601 }
556 602
557 603
591 637
592 if (conf->index == NGX_CONF_UNSET) { 638 if (conf->index == NGX_CONF_UNSET) {
593 conf->index = prev->index; 639 conf->index = prev->index;
594 } 640 }
595 641
642 ngx_conf_merge_uint_value(conf->gzip_flag, prev->gzip_flag, 0);
643
596 return NGX_CONF_OK; 644 return NGX_CONF_OK;
597 } 645 }
598 646
599 647
600 static char * 648 static char *