~ubuntu-branches/ubuntu/trusty/nginx/trusty-proposed

« back to all changes in this revision

Viewing changes to src/http/modules/ngx_http_memcached_module.c

  • Committer: Package Import Robot
  • Author(s): Kartik Mistry
  • Date: 2013-04-25 12:51:45 UTC
  • mfrom: (1.3.28)
  • mto: (1.3.29) (15.1.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 64.
  • Revision ID: package-import@ubuntu.com-20130425125145-ugl0wor6bq0u5eae
Tags: upstream-1.4.0
ImportĀ upstreamĀ versionĀ 1.4.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
 
2
2
/*
3
3
 * Copyright (C) Igor Sysoev
 
4
 * Copyright (C) Nginx, Inc.
4
5
 */
5
6
 
6
7
 
7
8
#include <ngx_config.h>
8
9
#include <ngx_core.h>
9
 
#include <ngx_event.h>
10
10
#include <ngx_http.h>
11
11
 
12
12
 
13
13
typedef struct {
14
14
    ngx_http_upstream_conf_t   upstream;
15
15
    ngx_int_t                  index;
 
16
    ngx_uint_t                 gzip_flag;
16
17
} ngx_http_memcached_loc_conf_t;
17
18
 
18
19
 
39
40
static char *ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd,
40
41
    void *conf);
41
42
 
42
 
static char *ngx_http_memcached_upstream_max_fails_unsupported(ngx_conf_t *cf,
43
 
    ngx_command_t *cmd, void *conf);
44
 
static char *ngx_http_memcached_upstream_fail_timeout_unsupported(ngx_conf_t *cf,
45
 
    ngx_command_t *cmd, void *conf);
46
 
 
47
43
 
48
44
static ngx_conf_bitmask_t  ngx_http_memcached_next_upstream_masks[] = {
49
45
    { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
64
60
      0,
65
61
      NULL },
66
62
 
 
63
    { ngx_string("memcached_bind"),
 
64
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
 
65
      ngx_http_upstream_bind_set_slot,
 
66
      NGX_HTTP_LOC_CONF_OFFSET,
 
67
      offsetof(ngx_http_memcached_loc_conf_t, upstream.local),
 
68
      NULL },
 
69
 
67
70
    { ngx_string("memcached_connect_timeout"),
68
71
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
69
72
      ngx_conf_set_msec_slot,
99
102
      offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream),
100
103
      &ngx_http_memcached_next_upstream_masks },
101
104
 
102
 
    { ngx_string("memcached_upstream_max_fails"),
103
 
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
104
 
      ngx_http_memcached_upstream_max_fails_unsupported,
105
 
      0,
106
 
      0,
107
 
      NULL },
108
 
 
109
 
    { ngx_string("memcached_upstream_fail_timeout"),
110
 
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
111
 
      ngx_http_memcached_upstream_fail_timeout_unsupported,
112
 
      0,
113
 
      0,
 
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),
114
110
      NULL },
115
111
 
116
112
      ngx_null_command
127
123
    NULL,                                  /* create server configuration */
128
124
    NULL,                                  /* merge server configuration */
129
125
 
130
 
    ngx_http_memcached_create_loc_conf,    /* create location configration */
131
 
    ngx_http_memcached_merge_loc_conf      /* merge location configration */
 
126
    ngx_http_memcached_create_loc_conf,    /* create location configuration */
 
127
    ngx_http_memcached_merge_loc_conf      /* merge location configuration */
132
128
};
133
129
 
134
130
 
177
173
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
178
174
    }
179
175
 
180
 
    mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module);
181
 
 
182
 
    u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
183
 
    if (u == NULL) {
 
176
    if (ngx_http_upstream_create(r) != NGX_OK) {
184
177
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
185
178
    }
186
179
 
187
 
    u->schema = mlcf->upstream.schema;
188
 
 
189
 
    u->peer.log = r->connection->log;
190
 
    u->peer.log_error = NGX_ERROR_ERR;
191
 
#if (NGX_THREADS)
192
 
    u->peer.lock = &r->connection->lock;
193
 
#endif
194
 
 
 
180
    u = r->upstream;
 
181
 
 
182
    ngx_str_set(&u->schema, "memcached://");
195
183
    u->output.tag = (ngx_buf_tag_t) &ngx_http_memcached_module;
196
184
 
 
185
    mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module);
 
186
 
197
187
    u->conf = &mlcf->upstream;
198
188
 
199
189
    u->create_request = ngx_http_memcached_create_request;
202
192
    u->abort_request = ngx_http_memcached_abort_request;
203
193
    u->finalize_request = ngx_http_memcached_finalize_request;
