Annotation of embedaddon/nginx/src/http/modules/ngx_http_memcached_module.c, revision 1.1

1.1     ! misho       1: 
        !             2: /*
        !             3:  * Copyright (C) Igor Sysoev
        !             4:  * Copyright (C) Nginx, Inc.
        !             5:  */
        !             6: 
        !             7: 
        !             8: #include <ngx_config.h>
        !             9: #include <ngx_core.h>
        !            10: #include <ngx_http.h>
        !            11: 
        !            12: 
        !            13: typedef struct {
        !            14:     ngx_http_upstream_conf_t   upstream;
        !            15:     ngx_int_t                  index;
        !            16:     ngx_uint_t                 gzip_flag;
        !            17: } ngx_http_memcached_loc_conf_t;
        !            18: 
        !            19: 
        !            20: typedef struct {
        !            21:     size_t                     rest;
        !            22:     ngx_http_request_t        *request;
        !            23:     ngx_str_t                  key;
        !            24: } ngx_http_memcached_ctx_t;
        !            25: 
        !            26: 
        !            27: static ngx_int_t ngx_http_memcached_create_request(ngx_http_request_t *r);
        !            28: static ngx_int_t ngx_http_memcached_reinit_request(ngx_http_request_t *r);
        !            29: static ngx_int_t ngx_http_memcached_process_header(ngx_http_request_t *r);
        !            30: static ngx_int_t ngx_http_memcached_filter_init(void *data);
        !            31: static ngx_int_t ngx_http_memcached_filter(void *data, ssize_t bytes);
        !            32: static void ngx_http_memcached_abort_request(ngx_http_request_t *r);
        !            33: static void ngx_http_memcached_finalize_request(ngx_http_request_t *r,
        !            34:     ngx_int_t rc);
        !            35: 
        !            36: static void *ngx_http_memcached_create_loc_conf(ngx_conf_t *cf);
        !            37: static char *ngx_http_memcached_merge_loc_conf(ngx_conf_t *cf,
        !            38:     void *parent, void *child);
        !            39: 
        !            40: static char *ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd,
        !            41:     void *conf);
        !            42: 
        !            43: 
        !            44: static ngx_conf_bitmask_t  ngx_http_memcached_next_upstream_masks[] = {
        !            45:     { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
        !            46:     { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
        !            47:     { ngx_string("invalid_response"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
        !            48:     { ngx_string("not_found"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
        !            49:     { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
        !            50:     { ngx_null_string, 0 }
        !            51: };
        !            52: 
        !            53: 
        !            54: static ngx_command_t  ngx_http_memcached_commands[] = {
        !            55: 
        !            56:     { ngx_string("memcached_pass"),
        !            57:       NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
        !            58:       ngx_http_memcached_pass,
        !            59:       NGX_HTTP_LOC_CONF_OFFSET,
        !            60:       0,
        !            61:       NULL },
        !            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: 
        !            70:     { ngx_string("memcached_connect_timeout"),
        !            71:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !            72:       ngx_conf_set_msec_slot,
        !            73:       NGX_HTTP_LOC_CONF_OFFSET,
        !            74:       offsetof(ngx_http_memcached_loc_conf_t, upstream.connect_timeout),
        !            75:       NULL },
        !            76: 
        !            77:     { ngx_string("memcached_send_timeout"),
        !            78:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !            79:       ngx_conf_set_msec_slot,
        !            80:       NGX_HTTP_LOC_CONF_OFFSET,
        !            81:       offsetof(ngx_http_memcached_loc_conf_t, upstream.send_timeout),
        !            82:       NULL },
        !            83: 
        !            84:     { ngx_string("memcached_buffer_size"),
        !            85:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !            86:       ngx_conf_set_size_slot,
        !            87:       NGX_HTTP_LOC_CONF_OFFSET,
        !            88:       offsetof(ngx_http_memcached_loc_conf_t, upstream.buffer_size),
        !            89:       NULL },
        !            90: 
        !            91:     { ngx_string("memcached_read_timeout"),
        !            92:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !            93:       ngx_conf_set_msec_slot,
        !            94:       NGX_HTTP_LOC_CONF_OFFSET,
        !            95:       offsetof(ngx_http_memcached_loc_conf_t, upstream.read_timeout),
        !            96:       NULL },
        !            97: 
        !            98:     { ngx_string("memcached_next_upstream"),
        !            99:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
        !           100:       ngx_conf_set_bitmask_slot,
        !           101:       NGX_HTTP_LOC_CONF_OFFSET,
        !           102:       offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream),
        !           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 },
        !           111: 
        !           112:       ngx_null_command
        !           113: };
        !           114: 
        !           115: 
        !           116: static ngx_http_module_t  ngx_http_memcached_module_ctx = {
        !           117:     NULL,                                  /* preconfiguration */
        !           118:     NULL,                                  /* postconfiguration */
        !           119: 
        !           120:     NULL,                                  /* create main configuration */
        !           121:     NULL,                                  /* init main configuration */
        !           122: 
        !           123:     NULL,                                  /* create server configuration */
        !           124:     NULL,                                  /* merge server configuration */
        !           125: 
        !           126:     ngx_http_memcached_create_loc_conf,    /* create location configuration */
        !           127:     ngx_http_memcached_merge_loc_conf      /* merge location configuration */
        !           128: };
        !           129: 
        !           130: 
        !           131: ngx_module_t  ngx_http_memcached_module = {
        !           132:     NGX_MODULE_V1,
        !           133:     &ngx_http_memcached_module_ctx,        /* module context */
        !           134:     ngx_http_memcached_commands,           /* module directives */
        !           135:     NGX_HTTP_MODULE,                       /* module type */
        !           136:     NULL,                                  /* init master */
        !           137:     NULL,                                  /* init module */
        !           138:     NULL,                                  /* init process */
        !           139:     NULL,                                  /* init thread */
        !           140:     NULL,                                  /* exit thread */
        !           141:     NULL,                                  /* exit process */
        !           142:     NULL,                                  /* exit master */
        !           143:     NGX_MODULE_V1_PADDING
        !           144: };
        !           145: 
        !           146: 
        !           147: static ngx_str_t  ngx_http_memcached_key = ngx_string("memcached_key");
        !           148: 
        !           149: 
        !           150: #define NGX_HTTP_MEMCACHED_END   (sizeof(ngx_http_memcached_end) - 1)
        !           151: static u_char  ngx_http_memcached_end[] = CRLF "END" CRLF;
        !           152: 
        !           153: 
        !           154: static ngx_int_t
        !           155: ngx_http_memcached_handler(ngx_http_request_t *r)
        !           156: {
        !           157:     ngx_int_t                       rc;
        !           158:     ngx_http_upstream_t            *u;
        !           159:     ngx_http_memcached_ctx_t       *ctx;
        !           160:     ngx_http_memcached_loc_conf_t  *mlcf;
        !           161: 
        !           162:     if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
        !           163:         return NGX_HTTP_NOT_ALLOWED;
        !           164:     }
        !           165: 
        !           166:     rc = ngx_http_discard_request_body(r);
        !           167: 
        !           168:     if (rc != NGX_OK) {
        !           169:         return rc;
        !           170:     }
        !           171: 
        !           172:     if (ngx_http_set_content_type(r) != NGX_OK) {
        !           173:         return NGX_HTTP_INTERNAL_SERVER_ERROR;
        !           174:     }
        !           175: 
        !           176:     if (ngx_http_upstream_create(r) != NGX_OK) {
        !           177:         return NGX_HTTP_INTERNAL_SERVER_ERROR;
        !           178:     }
        !           179: 
        !           180:     u = r->upstream;
        !           181: 
        !           182:     ngx_str_set(&u->schema, "memcached://");
        !           183:     u->output.tag = (ngx_buf_tag_t) &ngx_http_memcached_module;
        !           184: 
        !           185:     mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module);
        !           186: 
        !           187:     u->conf = &mlcf->upstream;
        !           188: 
        !           189:     u->create_request = ngx_http_memcached_create_request;
        !           190:     u->reinit_request = ngx_http_memcached_reinit_request;
        !           191:     u->process_header = ngx_http_memcached_process_header;
        !           192:     u->abort_request = ngx_http_memcached_abort_request;
        !           193:     u->finalize_request = ngx_http_memcached_finalize_request;
        !           194: 
        !           195:     ctx = ngx_palloc(r->pool, sizeof(ngx_http_memcached_ctx_t));
        !           196:     if (ctx == NULL) {
        !           197:         return NGX_HTTP_INTERNAL_SERVER_ERROR;
        !           198:     }
        !           199: 
        !           200:     ctx->rest = NGX_HTTP_MEMCACHED_END;
        !           201:     ctx->request = r;
        !           202: 
        !           203:     ngx_http_set_ctx(r, ctx, ngx_http_memcached_module);
        !           204: 
        !           205:     u->input_filter_init = ngx_http_memcached_filter_init;
        !           206:     u->input_filter = ngx_http_memcached_filter;
        !           207:     u->input_filter_ctx = ctx;
        !           208: 
        !           209:     r->main->count++;
        !           210: 
        !           211:     ngx_http_upstream_init(r);
        !           212: 
        !           213:     return NGX_DONE;
        !           214: }
        !           215: 
        !           216: 
        !           217: static ngx_int_t
        !           218: ngx_http_memcached_create_request(ngx_http_request_t *r)
        !           219: {
        !           220:     size_t                          len;
        !           221:     uintptr_t                       escape;
        !           222:     ngx_buf_t                      *b;
        !           223:     ngx_chain_t                    *cl;
        !           224:     ngx_http_memcached_ctx_t       *ctx;
        !           225:     ngx_http_variable_value_t      *vv;
        !           226:     ngx_http_memcached_loc_conf_t  *mlcf;
        !           227: 
        !           228:     mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module);
        !           229: 
        !           230:     vv = ngx_http_get_indexed_variable(r, mlcf->index);
        !           231: 
        !           232:     if (vv == NULL || vv->not_found || vv->len == 0) {
        !           233:         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        !           234:                       "the \"$memcached_key\" variable is not set");
        !           235:         return NGX_ERROR;
        !           236:     }
        !           237: 
        !           238:     escape = 2 * ngx_escape_uri(NULL, vv->data, vv->len, NGX_ESCAPE_MEMCACHED);
        !           239: 
        !           240:     len = sizeof("get ") - 1 + vv->len + escape + sizeof(CRLF) - 1;
        !           241: 
        !           242:     b = ngx_create_temp_buf(r->pool, len);
        !           243:     if (b == NULL) {
        !           244:         return NGX_ERROR;
        !           245:     }
        !           246: 
        !           247:     cl = ngx_alloc_chain_link(r->pool);
        !           248:     if (cl == NULL) {
        !           249:         return NGX_ERROR;
        !           250:     }
        !           251: 
        !           252:     cl->buf = b;
        !           253:     cl->next = NULL;
        !           254: 
        !           255:     r->upstream->request_bufs = cl;
        !           256: 
        !           257:     *b->last++ = 'g'; *b->last++ = 'e'; *b->last++ = 't'; *b->last++ = ' ';
        !           258: 
        !           259:     ctx = ngx_http_get_module_ctx(r, ngx_http_memcached_module);
        !           260: 
        !           261:     ctx->key.data = b->last;
        !           262: 
        !           263:     if (escape == 0) {
        !           264:         b->last = ngx_copy(b->last, vv->data, vv->len);
        !           265: 
        !           266:     } else {
        !           267:         b->last = (u_char *) ngx_escape_uri(b->last, vv->data, vv->len,
        !           268:                                             NGX_ESCAPE_MEMCACHED);
        !           269:     }
        !           270: 
        !           271:     ctx->key.len = b->last - ctx->key.data;
        !           272: 
        !           273:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !           274:                    "http memcached request: \"%V\"", &ctx->key);
        !           275: 
        !           276:     *b->last++ = CR; *b->last++ = LF;
        !           277: 
        !           278:     return NGX_OK;
        !           279: }
        !           280: 
        !           281: 
        !           282: static ngx_int_t
        !           283: ngx_http_memcached_reinit_request(ngx_http_request_t *r)
        !           284: {
        !           285:     return NGX_OK;
        !           286: }
        !           287: 
        !           288: 
        !           289: static ngx_int_t
        !           290: ngx_http_memcached_process_header(ngx_http_request_t *r)
        !           291: {
        !           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;
        !           299: 
        !           300:     u = r->upstream;
        !           301: 
        !           302:     for (p = u->buffer.pos; p < u->buffer.last; p++) {
        !           303:         if (*p == LF) {
        !           304:             goto found;
        !           305:         }
        !           306:     }
        !           307: 
        !           308:     return NGX_AGAIN;
        !           309: 
        !           310: found:
        !           311: 
        !           312:     *p = '\0';
        !           313: 
        !           314:     line.len = p - u->buffer.pos - 1;
        !           315:     line.data = u->buffer.pos;
        !           316: 
        !           317:     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !           318:                    "memcached: \"%V\"", &line);
        !           319: 
        !           320:     p = u->buffer.pos;
        !           321: 
        !           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);
        !           324: 
        !           325:     if (ngx_strncmp(p, "VALUE ", sizeof("VALUE ") - 1) == 0) {
        !           326: 
        !           327:         p += sizeof("VALUE ") - 1;
        !           328: 
        !           329:         if (ngx_strncmp(p, ctx->key.data, ctx->key.len) != 0) {
        !           330:             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        !           331:                           "memcached sent invalid key in response \"%V\" "
        !           332:                           "for key \"%V\"",
        !           333:                           &line, &ctx->key);
        !           334: 
        !           335:             return NGX_HTTP_UPSTREAM_INVALID_HEADER;
        !           336:         }
        !           337: 
        !           338:         p += ctx->key.len;
        !           339: 
        !           340:         if (*p++ != ' ') {
        !           341:             goto no_valid;
        !           342:         }
        !           343: 
        !           344:         /* flags */
        !           345: 
        !           346:         start = p;
        !           347: 
        !           348:         while (*p) {
        !           349:             if (*p++ == ' ') {
        !           350:                 if (mlcf->gzip_flag) {
        !           351:                     goto flags;
        !           352:                 } else {
        !           353:                     goto length;
        !           354:                 }
        !           355:             }
        !           356:         }
        !           357: 
        !           358:         goto no_valid;
        !           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: 
        !           387:     length:
        !           388: 
        !           389:         start = p;
        !           390: 
        !           391:         while (*p && *p++ != CR) { /* void */ }
        !           392: 
        !           393:         u->headers_in.content_length_n = ngx_atoof(start, p - start - 1);
        !           394:         if (u->headers_in.content_length_n == -1) {
        !           395:             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        !           396:                           "memcached sent invalid length in response \"%V\" "
        !           397:                           "for key \"%V\"",
        !           398:                           &line, &ctx->key);
        !           399:             return NGX_HTTP_UPSTREAM_INVALID_HEADER;
        !           400:         }
        !           401: 
        !           402:         u->headers_in.status_n = 200;
        !           403:         u->state->status = 200;
        !           404:         u->buffer.pos = p + 1;
        !           405: 
        !           406:         return NGX_OK;
        !           407:     }
        !           408: 
        !           409:     if (ngx_strcmp(p, "END\x0d") == 0) {
        !           410:         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
        !           411:                       "key: \"%V\" was not found by memcached", &ctx->key);
        !           412: 
        !           413:         u->headers_in.status_n = 404;
        !           414:         u->state->status = 404;
        !           415:         u->keepalive = 1;
        !           416: 
        !           417:         return NGX_OK;
        !           418:     }
        !           419: 
        !           420: no_valid:
        !           421: 
        !           422:     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        !           423:                   "memcached sent invalid response: \"%V\"", &line);
        !           424: 
        !           425:     return NGX_HTTP_UPSTREAM_INVALID_HEADER;
        !           426: }
        !           427: 
        !           428: 
        !           429: static ngx_int_t
        !           430: ngx_http_memcached_filter_init(void *data)
        !           431: {
        !           432:     ngx_http_memcached_ctx_t  *ctx = data;
        !           433: 
        !           434:     ngx_http_upstream_t  *u;
        !           435: 
        !           436:     u = ctx->request->upstream;
        !           437: 
        !           438:     u->length += NGX_HTTP_MEMCACHED_END;
        !           439: 
        !           440:     return NGX_OK;
        !           441: }
        !           442: 
        !           443: 
        !           444: static ngx_int_t
        !           445: ngx_http_memcached_filter(void *data, ssize_t bytes)
        !           446: {
        !           447:     ngx_http_memcached_ctx_t  *ctx = data;
        !           448: 
        !           449:     u_char               *last;
        !           450:     ngx_buf_t            *b;
        !           451:     ngx_chain_t          *cl, **ll;
        !           452:     ngx_http_upstream_t  *u;
        !           453: 
        !           454:     u = ctx->request->upstream;
        !           455:     b = &u->buffer;
        !           456: 
        !           457:     if (u->length == (ssize_t) ctx->rest) {
        !           458: 
        !           459:         if (ngx_strncmp(b->last,
        !           460:                    ngx_http_memcached_end + NGX_HTTP_MEMCACHED_END - ctx->rest,
        !           461:                    bytes)
        !           462:             != 0)
        !           463:         {
        !           464:             ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
        !           465:                           "memcached sent invalid trailer");
        !           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:         }
        !           479: 
        !           480:         return NGX_OK;
        !           481:     }
        !           482: 
        !           483:     for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
        !           484:         ll = &cl->next;
        !           485:     }
        !           486: 
        !           487:     cl = ngx_chain_get_free_buf(ctx->request->pool, &u->free_bufs);
        !           488:     if (cl == NULL) {
        !           489:         return NGX_ERROR;
        !           490:     }
        !           491: 
        !           492:     cl->buf->flush = 1;
        !           493:     cl->buf->memory = 1;
        !           494: 
        !           495:     *ll = cl;
        !           496: 
        !           497:     last = b->last;
        !           498:     cl->buf->pos = last;
        !           499:     b->last += bytes;
        !           500:     cl->buf->last = b->last;
        !           501:     cl->buf->tag = u->output.tag;
        !           502: 
        !           503:     ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
        !           504:                    "memcached filter bytes:%z size:%z length:%z rest:%z",
        !           505:                    bytes, b->last - b->pos, u->length, ctx->rest);
        !           506: 
        !           507:     if (bytes <= (ssize_t) (u->length - NGX_HTTP_MEMCACHED_END)) {
        !           508:         u->length -= bytes;
        !           509:         return NGX_OK;
        !           510:     }
        !           511: 
        !           512:     last += u->length - NGX_HTTP_MEMCACHED_END;
        !           513: 
        !           514:     if (ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0) {
        !           515:         ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
        !           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;
        !           524:     }
        !           525: 
        !           526:     ctx->rest -= b->last - last;
        !           527:     b->last = last;
        !           528:     cl->buf->last = last;
        !           529:     u->length = ctx->rest;
        !           530: 
        !           531:     if (u->length == 0) {
        !           532:         u->keepalive = 1;
        !           533:     }
        !           534: 
        !           535:     return NGX_OK;
        !           536: }
        !           537: 
        !           538: 
        !           539: static void
        !           540: ngx_http_memcached_abort_request(ngx_http_request_t *r)
        !           541: {
        !           542:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !           543:                    "abort http memcached request");
        !           544:     return;
        !           545: }
        !           546: 
        !           547: 
        !           548: static void
        !           549: ngx_http_memcached_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
        !           550: {
        !           551:     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
        !           552:                    "finalize http memcached request");
        !           553:     return;
        !           554: }
        !           555: 
        !           556: 
        !           557: static void *
        !           558: ngx_http_memcached_create_loc_conf(ngx_conf_t *cf)
        !           559: {
        !           560:     ngx_http_memcached_loc_conf_t  *conf;
        !           561: 
        !           562:     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_memcached_loc_conf_t));
        !           563:     if (conf == NULL) {
        !           564:         return NULL;
        !           565:     }
        !           566: 
        !           567:     /*
        !           568:      * set by ngx_pcalloc():
        !           569:      *
        !           570:      *     conf->upstream.bufs.num = 0;
        !           571:      *     conf->upstream.next_upstream = 0;
        !           572:      *     conf->upstream.temp_path = NULL;
        !           573:      *     conf->upstream.uri = { 0, NULL };
        !           574:      *     conf->upstream.location = NULL;
        !           575:      */
        !           576: 
        !           577:     conf->upstream.local = NGX_CONF_UNSET_PTR;
        !           578:     conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
        !           579:     conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
        !           580:     conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
        !           581: 
        !           582:     conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
        !           583: 
        !           584:     /* the hardcoded values */
        !           585:     conf->upstream.cyclic_temp_file = 0;
        !           586:     conf->upstream.buffering = 0;
        !           587:     conf->upstream.ignore_client_abort = 0;
        !           588:     conf->upstream.send_lowat = 0;
        !           589:     conf->upstream.bufs.num = 0;
        !           590:     conf->upstream.busy_buffers_size = 0;
        !           591:     conf->upstream.max_temp_file_size = 0;
        !           592:     conf->upstream.temp_file_write_size = 0;
        !           593:     conf->upstream.intercept_errors = 1;
        !           594:     conf->upstream.intercept_404 = 1;
        !           595:     conf->upstream.pass_request_headers = 0;
        !           596:     conf->upstream.pass_request_body = 0;
        !           597: 
        !           598:     conf->index = NGX_CONF_UNSET;
        !           599:     conf->gzip_flag = NGX_CONF_UNSET_UINT;
        !           600: 
        !           601:     return conf;
        !           602: }
        !           603: 
        !           604: 
        !           605: static char *
        !           606: ngx_http_memcached_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
        !           607: {
        !           608:     ngx_http_memcached_loc_conf_t *prev = parent;
        !           609:     ngx_http_memcached_loc_conf_t *conf = child;
        !           610: 
        !           611:     ngx_conf_merge_ptr_value(conf->upstream.local,
        !           612:                               prev->upstream.local, NULL);
        !           613: 
        !           614:     ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
        !           615:                               prev->upstream.connect_timeout, 60000);
        !           616: 
        !           617:     ngx_conf_merge_msec_value(conf->upstream.send_timeout,
        !           618:                               prev->upstream.send_timeout, 60000);
        !           619: 
        !           620:     ngx_conf_merge_msec_value(conf->upstream.read_timeout,
        !           621:                               prev->upstream.read_timeout, 60000);
        !           622: 
        !           623:     ngx_conf_merge_size_value(conf->upstream.buffer_size,
        !           624:                               prev->upstream.buffer_size,
        !           625:                               (size_t) ngx_pagesize);
        !           626: 
        !           627:     ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
        !           628:                               prev->upstream.next_upstream,
        !           629:                               (NGX_CONF_BITMASK_SET
        !           630:                                |NGX_HTTP_UPSTREAM_FT_ERROR
        !           631:                                |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
        !           632: 
        !           633:     if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
        !           634:         conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
        !           635:                                        |NGX_HTTP_UPSTREAM_FT_OFF;
        !           636:     }
        !           637: 
        !           638:     if (conf->upstream.upstream == NULL) {
        !           639:         conf->upstream.upstream = prev->upstream.upstream;
        !           640:     }
        !           641: 
        !           642:     if (conf->index == NGX_CONF_UNSET) {
        !           643:         conf->index = prev->index;
        !           644:     }
        !           645: 
        !           646:     ngx_conf_merge_uint_value(conf->gzip_flag, prev->gzip_flag, 0);
        !           647: 
        !           648:     return NGX_CONF_OK;
        !           649: }
        !           650: 
        !           651: 
        !           652: static char *
        !           653: ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
        !           654: {
        !           655:     ngx_http_memcached_loc_conf_t *mlcf = conf;
        !           656: 
        !           657:     ngx_str_t                 *value;
        !           658:     ngx_url_t                  u;
        !           659:     ngx_http_core_loc_conf_t  *clcf;
        !           660: 
        !           661:     if (mlcf->upstream.upstream) {
        !           662:         return "is duplicate";
        !           663:     }
        !           664: 
        !           665:     value = cf->args->elts;
        !           666: 
        !           667:     ngx_memzero(&u, sizeof(ngx_url_t));
        !           668: 
        !           669:     u.url = value[1];
        !           670:     u.no_resolve = 1;
        !           671: 
        !           672:     mlcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
        !           673:     if (mlcf->upstream.upstream == NULL) {
        !           674:         return NGX_CONF_ERROR;
        !           675:     }
        !           676: 
        !           677:     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
        !           678: 
        !           679:     clcf->handler = ngx_http_memcached_handler;
        !           680: 
        !           681:     if (clcf->name.data[clcf->name.len - 1] == '/') {
        !           682:         clcf->auto_redirect = 1;
        !           683:     }
        !           684: 
        !           685:     mlcf->index = ngx_http_get_variable_index(cf, &ngx_http_memcached_key);
        !           686: 
        !           687:     if (mlcf->index == NGX_ERROR) {
        !           688:         return NGX_CONF_ERROR;
        !           689:     }
        !           690: 
        !           691:     return NGX_CONF_OK;
        !           692: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>