nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev
17 years ago
1 | 1 | #define _NGINX_H_INCLUDED_ |
2 | 2 | |
3 | 3 | |
4 | #define NGINX_VER "nginx/0.0.11" | |
4 | #define NGINX_VER "nginx/0.0.12" | |
5 | 5 | |
6 | 6 | #define NGINX_VAR "NGINX" |
7 | 7 | #define NGX_NEWPID_EXT ".newbin" |
36 | 36 | } ngx_http_rewrite_srv_conf_t; |
37 | 37 | |
38 | 38 | |
39 | typedef struct { | |
40 | ngx_str_t redirect; | |
41 | } ngx_http_rewrite_loc_conf_t; | |
42 | ||
43 | ||
39 | 44 | static void *ngx_http_rewrite_create_srv_conf(ngx_conf_t *cf); |
40 | 45 | static char *ngx_http_rewrite_merge_srv_conf(ngx_conf_t *cf, |
41 | 46 | void *parent, void *child); |
47 | static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf); | |
42 | 48 | static char *ngx_http_rewrite_rule(ngx_conf_t *cf, ngx_command_t *cmd, |
43 | 49 | void *conf); |
50 | static char *ngx_http_redirect(ngx_conf_t *cf, void *post, void *data); | |
44 | 51 | static ngx_int_t ngx_http_rewrite_init(ngx_cycle_t *cycle); |
52 | ||
53 | ||
54 | static ngx_conf_post_handler_pt ngx_http_redirect_p = ngx_http_redirect; | |
45 | 55 | |
46 | 56 | |
47 | 57 | static ngx_command_t ngx_http_rewrite_commands[] = { |
53 | 63 | 0, |
54 | 64 | NULL }, |
55 | 65 | |
66 | { ngx_string("redirect"), | |
67 | NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
68 | ngx_conf_set_str_slot, | |
69 | NGX_HTTP_LOC_CONF_OFFSET, | |
70 | 0, | |
71 | &ngx_http_redirect_p }, | |
72 | ||
56 | 73 | { ngx_string("rewrite_log"), |
57 | 74 | NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, |
58 | 75 | ngx_conf_set_flag_slot, |
73 | 90 | ngx_http_rewrite_create_srv_conf, /* create server configuration */ |
74 | 91 | ngx_http_rewrite_merge_srv_conf, /* merge server configuration */ |
75 | 92 | |
76 | NULL, /* create location configration */ | |
93 | ngx_http_rewrite_create_loc_conf, /* create location configration */ | |
77 | 94 | NULL, /* merge location configration */ |
78 | 95 | }; |
79 | 96 | |
202 | 219 | } |
203 | 220 | |
204 | 221 | |
222 | static ngx_int_t ngx_http_redirect_handler(ngx_http_request_t *r) | |
223 | { | |
224 | u_char *p; | |
225 | ngx_http_rewrite_loc_conf_t *rlcf; | |
226 | ||
227 | ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
228 | "http redirect handler"); | |
229 | ||
230 | rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module); | |
231 | ||
232 | r->headers_out.location = ngx_list_push(&r->headers_out.headers); | |
233 | if (r->headers_out.location == NULL) { | |
234 | return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
235 | } | |
236 | ||
237 | if (rlcf->redirect.data[0] != '/') { | |
238 | r->headers_out.location->key.len = sizeof("Location") - 1; | |
239 | r->headers_out.location->key.data = (u_char *) "Location"; | |
240 | } | |
241 | ||
242 | r->headers_out.location->value.len = rlcf->redirect.len | |
243 | + r->unparsed_uri.len; | |
244 | r->headers_out.location->value.data = ngx_palloc(r->pool, | |
245 | r->headers_out.location->value.len); | |
246 | ||
247 | if (r->headers_out.location->value.data == NULL) { | |
248 | return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
249 | } | |
250 | ||
251 | p = ngx_cpymem(r->headers_out.location->value.data, rlcf->redirect.data, | |
252 | rlcf->redirect.len); | |
253 | p = ngx_cpystrn(p, r->unparsed_uri.data + 1, r->unparsed_uri.len); | |
254 | ||
255 | return NGX_HTTP_MOVED_TEMPORARILY; | |
256 | } | |
257 | ||
258 | ||
205 | 259 | static void *ngx_http_rewrite_create_srv_conf(ngx_conf_t *cf) |
206 | 260 | { |
207 | 261 | ngx_http_rewrite_srv_conf_t *conf; |
228 | 282 | ngx_conf_merge_value(conf->log, prev->log, 0); |
229 | 283 | |
230 | 284 | return NGX_CONF_OK; |
285 | } | |
286 | ||
287 | ||
288 | static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf) | |
289 | { | |
290 | ngx_http_rewrite_loc_conf_t *conf; | |
291 | ||
292 | if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_rewrite_loc_conf_t)))) { | |
293 | return NGX_CONF_ERROR; | |
294 | } | |
295 | ||
296 | return conf; | |
231 | 297 | } |
232 | 298 | |
233 | 299 | |
365 | 431 | } |
366 | 432 | |
367 | 433 | |
434 | static char *ngx_http_redirect(ngx_conf_t *cf, void *post, void *data) | |
435 | { | |
436 | ngx_http_core_loc_conf_t *clcf; | |
437 | ||
438 | clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); | |
439 | clcf->handler = ngx_http_redirect_handler; | |
440 | ||
441 | return NGX_CONF_OK; | |
442 | } | |
443 | ||
444 | ||
368 | 445 | static ngx_int_t ngx_http_rewrite_init(ngx_cycle_t *cycle) |
369 | 446 | { |
370 | 447 | ngx_http_handler_pt *h; |
400 | 400 | |
401 | 401 | if (!p->cachable && p->upstream->peer.connection) { |
402 | 402 | ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno, |
403 | "kevent() reported that client have closed " | |
403 | "kevent() reported that client closed " | |
404 | 404 | "prematurely connection, " |
405 | 405 | "so upstream connection is closed too"); |
406 | 406 | ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST); |
408 | 408 | } |
409 | 409 | |
410 | 410 | ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno, |
411 | "kevent() reported that client have closed " | |
411 | "kevent() reported that client closed " | |
412 | 412 | "prematurely connection"); |
413 | 413 | |
414 | 414 | if (p->upstream == NULL || p->upstream->peer.connection == NULL) { |
463 | 463 | |
464 | 464 | if (!p->cachable && p->upstream->peer.connection) { |
465 | 465 | ngx_log_error(NGX_LOG_INFO, ev->log, err, |
466 | "client have closed prematurely connection, " | |
466 | "client closed prematurely connection, " | |
467 | 467 | "so upstream connection is closed too"); |
468 | 468 | ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST); |
469 | 469 | return; |
470 | 470 | } |
471 | 471 | |
472 | 472 | ngx_log_error(NGX_LOG_INFO, ev->log, err, |
473 | "client have closed prematurely connection"); | |
473 | "client closed prematurely connection"); | |
474 | 474 | |
475 | 475 | if (p->upstream == NULL || p->upstream->peer.connection == NULL) { |
476 | 476 | ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST); |
233 | 233 | 0, |
234 | 234 | NULL }, |
235 | 235 | |
236 | { ngx_string("keepalive_buffers"), | |
237 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
238 | ngx_conf_set_flag_slot, | |
239 | NGX_HTTP_LOC_CONF_OFFSET, | |
240 | offsetof(ngx_http_core_loc_conf_t, keepalive_buffers), | |
241 | NULL }, | |
242 | ||
243 | 236 | { ngx_string("lingering_time"), |
244 | 237 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
245 | 238 | ngx_conf_set_msec_slot, |
1394 | 1387 | lcf->limit_rate = NGX_CONF_UNSET_SIZE; |
1395 | 1388 | lcf->keepalive_timeout = NGX_CONF_UNSET_MSEC; |
1396 | 1389 | lcf->keepalive_header = NGX_CONF_UNSET; |
1397 | lcf->keepalive_buffers = NGX_CONF_UNSET; | |
1398 | 1390 | lcf->lingering_time = NGX_CONF_UNSET_MSEC; |
1399 | 1391 | lcf->lingering_timeout = NGX_CONF_UNSET_MSEC; |
1400 | 1392 | lcf->reset_timedout_connection = NGX_CONF_UNSET; |
1483 | 1475 | prev->keepalive_timeout, 75000); |
1484 | 1476 | ngx_conf_merge_sec_value(conf->keepalive_header, |
1485 | 1477 | prev->keepalive_header, 0); |
1486 | ngx_conf_merge_value(conf->keepalive_buffers, prev->keepalive_buffers, 1); | |
1487 | 1478 | ngx_conf_merge_msec_value(conf->lingering_time, |
1488 | 1479 | prev->lingering_time, 30000); |
1489 | 1480 | ngx_conf_merge_msec_value(conf->lingering_timeout, |
1544 | 1535 | } |
1545 | 1536 | |
1546 | 1537 | port = ngx_atoi(&addr[p], args[1].len - p); |
1538 | ||
1547 | 1539 | if (port == NGX_ERROR && p == 0) { |
1548 | 1540 | |
1549 | 1541 | /* "listen host" */ |
1563 | 1555 | ls->addr = INADDR_ANY; |
1564 | 1556 | ls->port = (in_port_t) port; |
1565 | 1557 | return NGX_CONF_OK; |
1566 | } | |
1567 | ||
1568 | ls->port = (in_port_t) port; | |
1558 | ||
1559 | } else { | |
1560 | ls->port = (in_port_t) port; | |
1561 | } | |
1569 | 1562 | |
1570 | 1563 | ls->addr = inet_addr((const char *) addr); |
1571 | 1564 | if (ls->addr == INADDR_NONE) { |
163 | 163 | |
164 | 164 | time_t keepalive_header; /* keepalive_timeout */ |
165 | 165 | |
166 | ngx_flag_t keepalive_buffers; /* keepalive_buffers */ | |
167 | 166 | ngx_flag_t sendfile; /* sendfile */ |
168 | 167 | ngx_flag_t tcp_nopush; /* tcp_nopush */ |
169 | 168 | ngx_flag_t reset_timedout_connection; /* reset_timedout_connection */ |
196 | 196 | |
197 | 197 | hc = c->data; |
198 | 198 | |
199 | if (hc == NULL) { | |
199 | if (hc) { | |
200 | ||
201 | #if (NGX_STAT_STUB) | |
202 | (*ngx_stat_reading)++; | |
203 | #endif | |
204 | ||
205 | } else { | |
200 | 206 | if (!(hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t)))) { |
201 | 207 | |
202 | 208 | #if (NGX_STAT_STUB) |
218 | 224 | if (hc->nbusy) { |
219 | 225 | r->header_in = hc->busy[0]; |
220 | 226 | } |
221 | ||
222 | #if (NGX_STAT_STUB) | |
223 | (*ngx_stat_reading)++; | |
224 | #endif | |
225 | 227 | |
226 | 228 | } else { |
227 | 229 | if (!(r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)))) { |
682 | 684 | |
683 | 685 | /* NGX_AGAIN: a request line parsing is still incomplete */ |
684 | 686 | |
685 | if (r->header_in->last == r->header_in->end) { | |
687 | if (r->header_in->pos == r->header_in->end) { | |
686 | 688 | |
687 | 689 | rv = ngx_http_alloc_large_header_buffer(r, 1); |
688 | 690 | |
727 | 729 | |
728 | 730 | if (rc == NGX_AGAIN) { |
729 | 731 | |
730 | if (r->header_in->last == r->header_in->end) { | |
732 | if (r->header_in->pos == r->header_in->end) { | |
731 | 733 | |
732 | 734 | rv = ngx_http_alloc_large_header_buffer(r, 0); |
733 | 735 | |
970 | 972 | if (hc->nfree) { |
971 | 973 | b = hc->free[--hc->nfree]; |
972 | 974 | |
975 | ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
976 | "http large header free: " PTR_FMT " " SIZE_T_FMT, | |
977 | b->pos, b->end - b->last); | |
978 | ||
973 | 979 | } else if (hc->nbusy < cscf->large_client_header_buffers.num) { |
974 | 980 | |
975 | 981 | if (hc->busy == NULL) { |
985 | 991 | if (b == NULL) { |
986 | 992 | return NGX_ERROR; |
987 | 993 | } |
994 | ||
995 | ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
996 | "http large header alloc: " PTR_FMT " " SIZE_T_FMT, | |
997 | b->pos, b->end - b->last); | |
988 | 998 | |
989 | 999 | } else { |
990 | 1000 | return NGX_DECLINED; |
1004 | 1014 | return NGX_OK; |
1005 | 1015 | } |
1006 | 1016 | |
1017 | ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1018 | "http large header copy: %d", r->header_in->pos - old); | |
1019 | ||
1007 | 1020 | new = b->start; |
1008 | 1021 | |
1009 | ngx_memcpy(new, old, r->header_in->last - old); | |
1022 | ngx_memcpy(new, old, r->header_in->pos - old); | |
1010 | 1023 | |
1011 | 1024 | b->pos = new + (r->header_in->pos - old); |
1012 | b->last = new + (r->header_in->last - old); | |
1025 | b->last = new + (r->header_in->pos - old); | |
1013 | 1026 | |
1014 | 1027 | if (request_line) { |
1015 | 1028 | r->request_start = new; |
1551 | 1564 | hc = r->http_connection; |
1552 | 1565 | b = r->header_in; |
1553 | 1566 | |
1554 | clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
1555 | ||
1556 | if (b->pos < b->last || clcf->keepalive_buffers) { | |
1557 | ||
1558 | /* | |
1559 | * the pipelined request or we like to keep the allocated | |
1560 | * ngx_http_request_t and the client header buffers while keepalive | |
1561 | */ | |
1567 | if (b->pos < b->last) { | |
1568 | ||
1569 | /* the pipelined request */ | |
1562 | 1570 | |
1563 | 1571 | if (b != c->buffer) { |
1564 | 1572 | |
1569 | 1577 | if (hc->free == NULL) { |
1570 | 1578 | hc->free = ngx_palloc(c->pool, |
1571 | 1579 | cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *)); |
1580 | ||
1572 | 1581 | if (hc->free == NULL) { |
1573 | 1582 | ngx_http_close_connection(c); |
1574 | 1583 | return; |
1590 | 1599 | ngx_http_close_request(r, 0); |
1591 | 1600 | c->data = hc; |
1592 | 1601 | |
1602 | clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
1593 | 1603 | ngx_add_timer(rev, clcf->keepalive_timeout); |
1594 | 1604 | |
1595 | 1605 | if (ngx_handle_level_read_event(rev) == NGX_ERROR) { |
1601 | 1611 | wev->event_handler = ngx_http_empty_handler; |
1602 | 1612 | |
1603 | 1613 | if (b->pos < b->last) { |
1604 | ||
1605 | /* the pipelined request */ | |
1606 | 1614 | |
1607 | 1615 | ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request"); |
1608 | 1616 | |
1614 | 1622 | |
1615 | 1623 | hc->pipeline = 0; |
1616 | 1624 | |
1617 | b->pos = b->last = b->start; | |
1618 | ||
1619 | if (!clcf->keepalive_buffers) { | |
1620 | ||
1621 | if (ngx_pfree(c->pool, r) == NGX_OK) { | |
1622 | hc->request = NULL; | |
1623 | } | |
1624 | ||
1625 | if (ngx_pfree(c->pool, c->buffer->start) == NGX_OK) { | |
1626 | c->buffer = NULL; | |
1627 | } | |
1628 | ||
1629 | if (hc->free) { | |
1630 | for (i = 0; i < hc->nfree; i++) { | |
1631 | ngx_pfree(c->pool, hc->free[i]); | |
1632 | hc->free[i] = NULL; | |
1633 | } | |
1634 | ||
1635 | hc->nfree = 0; | |
1636 | } | |
1637 | ||
1638 | if (hc->busy) { | |
1639 | for (i = 0; i < hc->nbusy; i++) { | |
1640 | ngx_pfree(c->pool, hc->busy[i]); | |
1641 | hc->busy[i] = NULL; | |
1642 | } | |
1643 | ||
1644 | hc->nbusy = 0; | |
1645 | } | |
1625 | if (ngx_pfree(c->pool, r) == NGX_OK) { | |
1626 | hc->request = NULL; | |
1627 | } | |
1628 | ||
1629 | b = c->buffer; | |
1630 | ||
1631 | if (ngx_pfree(c->pool, b->start) == NGX_OK) { | |
1632 | b->pos = NULL; | |
1633 | ||
1634 | } else { | |
1635 | b->pos = b->start; | |
1636 | b->last = b->start; | |
1637 | } | |
1638 | ||
1639 | ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: " PTR_FMT " %d", | |
1640 | hc->free, hc->nfree); | |
1641 | ||
1642 | if (hc->free) { | |
1643 | for (i = 0; i < hc->nfree; i++) { | |
1644 | ngx_pfree(c->pool, hc->free[i]); | |
1645 | hc->free[i] = NULL; | |
1646 | } | |
1647 | ||
1648 | hc->nfree = 0; | |
1649 | } | |
1650 | ||
1651 | ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: " PTR_FMT " %d", | |
1652 | hc->busy, hc->nbusy); | |
1653 | ||
1654 | if (hc->busy) { | |
1655 | for (i = 0; i < hc->nbusy; i++) { | |
1656 | ngx_pfree(c->pool, hc->busy[i]); | |
1657 | hc->busy[i] = NULL; | |
1658 | } | |
1659 | ||
1660 | hc->nbusy = 0; | |
1646 | 1661 | } |
1647 | 1662 | |
1648 | 1663 | rev->event_handler = ngx_http_keepalive_handler; |
1688 | 1703 | |
1689 | 1704 | static void ngx_http_keepalive_handler(ngx_event_t *rev) |
1690 | 1705 | { |
1706 | size_t size; | |
1691 | 1707 | ssize_t n; |
1692 | 1708 | ngx_buf_t *b; |
1693 | 1709 | ngx_connection_t *c; |
1703 | 1719 | return; |
1704 | 1720 | } |
1705 | 1721 | |
1722 | ctx = (ngx_http_log_ctx_t *) rev->log->data; | |
1723 | ||
1724 | #if (HAVE_KQUEUE) | |
1725 | ||
1726 | if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) { | |
1727 | if (rev->pending_eof) { | |
1728 | ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno, | |
1729 | "kevent() reported that client %s closed " | |
1730 | "keepalive connection", ctx->client); | |
1731 | ngx_http_close_connection(c); | |
1732 | return; | |
1733 | } | |
1734 | } | |
1735 | ||
1736 | #endif | |
1737 | ||
1706 | 1738 | hc = c->data; |
1707 | b = hc->nbusy ? hc->busy[0] : c->buffer; | |
1739 | b = c->buffer; | |
1740 | size = b->end - b->start; | |
1741 | ||
1742 | if (b->pos == NULL) { | |
1743 | if (!(b->pos = ngx_palloc(c->pool, size))) { | |
1744 | ngx_http_close_connection(c); | |
1745 | return; | |
1746 | } | |
1747 | ||
1748 | b->start = b->pos; | |
1749 | b->last = b->pos; | |
1750 | b->end = b->pos + size; | |
1751 | } | |
1708 | 1752 | |
1709 | 1753 | /* |
1710 | 1754 | * MSIE closes a keepalive connection with RST flag |
1714 | 1758 | c->log_error = NGX_ERROR_IGNORE_ECONNRESET; |
1715 | 1759 | ngx_set_socket_errno(0); |
1716 | 1760 | |
1717 | n = c->recv(c, b->last, b->end - b->last); | |
1761 | n = c->recv(c, b->last, size); | |
1718 | 1762 | c->log_error = NGX_ERROR_INFO; |
1719 | 1763 | |
1720 | 1764 | if (n == NGX_AGAIN) { |
1726 | 1770 | return; |
1727 | 1771 | } |
1728 | 1772 | |
1729 | ctx = (ngx_http_log_ctx_t *) rev->log->data; | |
1730 | 1773 | rev->log->handler = NULL; |
1731 | 1774 | |
1732 | 1775 | if (n == 0) { |