204
194
 
205
 
    r->upstream = u;
206
 
 
207
195
    ctx = ngx_palloc(r->pool, sizeof(ngx_http_memcached_ctx_t));
208
196
    if (ctx == NULL) {
209
197
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
218
206
    u->input_filter = ngx_http_memcached_filter;
219
207
    u->input_filter_ctx = ctx;
220
208
 
 
209
    r->main->count++;
 
210
 
221
211
    ngx_http_upstream_init(r);
222
212
 
223
213
    return NGX_DONE;
299
289
static ngx_int_t
300
290
ngx_http_memcached_process_header(ngx_http_request_t *r)
301
291
{
302
 
    u_char                    *p, *len;
303
 
    ngx_str_t                  line;
304
 
    ngx_http_upstream_t       *u;
305
 
    ngx_http_memcached_ctx_t  *ctx;
 
292
    u_char                         *p, *start;
 
293
    ngx_str_t                       line;
 
294
    ngx_uint_t                      flags;
 
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;
306
299
 
307
300
    u = r->upstream;
308
301
 
327
320
    p = u->buffer.pos;
328
321
 
329
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);
330
324
 
331
325
    if (ngx_strncmp(p, "VALUE ", sizeof("VALUE ") - 1) == 0) {
332
326
 
347
341
            goto no_valid;
348
342
        }
349
343
 
350
 
        /* skip flags */
 
344
        /* flags */
 
345
 
 
346
        start = p;
351
347
 
352
348
        while (*p) {
353
349
            if (*p++ == ' ') {
354
 
                goto length;
 
350
                if (mlcf->gzip_flag) {
 
351
                    goto flags;
 
352
                } else {
 
353
                    goto length;
 
354
                }
355
355
            }
356
356
        }
357
357
 
358
358
        goto no_valid;
359
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
 
360
387
    length:
361
388
 
362
 
        len = p;
 
389
        start = p;
363
390
 
364
391
        while (*p && *p++ != CR) { /* void */ }
365
392
 
366
 
        r->headers_out.content_length_n = ngx_atoof(len, p - len - 1);
367
 
        if (r->headers_out.content_length_n == -1) {
 
393
        u->headers_in.content_length_n = ngx_atoof(start, p - start - 1);
 
394
        if (u->headers_in.content_length_n == -1) {
368
395
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
369
396
                          "memcached sent invalid length in response \"%V\" "
370
397
                          "for key \"%V\"",
385
412
 
386
413
        u->headers_in.status_n = 404;
387
414
        u->state->status = 404;
 
415
        u->keepalive = 1;
388
416
 
389
417
        return NGX_OK;
390
418
    }
426
454
    u = ctx->request->upstream;
427
455
    b = &u->buffer;
428
456
 
429
 
    if (u->length == ctx->rest) {
 
457
    if (u->length == (ssize_t) ctx->rest) {
430
458
 
431
459
        if (ngx_strncmp(b->last,
432
460
                   ngx_http_memcached_end + NGX_HTTP_MEMCACHED_END - ctx->rest,
433
 
                   ctx->rest)
 
461
                   bytes)
434
462
            != 0)
435
463
        {
436
464
            ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
437
465
                          "memcached sent invalid trailer");
438
 
        }
439
 
 
440
 
        u->length = 0;
441
 
        ctx->rest = 0;
 
466
 
 
467
            u->length = 0;
 
468
            ctx->rest = 0;
 
469
 
 
470
            return NGX_OK;
 
471
        }
 
472
 
 
473
        u->length -= bytes;
 
474
        ctx->rest -= bytes;
 
475
 
 
476
        if (u->length == 0) {
 
477
            u->keepalive = 1;
 
478
        }
442
479
 
443
480
        return NGX_OK;
444
481
    }
477
514
    if (ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0) {
478
515
        ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
479
516
                      "memcached sent invalid trailer");
 
517
 
 
518
        b->last = last;
 
519
        cl->buf->last = last;
 
520
        u->length = 0;
 
521
        ctx->rest = 0;
 
522
 
 
523
        return NGX_OK;
480
524
    }
481
525
 
482
526
    ctx->rest -= b->last - last;
484
528
    cl->buf->last = last;
485
529
    u->length = ctx->rest;
486
530
 
 
531
    if (u->length == 0) {
 
532
        u->keepalive = 1;
 
533
    }
 
534
 
487
535
    return NGX_OK;
488
536
}
489
537
 
513
561
 
514
562
    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_memcached_loc_conf_t));
515
563
    if (conf == NULL) {
516
 
        return NGX_CONF_ERROR;
 
564
        return NULL;
517
565
    }
518
566
 
