1 /*
2 * Copyright (c) 2010, FRiCKLE Piotr Sikora <info@frickle.com>
3 * Copyright (c) 2009-2010, Xiaozhe Wang <chaoslawful@gmail.com>
4 * Copyright (c) 2009-2010, Yichun Zhang <agentzh@gmail.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #ifndef DDEBUG
30 #define DDEBUG 0
31 #endif
32
33 #include "ngx_postgres_ddebug.h"
34 #include "ngx_postgres_escape.h"
35 #include "ngx_postgres_handler.h"
36 #include "ngx_postgres_keepalive.h"
37 #include "ngx_postgres_module.h"
38 #include "ngx_postgres_output.h"
39 #include "ngx_postgres_upstream.h"
40 #include "ngx_postgres_util.h"
41 #include "ngx_postgres_variable.h"
42 #include "ngx_postgres_rewrite.h"
43
44
45 #define NGX_CONF_TAKE34 (NGX_CONF_TAKE3|NGX_CONF_TAKE4)
46
47
48 static ngx_command_t ngx_postgres_module_commands[] = {
49
50 { ngx_string("postgres_server"),
51 NGX_HTTP_UPS_CONF|NGX_CONF_1MORE,
52 ngx_postgres_conf_server,
53 NGX_HTTP_SRV_CONF_OFFSET,
54 0,
55 NULL },
56
57 { ngx_string("postgres_keepalive"),
58 NGX_HTTP_UPS_CONF|NGX_CONF_1MORE,
59 ngx_postgres_conf_keepalive,
60 NGX_HTTP_SRV_CONF_OFFSET,
61 0,
62 NULL },
63
64 { ngx_string("postgres_pass"),
65 NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
66 ngx_postgres_conf_pass,
67 NGX_HTTP_LOC_CONF_OFFSET,
68 0,
69 NULL },
70
71 { ngx_string("postgres_query"),
72 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|
73 NGX_HTTP_LIF_CONF|NGX_CONF_1MORE,
74 ngx_postgres_conf_query,
75 NGX_HTTP_LOC_CONF_OFFSET,
76 0,
77 NULL },
78
79 { ngx_string("postgres_rewrite"),
80 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|
81 NGX_HTTP_LIF_CONF|NGX_CONF_2MORE,
82 ngx_postgres_conf_rewrite,
83 NGX_HTTP_LOC_CONF_OFFSET,
84 0,
85 NULL },
86
87 { ngx_string("postgres_output"),
88 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|
89 NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
90 ngx_postgres_conf_output,
91 NGX_HTTP_LOC_CONF_OFFSET,
92 0,
93 NULL },
94
95 { ngx_string("postgres_set"),
96 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE34,
97 ngx_postgres_conf_set,
98 NGX_HTTP_LOC_CONF_OFFSET,
99 0,
100 NULL },
101
102 { ngx_string("postgres_escape"),
103 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
104 ngx_postgres_conf_escape,
105 NGX_HTTP_LOC_CONF_OFFSET,
106 0,
107 NULL },
108
109 { ngx_string("postgres_connect_timeout"),
110 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
111 ngx_conf_set_msec_slot,
112 NGX_HTTP_LOC_CONF_OFFSET,
113 offsetof(ngx_postgres_loc_conf_t, upstream.connect_timeout),
114 NULL },
115
116 { ngx_string("postgres_result_timeout"),
117 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
118 ngx_conf_set_msec_slot,
119 NGX_HTTP_LOC_CONF_OFFSET,
120 offsetof(ngx_postgres_loc_conf_t, upstream.read_timeout),
121 NULL },
122
123 ngx_null_command
124 };
125
126 static ngx_http_variable_t ngx_postgres_module_variables[] = {
127
128 { ngx_string("postgres_columns"), NULL,
129 ngx_postgres_variable_columns, 0,
130 NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
131
132 { ngx_string("postgres_rows"), NULL,
133 ngx_postgres_variable_rows, 0,
134 NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
135
136 { ngx_string("postgres_affected"), NULL,
137 ngx_postgres_variable_affected, 0,
138 NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
139
140 { ngx_string("postgres_query"), NULL,
141 ngx_postgres_variable_query, 0,
142 NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
143
144 { ngx_null_string, NULL, NULL, 0, 0, 0 }
145 };
146
147 static ngx_http_module_t ngx_postgres_module_ctx = {
148 ngx_postgres_add_variables, /* preconfiguration */
149 NULL, /* postconfiguration */
150
151 NULL, /* create main configuration */
152 NULL, /* init main configuration */
153
154 ngx_postgres_create_upstream_srv_conf, /* create server configuration */
155 NULL, /* merge server configuration */
156
157 ngx_postgres_create_loc_conf, /* create location configuration */
158 ngx_postgres_merge_loc_conf /* merge location configuration */
159 };
160
161 ngx_module_t ngx_postgres_module = {
162 NGX_MODULE_V1,
163 &ngx_postgres_module_ctx, /* module context */
164 ngx_postgres_module_commands, /* module directives */
165 NGX_HTTP_MODULE, /* module type */
166 NULL, /* init master */
167 NULL, /* init module */
168 NULL, /* init process */
169 NULL, /* init thread */
170 NULL, /* exit thread */
171 NULL, /* exit process */
172 NULL, /* exit master */
173 NGX_MODULE_V1_PADDING
174 };
175
176 ngx_conf_bitmask_t ngx_postgres_http_methods[] = {
177 { ngx_string("GET"), NGX_HTTP_GET },
178 { ngx_string("HEAD"), NGX_HTTP_HEAD },
179 { ngx_string("POST"), NGX_HTTP_POST },
180 { ngx_string("PUT"), NGX_HTTP_PUT },
181 { ngx_string("DELETE"), NGX_HTTP_DELETE },
182 { ngx_string("MKCOL"), NGX_HTTP_MKCOL },
183 { ngx_string("COPY"), NGX_HTTP_COPY },
184 { ngx_string("MOVE"), NGX_HTTP_MOVE },
185 { ngx_string("OPTIONS"), NGX_HTTP_OPTIONS },
186 { ngx_string("PROPFIND"), NGX_HTTP_PROPFIND },
187 { ngx_string("PROPPATCH"), NGX_HTTP_PROPPATCH },
188 { ngx_string("LOCK"), NGX_HTTP_LOCK },
189 { ngx_string("UNLOCK"), NGX_HTTP_UNLOCK },
190 #if defined(nginx_version) && (nginx_version >= 8041)
191 { ngx_string("PATCH"), NGX_HTTP_PATCH },
192 #endif
193 { ngx_null_string, 0 }
194 };
195
196 ngx_conf_enum_t ngx_postgres_upstream_mode_options[] = {
197 { ngx_string("multi"), 0 },
198 { ngx_string("single"), 1 },
199 { ngx_null_string, 0 }
200 };
201
202 ngx_conf_enum_t ngx_postgres_upstream_overflow_options[] = {
203 { ngx_string("ignore"), 0 },
204 { ngx_string("reject"), 1 },
205 { ngx_null_string, 0 }
206 };
207
208 ngx_conf_enum_t ngx_postgres_requirement_options[] = {
209 { ngx_string("optional"), 0 },
210 { ngx_string("required"), 1 },
211 { ngx_null_string, 0 }
212 };
213
214 ngx_postgres_rewrite_enum_t ngx_postgres_rewrite_handlers[] = {
215 { ngx_string("no_changes"), 0, ngx_postgres_rewrite_changes },
216 { ngx_string("changes"), 1, ngx_postgres_rewrite_changes },
217 { ngx_string("no_rows"), 2, ngx_postgres_rewrite_rows },
218 { ngx_string("rows"), 3, ngx_postgres_rewrite_rows },
219 { ngx_string("no_errors"), 4, ngx_postgres_rewrite_valid },
220 { ngx_string("errors"), 5, ngx_postgres_rewrite_valid },
221 { ngx_null_string, 0, NULL }
222 };
223
224 ngx_postgres_output_enum_t ngx_postgres_output_handlers[] = {
225 { ngx_string("none"), 0, NULL },
226 { ngx_string("rds"), 0, ngx_postgres_output_rds },
227 { ngx_string("text") , 0, ngx_postgres_output_text },
228 { ngx_string("value"), 0, ngx_postgres_output_value },
229 { ngx_string("binary_value"), 1, ngx_postgres_output_value },
230 { ngx_string("json"), 0, ngx_postgres_output_json },
231 { ngx_string("hex"), 0, ngx_postgres_output_hex },
232 { ngx_null_string, 0, NULL }
233 };
234
235
236 ngx_int_t
ngx_postgres_add_variables(ngx_conf_t * cf)237 ngx_postgres_add_variables(ngx_conf_t *cf)
238 {
239 ngx_http_variable_t *var, *v;
240
241 dd("entering");
242
243 for (v = ngx_postgres_module_variables; v->name.len; v++) {
244 var = ngx_http_add_variable(cf, &v->name, v->flags);
245 if (var == NULL) {
246 dd("returning NGX_ERROR");
247 return NGX_ERROR;
248 }
249
250 var->get_handler = v->get_handler;
251 var->data = v->data;
252 }
253
254 dd("returning NGX_OK");
255 return NGX_OK;
256 }
257
258 void *
ngx_postgres_create_upstream_srv_conf(ngx_conf_t * cf)259 ngx_postgres_create_upstream_srv_conf(ngx_conf_t *cf)
260 {
261 ngx_postgres_upstream_srv_conf_t *conf;
262 ngx_pool_cleanup_t *cln;
263
264 dd("entering");
265
266 conf = ngx_pcalloc(cf->pool, sizeof(ngx_postgres_upstream_srv_conf_t));
267 if (conf == NULL) {
268 dd("returning NULL");
269 return NULL;
270 }
271
272 /*
273 * set by ngx_pcalloc():
274 *
275 * conf->peers = NULL
276 * conf->current = 0
277 * conf->servers = NULL
278 * conf->free = { NULL, NULL }
279 * conf->cache = { NULL, NULL }
280 * conf->active_conns = 0
281 * conf->reject = 0
282 */
283
284 conf->pool = cf->pool;
285
286 /* enable keepalive (single) by default */
287 conf->max_cached = 10;
288 conf->single = 1;
289
290 cln = ngx_pool_cleanup_add(cf->pool, 0);
291 cln->handler = ngx_postgres_keepalive_cleanup;
292 cln->data = conf;
293
294 dd("returning");
295 return conf;
296 }
297
298 void *
ngx_postgres_create_loc_conf(ngx_conf_t * cf)299 ngx_postgres_create_loc_conf(ngx_conf_t *cf)
300 {
301 ngx_postgres_loc_conf_t *conf;
302
303 dd("entering");
304
305 conf = ngx_pcalloc(cf->pool, sizeof(ngx_postgres_loc_conf_t));
306 if (conf == NULL) {
307 dd("returning NULL");
308 return NULL;
309 }
310
311 /*
312 * set by ngx_pcalloc():
313 *
314 * conf->upstream.* = 0 / NULL
315 * conf->upstream_cv = NULL
316 * conf->query.methods_set = 0
317 * conf->query.methods = NULL
318 * conf->query.def = NULL
319 * conf->output_binary = 0
320 */
321
322 conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
323 conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
324
325 conf->rewrites = NGX_CONF_UNSET_PTR;
326 conf->output_handler = NGX_CONF_UNSET_PTR;
327 conf->variables = NGX_CONF_UNSET_PTR;
328
329 /* the hardcoded values */
330 conf->upstream.cyclic_temp_file = 0;
331 conf->upstream.buffering = 1;
332 conf->upstream.ignore_client_abort = 1;
333 conf->upstream.send_lowat = 0;
334 conf->upstream.bufs.num = 0;
335 conf->upstream.busy_buffers_size = 0;
336 conf->upstream.max_temp_file_size = 0;
337 conf->upstream.temp_file_write_size = 0;
338 conf->upstream.intercept_errors = 1;
339 conf->upstream.intercept_404 = 1;
340 conf->upstream.pass_request_headers = 0;
341 conf->upstream.pass_request_body = 0;
342
343 dd("returning");
344 return conf;
345 }
346
347 char *
ngx_postgres_merge_loc_conf(ngx_conf_t * cf,void * parent,void * child)348 ngx_postgres_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
349 {
350 ngx_postgres_loc_conf_t *prev = parent;
351 ngx_postgres_loc_conf_t *conf = child;
352
353 dd("entering");
354
355 ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
356 prev->upstream.connect_timeout, 10000);
357
358 ngx_conf_merge_msec_value(conf->upstream.read_timeout,
359 prev->upstream.read_timeout, 30000);
360
361 if ((conf->upstream.upstream == NULL) && (conf->upstream_cv == NULL)) {
362 conf->upstream.upstream = prev->upstream.upstream;
363 conf->upstream_cv = prev->upstream_cv;
364 }
365
366 if ((conf->query.def == NULL) && (conf->query.methods == NULL)) {
367 conf->query.methods_set = prev->query.methods_set;
368 conf->query.methods = prev->query.methods;
369 conf->query.def = prev->query.def;
370 }
371
372 ngx_conf_merge_ptr_value(conf->rewrites, prev->rewrites, NULL);
373
374 if (conf->output_handler == NGX_CONF_UNSET_PTR) {
375 if (prev->output_handler == NGX_CONF_UNSET_PTR) {
376 /* default */
377 conf->output_handler = ngx_postgres_output_rds;
378 conf->output_binary = 0;
379 } else {
380 /* merge */
381 conf->output_handler = prev->output_handler;
382 conf->output_binary = prev->output_binary;
383 }
384 }
385
386 ngx_conf_merge_ptr_value(conf->variables, prev->variables, NULL);
387
388 dd("returning NGX_CONF_OK");
389 return NGX_CONF_OK;
390 }
391
392 /*
393 * Based on: ngx_http_upstream.c/ngx_http_upstream_server
394 * Copyright (C) Igor Sysoev
395 */
396 char *
ngx_postgres_conf_server(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)397 ngx_postgres_conf_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
398 {
399 ngx_str_t *value = cf->args->elts;
400 ngx_postgres_upstream_srv_conf_t *pgscf = conf;
401 ngx_postgres_upstream_server_t *pgs;
402 ngx_http_upstream_srv_conf_t *uscf;
403 ngx_url_t u;
404 ngx_uint_t i;
405
406 dd("entering");
407
408 uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
409
410 if (pgscf->servers == NULL) {
411 pgscf->servers = ngx_array_create(cf->pool, 4,
412 sizeof(ngx_postgres_upstream_server_t));
413 if (pgscf->servers == NULL) {
414 dd("returning NGX_CONF_ERROR");
415 return NGX_CONF_ERROR;
416 }
417
418 uscf->servers = pgscf->servers;
419 }
420
421 pgs = ngx_array_push(pgscf->servers);
422 if (pgs == NULL) {
423 dd("returning NGX_CONF_ERROR");
424 return NGX_CONF_ERROR;
425 }
426
427 ngx_memzero(pgs, sizeof(ngx_postgres_upstream_server_t));
428
429 /* parse the first name:port argument */
430
431 ngx_memzero(&u, sizeof(ngx_url_t));
432
433 u.url = value[1];
434 u.default_port = 5432; /* PostgreSQL default */
435
436 if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
437 if (u.err) {
438 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
439 "postgres: %s in upstream \"%V\"",
440 u.err, &u.url);
441 }
442
443 dd("returning NGX_CONF_ERROR");
444 return NGX_CONF_ERROR;
445 }
446
447 pgs->addrs = u.addrs;
448 pgs->naddrs = u.naddrs;
449 pgs->port = u.family == AF_UNIX ? u.default_port : u.port;
450 pgs->family = u.family;
451
452 /* parse various options */
453 for (i = 2; i < cf->args->nelts; i++) {
454
455 if (ngx_strncmp(value[i].data, "port=", sizeof("port=") - 1)
456 == 0)
457 {
458 pgs->port = (in_port_t) ngx_atoi(&value[i].data[sizeof("port=") - 1], value[i].len - (sizeof("port=") - 1));
459 continue;
460 }
461
462 if (ngx_strncmp(value[i].data, "dbname=", sizeof("dbname=") - 1)
463 == 0)
464 {
465 pgs->dbname.len = value[i].len - (sizeof("dbname=") - 1);
466 pgs->dbname.data = &value[i].data[sizeof("dbname=") - 1];
467 continue;
468 }
469
470 if (ngx_strncmp(value[i].data, "user=", sizeof("user=") - 1)
471 == 0)
472 {
473 pgs->user.len = value[i].len - (sizeof("user=") - 1);
474 pgs->user.data = &value[i].data[sizeof("user=") - 1];
475 continue;
476 }
477
478 if (ngx_strncmp(value[i].data, "password=", sizeof("password=") - 1)
479 == 0)
480 {
481 pgs->password.len = value[i].len - (sizeof("password=") - 1);
482 pgs->password.data = &value[i].data[sizeof("password=") - 1];
483 continue;
484 }
485
486 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
487 "postgres: invalid parameter \"%V\" in"
488 " \"postgres_server\"", &value[i]);
489
490 dd("returning NGX_CONF_ERROR");
491 return NGX_CONF_ERROR;
492 }
493
494 uscf->peer.init_upstream = ngx_postgres_upstream_init;
495
496 dd("returning NGX_CONF_OK");
497 return NGX_CONF_OK;
498 }
499
500 char *
ngx_postgres_conf_keepalive(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)501 ngx_postgres_conf_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
502 {
503 ngx_str_t *value = cf->args->elts;
504 ngx_postgres_upstream_srv_conf_t *pgscf = conf;
505 ngx_conf_enum_t *e;
506 ngx_uint_t i, j;
507 ngx_int_t n;
508
509 dd("entering");
510
511 if (pgscf->max_cached != 10 /* default */) {
512 dd("returning");
513 return "is duplicate";
514 }
515
516 if ((cf->args->nelts == 2) && (ngx_strcmp(value[1].data, "off") == 0)) {
517 pgscf->max_cached = 0;
518
519 dd("returning NGX_CONF_OK");
520 return NGX_CONF_OK;
521 }
522
523 for (i = 1; i < cf->args->nelts; i++) {
524
525 if (ngx_strncmp(value[i].data, "max=", sizeof("max=") - 1)
526 == 0)
527 {
528 value[i].len = value[i].len - (sizeof("max=") - 1);
529 value[i].data = &value[i].data[sizeof("max=") - 1];
530
531 n = ngx_atoi(value[i].data, value[i].len);
532 if (n == NGX_ERROR) {
533 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
534 "postgres: invalid \"max\" value \"%V\""
535 " in \"%V\" directive",
536 &value[i], &cmd->name);
537
538 dd("returning NGX_CONF_ERROR");
539 return NGX_CONF_ERROR;
540 }
541
542 pgscf->max_cached = (ngx_uint_t) n;
543
544 continue;
545 }
546
547 if (ngx_strncmp(value[i].data, "mode=", sizeof("mode=") - 1)
548 == 0)
549 {
550 value[i].len = value[i].len - (sizeof("mode=") - 1);
551 value[i].data = &value[i].data[sizeof("mode=") - 1];
552
553 e = ngx_postgres_upstream_mode_options;
554 for (j = 0; e[j].name.len; j++) {
555 if ((e[j].name.len == value[i].len)
556 && (ngx_strcasecmp(e[j].name.data, value[i].data) == 0))
557 {
558 pgscf->single = e[j].value;
559 break;
560 }
561 }
562
563 if (e[j].name.len == 0) {
564 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
565 "postgres: invalid \"mode\" value \"%V\""
566 " in \"%V\" directive",
567 &value[i], &cmd->name);
568
569 dd("returning NGX_CONF_ERROR");
570 return NGX_CONF_ERROR;
571 }
572
573 continue;
574 }
575
576 if (ngx_strncmp(value[i].data, "overflow=", sizeof("overflow=") - 1)
577 == 0)
578 {
579 value[i].len = value[i].len - (sizeof("overflow=") - 1);
580 value[i].data = &value[i].data[sizeof("overflow=") - 1];
581
582 e = ngx_postgres_upstream_overflow_options;
583 for (j = 0; e[j].name.len; j++) {
584 if ((e[j].name.len == value[i].len)
585 && (ngx_strcasecmp(e[j].name.data, value[i].data) == 0))
586 {
587 pgscf->reject = e[j].value;
588 break;
589 }
590 }
591
592 if (e[j].name.len == 0) {
593 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
594 "postgres: invalid \"overflow\" value \"%V\""
595 " in \"%V\" directive",
596 &value[i], &cmd->name);
597
598 dd("returning NGX_CONF_ERROR");
599 return NGX_CONF_ERROR;
600 }
601
602 continue;
603 }
604
605 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
606 "postgres: invalid parameter \"%V\" in"
607 " \"%V\" directive",
608 &value[i], &cmd->name);
609
610 dd("returning NGX_CONF_ERROR");
611 return NGX_CONF_ERROR;
612 }
613
614 dd("returning NGX_CONF_OK");
615 return NGX_CONF_OK;
616 }
617
618 char *
ngx_postgres_conf_pass(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)619 ngx_postgres_conf_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
620 {
621 ngx_str_t *value = cf->args->elts;
622 ngx_postgres_loc_conf_t *pglcf = conf;
623 ngx_http_core_loc_conf_t *clcf;
624 ngx_http_compile_complex_value_t ccv;
625 ngx_url_t url;
626
627 dd("entering");
628
629 if ((pglcf->upstream.upstream != NULL) || (pglcf->upstream_cv != NULL)) {
630 dd("returning");
631 return "is duplicate";
632 }
633
634 if (value[1].len == 0) {
635 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
636 "postgres: empty upstream in \"%V\" directive",
637 &cmd->name);
638
639 dd("returning NGX_CONF_ERROR");
640 return NGX_CONF_ERROR;
641 }
642
643 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
644
645 clcf->handler = ngx_postgres_handler;
646
647 if (clcf->name.data[clcf->name.len - 1] == '/') {
648 clcf->auto_redirect = 1;
649 }
650
651 if (ngx_http_script_variables_count(&value[1])) {
652 /* complex value */
653 dd("complex value");
654
655 pglcf->upstream_cv = ngx_palloc(cf->pool,
656 sizeof(ngx_http_complex_value_t));
657 if (pglcf->upstream_cv == NULL) {
658 dd("returning NGX_CONF_ERROR");
659 return NGX_CONF_ERROR;
660 }
661
662 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
663
664 ccv.cf = cf;
665 ccv.value = &value[1];
666 ccv.complex_value = pglcf->upstream_cv;
667
668 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
669 dd("returning NGX_CONF_ERROR");
670 return NGX_CONF_ERROR;
671 }
672
673 dd("returning NGX_CONF_OK");
674 return NGX_CONF_OK;
675 } else {
676 /* simple value */
677 dd("simple value");
678
679 ngx_memzero(&url, sizeof(ngx_url_t));
680
681 url.url = value[1];
682 url.no_resolve = 1;
683
684 pglcf->upstream.upstream = ngx_http_upstream_add(cf, &url, 0);
685 if (pglcf->upstream.upstream == NULL) {
686 dd("returning NGX_CONF_ERROR");
687 return NGX_CONF_ERROR;
688 }
689
690 dd("returning NGX_CONF_OK");
691 return NGX_CONF_OK;
692 }
693 }
694
695 char *
ngx_postgres_conf_query(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)696 ngx_postgres_conf_query(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
697 {
698 ngx_str_t *value = cf->args->elts;
699 ngx_str_t sql = value[cf->args->nelts - 1];
700 ngx_postgres_loc_conf_t *pglcf = conf;
701 ngx_http_compile_complex_value_t ccv;
702 ngx_postgres_mixed_t *query;
703 ngx_conf_bitmask_t *b;
704 ngx_uint_t methods, i, j;
705
706 dd("entering");
707
708 if (sql.len == 0) {
709 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
710 "postgres: empty query in \"%V\" directive",
711 &cmd->name);
712
713 dd("returning NGX_CONF_ERROR");
714 return NGX_CONF_ERROR;
715 }
716
717 if (cf->args->nelts == 2) {
718 /* default query */
719 dd("default query");
720
721 if (pglcf->query.def != NULL) {
722 dd("returning");
723 return "is duplicate";
724 }
725
726 pglcf->query.def = ngx_palloc(cf->pool, sizeof(ngx_postgres_mixed_t));
727 if (pglcf->query.def == NULL) {
728 dd("returning NGX_CONF_ERROR");
729 return NGX_CONF_ERROR;
730 }
731
732 methods = 0xFFFF;
733 query = pglcf->query.def;
734 } else {
735 /* method-specific query */
736 dd("method-specific query");
737
738 methods = 0;
739
740 for (i = 1; i < cf->args->nelts - 1; i++) {
741 b = ngx_postgres_http_methods;
742 for (j = 0; b[j].name.len; j++) {
743 if ((b[j].name.len == value[i].len)
744 && (ngx_strcasecmp(b[j].name.data, value[i].data) == 0))
745 {
746 if (pglcf->query.methods_set & b[j].mask) {
747 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
748 "postgres: method \"%V\" is"
749 " duplicate in \"%V\" directive",
750 &value[i], &cmd->name);
751
752 dd("returning NGX_CONF_ERROR");
753 return NGX_CONF_ERROR;
754 }
755
756 methods |= b[j].mask;
757 break;
758 }
759 }
760
761 if (b[j].name.len == 0) {
762 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
763 "postgres: invalid method \"%V\""
764 " in \"%V\" directive",
765 &value[i], &cmd->name);
766
767 dd("returning NGX_CONF_ERROR");
768 return NGX_CONF_ERROR;
769 }
770 }
771
772 if (pglcf->query.methods == NULL) {
773 pglcf->query.methods = ngx_array_create(cf->pool, 4,
774 sizeof(ngx_postgres_mixed_t));
775 if (pglcf->query.methods == NULL) {
776 dd("returning NGX_CONF_ERROR");
777 return NGX_CONF_ERROR;
778 }
779 }
780
781 query = ngx_array_push(pglcf->query.methods);
782 if (query == NULL) {
783 dd("returning NGX_CONF_ERROR");
784 return NGX_CONF_ERROR;
785 }
786
787 pglcf->query.methods_set |= methods;
788 }
789
790 if (ngx_http_script_variables_count(&sql)) {
791 /* complex value */
792 dd("complex value");
793
794 query->key = methods;
795
796 query->cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
797 if (query->cv == NULL) {
798 dd("returning NGX_CONF_ERROR");
799 return NGX_CONF_ERROR;
800 }
801
802 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
803
804 ccv.cf = cf;
805 ccv.value = &sql;
806 ccv.complex_value = query->cv;
807
808 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
809 dd("returning NGX_CONF_ERROR");
810 return NGX_CONF_ERROR;
811 }
812 } else {
813 /* simple value */
814 dd("simple value");
815
816 query->key = methods;
817 query->sv = sql;
818 query->cv = NULL;
819 }
820
821 dd("returning NGX_CONF_OK");
822 return NGX_CONF_OK;
823 }
824
825 char *
ngx_postgres_conf_rewrite(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)826 ngx_postgres_conf_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
827 {
828 ngx_str_t *value = cf->args->elts;
829 ngx_str_t what = value[cf->args->nelts - 2];
830 ngx_str_t to = value[cf->args->nelts - 1];
831 ngx_postgres_loc_conf_t *pglcf = conf;
832 ngx_postgres_rewrite_conf_t *pgrcf;
833 ngx_postgres_rewrite_t *rewrite;
834 ngx_postgres_rewrite_enum_t *e;
835 ngx_conf_bitmask_t *b;
836 ngx_uint_t methods, keep_body, i, j;
837
838 dd("entering");
839
840 e = ngx_postgres_rewrite_handlers;
841 for (i = 0; e[i].name.len; i++) {
842 if ((e[i].name.len == what.len)
843 && (ngx_strcasecmp(e[i].name.data, what.data) == 0))
844 {
845 break;
846 }
847 }
848
849 if (e[i].name.len == 0) {
850 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
851 "postgres: invalid condition \"%V\""
852 " in \"%V\" directive", &what, &cmd->name);
853
854 dd("returning NGX_CONF_ERROR");
855 return NGX_CONF_ERROR;
856 }
857
858 if (pglcf->rewrites == NGX_CONF_UNSET_PTR) {
859 pglcf->rewrites = ngx_array_create(cf->pool, 2,
860 sizeof(ngx_postgres_rewrite_conf_t));
861 if (pglcf->rewrites == NULL) {
862 dd("returning NGX_CONF_ERROR");
863 return NGX_CONF_ERROR;
864 }
865 } else {
866 pgrcf = pglcf->rewrites->elts;
867 for (j = 0; j < pglcf->rewrites->nelts; j++) {
868 if (pgrcf[j].key == e[i].key) {
869 pgrcf = &pgrcf[j];
870 goto found;
871 }
872 }
873 }
874
875 pgrcf = ngx_array_push(pglcf->rewrites);
876 if (pgrcf == NULL) {
877 dd("returning NGX_CONF_ERROR");
878 return NGX_CONF_ERROR;
879 }
880
881 ngx_memzero(pgrcf, sizeof(ngx_postgres_rewrite_conf_t));
882
883 pgrcf->key = e[i].key;
884 pgrcf->handler = e[i].handler;
885
886 found:
887
888 if (cf->args->nelts == 3) {
889 /* default rewrite */
890 dd("default rewrite");
891
892 if (pgrcf->def != NULL) {
893 dd("returning");
894 return "is duplicate";
895 }
896
897 pgrcf->def = ngx_palloc(cf->pool, sizeof(ngx_postgres_rewrite_t));
898 if (pgrcf->def == NULL) {
899 dd("returning NGX_CONF_ERROR");
900 return NGX_CONF_ERROR;
901 }
902
903 methods = 0xFFFF;
904 rewrite = pgrcf->def;
905 } else {
906 /* method-specific rewrite */
907 dd("method-specific rewrite");
908
909 methods = 0;
910
911 for (i = 1; i < cf->args->nelts - 2; i++) {
912 b = ngx_postgres_http_methods;
913 for (j = 0; b[j].name.len; j++) {
914 if ((b[j].name.len == value[i].len)
915 && (ngx_strcasecmp(b[j].name.data, value[i].data) == 0))
916 {
917 if (pgrcf->methods_set & b[j].mask) {
918 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
919 "postgres: method \"%V\" for"
920 " condition \"%V\" is duplicate"
921 " in \"%V\" directive",
922 &value[i], &what, &cmd->name);
923
924 dd("returning NGX_CONF_ERROR");
925 return NGX_CONF_ERROR;
926 }
927
928 methods |= b[j].mask;
929 break;
930 }
931 }
932
933 if (b[j].name.len == 0) {
934 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
935 "postgres: invalid method \"%V\" for"
936 " condition \"%V\" in \"%V\" directive",
937 &value[i], &what, &cmd->name);
938
939 dd("returning NGX_CONF_ERROR");
940 return NGX_CONF_ERROR;
941 }
942 }
943
944 if (pgrcf->methods == NULL) {
945 pgrcf->methods = ngx_array_create(cf->pool, 4,
946 sizeof(ngx_postgres_rewrite_t));
947 if (pgrcf->methods == NULL) {
948 dd("returning NGX_CONF_ERROR");
949 return NGX_CONF_ERROR;
950 }
951 }
952
953 rewrite = ngx_array_push(pgrcf->methods);
954 if (rewrite == NULL) {
955 dd("returning NGX_CONF_ERROR");
956 return NGX_CONF_ERROR;
957 }
958
959 pgrcf->methods_set |= methods;
960 }
961
962 if (to.data[0] == '=') {
963 keep_body = 1;
964 to.len--;
965 to.data++;
966 } else {
967 keep_body = 0;
968 }
969
970 rewrite->key = methods;
971 rewrite->status = ngx_atoi(to.data, to.len);
972 if ((rewrite->status == NGX_ERROR)
973 || (rewrite->status < NGX_HTTP_OK)
974 || (rewrite->status > NGX_HTTP_INSUFFICIENT_STORAGE)
975 || ((rewrite->status >= NGX_HTTP_SPECIAL_RESPONSE)
976 && (rewrite->status < NGX_HTTP_BAD_REQUEST)))
977 {
978 rewrite->location = to;
979 //dd("returning NGX_CONF_ERROR");
980
981 //return NGX_CONF_ERROR;
982 }
983
984 if (keep_body) {
985 rewrite->status = -rewrite->status;
986 }
987
988 dd("returning NGX_CONF_OK");
989 return NGX_CONF_OK;
990 }
991
992 char *
ngx_postgres_conf_output(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)993 ngx_postgres_conf_output(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
994 {
995 ngx_str_t *value = cf->args->elts;
996 ngx_postgres_loc_conf_t *pglcf = conf;
997 ngx_postgres_output_enum_t *e;
998 ngx_uint_t i;
999
1000 dd("entering");
1001
1002 if (pglcf->output_handler != NGX_CONF_UNSET_PTR) {
1003 dd("returning");
1004 return "is duplicate";
1005 }
1006
1007 e = ngx_postgres_output_handlers;
1008 for (i = 0; e[i].name.len; i++) {
1009 if ((e[i].name.len == value[1].len)
1010 && (ngx_strcasecmp(e[i].name.data, value[1].data) == 0))
1011 {
1012 pglcf->output_handler = e[i].handler;
1013 break;
1014 }
1015 }
1016
1017 if (e[i].name.len == 0) {
1018 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1019 "postgres: invalid output format \"%V\""
1020 " in \"%V\" directive", &value[1], &cmd->name);
1021
1022 dd("returning NGX_CONF_ERROR");
1023 return NGX_CONF_ERROR;
1024 }
1025
1026 pglcf->output_binary = e[i].binary;
1027
1028 dd("returning NGX_CONF_OK");
1029 return NGX_CONF_OK;
1030 }
1031
1032 char *
ngx_postgres_conf_set(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)1033 ngx_postgres_conf_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1034 {
1035 ngx_str_t *value = cf->args->elts;
1036 ngx_postgres_loc_conf_t *pglcf = conf;
1037 ngx_postgres_variable_t *pgvar;
1038 ngx_conf_enum_t *e;
1039 ngx_int_t idx;
1040 ngx_uint_t i;
1041
1042 dd("entering");
1043
1044 if (value[1].len < 2) {
1045 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1046 "postgres: empty variable name in \"%V\" directive",
1047 &cmd->name);
1048
1049 dd("returning NGX_CONF_ERROR");
1050 return NGX_CONF_ERROR;
1051 }
1052
1053 if (value[1].data[0] != '$') {
1054 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1055 "postgres: invalid variable name \"%V\""
1056 " in \"%V\" directive", &value[1], &cmd->name);
1057
1058 dd("returning NGX_CONF_ERROR");
1059 return NGX_CONF_ERROR;
1060 }
1061
1062 value[1].len--;
1063 value[1].data++;
1064
1065 if (value[3].len == 0) {
1066 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1067 "postgres: empty column in \"%V\" directive",
1068 &cmd->name);
1069
1070 dd("returning NGX_CONF_ERROR");
1071 return NGX_CONF_ERROR;
1072 }
1073
1074 if (pglcf->variables == NGX_CONF_UNSET_PTR) {
1075 pglcf->variables = ngx_array_create(cf->pool, 4,
1076 sizeof(ngx_postgres_variable_t));
1077 if (pglcf->variables == NULL) {
1078 dd("returning NGX_CONF_ERROR");
1079 return NGX_CONF_ERROR;
1080 }
1081 }
1082
1083 pgvar = ngx_array_push(pglcf->variables);
1084 if (pgvar == NULL) {
1085 dd("returning NGX_CONF_ERROR");
1086 return NGX_CONF_ERROR;
1087 }
1088
1089 pgvar->idx = pglcf->variables->nelts - 1;
1090
1091 pgvar->var = ngx_http_add_variable(cf, &value[1], 0);
1092 if (pgvar->var == NULL) {
1093 dd("returning NGX_CONF_ERROR");
1094 return NGX_CONF_ERROR;
1095 }
1096
1097 idx = ngx_http_get_variable_index(cf, &value[1]);
1098 if (idx == NGX_ERROR) {
1099 dd("returning NGX_CONF_ERROR");
1100 return NGX_CONF_ERROR;
1101 }
1102
1103 /*
1104 * Check if "$variable" was previously defined,
1105 * back-off even if it was marked as "CHANGEABLE".
1106 */
1107 if (pgvar->var->get_handler != NULL) {
1108 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1109 "postgres: variable \"$%V\" is duplicate"
1110 " in \"%V\" directive", &value[1], &cmd->name);
1111
1112 dd("returning NGX_CONF_ERROR");
1113 return NGX_CONF_ERROR;
1114 }
1115
1116 pgvar->var->get_handler = ngx_postgres_variable_get_custom;
1117 pgvar->var->data = (uintptr_t) pgvar;
1118
1119 pgvar->value.row = ngx_atoi(value[2].data, value[2].len);
1120 if (pgvar->value.row == NGX_ERROR) {
1121 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1122 "postgres: invalid row number \"%V\""
1123 " in \"%V\" directive", &value[2], &cmd->name);
1124
1125 dd("returning NGX_CONF_ERROR");
1126 return NGX_CONF_ERROR;
1127 }
1128
1129 pgvar->value.column = ngx_atoi(value[3].data, value[3].len);
1130 if (pgvar->value.column == NGX_ERROR) {
1131 /* get column by name */
1132 pgvar->value.col_name = ngx_pnalloc(cf->pool, value[3].len + 1);
1133 if (pgvar->value.col_name == NULL) {
1134 dd("returning NGX_CONF_ERROR");
1135 return NGX_CONF_ERROR;
1136 }
1137
1138 (void) ngx_cpystrn(pgvar->value.col_name,
1139 value[3].data, value[3].len + 1);
1140 }
1141
1142 if (cf->args->nelts == 4) {
1143 /* default value */
1144 pgvar->value.required = 0;
1145 } else {
1146 /* user-specified value */
1147 e = ngx_postgres_requirement_options;
1148 for (i = 0; e[i].name.len; i++) {
1149 if ((e[i].name.len == value[4].len)
1150 && (ngx_strcasecmp(e[i].name.data, value[4].data) == 0))
1151 {
1152 pgvar->value.required = e[i].value;
1153 break;
1154 }
1155 }
1156
1157 if (e[i].name.len == 0) {
1158 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1159 "postgres: invalid requirement option \"%V\""
1160 " in \"%V\" directive", &value[4], &cmd->name);
1161
1162 dd("returning NGX_CONF_ERROR");
1163 return NGX_CONF_ERROR;
1164 }
1165 }
1166
1167 dd("returning NGX_CONF_OK");
1168 return NGX_CONF_OK;
1169 }
1170
1171 /*
1172 * Based on: ngx_http_rewrite_module.c/ngx_http_rewrite_set
1173 * Copyright (C) Igor Sysoev
1174 */
1175 char *
ngx_postgres_conf_escape(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)1176 ngx_postgres_conf_escape(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1177 {
1178 ngx_str_t *value = cf->args->elts;
1179 ngx_str_t src = value[cf->args->nelts - 1];
1180 ngx_int_t index;
1181 ngx_http_variable_t *v;
1182 ngx_http_script_var_code_t *vcode;
1183 ngx_http_script_var_handler_code_t *vhcode;
1184 ngx_postgres_rewrite_loc_conf_t *rlcf;
1185 ngx_postgres_escape_t *pge;
1186 ngx_str_t dst;
1187 ngx_uint_t empty;
1188
1189 dd("entering");
1190
1191 if ((src.len != 0) && (src.data[0] == '=')) {
1192 empty = 1;
1193 src.len--;
1194 src.data++;
1195 } else {
1196 empty = 0;
1197 }
1198
1199 if (src.len == 0) {
1200 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1201 "postgres: empty value in \"%V\" directive",
1202 &cmd->name);
1203
1204 dd("returning NGX_CONF_ERROR");
1205 return NGX_CONF_ERROR;
1206 }
1207
1208 if (cf->args->nelts == 2) {
1209 dst = src;
1210 } else {
1211 dst = value[1];
1212 }
1213
1214 if (dst.len < 2) {
1215 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1216 "postgres: empty variable name in \"%V\" directive",
1217 &cmd->name);
1218
1219 dd("returning NGX_CONF_ERROR");
1220 return NGX_CONF_ERROR;
1221 }
1222
1223 if (dst.data[0] != '$') {
1224 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1225 "postgres: invalid variable name \"%V\""
1226 " in \"%V\" directive", &dst, &cmd->name);
1227
1228 dd("returning NGX_CONF_ERROR");
1229 return NGX_CONF_ERROR;
1230 }
1231
1232 dst.len--;
1233 dst.data++;
1234
1235 v = ngx_http_add_variable(cf, &dst, NGX_HTTP_VAR_CHANGEABLE);
1236 if (v == NULL) {
1237 dd("returning NGX_CONF_ERROR");
1238 return NGX_CONF_ERROR;
1239 }
1240
1241 index = ngx_http_get_variable_index(cf, &dst);
1242 if (index == NGX_ERROR) {
1243 dd("returning NGX_CONF_ERROR");
1244 return NGX_CONF_ERROR;
1245 }
1246
1247 if (v->get_handler == NULL
1248 && ngx_strncasecmp(dst.data, (u_char *) "http_", 5) != 0
1249 && ngx_strncasecmp(dst.data, (u_char *) "sent_http_", 10) != 0
1250 && ngx_strncasecmp(dst.data, (u_char *) "upstream_http_", 14) != 0)
1251 {
1252 v->get_handler = ngx_postgres_rewrite_var;
1253 v->data = index;
1254 }
1255
1256 rlcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_rewrite_module);
1257
1258 if (ngx_postgres_rewrite_value(cf, rlcf, &src) != NGX_CONF_OK) {
1259 dd("returning NGX_CONF_ERROR");
1260 return NGX_CONF_ERROR;
1261 }
1262
1263 pge = ngx_http_script_start_code(cf->pool, &rlcf->codes,
1264 sizeof(ngx_postgres_escape_t));
1265 if (pge == NULL) {
1266 dd("returning NGX_CONF_ERROR");
1267 return NGX_CONF_ERROR;
1268 }
1269
1270 pge->code = ngx_postgres_escape_string;
1271 pge->empty = empty;
1272
1273 if (v->set_handler) {
1274 vhcode = ngx_http_script_start_code(cf->pool, &rlcf->codes,
1275 sizeof(ngx_http_script_var_handler_code_t));
1276 if (vhcode == NULL) {
1277 dd("returning NGX_CONF_ERROR");
1278 return NGX_CONF_ERROR;
1279 }
1280
1281 vhcode->code = ngx_http_script_var_set_handler_code;
1282 vhcode->handler = v->set_handler;
1283 vhcode->data = v->data;
1284
1285 dd("returning NGX_CONF_OK");
1286 return NGX_CONF_OK;
1287 }
1288
1289 vcode = ngx_http_script_start_code(cf->pool, &rlcf->codes,
1290 sizeof(ngx_http_script_var_code_t));
1291 if (vcode == NULL) {
1292 dd("returning NGX_CONF_ERROR");
1293 return NGX_CONF_ERROR;
1294 }
1295
1296 vcode->code = ngx_http_script_set_var_code;
1297 vcode->index = (uintptr_t) index;
1298
1299 dd("returning NGX_CONF_OK");
1300 return NGX_CONF_OK;
1301 }
1302
1303 ngx_http_upstream_srv_conf_t *
ngx_postgres_find_upstream(ngx_http_request_t * r,ngx_url_t * url)1304 ngx_postgres_find_upstream(ngx_http_request_t *r, ngx_url_t *url)
1305 {
1306 ngx_http_upstream_main_conf_t *umcf;
1307 ngx_http_upstream_srv_conf_t **uscfp;
1308 ngx_uint_t i;
1309
1310 dd("entering");
1311
1312 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
1313
1314 uscfp = umcf->upstreams.elts;
1315
1316 for (i = 0; i < umcf->upstreams.nelts; i++) {
1317
1318 if ((uscfp[i]->host.len != url->host.len)
1319 || (ngx_strncasecmp(uscfp[i]->host.data, url->host.data,
1320 url->host.len) != 0))
1321 {
1322 dd("host doesn't match");
1323 continue;
1324 }
1325
1326 #if (nginx_version < 1011006)
1327 if (uscfp[i]->port != url->port) {
1328 dd("port doesn't match: %d != %d",
1329 (int) uscfp[i]->port, (int) url->port);
1330 continue;
1331 }
1332
1333 if (uscfp[i]->default_port && url->default_port
1334 && (uscfp[i]->default_port != url->default_port))
1335 {
1336 dd("default_port doesn't match");
1337 continue;
1338 }
1339
1340 #endif
1341 dd("returning");
1342 return uscfp[i];
1343 }
1344
1345 dd("returning NULL");
1346 return NULL;
1347 }
1348