Mercurial > hg > nginx-vendor-0-6
comparison src/imap/ngx_imap_proxy_module.c @ 76:da9a3b14312d NGINX_0_1_38
nginx 0.1.38
*) Feature: the "limit_rate" directive is supported in in proxy and
FastCGI mode.
*) Feature: the "X-Accel-Limit-Rate" response header line is supported
in proxy and FastCGI mode.
*) Feature: the "break" directive.
*) Feature: the "log_not_found" directive.
*) Bugfix: the response status code was not changed when request was
redirected by the ""X-Accel-Redirect" header line.
*) Bugfix: the variables set by the "set" directive could not be used
in SSI.
*) Bugfix: the segmentation fault may occurred if the SSI page has more
than one remote subrequest.
*) Bugfix: nginx treated the backend response as invalid if the status
line in the header was transferred in two packets; bug appeared in
0.1.29.
*) Feature: the "ssi_types" directive.
*) Feature: the "autoindex_exact_size" directive.
*) Bugfix: the ngx_http_autoindex_module did not support the long file
names in UTF-8.
*) Feature: the IMAP/POP3 proxy.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Fri, 08 Jul 2005 00:00:00 +0400 |
parents | |
children | 9db7e0b5b27f |
comparison
equal
deleted
inserted
replaced
75:985847bb65f9 | 76:da9a3b14312d |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_event.h> | |
10 #include <ngx_event_connect.h> | |
11 #include <ngx_imap.h> | |
12 | |
13 | |
14 typedef struct { | |
15 ngx_flag_t enable; | |
16 } ngx_imap_proxy_conf_t; | |
17 | |
18 | |
19 static void ngx_imap_proxy_block_read(ngx_event_t *rev); | |
20 static void ngx_imap_proxy_imap_handler(ngx_event_t *rev); | |
21 static void ngx_imap_proxy_pop3_handler(ngx_event_t *rev); | |
22 static void ngx_imap_proxy_dummy_handler(ngx_event_t *ev); | |
23 static ngx_int_t ngx_imap_proxy_read_response(ngx_imap_session_t *s, | |
24 ngx_uint_t what); | |
25 static void ngx_imap_proxy_handler(ngx_event_t *ev); | |
26 static void ngx_imap_proxy_internal_server_error(ngx_imap_session_t *s); | |
27 static void ngx_imap_proxy_close_session(ngx_imap_session_t *s); | |
28 static void *ngx_imap_proxy_create_conf(ngx_conf_t *cf); | |
29 static char *ngx_imap_proxy_merge_conf(ngx_conf_t *cf, void *parent, | |
30 void *child); | |
31 | |
32 | |
33 #define NGX_IMAP_WAIT_OK 0 | |
34 #define NGX_IMAP_WAIT_NEXT 1 | |
35 | |
36 | |
37 static ngx_command_t ngx_imap_proxy_commands[] = { | |
38 { ngx_string("proxy"), | |
39 NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_FLAG, | |
40 ngx_conf_set_flag_slot, | |
41 NGX_IMAP_SRV_CONF_OFFSET, | |
42 offsetof(ngx_imap_proxy_conf_t, enable), | |
43 NULL }, | |
44 | |
45 ngx_null_command | |
46 }; | |
47 | |
48 | |
49 static ngx_imap_module_t ngx_imap_proxy_module_ctx = { | |
50 NULL, /* create main configuration */ | |
51 NULL, /* init main configuration */ | |
52 | |
53 ngx_imap_proxy_create_conf, /* create server configuration */ | |
54 ngx_imap_proxy_merge_conf /* merge server configuration */ | |
55 }; | |
56 | |
57 | |
58 ngx_module_t ngx_imap_proxy_module = { | |
59 NGX_MODULE_V1, | |
60 &ngx_imap_proxy_module_ctx, /* module context */ | |
61 ngx_imap_proxy_commands, /* module directives */ | |
62 NGX_IMAP_MODULE, /* module type */ | |
63 NULL, /* init module */ | |
64 NULL /* init process */ | |
65 }; | |
66 | |
67 | |
68 void | |
69 ngx_imap_proxy_init(ngx_imap_session_t *s, ngx_peers_t *peers) | |
70 { | |
71 ngx_int_t rc; | |
72 ngx_imap_proxy_ctx_t *p; | |
73 ngx_imap_core_srv_conf_t *cscf; | |
74 | |
75 p = ngx_pcalloc(s->connection->pool, sizeof(ngx_imap_proxy_ctx_t)); | |
76 if (p == NULL) { | |
77 ngx_imap_session_internal_server_error(s); | |
78 return; | |
79 } | |
80 | |
81 s->proxy = p; | |
82 | |
83 p->upstream.peers = peers; | |
84 p->upstream.log = s->connection->log; | |
85 p->upstream.log_error = NGX_ERROR_ERR; | |
86 | |
87 rc = ngx_event_connect_peer(&p->upstream); | |
88 | |
89 if (rc == NGX_ERROR) { | |
90 ngx_imap_session_internal_server_error(s); | |
91 return; | |
92 } | |
93 | |
94 cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); | |
95 ngx_add_timer(p->upstream.connection->read, cscf->timeout); | |
96 | |
97 p->upstream.connection->data = s; | |
98 p->upstream.connection->pool = s->connection->pool; | |
99 | |
100 s->connection->read->handler = ngx_imap_proxy_block_read; | |
101 p->upstream.connection->write->handler = ngx_imap_proxy_dummy_handler; | |
102 | |
103 if (s->protocol == NGX_IMAP_POP3_PROTOCOL) { | |
104 p->upstream.connection->read->handler = ngx_imap_proxy_pop3_handler; | |
105 s->imap_state = ngx_pop3_start; | |
106 | |
107 } else { | |
108 p->upstream.connection->read->handler = ngx_imap_proxy_imap_handler; | |
109 s->imap_state = ngx_imap_start; | |
110 } | |
111 } | |
112 | |
113 | |
114 static void | |
115 ngx_imap_proxy_block_read(ngx_event_t *rev) | |
116 { | |
117 ngx_connection_t *c; | |
118 ngx_imap_session_t *s; | |
119 | |
120 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0, "imap proxy block read"); | |
121 | |
122 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) { | |
123 c = rev->data; | |
124 s = c->data; | |
125 | |
126 ngx_imap_proxy_close_session(s); | |
127 } | |
128 } | |
129 | |
130 | |
131 static void | |
132 ngx_imap_proxy_imap_handler(ngx_event_t *rev) | |
133 { | |
134 u_char *p; | |
135 ngx_int_t rc; | |
136 ngx_str_t line; | |
137 ngx_connection_t *c; | |
138 ngx_imap_session_t *s; | |
139 ngx_imap_core_srv_conf_t *cscf; | |
140 | |
141 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0, | |
142 "imap proxy imap auth handler"); | |
143 | |
144 c = rev->data; | |
145 s = c->data; | |
146 | |
147 if (rev->timedout) { | |
148 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, | |
149 "upstream timed out"); | |
150 ngx_imap_proxy_internal_server_error(s); | |
151 return; | |
152 } | |
153 | |
154 if (s->proxy->buffer == NULL) { | |
155 cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); | |
156 | |
157 s->proxy->buffer = ngx_create_temp_buf(c->pool, | |
158 cscf->proxy_buffer_size); | |
159 if (s->proxy->buffer == NULL) { | |
160 ngx_imap_proxy_internal_server_error(s); | |
161 return; | |
162 } | |
163 } | |
164 | |
165 rc = ngx_imap_proxy_read_response(s, s->imap_state == ngx_imap_start ? | |
166 NGX_IMAP_WAIT_OK : NGX_IMAP_WAIT_NEXT); | |
167 | |
168 if (rc == NGX_AGAIN) { | |
169 return; | |
170 } | |
171 | |
172 if (rc == NGX_ERROR) { | |
173 ngx_imap_proxy_internal_server_error(s); | |
174 return; | |
175 } | |
176 | |
177 switch (s->imap_state) { | |
178 | |
179 case ngx_imap_start: | |
180 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0, | |
181 "imap proxy send login"); | |
182 | |
183 line.len = s->tag.len + sizeof("LOGIN ") - 1 | |
184 + 1 + NGX_SIZE_T_LEN + 1 + 2; | |
185 line.data = ngx_palloc(c->pool, line.len); | |
186 if (line.data == NULL) { | |
187 ngx_imap_proxy_internal_server_error(s); | |
188 return; | |
189 } | |
190 | |
191 line.len = ngx_sprintf(line.data, "%VLOGIN {%uz}" CRLF, | |
192 &s->tag, s->login.len) | |
193 - line.data; | |
194 | |
195 s->imap_state = ngx_imap_login; | |
196 break; | |
197 | |
198 case ngx_imap_login: | |
199 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0, "imap proxy send user"); | |
200 | |
201 line.len = s->login.len + 1 + NGX_SIZE_T_LEN + 1 + 2; | |
202 line.data = ngx_palloc(c->pool, line.len); | |
203 if (line.data == NULL) { | |
204 ngx_imap_proxy_internal_server_error(s); | |
205 return; | |
206 } | |
207 | |
208 line.len = ngx_sprintf(line.data, "%V{%uz}" CRLF, | |
209 &s->login, s->passwd.len) | |
210 - line.data; | |
211 | |
212 s->imap_state = ngx_imap_user; | |
213 break; | |
214 | |
215 case ngx_imap_user: | |
216 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0, | |
217 "imap proxy send passwd"); | |
218 | |
219 line.len = s->passwd.len + 2; | |
220 line.data = ngx_palloc(c->pool, line.len); | |
221 if (line.data == NULL) { | |
222 ngx_imap_proxy_internal_server_error(s); | |
223 return; | |
224 } | |
225 | |
226 p = ngx_cpymem(line.data, s->passwd.data, s->passwd.len); | |
227 *p++ = CR; *p = LF; | |
228 | |
229 s->imap_state = ngx_imap_passwd; | |
230 break; | |
231 | |
232 default: | |
233 #if (NGX_SUPPRESS_WARN) | |
234 line.len = 0; | |
235 line.data = NULL; | |
236 #endif | |
237 break; | |
238 } | |
239 | |
240 if (ngx_send(c, line.data, line.len) < (ssize_t) line.len) { | |
241 /* | |
242 * we treat the incomplete sending as NGX_ERROR | |
243 * because it is very strange here | |
244 */ | |
245 ngx_imap_proxy_internal_server_error(s); | |
246 return; | |
247 } | |
248 | |
249 s->proxy->buffer->pos = s->proxy->buffer->start; | |
250 s->proxy->buffer->last = s->proxy->buffer->start; | |
251 | |
252 if (s->imap_state == ngx_imap_passwd) { | |
253 s->connection->read->handler = ngx_imap_proxy_handler; | |
254 s->connection->write->handler = ngx_imap_proxy_handler; | |
255 rev->handler = ngx_imap_proxy_handler; | |
256 c->write->handler = ngx_imap_proxy_handler; | |
257 } | |
258 } | |
259 | |
260 | |
261 static void | |
262 ngx_imap_proxy_pop3_handler(ngx_event_t *rev) | |
263 { | |
264 u_char *p; | |
265 ngx_int_t rc; | |
266 ngx_str_t line; | |
267 ngx_connection_t *c; | |
268 ngx_imap_session_t *s; | |
269 ngx_imap_core_srv_conf_t *cscf; | |
270 | |
271 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0, | |
272 "imap proxy pop3 auth handler"); | |
273 | |
274 c = rev->data; | |
275 s = c->data; | |
276 | |
277 if (rev->timedout) { | |
278 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, | |
279 "upstream timed out"); | |
280 ngx_imap_proxy_internal_server_error(s); | |
281 return; | |
282 } | |
283 | |
284 if (s->proxy->buffer == NULL) { | |
285 cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); | |
286 | |
287 s->proxy->buffer = ngx_create_temp_buf(c->pool, | |
288 cscf->proxy_buffer_size); | |
289 if (s->proxy->buffer == NULL) { | |
290 ngx_imap_proxy_internal_server_error(s); | |
291 return; | |
292 } | |
293 } | |
294 | |
295 rc = ngx_imap_proxy_read_response(s, NGX_IMAP_WAIT_OK); | |
296 | |
297 if (rc == NGX_AGAIN) { | |
298 return; | |
299 } | |
300 | |
301 if (rc == NGX_ERROR) { | |
302 ngx_imap_proxy_internal_server_error(s); | |
303 return; | |
304 } | |
305 | |
306 switch (s->imap_state) { | |
307 | |
308 case ngx_pop3_start: | |
309 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0, "imap proxy send user"); | |
310 | |
311 line.len = sizeof("USER ") - 1 + s->login.len + 2; | |
312 line.data = ngx_palloc(c->pool, line.len); | |
313 if (line.data == NULL) { | |
314 ngx_imap_proxy_internal_server_error(s); | |
315 return; | |
316 } | |
317 | |
318 p = ngx_cpymem(line.data, "USER ", sizeof("USER ") - 1); | |
319 p = ngx_cpymem(p, s->login.data, s->login.len); | |
320 *p++ = CR; *p = LF; | |
321 | |
322 s->imap_state = ngx_pop3_user; | |
323 break; | |
324 | |
325 case ngx_pop3_user: | |
326 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0, "imap proxy send pass"); | |
327 | |
328 line.len = sizeof("PASS ") - 1 + s->passwd.len + 2; | |
329 line.data = ngx_palloc(c->pool, line.len); | |
330 if (line.data == NULL) { | |
331 ngx_imap_proxy_internal_server_error(s); | |
332 return; | |
333 } | |
334 | |
335 p = ngx_cpymem(line.data, "PASS ", sizeof("PASS ") - 1); | |
336 p = ngx_cpymem(p, s->passwd.data, s->passwd.len); | |
337 *p++ = CR; *p = LF; | |
338 | |
339 s->imap_state = ngx_pop3_passwd; | |
340 break; | |
341 | |
342 default: | |
343 #if (NGX_SUPPRESS_WARN) | |
344 line.len = 0; | |
345 line.data = NULL; | |
346 #endif | |
347 break; | |
348 } | |
349 | |
350 if (ngx_send(c, line.data, line.len) < (ssize_t) line.len) { | |
351 /* | |
352 * we treat the incomplete sending as NGX_ERROR | |
353 * because it is very strange here | |
354 */ | |
355 ngx_imap_proxy_internal_server_error(s); | |
356 return; | |
357 } | |
358 | |
359 s->proxy->buffer->pos = s->proxy->buffer->start; | |
360 s->proxy->buffer->last = s->proxy->buffer->start; | |
361 | |
362 if (s->imap_state == ngx_pop3_passwd) { | |
363 s->connection->read->handler = ngx_imap_proxy_handler; | |
364 s->connection->write->handler = ngx_imap_proxy_handler; | |
365 rev->handler = ngx_imap_proxy_handler; | |
366 c->write->handler = ngx_imap_proxy_handler; | |
367 } | |
368 } | |
369 | |
370 | |
371 static void | |
372 ngx_imap_proxy_dummy_handler(ngx_event_t *ev) | |
373 { | |
374 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, ev->log, 0, "imap proxy dummy handler"); | |
375 } | |
376 | |
377 | |
378 static ngx_int_t | |
379 ngx_imap_proxy_read_response(ngx_imap_session_t *s, ngx_uint_t what) | |
380 { | |
381 u_char *p; | |
382 ssize_t n; | |
383 ngx_buf_t *b; | |
384 | |
385 b = s->proxy->buffer; | |
386 | |
387 n = ngx_recv(s->proxy->upstream.connection, b->last, b->end - b->last); | |
388 | |
389 if (n == NGX_ERROR || n == 0) { | |
390 return NGX_ERROR; | |
391 } | |
392 | |
393 if (n == NGX_AGAIN) { | |
394 return NGX_AGAIN; | |
395 } | |
396 | |
397 b->last += n; | |
398 | |
399 if (b->last - b->pos < 5) { | |
400 return NGX_AGAIN; | |
401 } | |
402 | |
403 if (*(b->last - 2) != CR || *(b->last - 1) != LF) { | |
404 if (b->last == b->end) { | |
405 *(b->last - 1) = '\0'; | |
406 ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, | |
407 "upstream sent too long response line: \"%s\"", | |
408 b->pos); | |
409 return NGX_IMAP_PROXY_INVALID; | |
410 } | |
411 | |
412 return NGX_AGAIN; | |
413 } | |
414 | |
415 p = b->pos; | |
416 | |
417 if (s->protocol == NGX_IMAP_POP3_PROTOCOL) { | |
418 if (p[0] == '+' && p[1] == 'O' && p[2] == 'K') { | |
419 return NGX_OK; | |
420 } | |
421 | |
422 if (p[0] == '-' && p[1] == 'E' && p[2] == 'R' && p[3] == 'R') { | |
423 return NGX_IMAP_PROXY_ERROR; | |
424 } | |
425 | |
426 } else { | |
427 if (what == NGX_IMAP_WAIT_OK) { | |
428 if (p[0] == '*' && p[1] == ' ' && p[2] == 'O' && p[3] == 'K') { | |
429 return NGX_OK; | |
430 } | |
431 | |
432 } else { | |
433 if (p[0] == '+' && p[1] == ' ' && p[2] == 'O' && p[3] == 'K') { | |
434 return NGX_OK; | |
435 } | |
436 } | |
437 } | |
438 | |
439 *(b->last - 2) = '\0'; | |
440 ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, | |
441 "upstream sent invalid response: \"%s\"", p); | |
442 | |
443 return NGX_IMAP_PROXY_INVALID; | |
444 } | |
445 | |
446 | |
447 static void | |
448 ngx_imap_proxy_handler(ngx_event_t *ev) | |
449 { | |
450 size_t size; | |
451 ssize_t n; | |
452 ngx_buf_t *b; | |
453 ngx_uint_t again, do_write; | |
454 ngx_connection_t *c, *src, *dst; | |
455 ngx_imap_session_t *s; | |
456 | |
457 c = ev->data; | |
458 s = c->data; | |
459 | |
460 if (ev->timedout) { | |
461 if (c == s->connection) { | |
462 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, | |
463 "client timed out"); | |
464 } else { | |
465 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, | |
466 "upstream timed out"); | |
467 } | |
468 | |
469 ngx_imap_proxy_close_session(s); | |
470 return; | |
471 } | |
472 | |
473 if (c == s->connection) { | |
474 if (ev->write) { | |
475 src = s->proxy->upstream.connection; | |
476 dst = c; | |
477 b = s->proxy->buffer; | |
478 | |
479 } else { | |
480 src = c; | |
481 dst = s->proxy->upstream.connection; | |
482 b = s->buffer; | |
483 } | |
484 | |
485 } else { | |
486 if (ev->write) { | |
487 src = s->connection; | |
488 dst = c; | |
489 b = s->buffer; | |
490 | |
491 } else { | |
492 src = c; | |
493 dst = s->connection; | |
494 b = s->proxy->buffer; | |
495 } | |
496 } | |
497 | |
498 do_write = ev->write ? 1 : 0; | |
499 | |
500 ngx_log_debug3(NGX_LOG_DEBUG_IMAP, ev->log, 0, | |
501 "imap proxy handler: %d, #%d > #%d", | |
502 do_write, src->fd, dst->fd); | |
503 | |
504 do { | |
505 again = 0; | |
506 | |
507 if (do_write == 1) { | |
508 | |
509 size = b->last - b->pos; | |
510 | |
511 if (size && dst->write->ready) { | |
512 n = ngx_send(dst, b->pos, size); | |
513 | |
514 if (n == NGX_ERROR) { | |
515 ngx_imap_proxy_close_session(s); | |
516 return; | |
517 } | |
518 | |
519 if (n > 0) { | |
520 again = 1; | |
521 b->pos += n; | |
522 | |
523 if (b->pos == b->last) { | |
524 b->pos = b->start; | |
525 b->last = b->start; | |
526 } | |
527 } | |
528 | |
529 if (n == NGX_AGAIN || n < (ssize_t) size) { | |
530 if (ngx_handle_write_event(dst->write, /* TODO: LOWAT */ 0) | |
531 == NGX_ERROR) | |
532 { | |
533 ngx_imap_proxy_close_session(s); | |
534 return; | |
535 } | |
536 } | |
537 } | |
538 } | |
539 | |
540 size = b->end - b->last; | |
541 | |
542 if (size && src->read->ready) { | |
543 n = ngx_recv(src, b->last, size); | |
544 | |
545 if (n == NGX_ERROR || n == 0) { | |
546 ngx_imap_proxy_close_session(s); | |
547 return; | |
548 } | |
549 | |
550 if (n > 0) { | |
551 again = 1; | |
552 do_write = 1; | |
553 b->last += n; | |
554 } | |
555 | |
556 if (n == NGX_AGAIN || n < (ssize_t) size) { | |
557 if (ngx_handle_read_event(src->read, 0) == NGX_ERROR) { | |
558 ngx_imap_proxy_close_session(s); | |
559 return; | |
560 } | |
561 } | |
562 } | |
563 | |
564 } while (again); | |
565 } | |
566 | |
567 | |
568 static void | |
569 ngx_imap_proxy_internal_server_error(ngx_imap_session_t *s) | |
570 { | |
571 if (s->proxy->upstream.connection) { | |
572 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, s->connection->log, 0, | |
573 "close imap proxy connection: %d", | |
574 s->proxy->upstream.connection->fd); | |
575 | |
576 ngx_close_connection(s->proxy->upstream.connection); | |
577 } | |
578 | |
579 ngx_imap_session_internal_server_error(s); | |
580 } | |
581 | |
582 | |
583 static void | |
584 ngx_imap_proxy_close_session(ngx_imap_session_t *s) | |
585 { | |
586 if (s->proxy->upstream.connection) { | |
587 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, s->connection->log, 0, | |
588 "close imap proxy connection: %d", | |
589 s->proxy->upstream.connection->fd); | |
590 | |
591 ngx_close_connection(s->proxy->upstream.connection); | |
592 } | |
593 | |
594 ngx_imap_close_connection(s->connection); | |
595 } | |
596 | |
597 | |
598 static void * | |
599 ngx_imap_proxy_create_conf(ngx_conf_t *cf) | |
600 { | |
601 ngx_imap_proxy_conf_t *pcf; | |
602 | |
603 pcf = ngx_pcalloc(cf->pool, sizeof(ngx_imap_proxy_conf_t)); | |
604 if (pcf == NULL) { | |
605 return NGX_CONF_ERROR; | |
606 } | |
607 | |
608 pcf->enable = NGX_CONF_UNSET; | |
609 | |
610 return pcf; | |
611 } | |
612 | |
613 | |
614 static char * | |
615 ngx_imap_proxy_merge_conf(ngx_conf_t *cf, void *parent, void *child) | |
616 { | |
617 ngx_imap_proxy_conf_t *prev = parent; | |
618 ngx_imap_proxy_conf_t *conf = child; | |
619 | |
620 ngx_conf_merge_msec_value(conf->enable, prev->enable, 0); | |
621 | |
622 return NGX_CONF_OK; | |
623 } |