519
567
    /*
522
570
     *     conf->upstream.bufs.num = 0;
523
571
     *     conf->upstream.next_upstream = 0;
524
572
     *     conf->upstream.temp_path = NULL;
525
 
     *     conf->upstream.schema = { 0, NULL };
526
573
     *     conf->upstream.uri = { 0, NULL };
527
574
     *     conf->upstream.location = NULL;
528
575
     */
529
576
 
 
577
    conf->upstream.local = NGX_CONF_UNSET_PTR;
530
578
    conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
531
579
    conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
532
580
    conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
548
596
    conf->upstream.pass_request_body = 0;
549
597
 
550
598
    conf->index = NGX_CONF_UNSET;
 
599
    conf->gzip_flag = NGX_CONF_UNSET_UINT;
551
600
 
552
601
    return conf;
553
602
}
559
608
    ngx_http_memcached_loc_conf_t *prev = parent;
560
609
    ngx_http_memcached_loc_conf_t *conf = child;
561
610
 
 
611
    ngx_conf_merge_ptr_value(conf->upstream.local,
 
612
                              prev->upstream.local, NULL);
 
613
 
562
614
    ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
563
615
                              prev->upstream.connect_timeout, 60000);
564
616
 
585
637
 
586
638
    if (conf->upstream.upstream == NULL) {
587
639
        conf->upstream.upstream = prev->upstream.upstream;
588
 
        conf->upstream.schema = prev->upstream.schema;
589
640
    }
590
641
 
591
642
    if (conf->index == NGX_CONF_UNSET) {
592
643
        conf->index = prev->index;
593
644
    }
594
645
 
 
646
    ngx_conf_merge_uint_value(conf->gzip_flag, prev->gzip_flag, 0);
 
647
 
595
648
    return NGX_CONF_OK;
596
649
}
597
650
 
599
652
static char *
600
653
ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
601
654
{
602
 
    ngx_http_memcached_loc_conf_t *lcf = conf;
 
655
    ngx_http_memcached_loc_conf_t *mlcf = conf;
603
656
 
604
657
    ngx_str_t                 *value;
605
658
    ngx_url_t                  u;
606
659
    ngx_http_core_loc_conf_t  *clcf;
607
660
 
608
 
    if (lcf->upstream.schema.len) {
 
661
    if (mlcf->upstream.upstream) {
609
662
        return "is duplicate";
610
663
    }
611
664
 
616
669
    u.url = value[1];
617
670
    u.no_resolve = 1;
618
671
 
619
 
    lcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
620
 
    if (lcf->upstream.upstream == NULL) {
 
672
    mlcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
 
673
    if (mlcf->upstream.upstream == NULL) {
621
674
        return NGX_CONF_ERROR;
622
675
    }
623
676
 
624
 
    lcf->upstream.schema.len = sizeof("memcached://") - 1;
625
 
    lcf->upstream.schema.data = (u_char *) "memcached://";
626
 
 
627
677
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
628
678
 
629
679
    clcf->handler = ngx_http_memcached_handler;
632
682
        clcf->auto_redirect = 1;
633
683
    }
634
684
 
635
 
    lcf->index = ngx_http_get_variable_index(cf, &ngx_http_memcached_key);
 
685
    mlcf->index = ngx_http_get_variable_index(cf, &ngx_http_memcached_key);
636
686
 
637
 
    if (lcf->index == NGX_ERROR) {
 
687
    if (mlcf->index == NGX_ERROR) {
638
688
        return NGX_CONF_ERROR;
639
689
    }
640
690
 
641
691
    return NGX_CONF_OK;
642
692
}
643
 
 
644
 
 
645
 
static char *
646
 
ngx_http_memcached_upstream_max_fails_unsupported(ngx_conf_t *cf,
647
 
    ngx_command_t *cmd, void *conf)
648
 
{
649
 
    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
650
 
         "\"memcached_upstream_max_fails\" is not supported, "
651
 
         "use the \"max_fails\" parameter of the \"server\" directive ",
652
 
         "inside the \"upstream\" block");
653
 
 
654
 
    return NGX_CONF_ERROR;
655
 
}
656
 
 
657
 
 
658
 
static char *
659
 
ngx_http_memcached_upstream_fail_timeout_unsupported(ngx_conf_t *cf,
660
 
    ngx_command_t *cmd, void *conf)
661
 
{
662
 
    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
663
 
         "\"memcached_upstream_fail_timeout\" is not supported, "
664
 
         "use the \"fail_timeout\" parameter of the \"server\" directive ",
665
 
         "inside the \"upstream\" block");
666
 
 
667
 
    return NGX_CONF_ERROR;
668
 
}