Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2003-03-20 19:09:44 +0300
committerIgor Sysoev <igor@sysoev.ru>2003-03-20 19:09:44 +0300
commitdc479b4d98d5b65b78689c5282a31c70efadd928 (patch)
tree7caf32d89eec03484b14ebe74dfefd2a80c8fa02
parent90ace68b69606b885578686e19d499a50d5e80b7 (diff)
nginx-0.0.1-2003-03-20-19:09:44 import
-rw-r--r--src/core/ngx_core.h2
-rw-r--r--src/core/ngx_string.c70
-rw-r--r--src/core/ngx_string.h1
-rw-r--r--src/event/modules/ngx_devpoll_module.c5
-rw-r--r--src/event/modules/ngx_iocp_module.c6
-rw-r--r--src/event/modules/ngx_kqueue_module.c53
-rw-r--r--src/event/modules/ngx_poll_module.c5
-rw-r--r--src/event/modules/ngx_select_module.c5
-rw-r--r--src/event/ngx_event.h19
-rw-r--r--src/event/ngx_event_accept.c1
-rw-r--r--src/event/ngx_event_acceptex.c1
-rw-r--r--src/event/ngx_event_recv.c130
-rw-r--r--src/http/modules/ngx_http_event_proxy_handler.c503
-rw-r--r--src/http/modules/ngx_http_event_proxy_handler.h52
-rw-r--r--src/http/modules/ngx_http_index_handler.c19
-rw-r--r--src/http/modules/ngx_http_log_handler.c1
-rw-r--r--src/http/modules/ngx_http_static_handler.c16
-rw-r--r--src/http/ngx_http.c33
-rw-r--r--src/http/ngx_http.h78
-rw-r--r--src/http/ngx_http_config.h28
-rw-r--r--src/http/ngx_http_core_module.c148
-rw-r--r--src/http/ngx_http_core_module.h15
-rw-r--r--src/http/ngx_http_event.c641
-rw-r--r--src/http/ngx_http_header_filter.c20
-rw-r--r--src/http/ngx_http_output_filter.c26
-rw-r--r--src/http/ngx_http_special_response.c81
-rw-r--r--src/http/ngx_http_write_filter.c19
27 files changed, 1303 insertions, 675 deletions
diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h
index 8170f858d..882b256eb 100644
--- a/src/core/ngx_core.h
+++ b/src/core/ngx_core.h
@@ -6,7 +6,7 @@
#define NGX_ERROR -1
#define NGX_DONE NGX_ERROR
#define NGX_AGAIN -2
-#define NGX_WAITING -3
+#define NGX_BUSY -3
#define NGX_DECLINED -4
#define NGX_ALERT -5
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
index 9e32b56f5..4beb11d67 100644
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -1,5 +1,6 @@
#include <ngx_config.h>
+#include <ngx_core.h>
#include <ngx_string.h>
@@ -19,3 +20,72 @@ char *ngx_cpystrn(char *dst, char *src, size_t n)
return dst;
}
+
+
+int ngx_atoi(char *line, size_t n)
+{
+ int value;
+
+ for (value = 0; n--; line++) {
+ if (*line < '0' || *line > '9') {
+ return NGX_ERROR;
+ }
+
+ value = value * 10 + (*line - '0');
+ }
+
+ return value;
+}
+
+
+#if 0
+char *ngx_psprintf(ngx_pool_t *p, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+
+ while (*fmt) {
+ switch(*fmt++) {
+ case '%':
+ switch(*fmt++) {
+ case 's':
+ s = va_arg(args, char *);
+ n += ngx_strlen(s);
+ break;
+
+ default:
+ n++;
+ }
+ default:
+ n++;
+ }
+ }
+
+ str = ngx_palloc(p, n);
+
+ va_start(args, fmt);
+
+ for (i = 0; i < n; i++) {
+ switch(*fmt++) {
+ case '%':
+ switch(*fmt++) {
+ case 's':
+ s = va_arg(args, char *);
+ while (str[i++] = s);
+ break;
+
+ default:
+ n++;
+ }
+ default:
+ str[i] = *fmt;
+ }
+ }
+
+ len += ngx_vsnprintf(errstr + len, sizeof(errstr) - len - 1, fmt, args);
+
+ va_end(args);
+
+}
+#endif
diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h
index c9d5d8049..8566d46e8 100644
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -49,6 +49,7 @@ typedef struct {
#define ngx_cpymem(dst, src, n) memcpy(dst, src, n) + n
char *ngx_cpystrn(char *dst, char *src, size_t n);
+int ngx_atoi(char *line, size_t n);
#endif /* _NGX_STRING_H_INCLUDED_ */
diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c
index e2e7750f1..fbbcf5992 100644
--- a/src/event/modules/ngx_devpoll_module.c
+++ b/src/event/modules/ngx_devpoll_module.c
@@ -236,6 +236,7 @@ int ngx_devpoll_process_events(ngx_log_t *log)
if ((int) timer != INFTIM) {
gettimeofday(&tv, NULL);
delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta;
+ ngx_event_expire_timers(delta);
} else {
if (events == 0) {
@@ -305,9 +306,5 @@ int ngx_devpoll_process_events(ngx_log_t *log)
}
}
- if ((int) timer != INFTIM) {
- ngx_event_expire_timers(delta);
- }
-
return NGX_OK;
}
diff --git a/src/event/modules/ngx_iocp_module.c b/src/event/modules/ngx_iocp_module.c
index f474c4c61..a84daa8e5 100644
--- a/src/event/modules/ngx_iocp_module.c
+++ b/src/event/modules/ngx_iocp_module.c
@@ -110,6 +110,7 @@ int ngx_iocp_process_events(ngx_log_t *log)
if (timer != INFINITE) {
delta = ngx_msec() - delta;
+ ngx_event_expire_timers(delta);
}
if (ovlp) {
@@ -118,6 +119,7 @@ int ngx_iocp_process_events(ngx_log_t *log)
ngx_log_debug(log, "iocp ev: %08x" _ ev);
if (ev == e) {
+ /* it's not AcceptEx() completion */
ev->ready = 1;
ev->available = bytes;
}
@@ -129,9 +131,5 @@ ngx_log_debug(log, "iocp ev: %08x" _ ev->event_handler);
}
}
- if (timer != INFINITE) {
- ngx_event_expire_timers(delta);
- }
-
return NGX_OK;
}
diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c
index b49eb62bb..bc2fe217e 100644
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -110,6 +110,13 @@ int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags)
ev->active = 1;
ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0;
+ /* The event addition or change should be always passed to a kernel
+ because there can be case when event was passed to a kernel then
+ added again to the change_list and then deleted from the change_list
+ by ngx_kqueue_del_event() so the first event still remains in a kernel */
+
+#if 0
+
if (nchanges > 0
&& ev->index < nchanges
&& change_list[ev->index].udata == ev)
@@ -118,12 +125,17 @@ int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags)
ngx_connection_t *c = (ngx_connection_t *) ev->data;
ngx_log_debug(ev->log, "kqueue add event: %d: ft:%d" _ c->fd _ event);
#endif
+
+ /* if the event is still not passed to a kernel we change it */
+
change_list[ev->index].filter = event;
change_list[ev->index].flags = flags;
return NGX_OK;
}
+#endif
+
return ngx_kqueue_set_event(ev, event, EV_ADD | flags);
}
@@ -142,6 +154,9 @@ int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags)
ngx_connection_t *c = (ngx_connection_t *) ev->data;
ngx_log_debug(ev->log, "kqueue del event: %d: ft:%d" _ c->fd _ event);
#endif
+
+ /* if the event is still not passed to a kernel we will not pass it */
+
if (ev->index < --nchanges) {
e = (ngx_event_t *) change_list[nchanges].udata;
change_list[ev->index] = change_list[nchanges];
@@ -151,6 +166,9 @@ int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags)
return NGX_OK;
}
+ /* when a socket is closed kqueue automatically deletes its filters
+ so we do not need to delete a event explicity before a socket closing */
+
if (flags & NGX_CLOSE_EVENT) {
return NGX_OK;
}
@@ -257,6 +275,11 @@ int ngx_kqueue_process_events(ngx_log_t *log)
gettimeofday(&tv, NULL);
delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta;
+ /* Expired timers must be deleted before the events processing
+ because the new timers can be added during the processing */
+
+ ngx_event_expire_timers(delta);
+
} else {
if (events == 0) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
@@ -295,6 +318,9 @@ int ngx_kqueue_process_events(ngx_log_t *log)
ev = (ngx_event_t *) event_list[i].udata;
+ /* It's a stale event from a socket
+ that was just closed in this iteration */
+
if (!ev->active) {
continue;
}
@@ -303,6 +329,29 @@ int ngx_kqueue_process_events(ngx_log_t *log)
case EVFILT_READ:
case EVFILT_WRITE:
+
+ if (ev->first) {
+ if (nchanges > 0
+ && ev->index < nchanges
+ && change_list[ev->index].udata == ev) {
+
+ /* It's a stale event from a socket that was just closed
+ in this iteration and during processing another socket
+ was opened with the same number by accept() or socket()
+ and its event has been added the event to the change_list
+ but has not been passed to a kernel. Nevertheless
+ there's small chance that ngx_kqueue_set_event() has
+ flushed the new event if the change_list was filled up.
+ In this very rare case we would get EAGAIN while
+ a reading or a writing */
+
+ continue;
+
+ } else {
+ ev->first = 0;
+ }
+ }
+
ev->available = event_list[i].data;
if (event_list[i].flags & EV_EOF) {
@@ -332,9 +381,5 @@ int ngx_kqueue_process_events(ngx_log_t *log)
}
}
- if (timer) {
- ngx_event_expire_timers(delta);
- }
-
return NGX_OK;
}
diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_poll_module.c
index 25319c806..23bcc3f33 100644
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_poll_module.c
@@ -175,6 +175,7 @@ int ngx_poll_process_events(ngx_log_t *log)
if ((int) timer != INFTIM) {
delta = ngx_msec() - delta;
+ ngx_event_expire_timers(delta);
} else {
if (ready == 0) {
@@ -259,9 +260,5 @@ int ngx_poll_process_events(ngx_log_t *log)
ngx_log_error(NGX_LOG_ALERT, log, 0, "poll ready != events");
}
- if ((int) timer != INFTIM) {
- ngx_event_expire_timers(delta);
- }
-
return NGX_OK;
}
diff --git a/src/event/modules/ngx_select_module.c b/src/event/modules/ngx_select_module.c
index 50d030c74..e7abfaa6c 100644
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -243,6 +243,7 @@ int ngx_select_process_events(ngx_log_t *log)
if (timer) {
delta = ngx_msec() - delta;
+ ngx_event_expire_timers(delta);
} else {
if (ready == 0) {
@@ -312,9 +313,5 @@ int ngx_select_process_events(ngx_log_t *log)
ngx_log_error(NGX_LOG_ALERT, log, 0, "select ready != events");
}
- if (timer) {
- ngx_event_expire_timers(delta);
- }
-
return NGX_OK;
}
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h
index c36306db7..4c553c001 100644
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -63,6 +63,7 @@ struct ngx_event_s {
#endif
unsigned write:1;
+ unsigned first:1;
unsigned active:1;
unsigned ready:1;
unsigned timedout:1;
@@ -179,8 +180,8 @@ typedef struct {
#define NGX_USE_LEVEL_EVENT 0x00010000
-/* Event filter is deleted before closing file. Has no meaning
- for select, poll, epoll.
+/* Event filter is deleted before closing file.
+ Has no meaning for select, poll, epoll.
kqueue: kqueue deletes event filters for file that closed
so we need only to delete filters in user-level batch array
@@ -193,16 +194,24 @@ typedef struct {
#define NGX_READ_EVENT EVFILT_READ
#define NGX_WRITE_EVENT EVFILT_WRITE
+#define NGX_ENABLE_EVENT EV_ENABLE
+#define NGX_DISABLE_EVENT EV_DISABLE
+
+/* NGX_CLOSE_EVENT is the module flag and it would not go into a kernel
+ so we need to choose the value that would not interfere with any existent
+ and future flags. kqueue has such values - EV_FLAG1, EV_EOF and EV_ERROR.
+ They are reserved and cleared on a kernel entrance */
+#undef NGX_CLOSE_EVENT
+#define NGX_CLOSE_EVENT EV_FLAG1
+
#define NGX_LEVEL_EVENT 0
#define NGX_ONESHOT_EVENT EV_ONESHOT
+#define NGX_CLEAR_EVENT EV_CLEAR
#ifndef HAVE_CLEAR_EVENT
#define HAVE_CLEAR_EVENT 1
#endif
-#if (HAVE_CLEAR_EVENT)
-#define NGX_CLEAR_EVENT EV_CLEAR
-#endif
#elif (HAVE_POLL) || (HAVE_DEVPOLL)
diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c
index 3bb141e2f..56e90a3f9 100644
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -117,6 +117,7 @@ int ngx_event_accept(ngx_event_t *ev)
c->fd = s;
c->unexpected_eof = 1;
wev->write = 1;
+ rev->first = wev->first = 1;
#if (HAVE_AIO_EVENT)
if (!(ngx_event_flags & NGX_HAVE_AIO_EVENT)) {
diff --git a/src/event/ngx_event_acceptex.c b/src/event/ngx_event_acceptex.c
index 0654c80fa..07d999388 100644
--- a/src/event/ngx_event_acceptex.c
+++ b/src/event/ngx_event_acceptex.c
@@ -104,6 +104,7 @@ int ngx_event_post_acceptex(ngx_listen_t *ls, int n)
c->unexpected_eof = 1;
wev->write = 1;
+ rev->first = wev->first = 1;
c->handler = ls->handler;
rev->event_handler = ngx_event_acceptex;
diff --git a/src/event/ngx_event_recv.c b/src/event/ngx_event_recv.c
index 46c165af1..c083e8f61 100644
--- a/src/event/ngx_event_recv.c
+++ b/src/event/ngx_event_recv.c
@@ -8,18 +8,13 @@
ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size)
{
- int n;
- ngx_err_t err;
- ngx_event_t *ev;
+ ssize_t n;
+ ngx_err_t err;
+ ngx_event_t *ev;
ev = c->read;
- if (ev->timedout) {
- ngx_set_socket_errno(NGX_ETIMEDOUT);
- ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, "recv() failed");
- return NGX_ERROR;
- }
-
+/* DEBUG */
#if (HAVE_KQUEUE)
if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
ngx_log_debug(c->log, "ngx_event_recv: eof:%d, avail:%d, err:%d" _
@@ -30,54 +25,77 @@ ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size)
#if (USE_KQUEUE)
if (ev->eof && ev->available == 0) {
- if (ev->error) {
- ngx_set_socket_errno(ev->error);
- if (ev->error == NGX_ECONNRESET && ev->ignore_econnreset) {
- return 0;
- }
+ if (ev->error == 0) {
+ return 0;
+ }
+
+ ngx_set_socket_errno(ev->error);
+ err = ev->error;
+ n = -1;
+
+ } else {
+ n = ngx_recv(c->fd, buf, size, 0);
+
+ if (n == -1) {
+ err = ngx_socket_errno;
+ }
+ }
+
+ if (n == -1) {
+ ev->ready = 0;
- ngx_log_error(NGX_LOG_ERR, c->log, ev->error,
- "recv() failed");
- return NGX_ERROR;
+ if (err == NGX_ECONNRESET && ev->ignore_econnreset) {
+ return 0;
}
- return 0;
+ if (err == NGX_EAGAIN) {
+ ngx_log_error(NGX_LOG_INFO, c->log, err, "recv() returned EAGAIN");
+ return NGX_AGAIN;
+ }
+
+ ngx_log_error(NGX_LOG_ERR, c->log, err, "recv() failed");
+ return NGX_ERROR;
}
-#elif (HAVE_KQUEUE)
+ ev->available -= n;
+ if (ev->available == 0) {
+ ev->ready = 0;
+ }
- if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
- if (ev->eof && ev->available == 0) {
- if (ev->error) {
- ngx_set_socket_errno(ev->error);
+ return n;
- if (ev->error == NGX_ECONNRESET && ev->ignore_econnreset) {
- return 0;
- }
+#elif (HAVE_KQUEUE)
- ngx_log_error(NGX_LOG_ERR, c->log, ev->error,
- "recv() failed");
- return NGX_ERROR;
- }
+ if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT)
+ && ev->eof && ev->available == 0) {
+ if (ev->error == 0) {
return 0;
}
- }
-#endif
+ ngx_set_socket_errno(ev->error);
+ err = ev->error;
+ n = -1;
- n = ngx_recv(c->fd, buf, size, 0);
+ } else {
+ n = ngx_recv(c->fd, buf, size, 0);
+ngx_log_debug(c->log, "ngx_event_recv: read:%d:%d" _ n _ size);
+
+ if (n == -1) {
+ err = ngx_socket_errno;
+ }
+ }
if (n == -1) {
- err = ngx_socket_errno;
+ ev->ready = 0;
- if (ev->error == NGX_ECONNRESET && ev->ignore_econnreset) {
+ if (err == NGX_ECONNRESET && ev->ignore_econnreset) {
return 0;
}
if (err == NGX_EAGAIN) {
- ngx_log_error(NGX_LOG_INFO, c->log, err, "recv() returns EAGAIN");
+ ngx_log_error(NGX_LOG_INFO, c->log, err, "recv() returned EAGAIN");
return NGX_AGAIN;
}
@@ -85,17 +103,45 @@ ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size)
return NGX_ERROR;
}
-#if (USE_KQUEUE)
+ if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
+ ev->available -= n;
+ if (ev->available == 0) {
+ ev->ready = 0;
+ }
- ev->available -= n;
+ } else if ((size_t) n < size) {
+ ev->ready = 0;
+ }
-#elif (HAVE_KQUEUE)
+ return n;
- if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
- ev->available -= n;
+#else /* not kqueue */
+
+ n = ngx_recv(c->fd, buf, size, 0);
+
+ if (n == -1) {
+ err = ngx_socket_errno;
+
+ ev->ready = 0;
+
+ if (err == NGX_ECONNRESET && ev->ignore_econnreset) {
+ return 0;
+ }
+
+ if (err == NGX_EAGAIN) {
+ ngx_log_error(NGX_LOG_INFO, c->log, err, "recv() returned EAGAIN");
+ return NGX_AGAIN;
+ }
+
+ ngx_log_error(NGX_LOG_ERR, c->log, err, "recv() failed");
+ return NGX_ERROR;
}
-#endif
+ if ((size_t) n < size) {
+ ev->ready = 0;
+ }
return n;
+
+#endif
}
diff --git a/src/http/modules/ngx_http_event_proxy_handler.c b/src/http/modules/ngx_http_event_proxy_handler.c
index 38fbb0694..ac475e3dc 100644
--- a/src/http/modules/ngx_http_event_proxy_handler.c
+++ b/src/http/modules/ngx_http_event_proxy_handler.c
@@ -14,6 +14,23 @@
#include <ngx_http_event_proxy_handler.h>
+static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r);
+static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p,
+ struct sockaddr_in *addr,
+ char *addr_text);
+static int ngx_http_proxy_send_request(ngx_event_t *ev);
+
+static int ngx_http_proxy_init_response(ngx_event_t *ev);
+static int ngx_http_proxy_read_response_header(ngx_event_t *ev);
+static int ngx_http_proxy_process_status_line(ngx_http_request_t *r,
+ ngx_http_proxy_ctx_t *p);
+
+static int ngx_http_proxy_read_response_body(ngx_event_t *ev);
+static int ngx_http_proxy_write_to_client(ngx_event_t *ev);
+
+static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx);
+
+
static ngx_command_t ngx_http_proxy_commands[] = {
{ngx_string("proxy_large_header"),
@@ -27,19 +44,13 @@ static ngx_command_t ngx_http_proxy_commands[] = {
static ngx_http_module_t ngx_http_proxy_module_ctx = {
- NGX_HTTP_MODULE,
-
NULL, /* create server config */
NULL, /* init server config */
+
NULL, /* create location config */
NULL, /* merge location config */
- NULL, /* translate handler */
-
- NULL, /* output header filter */
- NULL, /* next output header filter */
- NULL, /* output body filter */
- NULL /* next output body filter */
+ NULL /* init filters */
};
@@ -52,25 +63,16 @@ ngx_module_t ngx_http_proxy_module = {
};
-
-static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r);
-static int ngx_http_proxy_connect(ngx_http_request_t *r,
- struct sockaddr_in *addr,
- char *addr_text);
-static int ngx_http_proxy_send_request(ngx_event_t *ev);
-
-static int ngx_http_proxy_init_response(ngx_event_t *ev);
-static int ngx_http_proxy_read_response_header(ngx_event_t *ev);
-static int ngx_http_proxy_process_status_line(ngx_http_request_t *r,
- ngx_http_proxy_ctx_t *p);
-
-static int ngx_http_proxy_read_response_body(ngx_event_t *ev);
-static int ngx_http_proxy_write_to_client(ngx_event_t *ev);
-
-static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx);
+static ngx_str_t http_methods[] = {
+ ngx_string("GET "),
+ ngx_string("HEAD "),
+ ngx_string("POST ")
+};
-static char conn_close[] = "Connection: close" CRLF;
+static char http_version[] = " HTTP/1.0" CRLF;
+static char host_header[] = "Host: ";
+static char conn_close_header[] = "Connection: close" CRLF;
/* AF_INET only */
@@ -78,32 +80,57 @@ static char conn_close[] = "Connection: close" CRLF;
int ngx_http_proxy_handler(ngx_http_request_t *r)
{
- struct sockaddr_in addr;
- ngx_chain_t *chain;
- ngx_http_proxy_ctx_t *p;
+ struct sockaddr_in addr;
+ ngx_chain_t *chain;
+ ngx_http_proxy_ctx_t *p;
+ ngx_http_log_ctx_t *hcx;
+ ngx_http_proxy_log_ctx_t *lcx;
p = (ngx_http_proxy_ctx_t *)
- ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx);
+ ngx_http_get_module_ctx(r, ngx_http_proxy_module);
if (p == NULL) {
- ngx_http_create_ctx(r, p, ngx_http_proxy_module_ctx,
+ ngx_http_create_ctx(r, p, ngx_http_proxy_module,
sizeof(ngx_http_proxy_ctx_t),
NGX_HTTP_INTERNAL_SERVER_ERROR);
}
+ p->request = r;
+
+ ngx_test_null(p->log, ngx_palloc(r->pool, sizeof(ngx_log_t)),
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+ ngx_memcpy(p->log, r->connection->log, sizeof(ngx_log_t));
+ ngx_test_null(lcx, ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_log_ctx_t)),
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+
+ p->log->data = lcx;
+ hcx = r->connection->log->data;
+ lcx->client = hcx->client;
+
+ /*
+ if (!resolved) {
+ return ngx_dns_resolve(name, handler, p, r->pool, p->log);
+ }
+ */
+
chain = ngx_http_proxy_create_request(r);
if (chain == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
+ /* TODO: duplicate hunks and chain if there is backend farm */
p->out = chain;
ngx_memzero(&addr, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
+#if 0
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+#else
+ addr.sin_addr.s_addr = inet_addr("192.168.10.2");
+#endif
addr.sin_port = htons(9000);
- return ngx_http_proxy_connect(r, &addr, "connecting to 127.0.0.1:9000");
+ return ngx_http_proxy_connect(p, &addr, "connecting to 127.0.0.1:9000");
}
@@ -125,7 +152,7 @@ static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r)
/* TODO: Host length */
/* "Connection: close\r\n" */
- len += sizeof(conn_close) - 1;
+ len += sizeof(conn_close_header) - 1;
header = (ngx_table_elt_t *) r->headers_in.headers->elts;
for (i = 0; i < r->headers_in.headers->nelts; i++) {
@@ -146,16 +173,54 @@ static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r)
ngx_test_null(hunk, ngx_create_temp_hunk(r->pool, len, 0, 0), NULL);
ngx_add_hunk_to_chain(chain, hunk, r->pool, NULL);
- /* STUB: "method p->url HTTP/1.0" */
+#if 0
+
+ /* the request line */
+
+ ngx_memcpy(hunk->last, http_methods[p->method - 1].data,
+ http_methods[p->method - 1].len);
+ hunk->last += http_methods[p->method - 1].len;
+
+ ngx_memcpy(hunk->last, p->uri_start.data, p->uri_start.len);
+ hunk->last += p->uri_start.len;
+
+ ngx_memcpy(hunk->last, p->uri_rest.data, p->uri_rest.len);
+ hunk->last += p->uri_rest.len;
+
+ if (r->args) {
+ *(hunk->last++) = '?';
+ ngx_memcpy(hunk->last, r->uri_args.data, r->uri_args.len);
+ hunk->last += r->uri_args.len;
+ }
+
+ ngx_memcpy(hunk->last, http_version, sizeof(http_version) - 1);
+ hunk->last += sizeof(http_version) - 1;
+
+ /* the 'Host' header */
+
+ ngx_memcpy(hunk->last, host_header, sizeof(host_header) - 1);
+ hunk->last += sizeof(host_header) - 1;
+
+ ngx_memcpy(hunk->last, p->host.data, p->host.len);
+ hunk->last += p->host.len;
+
+ *(hunk->last++) = CR; *(hunk->last++) = LF;
+
+ /* the 'Connection: close' header */
+
+ ngx_memcpy(hunk->last, conn_close_header, sizeof(conn_close_header) - 1);
+ hunk->last += sizeof(conn_close_header) - 1;
+
+#else
ngx_memcpy(hunk->last, r->request_line.data, r->request_line.len);
hunk->last += r->request_line.len;
*(hunk->last++) = CR; *(hunk->last++) = LF;
- /* TODO: Host header */
+ ngx_memcpy(hunk->last, conn_close_header, sizeof(conn_close_header) - 1);
+ hunk->last += sizeof(conn_close_header) - 1;
- ngx_memcpy(hunk->last, conn_close, sizeof(conn_close) - 1);
- hunk->last += sizeof(conn_close) - 1;
+#endif
for (i = 0; i < r->headers_in.headers->nelts; i++) {
if (&header[i] == r->headers_in.host) {
@@ -190,7 +255,197 @@ static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r)
}
-static int ngx_http_proxy_connect(ngx_http_request_t *r,
+#if 0
+
+client_read()
+ if (!ev->write) {
+ if error close upstream ?
+ else block it
+ }
+
+
+static int ngx_http_proxy_process_upstream(ngx_event_t *ev)
+{
+ again = 0;
+
+ do {
+
+ if (p->state_write_upstream_handler ==
+ ngx_http_proxy_connect_to_upstream) {
+ if (!get_cached_connection())
+ get_next_upstream(p);
+ }
+
+ if (ev->write) {
+
+ /* ngx_http_proxy_connect_to_upstream()
+ ngx_http_proxy_send_request() */
+
+ rc = p->state_write_upstream_handler(p);
+
+ } else {
+
+ /* ngx_http_proxy_read_response() */
+
+ rc = p->state_read_upstream_handler(p);
+ }
+
+ if (rc == NGX_BUSY || rc == NGX_AGAIN || rc == NGX_OK) {
+ return rc;
+ }
+
+ if (rc == NGX_ERROR) {
+ return ngx_http_proxy_finalize_request(p,
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+ }
+
+ /* This NGX_HTTP_INTERNAL_SERVER_ERROR is sent by an upstream */
+
+ if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT
+ || (rc == NGX_HTTP_INTERNAL_SERVER_ERROR && lcf->retry_500)
+ {
+ ngx_http_close_connection(ev);
+
+ if (p->upstream->amount > 1) {
+ /* Here is the race condition on SMP machine
+ when the upstreams are shared between threads or processes
+ but it's not serious */
+ p->upstream->upstreams[p->cur_upstream].fails++;
+ }
+
+ p->upstreams--;
+
+ if (p->upstreams == 0) {
+ return ngx_http_proxy_finalize_request(p, rc);
+ }
+
+ p->cur_upstream++;
+ if (p->cur_upstream > p->upstream->amount) {
+ p->cur_upstream = 0;
+ }
+
+ p->state_read_upstream_handler = ignore;
+ p->state_write_upstream_handler =
+ ngx_http_proxy_connect_to_upstream;
+ again = 1;
+ }
+
+ if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) {
+ ???
+ }
+
+ } while (again);
+
+ return NGX_BUSY;
+}
+
+
+static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p)
+{
+ ngx_socket_t s;
+ ngx_connection_t *c;
+ ngx_http_log_ctx_t *lcx;
+
+ lcx = p->log->data;
+ lcx->action = "connecting to an upstream";
+ lcx->upstream = p->upstream.data;
+ p->log->handler = ngx_http_proxy_log_error;
+
+ s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0);
+ if (s == -1) {
+ ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno,
+ ngx_socket_n " failed");
+ return NGX_ERROR;
+ }
+
+ if (lcf->rcvbuf) {
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
+ (const void *) &rcvbuf, sizeof(int)) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno,
+ "setsockopt(SO_RCVBUF) failed");
+
+ if (ngx_close_socket(s) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno,
+ ngx_close_socket_n " failed");
+ }
+
+ return NGX_ERROR;
+ }
+ }
+
+ if (ngx_nonblocking(s) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno,
+ ngx_nonblocking_n " failed");
+
+ if (ngx_close_socket(s) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno,
+ ngx_close_socket_n " failed");
+ }
+
+ return NGX_ERROR;
+ }
+
+ rc = connect(s, (struct sockaddr *) p->addr, sizeof(struct sockaddr_in));
+
+ if (rc == -1) {
+ err = ngx_socket_errno;
+ if (err != NGX_EINPROGRESS) {
+ ngx_log_error(NGX_LOG_CRIT, p->log, err, "connect() failed");
+
+ if (ngx_close_socket(s) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno,
+ ngx_close_socket_n " failed");
+ }
+
+ return NGX_HTTP_BAD_GATEWAY;
+ }
+ }
+
+ c = &ngx_connections[s];
+ rev = &ngx_read_events[s];
+ wev = &ngx_write_events[s];
+
+ ngx_memzero(rev, sizeof(ngx_event_t));
+ ngx_memzero(wev, sizeof(ngx_event_t));
+ ngx_memzero(c, sizeof(ngx_connection_t));
+
+ rev->index = wev->index = NGX_INVALID_INDEX;
+
+ rev->data = wev->data = c;
+ c->read = rev;
+ c->write = wev;
+
+ rev->first = wev->first = 1;
+
+ c->data = p->request;
+ p->connection = c;
+
+ c->fd = s;
+
+ rev->log = wev->log = c->log = p->log;
+
+ ngx_test_null(c->pool, ngx_create_pool(lcf->conn_pool_size, p->log),
+ NGX_ERROR);
+
+}
+
+#if 0
+connect_upstream()
+ get next upstream
+ init connect to upstream
+ if error return error
+ if ok send_request();
+ if inprogress p->state_handler = send_request, return busy
+
+send_request()
+ if timeout inc fail counter
+ p->state_handler = connect_upstream, return 504
+#endif
+
+#endif
+
+
+static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p,
struct sockaddr_in *addr,
char *addr_text)
{
@@ -201,7 +456,7 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
ngx_connection_t *c, *pc;
ngx_http_log_ctx_t *ctx;
- c = r->connection;
+ c = p->request->connection;
ctx = c->log->data;
ctx->action = addr_text;
@@ -253,7 +508,7 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
ngx_close_socket_n " failed");
}
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ return NGX_HTTP_BAD_GATEWAY;
}
}
@@ -265,16 +520,21 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
ngx_memzero(wev, sizeof(ngx_event_t));
ngx_memzero(pc, sizeof(ngx_connection_t));
+ rev->index = wev->index = NGX_INVALID_INDEX;
+
rev->data = wev->data = pc;
pc->read = rev;
pc->write = wev;
- pc->data = r;
+ pc->data = p->request;;
+ p->connection = pc;
pc->fd = s;
pc->servers = c->servers;
- pc->log = rev->log = wev->log = c->log;
+ ngx_test_null(pc->log, ngx_palloc(c->pool, sizeof(ngx_log_t)), NGX_OK);
+ ngx_memcpy(pc->log, c->log, sizeof(ngx_log_t));
+ rev->log = wev->log = pc->log;
ngx_test_null(pc->pool,
ngx_create_pool(/* STUB */ 1024 /**/, pc->log),
@@ -282,6 +542,8 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
wev->event_handler = ngx_http_proxy_send_request;
rev->event_handler = ngx_http_proxy_init_response;
+ rev->close_handler = wev->close_handler = ngx_event_close_connection;
+
#if (USE_KQUEUE)
@@ -314,18 +576,25 @@ static int ngx_http_proxy_connect(ngx_http_request_t *r,
/* TODO: aio, iocp */
+ /* The connection has been established */
+ if (rc == 0) {
+ wev->write = 1;
+ wev->ready = 1;
+
+ return ngx_http_proxy_send_request(wev);
+ }
+
/* The connection is in a progress */
- if (rc == -1) {
- /* TODO: oneshot */
- if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_ONESHOT_EVENT) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
+
+ /* TODO: oneshot */
+ if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_ONESHOT_EVENT) != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- wev->write = 1;
- wev->ready = 1;
+ wev->timer_set = 1;
+ ngx_add_timer(wev, /* STUB: lcf->connect_timeout */ 10000);
- return ngx_http_proxy_send_request(wev);
+ return NGX_BUSY;
}
@@ -339,7 +608,11 @@ static int ngx_http_proxy_send_request(ngx_event_t *ev)
c = (ngx_connection_t *) ev->data;
r = (ngx_http_request_t *) c->data;
p = (ngx_http_proxy_ctx_t *)
- ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx);
+ ngx_http_get_module_ctx(r, ngx_http_proxy_module);
+
+ if (ev->timedout) {
+ return ngx_http_proxy_error(r, p, NGX_HTTP_GATEWAY_TIME_OUT);
+ }
chain = ngx_write_chain(c, p->out, 0);
if (chain == (ngx_chain_t *) -1) {
@@ -348,7 +621,7 @@ static int ngx_http_proxy_send_request(ngx_event_t *ev)
p->out = chain;
- return NGX_WAITING;
+ return NGX_BUSY;
}
@@ -368,7 +641,7 @@ static int ngx_http_proxy_init_response(ngx_event_t *ev)
}
p = (ngx_http_proxy_ctx_t *)
- ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx);
+ ngx_http_get_module_ctx(r, ngx_http_proxy_module);
ngx_test_null(p->header_in,
ngx_create_temp_hunk(r->pool,
@@ -407,7 +680,7 @@ static int ngx_http_proxy_read_response_header(ngx_event_t *ev)
c = (ngx_connection_t *) ev->data;
r = (ngx_http_request_t *) c->data;
p = (ngx_http_proxy_ctx_t *)
- ngx_http_get_module_ctx(r, ngx_http_proxy_module);
+ ngx_http_get_module_ctx(r, ngx_http_proxy_module);
if (ev->timedout) {
return ngx_http_proxy_error(r, p, NGX_HTTP_GATEWAY_TIME_OUT);
@@ -516,7 +789,7 @@ static int ngx_http_proxy_read_response_header(ngx_event_t *ev)
return ngx_http_proxy_read_response_body(ev);
}
- return NGX_WAITING;
+ return NGX_BUSY;
}
@@ -575,7 +848,7 @@ static int ngx_http_proxy_read_response_body(ngx_event_t *ev)
c = (ngx_connection_t *) ev->data;
r = (ngx_http_request_t *) c->data;
p = (ngx_http_proxy_ctx_t *)
- ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx);
+ ngx_http_get_module_ctx(r, ngx_http_proxy_module);
if (p->hunks.nelts > 0) {
h = ((ngx_hunk_t **) p->hunks.elts)[p->hunks.nelts - 1];
@@ -631,7 +904,7 @@ static int ngx_http_proxy_read_response_body(ngx_event_t *ev)
ngx_log_debug(c->log, "READ:%d" _ n);
if (n == NGX_AGAIN) {
- return NGX_WAITING;
+ return NGX_BUSY;
}
if (n == NGX_ERROR) {
@@ -660,7 +933,7 @@ static int ngx_http_proxy_read_response_body(ngx_event_t *ev)
return ngx_http_proxy_write_to_client(c->write);
}
- /* STUB */ return NGX_WAITING;
+ /* STUB */ return NGX_BUSY;
}
@@ -675,7 +948,7 @@ static int ngx_http_proxy_write_to_client(ngx_event_t *ev)
c = (ngx_connection_t *) ev->data;
r = (ngx_http_request_t *) c->data;
p = (ngx_http_proxy_ctx_t *)
- ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx);
+ ngx_http_get_module_ctx(r, ngx_http_proxy_module);
do {
h = ((ngx_hunk_t **) p->hunks.elts)[p->hunk_n];
@@ -706,6 +979,17 @@ static int ngx_http_proxy_error(ngx_http_request_t *r, ngx_http_proxy_ctx_t *p,
}
+static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len)
+{
+ ngx_http_proxy_log_ctx_t *lcx = (ngx_http_proxy_log_ctx_t *) data;
+
+ return ngx_snprintf(buf, len,
+ " while %s, upstream: %s, client: %s, URL: %s",
+ lcx->action, lcx->upstream, lcx->client, lcx->url);
+}
+
+
+
static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx)
{
char ch;
@@ -864,3 +1148,106 @@ static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx)
return NGX_AGAIN;
}
}
+
+
+#if 0
+
+static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd,
+ char *conf)
+{
+ ngx_http_proxy_conf_t *lcf = (ngx_http_proxy_conf_t *) conf;
+ char *url;
+ ngx_str_t *value;
+ ngx_http_proxy_pass_t *pass;
+
+ value = (ngx_str_t *) cf->args->elts;
+ url = value[1].data;
+
+ ngx_test_null(pass, ngx_push_array(lcf->proxy_pass), NGX_CONF_ERROR);
+
+ if (ngx_strncasecmp(url, "http://", 7) == 0) {
+ "invalid prefix in URL %s", url;
+ }
+
+ err = ngx_http_proxy_parse_upstream(url, u);
+
+ if (err) {
+ "%s %s", err, url;
+ }
+
+ h = ngx_gethostbyname(cmd->pool, u->host);
+
+ return NULL;
+}
+
+#endif
+
+
+static char *ngx_http_proxy_parse_upstream(ngx_str_t *url,
+ ngx_http_proxy_upstream_url_t *u)
+{
+ size_t i;
+
+ if (url->data[0] == ':' || url->data[0] == '/') {
+ return "invalid upstream URL";
+ }
+
+ u->host.data = url->data;
+ u->host_header.data = url->data;
+
+ for (i = 1; i < url->len; i++) {
+ if (url->data[i] == ':') {
+ u->port_name.data = &url->data[i];
+ u->host.len = i;
+ }
+
+ if (url->data[i] == '/') {
+ u->uri.data = &url->data[i];
+ u->uri.len = url->len - i;
+ u->host_header.len = i;
+
+ if (u->host.len == 0) {
+ u->host.len = i;
+ }
+
+ if (u->port_name.data == NULL) {
+ return NULL;
+ }
+
+ u->port_name.len = &url->data[i] - u->port_name.data;
+
+ if (u->port_name.len > 0) {
+ u->port = ngx_atoi(u->port_name.data, u->port_name.len);
+ if (u->port > 0) {
+ return NULL;
+ }
+ }
+
+ return "invalid port in upstream URL";
+ }
+ }
+
+ if (u->host.len == 0) {
+ u->host.len = i;
+ }
+
+ u->host_header.len = i;
+
+ u->uri.data = "/";
+ u->uri.len = 1;
+
+ if (u->port_name.data == NULL) {
+ return NULL;
+ }
+
+ u->port_name.len = &url->data[i] - u->port_name.data;
+
+ if (u->port_name.len > 0) {
+ u->port = ngx_atoi(u->port_name.data, u->port_name.len);
+ if (u->port > 0) {
+ return NULL;
+ }
+ }
+
+ return "invalid port in upstream URL";
+}
diff --git a/src/http/modules/ngx_http_event_proxy_handler.h b/src/http/modules/ngx_http_event_proxy_handler.h
index 0a438044a..60e1e33cc 100644
--- a/src/http/modules/ngx_http_event_proxy_handler.h
+++ b/src/http/modules/ngx_http_event_proxy_handler.h
@@ -20,6 +20,41 @@ typedef struct {
} ngx_http_proxy_loc_conf_t;
+typedef struct {
+ ngx_str_t host;
+ ngx_str_t uri;
+ ngx_str_t host_header;
+ ngx_str_t port_name;
+ int port;
+} ngx_http_proxy_upstream_url_t;
+
+
+typedef struct {
+ struct sockaddr_in;
+ ngx_str_t name;
+ time_t access;
+ int fails;
+} ngx_http_proxy_upstream_t;
+
+
+typedef struct {
+ int amount;
+ ngx_http_proxy_upstream_t *upstreams;
+} ngx_http_proxy_upstream_farm_t;
+
+
+#if 0
+/* location /one/ { proxy_pass http://localhost:9000/two/; } */
+
+typedef struct {
+ /* "/one/" */
+ /* "http://localhost:9000/two/" */
+ /* "/two/" */
+ *upstream_farm;
+} ngx_http_proxy_pass_t;
+#endif
+
+
typedef struct ngx_http_proxy_ctx_s ngx_http_proxy_ctx_t;
struct ngx_http_proxy_ctx_s {
@@ -30,9 +65,16 @@ struct ngx_http_proxy_ctx_s {
int hunk_n;
- ngx_connection_t *connection;
+ ngx_connection_t *connection;
+ ngx_http_request_t *request;
ngx_http_proxy_headers_in_t *headers_in;
+ ngx_http_proxy_upstream_farm_t *upstream;
+ int cur_upstream;
+ int upstreams;
+
+ ngx_log_t *log;
+
ngx_hunk_t *header_in;
int state;
int status;
@@ -43,6 +85,14 @@ struct ngx_http_proxy_ctx_s {
};
+typedef struct {
+ char *action;
+ char *upstream;
+ char *client;
+ char *url;
+} ngx_http_proxy_log_ctx_t;
+
+
extern ngx_module_t ngx_http_proxy_module;
diff --git a/src/http/modules/ngx_http_index_handler.c b/src/http/modules/ngx_http_index_handler.c
index ebbeac987..722ddecf1 100644
--- a/src/http/modules/ngx_http_index_handler.c
+++ b/src/http/modules/ngx_http_index_handler.c
@@ -35,20 +35,13 @@ static ngx_command_t ngx_http_index_commands[] = {
ngx_http_module_t ngx_http_index_module_ctx = {
- NGX_HTTP_MODULE,
-
NULL, /* create server config */
NULL, /* init server config */
+
ngx_http_index_create_conf, /* create location config */
ngx_http_index_merge_conf, /* merge location config */
- NULL, /* translate handler */
-
- NULL, /* output header filter */
- NULL, /* next output header filter */
- NULL, /* output body filter */
- NULL, /* next output body filter */
-
+ NULL /* init filters */
};
@@ -288,18 +281,18 @@ static char *ngx_http_index_merge_conf(ngx_pool_t *p, void *parent, void *child)
static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
char *conf)
{
- ngx_http_index_conf_t *icf = (ngx_http_index_conf_t *) conf;
+ ngx_http_index_conf_t *lcf = (ngx_http_index_conf_t *) conf;
int i;
ngx_str_t *index, *value;
value = (ngx_str_t *) cf->args->elts;
for (i = 1; i < cf->args->nelts; i++) {
- ngx_test_null(index, ngx_push_array(icf->indices), NGX_CONF_ERROR);
+ ngx_test_null(index, ngx_push_array(lcf->indices), NGX_CONF_ERROR);
index->len = value[i].len;
index->data = value[i].data;
- if (icf->max_index_len < index->len) {
- icf->max_index_len = index->len;
+ if (lcf->max_index_len < index->len) {
+ lcf->max_index_len = index->len;
}
}
diff --git a/src/http/modules/ngx_http_log_handler.c b/src/http/modules/ngx_http_log_handler.c
index e087adea3..44df45302 100644
--- a/src/http/modules/ngx_http_log_handler.c
+++ b/src/http/modules/ngx_http_log_handler.c
@@ -5,6 +5,7 @@
#include <ngx_alloc.h>
#include <ngx_time.h>
#include <ngx_http.h>
+#include <ngx_http_config.h>
ngx_http_module_t ngx_http_log_module;
diff --git a/src/http/modules/ngx_http_static_handler.c b/src/http/modules/ngx_http_static_handler.c
index 7b494ee7d..c8a014164 100644
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -5,23 +5,11 @@
#include <ngx_file.h>
#include <ngx_hunk.h>
#include <ngx_http.h>
+#include <ngx_http_config.h>
#include <ngx_http_output_filter.h>
-ngx_http_module_t ngx_http_static_module;
-
-#if 0
-/* STUB */
-static ngx_http_static_ctx_t module_ctx;
-
-void ngx_http_static_init()
-{
- module_ctx.out = NULL;
-
- ngx_http_static_module.ctx = &module_ctx;
-}
-/* */
-#endif
+ngx_http_module_t ngx_http_static_module;
int ngx_http_static_handler(ngx_http_request_t *r)
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 954b1cfc0..9c648f70a 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -28,6 +28,7 @@ int ngx_http_large_client_header = 1;
int ngx_http_url_in_error_log = 1;
+ngx_array_t ngx_http_translate_handlers;
ngx_array_t ngx_http_index_handlers;
@@ -61,13 +62,12 @@ ngx_module_t ngx_http_module = {
static void ngx_http_init_filters(ngx_pool_t *pool, ngx_module_t **modules)
{
- int i;
- ngx_http_module_t *module;
- int (*ohf)(ngx_http_request_t *r);
- int (*obf)(ngx_http_request_t *r, ngx_chain_t *ch);
+ int i;
+ ngx_http_module_t *module;
+ ngx_http_conf_filter_t cf;
- ohf = NULL;
- obf = NULL;
+ cf.output_header_filter = NULL;
+ cf.output_body_filter = NULL;
for (i = 0; modules[i]; i++) {
if (modules[i]->type != NGX_HTTP_MODULE_TYPE) {
@@ -76,18 +76,12 @@ static void ngx_http_init_filters(ngx_pool_t *pool, ngx_module_t **modules)
module = (ngx_http_module_t *) modules[i]->ctx;
- if (module->output_header_filter) {
- module->next_output_header_filter = ohf;
- ohf = module->output_header_filter;
- }
-
- if (module->output_body_filter) {
- module->next_output_body_filter = obf;
- obf = module->output_body_filter;
+ if (module->init_filters) {
+ module->init_filters(pool, &cf);
}
}
- ngx_http_top_header_filter = ohf;
+ ngx_http_top_header_filter = cf.output_header_filter;
}
@@ -119,10 +113,6 @@ static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy)
continue;
}
- /* STUB */
- module = (ngx_http_module_t *) ngx_modules[i]->ctx;
- module->index = ngx_http_max_module;
-
ngx_modules[i]->index = ngx_http_max_module++;
}
@@ -139,7 +129,7 @@ static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy)
module = (ngx_http_module_t *) ngx_modules[i]->ctx;
if (module->create_loc_conf) {
- ngx_test_null(ctx->loc_conf[module->index],
+ ngx_test_null(ctx->loc_conf[ngx_modules[i]->index],
module->create_loc_conf(cf->pool),
NGX_CONF_ERROR);
}
@@ -173,6 +163,9 @@ static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy)
/**/
#endif
+ ngx_init_array(ngx_http_translate_handlers,
+ cf->pool, 10, sizeof(ngx_http_handler_pt), NGX_CONF_ERROR);
+
ngx_init_array(ngx_http_index_handlers,
cf->pool, 3, sizeof(ngx_http_handler_pt), NGX_CONF_ERROR);
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index c549ed350..ce8f2b09d 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -38,14 +38,18 @@
#define NGX_HTTP_OK 200
+
#define NGX_HTTP_SPECIAL_RESPONSE 300
#define NGX_HTTP_MOVED_PERMANENTLY 301
#define NGX_HTTP_MOVED_TEMPORARILY 302
#define NGX_HTTP_NOT_MODIFIED 304
+
#define NGX_HTTP_BAD_REQUEST 400
#define NGX_HTTP_FORBIDDEN 403
#define NGX_HTTP_NOT_FOUND 404
+#define NGX_HTTP_REQUEST_TIME_OUT 408
#define NGX_HTTP_REQUEST_URI_TOO_LARGE 414
+
#define NGX_HTTP_INTERNAL_SERVER_ERROR 500
#define NGX_HTTP_NOT_IMPLEMENTED 501
#define NGX_HTTP_BAD_GATEWAY 502
@@ -59,9 +63,8 @@
typedef struct {
- size_t len;
- char *data;
- int offset;
+ ngx_str_t name;
+ int offset;
} ngx_http_header_t;
@@ -71,9 +74,10 @@ typedef struct {
ngx_table_elt_t *host;
ngx_table_elt_t *connection;
ngx_table_elt_t *if_modified_since;
- ngx_table_elt_t *user_agent;
ngx_table_elt_t *accept_encoding;
+ ngx_table_elt_t *user_agent;
+
ngx_table_t *headers;
} ngx_http_headers_in_t;
@@ -101,34 +105,34 @@ typedef struct {
typedef struct ngx_http_request_s ngx_http_request_t;
struct ngx_http_request_s {
- ngx_file_t file;
+ ngx_connection_t *connection;
- void **ctx;
- void **srv_conf;
- void **loc_conf;
+ void **ctx;
+ void **srv_conf;
+ void **loc_conf;
- ngx_pool_t *pool;
- ngx_hunk_t *header_in;
+ ngx_file_t file;
+
+ ngx_pool_t *pool;
+ ngx_hunk_t *header_in;
ngx_http_headers_in_t headers_in;
ngx_http_headers_out_t headers_out;
int (*handler)(ngx_http_request_t *r);
- int method;
-
time_t lingering_time;
- int http_version;
- int http_major;
- int http_minor;
-
- ngx_str_t request_line;
- ngx_str_t uri;
- ngx_str_t exten;
- ngx_http_request_t *main;
+ int method;
+ int http_version;
+ int http_major;
+ int http_minor;
- ngx_connection_t *connection;
+ ngx_str_t request_line;
+ ngx_str_t uri;
+ ngx_str_t args;
+ ngx_str_t exten;
+ ngx_http_request_t *main;
u_int in_addr;
@@ -192,32 +196,6 @@ typedef int (*ngx_http_output_body_filter_p)
(ngx_http_request_t *r, ngx_chain_t *chain);
-
-typedef struct {
- int index;
-
- void *(*create_srv_conf)(ngx_pool_t *p);
- char *(*init_srv_conf)(ngx_pool_t *p, void *conf);
- void *(*create_loc_conf)(ngx_pool_t *p);
- char *(*merge_loc_conf)(ngx_pool_t *p, void *prev, void *conf);
-
- int (*translate_handler)(ngx_http_request_t *r);
-
- int (*output_header_filter) (ngx_http_request_t *r);
- int (*next_output_header_filter) (ngx_http_request_t *r);
-
- int (*output_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
- int (*next_output_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
-} ngx_http_module_t;
-
-
-#define NGX_HTTP_MODULE 0x80000000
-
-#define NGX_HTTP_MODULE_TYPE 0x50545448 /* "HTTP" */
-
-
-#define ngx_http_get_module_srv_conf(r, module) r->srv_conf[module.index]
-#define ngx_http_get_module_loc_conf(r, module) r->loc_conf[module.index]
#define ngx_http_get_module_ctx(r, module) r->ctx[module.index]
#define ngx_http_create_ctx(r, cx, module, size, error) \
@@ -243,7 +221,7 @@ int ngx_http_handler(ngx_http_request_t *r);
int ngx_http_send_header(ngx_http_request_t *r);
-int ngx_http_special_response(ngx_http_request_t *r, int error);
+int ngx_http_special_response_handler(ngx_http_request_t *r, int error);
time_t ngx_http_parse_time(char *value, size_t len);
@@ -269,12 +247,10 @@ extern int ngx_http_discarded_buffer_size;
extern int ngx_http_url_in_error_log;
+extern ngx_array_t ngx_http_translate_handlers;
extern ngx_array_t ngx_http_index_handlers;
-extern ngx_http_module_t *ngx_http_modules[];
-
-
/* STUB */
int ngx_http_log_handler(ngx_http_request_t *r);
/**/
diff --git a/src/http/ngx_http_config.h b/src/http/ngx_http_config.h
index 6793208bf..97bc8a0d3 100644
--- a/src/http/ngx_http_config.h
+++ b/src/http/ngx_http_config.h
@@ -12,14 +12,39 @@ typedef struct {
} ngx_http_conf_ctx_t;
+typedef struct {
+ int (*output_header_filter) (ngx_http_request_t *r);
+ int (*output_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
+} ngx_http_conf_filter_t;
+
+
+typedef struct {
+ void *(*create_srv_conf)(ngx_pool_t *p);
+ char *(*init_srv_conf)(ngx_pool_t *p, void *conf);
+
+ void *(*create_loc_conf)(ngx_pool_t *p);
+ char *(*merge_loc_conf)(ngx_pool_t *p, void *prev, void *conf);
+
+ void (*init_filters) (ngx_pool_t *p, ngx_http_conf_filter_t *cf);
+} ngx_http_module_t;
+
+
+#define NGX_HTTP_MODULE_TYPE 0x50545448 /* "HTTP" */
+
+
#define NGX_HTTP_MAIN_CONF 0x1000000
#define NGX_HTTP_SRV_CONF 0x2000000
#define NGX_HTTP_LOC_CONF 0x6000000
+
#define NGX_HTTP_SRV_CONF_OFFSET offsetof(ngx_http_conf_ctx_t, srv_conf)
#define NGX_HTTP_LOC_CONF_OFFSET offsetof(ngx_http_conf_ctx_t, loc_conf)
+#define ngx_http_get_module_srv_conf(r, module) r->srv_conf[module.index]
+#define ngx_http_get_module_loc_conf(r, module) r->loc_conf[module.index]
+
+
int ngx_http_config_modules(ngx_pool_t *pool, ngx_module_t **modules);
@@ -28,8 +53,5 @@ extern ngx_module_t ngx_http_module;
extern int (*ngx_http_top_header_filter) (ngx_http_request_t *r);
-extern void **ngx_srv_conf;
-extern void **ngx_loc_conf;
-
#endif /* _NGX_HTTP_CONFIG_H_INCLUDED_ */
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 170634678..e104cfcd4 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -19,12 +19,15 @@ int ngx_http_proxy_handler(ngx_http_request_t *r);
static int ngx_http_core_index_handler(ngx_http_request_t *r);
-static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy);
-static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd,
- char *dummy);
+static int ngx_http_core_init(ngx_pool_t *pool);
+
static void *ngx_http_core_create_srv_conf(ngx_pool_t *pool);
static char *ngx_http_core_init_srv_conf(ngx_pool_t *pool, void *conf);
static void *ngx_http_core_create_loc_conf(ngx_pool_t *pool);
+
+static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy);
+static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd,
+ char *dummy);
static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, char *conf);
@@ -108,24 +111,18 @@ static ngx_command_t ngx_http_core_commands[] = {
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_core_loc_conf_t, lingering_timeout)},
- {ngx_string(""), 0, NULL, 0, 0}
+ {ngx_null_string, 0, NULL, 0, 0}
};
ngx_http_module_t ngx_http_core_module_ctx = {
- NGX_HTTP_MODULE,
-
ngx_http_core_create_srv_conf, /* create server config */
ngx_http_core_init_srv_conf, /* init server config */
+
ngx_http_core_create_loc_conf, /* create location config */
NULL, /* merge location config */
- ngx_http_core_translate_handler, /* translate handler */
-
- NULL, /* output header filter */
- NULL, /* next output header filter */
- NULL, /* output body filter */
- NULL /* next output body filter */
+ NULL /* init filters */
};
@@ -134,13 +131,14 @@ ngx_module_t ngx_http_core_module = {
&ngx_http_core_module_ctx, /* module context */
ngx_http_core_commands, /* module directives */
NGX_HTTP_MODULE_TYPE, /* module type */
- NULL /* init module */
+ ngx_http_core_init /* init module */
};
int ngx_http_handler(ngx_http_request_t *r)
{
int rc, a, n, i;
+ ngx_http_handler_pt *h;
ngx_http_module_t *module;
ngx_http_conf_ctx_t *ctx;
ngx_http_in_port_t *in_port;
@@ -149,8 +147,8 @@ int ngx_http_handler(ngx_http_request_t *r)
r->connection->unexpected_eof = 0;
+ r->keepalive = 1;
r->lingering_close = 1;
- r->keepalive = 0;
#if 1
r->filter = NGX_HTTP_FILTER_NEED_IN_MEMORY;
@@ -213,34 +211,25 @@ ngx_log_debug(r->connection->log, "srv_conf: %0x" _ r->srv_conf);
ngx_log_debug(r->connection->log, "loc_conf: %0x" _ r->loc_conf);
/* run translation phase */
- for (i = 0; ngx_modules[i]; i++) {
- if (ngx_modules[i]->type != NGX_HTTP_MODULE_TYPE) {
- continue;
- }
- module = (ngx_http_module_t *) ngx_modules[i]->ctx;
+ h = (ngx_http_handler_pt *) ngx_http_translate_handlers.elts;
+ for (i = 0; i < ngx_http_translate_handlers.nelts; i++) {
+ rc = h[i](r);
- if (module->translate_handler == NULL) {
+ if (rc == NGX_DECLINED) {
continue;
}
- rc = module->translate_handler(r);
if (rc == NGX_OK) {
break;
}
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
- return ngx_http_special_response(r, rc);
+ return rc;
}
}
- rc = r->handler(r);
-
- if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
- return ngx_http_special_response(r, rc);
- }
-
- return rc;
+ return r->handler(r);
}
@@ -252,27 +241,27 @@ int ngx_http_core_translate_handler(ngx_http_request_t *r)
ngx_table_elt_t *h;
ngx_http_server_name_t *s_name;
ngx_http_core_srv_conf_t *scf;
- ngx_http_core_loc_conf_t **lcf, *loc_conf;
+ ngx_http_core_loc_conf_t *lcf, **plcf;
scf = (ngx_http_core_srv_conf_t *)
- ngx_http_get_module_srv_conf(r, ngx_http_core_module_ctx);
+ ngx_http_get_module_srv_conf(r, ngx_http_core_module);
/* find location config */
- lcf = (ngx_http_core_loc_conf_t **) scf->locations.elts;
+ plcf = (ngx_http_core_loc_conf_t **) scf->locations.elts;
for (i = 0; i < scf->locations.nelts; i++) {
-ngx_log_debug(r->connection->log, "trans: %s" _ lcf[i]->name.data);
- if (r->uri.len < lcf[i]->name.len) {
+ngx_log_debug(r->connection->log, "trans: %s" _ plcf[i]->name.data);
+ if (r->uri.len < plcf[i]->name.len) {
continue;
}
- rc = ngx_strncmp(r->uri.data, lcf[i]->name.data, lcf[i]->name.len);
+ rc = ngx_strncmp(r->uri.data, plcf[i]->name.data, plcf[i]->name.len);
if (rc < 0) {
break;
}
if (rc == 0) {
- r->loc_conf = lcf[i]->loc_conf;
+ r->loc_conf = plcf[i]->loc_conf;
}
}
@@ -286,10 +275,10 @@ ngx_log_debug(r->connection->log, "trans: %s" _ lcf[i]->name.data);
return NGX_OK;
}
- loc_conf = (ngx_http_core_loc_conf_t *)
- ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
+ lcf = (ngx_http_core_loc_conf_t *)
+ ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-ngx_log_debug(r->connection->log, "doc_root: %08x" _ &loc_conf->doc_root);
+ngx_log_debug(r->connection->log, "doc_root: %08x" _ &lcf->doc_root);
s_name = (ngx_http_server_name_t *) scf->server_names.elts;
@@ -314,14 +303,14 @@ ngx_log_debug(r->connection->log, "doc_root: %08x" _ &loc_conf->doc_root);
port_len = (r->port != 80) ? r->port_name.len : 0;
/* "+ 7" is "http://" */
- if (loc_conf->doc_root.len > 7 + s_name[0].name.len + port_len) {
- len = loc_conf->doc_root.len;
+ if (lcf->doc_root.len > 7 + s_name[0].name.len + port_len) {
+ len = lcf->doc_root.len;
f_offset = 0;
l_offset = len - (7 + s_name[0].name.len + port_len);
} else {
len = 7 + s_name[0].name.len + port_len;
- f_offset = len - loc_conf->doc_root.len;
+ f_offset = len - lcf->doc_root.len;
l_offset = 0;
}
@@ -334,8 +323,8 @@ ngx_log_debug(r->connection->log, "doc_root: %08x" _ &loc_conf->doc_root);
r->file.name.data = buf + f_offset;
location = buf + l_offset;
- last = ngx_cpystrn(ngx_cpystrn(r->file.name.data, loc_conf->doc_root.data,
- loc_conf->doc_root.len + 1),
+ last = ngx_cpystrn(ngx_cpystrn(r->file.name.data, lcf->doc_root.data,
+ lcf->doc_root.len + 1),
r->uri.data, r->uri.len + 1);
r->file.name.len = last - r->file.name.data;
@@ -344,9 +333,9 @@ ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data);
#if (WIN9X)
- /* There is no way to open file or directory in Win9X with
- one syscall: Win9X has not FILE_FLAG_BACKUP_SEMANTICS flag.
- so we need to check its type before opening */
+ /* There is no way to open a file or a directory in Win9X with
+ one syscall: Win9X has no FILE_FLAG_BACKUP_SEMANTICS flag.
+ so we need to check its type before the opening */
r->file.info.dwFileAttributes = GetFileAttributes(r->file.name.data);
if (r->file.info.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
@@ -451,7 +440,7 @@ ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data);
return NGX_HTTP_MOVED_PERMANENTLY;
}
- /* TODO: r->handler = loc_conf->default_handler; */
+ /* TODO: r->handler = lcf->default_handler; */
/* STUB */ r->handler = ngx_http_static_handler;
return NGX_OK;
@@ -503,7 +492,7 @@ int ngx_http_redirect(ngx_http_request_t *r, int redirect)
/* log request */
- return ngx_http_close_request(r);
+ return ngx_http_close_request(r, 0);
}
@@ -514,17 +503,20 @@ int ngx_http_error(ngx_http_request_t *r, int error)
/* log request */
- ngx_http_special_response(r, error);
- return ngx_http_close_request(r);
+ ngx_http_special_response_handler(r, error);
+ return ngx_http_close_request(r, 0);
}
-int ngx_http_close_request(ngx_http_request_t *r)
+int ngx_http_close_request(ngx_http_request_t *r, int error)
{
ngx_connection_t *c;
ngx_http_log_ctx_t *ctx;
c = r->connection;
+ if (error) {
+ r->headers_out.status = error;
+ }
ngx_http_log_handler(r);
@@ -573,14 +565,26 @@ int ngx_http_internal_redirect(ngx_http_request_t *r, ngx_str_t uri)
}
+static int ngx_http_core_init(ngx_pool_t *pool)
+{
+ ngx_http_handler_pt *h;
+
+ ngx_test_null(h, ngx_push_array(&ngx_http_translate_handlers), NGX_ERROR);
+
+ *h = ngx_http_core_translate_handler;
+
+ return NGX_OK;
+}
+
+
static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy)
{
- int i, j;
- char *rv;
- ngx_http_module_t *module;
- ngx_http_conf_ctx_t *ctx, *prev;
- ngx_http_core_srv_conf_t *scf;
- ngx_http_core_loc_conf_t **lcf;
+ int i, j;
+ char *rv;
+ ngx_http_module_t *module;
+ ngx_http_conf_ctx_t *ctx, *prev;
+ ngx_http_core_srv_conf_t *scf;
+ ngx_http_core_loc_conf_t **plcf;
ngx_test_null(ctx,
ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)),
@@ -604,13 +608,13 @@ static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy)
module = (ngx_http_module_t *) ngx_modules[i]->ctx;
if (module->create_srv_conf) {
- ngx_test_null(ctx->srv_conf[module->index],
+ ngx_test_null(ctx->srv_conf[ngx_modules[i]->index],
module->create_srv_conf(cf->pool),
NGX_CONF_ERROR);
}
if (module->create_loc_conf) {
- ngx_test_null(ctx->loc_conf[module->index],
+ ngx_test_null(ctx->loc_conf[ngx_modules[i]->index],
module->create_loc_conf(cf->pool),
NGX_CONF_ERROR);
}
@@ -625,10 +629,10 @@ static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy)
return rv;
- scf = ctx->srv_conf[ngx_http_core_module_ctx.index];
+ scf = ctx->srv_conf[ngx_http_core_module.index];
scf->ctx = ctx;
- lcf = (ngx_http_core_loc_conf_t **)scf->locations.elts;
+ plcf = (ngx_http_core_loc_conf_t **)scf->locations.elts;
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->type != NGX_HTTP_MODULE_TYPE) {
@@ -639,7 +643,7 @@ static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy)
if (module->init_srv_conf) {
if (module->init_srv_conf(cf->pool,
- ctx->srv_conf[module->index])
+ ctx->srv_conf[ngx_modules[i]->index])
== NGX_CONF_ERROR) {
return NGX_CONF_ERROR;
}
@@ -647,16 +651,16 @@ static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy)
if (module->merge_loc_conf) {
if (module->merge_loc_conf(cf->pool,
- prev->loc_conf[module->index],
- ctx->loc_conf[module->index])
+ prev->loc_conf[ngx_modules[i]->index],
+ ctx->loc_conf[ngx_modules[i]->index])
== NGX_CONF_ERROR) {
return NGX_CONF_ERROR;
}
for (j = 0; j < scf->locations.nelts; j++) {
if (module->merge_loc_conf(cf->pool,
- ctx->loc_conf[module->index],
- lcf[j]->loc_conf[module->index])
+ ctx->loc_conf[ngx_modules[i]->index],
+ plcf[j]->loc_conf[ngx_modules[i]->index])
== NGX_CONF_ERROR) {
return NGX_CONF_ERROR;
}
@@ -676,7 +680,7 @@ static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy)
ngx_http_module_t *module;
ngx_http_conf_ctx_t *ctx, *prev;
ngx_http_core_srv_conf_t *scf;
- ngx_http_core_loc_conf_t *lcf, **loc;
+ ngx_http_core_loc_conf_t *lcf, **plcf;
ngx_test_null(ctx,
ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)),
@@ -697,7 +701,7 @@ static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy)
module = (ngx_http_module_t *) ngx_modules[i]->ctx;
if (module->create_loc_conf) {
- ngx_test_null(ctx->loc_conf[module->index],
+ ngx_test_null(ctx->loc_conf[ngx_modules[i]->index],
module->create_loc_conf(cf->pool),
NGX_CONF_ERROR);
}
@@ -712,8 +716,8 @@ static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy)
scf = (ngx_http_core_srv_conf_t *)
ctx->srv_conf[ngx_http_core_module.index];
- ngx_test_null(loc, ngx_push_array(&scf->locations), NGX_CONF_ERROR);
- *loc = lcf;
+ ngx_test_null(plcf, ngx_push_array(&scf->locations), NGX_CONF_ERROR);
+ *plcf = lcf;
cf->ctx = ctx;
rv = ngx_conf_parse(cf, NULL);
@@ -789,7 +793,7 @@ static void *ngx_http_core_create_loc_conf(ngx_pool_t *pool)
lcf->doc_root.len = 4;
lcf->doc_root.data = "html";
- lcf->send_timeout = 10;
+ lcf->send_timeout = 10000;
lcf->discarded_buffer_size = 1500;
lcf->lingering_time = 30000;
lcf->lingering_timeout = 5000;
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index c53c81554..2ca0b6381 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -57,12 +57,13 @@ typedef struct {
void **loc_conf; /* pointer to modules loc_conf,
used in translation handler */
- ngx_str_t doc_root; /* 'root' */
+ ngx_str_t doc_root; /* root */
- time_t send_timeout; /* 'send_timeout' */
- size_t discarded_buffer_size; /* 'discarded_buffer_size */
- time_t lingering_time; /* 'lingering_time */
- ngx_msec_t lingering_timeout; /* 'lingering_timeout */
+ time_t send_timeout; /* send_timeout */
+ size_t send_lowat; /* send_lowa */
+ size_t discarded_buffer_size; /* discarded_buffer_size */
+ time_t lingering_time; /* lingering_time */
+ ngx_msec_t lingering_timeout; /* lingering_timeout */
} ngx_http_core_loc_conf_t;
@@ -87,7 +88,9 @@ int ngx_http_core_translate_handler(ngx_http_request_t *r);
int ngx_http_internal_redirect(ngx_http_request_t *r, ngx_str_t uri);
int ngx_http_error(ngx_http_request_t *r, int error);
-int ngx_http_close_request(ngx_http_request_t *r);
+
+int ngx_http_finalize_request(ngx_http_request_t *r, int error);
+int ngx_http_close_request(ngx_http_request_t *r, int error);
#endif /* _NGX_HTTP_CORE_H_INCLUDED_ */
diff --git a/src/http/ngx_http_event.c b/src/http/ngx_http_event.c
index efeacf83d..76377a4d7 100644
--- a/src/http/ngx_http_event.c
+++ b/src/http/ngx_http_event.c
@@ -19,13 +19,11 @@
static int ngx_http_init_request(ngx_event_t *ev);
-static int ngx_http_process_request_header(ngx_event_t *ev);
-
+static int ngx_http_process_request(ngx_event_t *ev);
static int ngx_http_process_request_line(ngx_http_request_t *r);
static int ngx_http_process_request_headers(ngx_http_request_t *r);
static int ngx_http_process_request_header_line(ngx_http_request_t *r);
-
-static int ngx_http_event_request_handler(ngx_http_request_t *r);
+static int ngx_http_request_handler(ngx_http_request_t *r, int error);
static int ngx_http_writer(ngx_event_t *ev);
static int ngx_http_block_read(ngx_event_t *ev);
@@ -36,8 +34,7 @@ static int ngx_http_set_lingering_close(ngx_http_request_t *r);
static int ngx_http_lingering_close_handler(ngx_event_t *ev);
static int ngx_http_close_connection(ngx_event_t *ev);
-static int ngx_http_header_parse_error(ngx_http_request_t *r,
- int parse_err, int err);
+static void ngx_http_header_parse_error(ngx_http_request_t *r, int parse_err);
static size_t ngx_http_log_error(void *data, char *buf, size_t len);
@@ -56,26 +53,26 @@ static char *header_errors[] = {
static ngx_http_header_t headers_in[] = {
- { 4, "Host", offsetof(ngx_http_headers_in_t, host) },
- { 10, "Connection", offsetof(ngx_http_headers_in_t, connection) },
- { 17, "If-Modified-Since",
- offsetof(ngx_http_headers_in_t,if_modified_since) },
+ { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host) },
+ { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection) },
+ { ngx_string("If-Modified-Since"),
+ offsetof(ngx_http_headers_in_t,if_modified_since) },
- { 10, "User-Agent", offsetof(ngx_http_headers_in_t, user_agent) },
+ { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) },
- { 0, NULL, 0 }
+ { ngx_null_string, 0 }
};
int ngx_http_init_connection(ngx_connection_t *c)
{
- ngx_event_t *ev;
+ ngx_event_t *rev;
ngx_http_log_ctx_t *ctx;
- ev = c->read;
- ev->event_handler = ngx_http_init_request;
+ rev = c->read;
+ rev->event_handler = ngx_http_init_request;
- ev->close_handler = ngx_http_close_connection;
+ rev->close_handler = ngx_http_close_connection;
c->write->close_handler = ngx_http_close_connection;
ngx_test_null(c->addr_text.data, ngx_palloc(c->pool, c->addr_text_max_len),
@@ -97,52 +94,48 @@ int ngx_http_init_connection(ngx_connection_t *c)
#if (HAVE_DEFERRED_ACCEPT)
- if (ev->ready) {
- return ngx_http_init_request(ev);
+ if (rev->ready) {
+ return ngx_http_init_request(rev);
}
#endif
- ngx_add_timer(ev, c->post_accept_timeout);
- ev->timer_set = 1;
+ ngx_add_timer(rev, c->post_accept_timeout);
+ rev->timer_set = 1;
#if (USE_KQUEUE)
- return ngx_add_event(ev, NGX_READ_EVENT, NGX_CLEAR_EVENT);
+ return ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT);
#else
-#if (HAVE_CLEAR_EVENT) /* kqueue */
+ /* kqueue */
if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
- return ngx_add_event(ev, NGX_READ_EVENT, NGX_CLEAR_EVENT);
+ return ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT);
}
-#endif
-
-#if (HAVE_EDGE_EVENT) /* epoll */ || (HAVE_AIO_EVENT) /* aio, iocp */
+ /* aio, iocp, epoll */
- if (ngx_event_flags & (NGX_HAVE_EDGE_EVENT|NGX_HAVE_AIO_EVENT)) {
- return ngx_http_init_request(ev);
+ if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
+ return ngx_http_init_request(rev);
}
-#endif
-
/* select, poll, /dev/poll */
- return ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT);
+ return ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT);
#endif /* USE_KQUEUE */
}
-static int ngx_http_init_request(ngx_event_t *ev)
+static int ngx_http_init_request(ngx_event_t *rev)
{
ngx_connection_t *c;
ngx_http_request_t *r;
ngx_http_conf_ctx_t *ctx;
- c = (ngx_connection_t *) ev->data;
+ c = (ngx_connection_t *) rev->data;
c->sent = 0;
ngx_test_null(r, ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)),
@@ -165,12 +158,12 @@ static int ngx_http_init_request(ngx_event_t *ev)
r->pipeline = c->pipeline;
r->header_in = c->buffer;
- ngx_test_null(r->pool, ngx_create_pool(ngx_http_request_pool_size, ev->log),
+ ngx_test_null(r->pool, ngx_create_pool(ngx_http_request_pool_size, c->log),
NGX_ERROR);
ngx_test_null(r->ctx,
ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module),
- ngx_http_close_request(r));
+ ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR));
ctx = (ngx_http_conf_ctx_t *) c->ctx;
r->srv_conf = ctx->srv_conf;
@@ -180,36 +173,34 @@ static int ngx_http_init_request(ngx_event_t *ev)
r->headers_out.content_length = -1;
r->headers_out.last_modified_time = -1;
- ev->event_handler = ngx_http_process_request_header;
+ rev->event_handler = ngx_http_process_request;
r->state_handler = ngx_http_process_request_line;
- return ngx_http_process_request_header(ev);
+ return ngx_http_process_request(rev);
}
-static int ngx_http_process_request_header(ngx_event_t *ev)
+static int ngx_http_process_request(ngx_event_t *rev)
{
- int n, rc, again;
+ int n, rc;
ngx_connection_t *c;
ngx_http_request_t *r;
- ngx_http_log_ctx_t *ctx;
+ ngx_http_log_ctx_t *lcx;
- c = (ngx_connection_t *) ev->data;
+ c = (ngx_connection_t *) rev->data;
r = (ngx_http_request_t *) c->data;
- ngx_log_debug(ev->log, "http process request");
+ ngx_log_debug(c->log, "http process request");
+
+ if (rev->timedout) {
+ return ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
+ }
do {
if (r->header_read) {
- if (r->header_in->end - r->header_in->last == 0) {
- again = 1;
- } else {
- again = 0;
- }
-
r->header_read = 0;
- ngx_log_debug(ev->log, "http preread %d" _
+ ngx_log_debug(c->log, "http preread %d" _
r->header_in->last - r->header_in->pos);
} else {
@@ -219,38 +210,32 @@ static int ngx_http_process_request_header(ngx_event_t *ev)
if (n == NGX_AGAIN) {
if (!r->header_timeout_set) {
- if (ev->timer_set) {
- ngx_del_timer(ev);
+ if (rev->timer_set) {
+ ngx_del_timer(rev);
} else {
- ev->timer_set = 1;
+ rev->timer_set = 1;
}
- ngx_add_timer(ev, ngx_http_client_header_timeout);
+ ngx_add_timer(rev, ngx_http_client_header_timeout);
r->header_timeout_set = 1;
}
+
return NGX_AGAIN;
}
if (n == NGX_ERROR) {
- return ngx_http_close_request(r);
+ return ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
}
- ngx_log_debug(ev->log, "http read %d" _ n);
+ ngx_log_debug(c->log, "http read %d" _ n);
if (n == 0) {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
- "client has prematurely closed connection");
- return ngx_http_close_request(r);
+ "client closed prematurely connection");
+ return ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
}
r->header_in->last += n;
-
- if (ngx_http_large_client_header
- && r->header_in->end == r->header_in->last) {
- again = 1;
- } else {
- again = 0;
- }
}
/* the state_handlers are called in the following order:
@@ -258,51 +243,56 @@ static int ngx_http_process_request_header(ngx_event_t *ev)
ngx_http_process_request_headers(r) */
do {
- /* state_handlers return NGX_OK when the whole header done */
rc = (r->state_handler)(r);
- if (rc == NGX_ERROR) {
- return rc;
- }
-
} while (rc == NGX_AGAIN && r->header_in->pos < r->header_in->last);
-#if (HAVE_AIO_EVENT) /* aio, iocp */
+ } while (rc == NGX_AGAIN
+ && (rev->ready || ngx_event_flags & NGX_HAVE_AIO_EVENT));
+
+ if (rc >= NGX_OK) {
- if (ngx_event_flags & NGX_HAVE_AIO_EVENT) {
- again = 1;
+ /* HTTP header done */
+
+ rev->event_handler = ngx_http_block_read;
+
+ if (rc != NGX_OK) {
+ return ngx_http_finalize_request(r, rc);
}
-#endif
+ lcx = r->connection->log->data;
+ lcx->action = "processing client request";
- } while (rc == NGX_AGAIN && again);
+ rc = ngx_http_handler(r);
- if (rc == NGX_OK) {
- /* HTTP header done */
+ /* a handler is still busy */
+ if (rc == NGX_BUSY) {
+ return rc;
+ }
- if (ev->timer_set) {
- ngx_del_timer(ev);
- ev->timer_set = 0;
+ if (rc == NGX_ERROR) {
+ rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- return ngx_http_event_request_handler(r);
+ return ngx_http_finalize_request(r, rc);
- } else { /* NGX_AGAIN */
+ }
- if (!r->header_timeout_set) {
+ /* NGX_AGAIN */
- if (ev->timer_set) {
- ngx_del_timer(ev);
- } else {
- ev->timer_set = 1;
- }
+ if (!r->header_timeout_set) {
- ngx_add_timer(ev, ngx_http_client_header_timeout);
- r->header_timeout_set = 1;
+ if (rev->timer_set) {
+ ngx_del_timer(rev);
+ } else {
+ rev->timer_set = 1;
}
- return rc;
+ ngx_add_timer(rev, ngx_http_client_header_timeout);
+ r->header_timeout_set = 1;
}
+
+ return rc;
}
@@ -310,29 +300,40 @@ static int ngx_http_process_request_line(ngx_http_request_t *r)
{
int rc, offset;
ngx_connection_t *c;
- ngx_http_log_ctx_t *ctx;
+ ngx_http_log_ctx_t *lcx;
rc = ngx_read_http_request_line(r);
c = r->connection;
/* a request line has been parsed successfully */
+
if (rc == NGX_OK) {
+
/* copy URI */
- r->uri.len = (r->args_start ? r->args_start - 1 : r->uri_end)
- - r->uri_start;
+
+ if (r->args_start) {
+ r->uri.len = r->args_start - 1 - r->uri_start;
+ } else {
+ r->uri.len = r->uri_end - r->uri_start;
+ }
+
ngx_test_null(r->uri.data, ngx_palloc(r->pool, r->uri.len + 1),
- ngx_http_close_request(r));
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+
ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1);
+ r->request_line.len = r->request_end - r->request_start;
+
/* if the large client headers are enabled then
we need to copy a request line */
- r->request_line.len = r->request_end - r->request_start;
if (ngx_http_large_client_header) {
+
ngx_test_null(r->request_line.data,
ngx_palloc(r->pool, r->request_line.len + 1),
- ngx_http_close_request(r));
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+
ngx_cpystrn(r->request_line.data, r->request_start,
r->request_line.len + 1);
@@ -342,33 +343,59 @@ static int ngx_http_process_request_line(ngx_http_request_t *r)
}
/* copy URI extention if it exists */
+
if (r->uri_ext) {
- r->exten.len = (r->args_start ? r->args_start - 1 : r->uri_end)
- - r->uri_ext;
+ if (r->args_start) {
+ r->exten.len = r->args_start - 1 - r->uri_ext;
+ } else {
+ r->exten.len = r->uri_end - r->uri_ext;
+ }
+
ngx_test_null(r->exten.data,
ngx_palloc(r->pool, r->exten.len + 1),
- ngx_http_close_request(r));
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+
ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1);
}
+ /* copy URI arguments if they exist */
+
+ if (r->args_start && r->uri_end > r->args_start) {
+ r->args.len = r->uri_end - r->args_start;
+
+ ngx_test_null(r->args.data,
+ ngx_palloc(r->pool, r->args.len + 1),
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+
+ ngx_cpystrn(r->args.data, r->args_start, r->args.len + 1);
+ }
+
#if 1
if (r->exten.data == NULL) {
r->exten.data = "";
}
- ngx_log_debug(r->connection->log, "HTTP: %d, %d, '%s', '%s'" _
+ if (r->args.data == NULL) {
+ r->args.data = "";
+ }
+ ngx_log_debug(r->connection->log, "HTTP: %d, %d, '%s', '%s', '%s'" _
r->method _ r->http_version _
- r->uri.data _ r->exten.data);
+ r->uri.data _ r->exten.data _ r->args.data);
if (r->exten.data[0] == '\0') {
r->exten.data = NULL;
}
+ if (r->args.data[0] == '\0') {
+ r->args.data = NULL;
+ }
#endif
- ctx = r->connection->log->data;
+ lcx = r->connection->log->data;
+
if (ngx_http_url_in_error_log) {
- ngx_test_null(ctx->url,
+ ngx_test_null(lcx->url,
ngx_palloc(r->pool, r->uri_end - r->uri_start + 1),
- ngx_http_close_request(r));
- ngx_cpystrn(ctx->url, r->uri_start, r->uri_end - r->uri_start + 1);
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+
+ ngx_cpystrn(lcx->url, r->uri_start, r->uri_end - r->uri_start + 1);
}
/* if we need to parse the headers then return NGX_AGAIN
@@ -382,13 +409,21 @@ static int ngx_http_process_request_line(ngx_http_request_t *r)
r->headers_in.headers = ngx_create_table(r->pool, 10);
r->state_handler = ngx_http_process_request_headers;
- ctx->action = "reading client request headers";
+ lcx->action = "reading client request headers";
+
+ if (ngx_http_large_client_header
+ && r->header_in->pos == r->header_in->last)
+ {
+ r->header_in->pos = r->header_in->last = r->header_in->start;
+ }
return NGX_AGAIN;
/* there was error while a request line parsing */
+
} else if (rc != NGX_AGAIN) {
- return ngx_http_header_parse_error(r, rc, NGX_HTTP_BAD_REQUEST);
+ ngx_http_header_parse_error(r, rc);
+ return NGX_HTTP_BAD_REQUEST;
}
/* NGX_AGAIN: a request line parsing is still not complete */
@@ -405,9 +440,8 @@ static int ngx_http_process_request_line(ngx_http_request_t *r)
offset = r->request_start - r->header_in->start;
if (offset == 0) {
- return ngx_http_header_parse_error(r,
- NGX_HTTP_PARSE_TOO_LONG_URI,
- NGX_HTTP_REQUEST_URI_TOO_LARGE);
+ ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI);
+ return NGX_HTTP_REQUEST_URI_TOO_LARGE;
}
ngx_memcpy(r->header_in->start, r->request_start,
@@ -427,9 +461,8 @@ static int ngx_http_process_request_line(ngx_http_request_t *r)
}
} else {
- return ngx_http_header_parse_error(r,
- NGX_HTTP_PARSE_TOO_LONG_URI,
- NGX_HTTP_REQUEST_URI_TOO_LARGE);
+ ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI);
+ return NGX_HTTP_REQUEST_URI_TOO_LARGE;
}
}
@@ -447,14 +480,22 @@ static int ngx_http_process_request_headers(ngx_http_request_t *r)
rc = ngx_read_http_header_line(r, r->header_in);
/* a header line has been parsed successfully */
+
if (rc == NGX_OK) {
if (ngx_http_process_request_header_line(r) == NGX_ERROR) {
- return ngx_http_error(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ if (ngx_http_large_client_header
+ && r->header_in->pos == r->header_in->last)
+ {
+ r->header_in->pos = r->header_in->last = r->header_in->start;
}
return NGX_AGAIN;
/* a whole header has been parsed successfully */
+
} else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
ngx_log_debug(r->connection->log, "HTTP header done");
@@ -468,9 +509,9 @@ static int ngx_http_process_request_headers(ngx_http_request_t *r)
} else {
if (r->http_version > NGX_HTTP_VERSION_10) {
- return ngx_http_header_parse_error(r,
- NGX_HTTP_PARSE_NO_HOST_HEADER,
- NGX_HTTP_BAD_REQUEST);
+ ngx_http_header_parse_error(r,
+ NGX_HTTP_PARSE_NO_HOST_HEADER);
+ return NGX_HTTP_BAD_REQUEST;
}
r->headers_in.host_name_len = 0;
}
@@ -479,8 +520,10 @@ static int ngx_http_process_request_headers(ngx_http_request_t *r)
return NGX_OK;
/* there was error while a header line parsing */
+
} else if (rc != NGX_AGAIN) {
- return ngx_http_header_parse_error(r, rc, NGX_HTTP_BAD_REQUEST);
+ ngx_http_header_parse_error(r, rc);
+ return NGX_HTTP_BAD_REQUEST;
}
/* NGX_AGAIN: a header line parsing is still not complete */
@@ -494,9 +537,9 @@ static int ngx_http_process_request_headers(ngx_http_request_t *r)
offset = r->header_name_start - r->header_in->start;
if (offset == 0) {
- return ngx_http_header_parse_error(r,
- NGX_HTTP_PARSE_TOO_LONG_HEADER,
- NGX_HTTP_BAD_REQUEST);
+ ngx_http_header_parse_error(r,
+ NGX_HTTP_PARSE_TOO_LONG_HEADER);
+ return NGX_HTTP_BAD_REQUEST;
}
ngx_memcpy(r->header_in->start, r->header_name_start,
@@ -510,9 +553,8 @@ static int ngx_http_process_request_headers(ngx_http_request_t *r)
r->header_end -= offset;
} else {
- return ngx_http_header_parse_error(r,
- NGX_HTTP_PARSE_TOO_LONG_HEADER,
- NGX_HTTP_BAD_REQUEST);
+ ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER);
+ return NGX_HTTP_BAD_REQUEST;
}
}
@@ -524,17 +566,17 @@ static int ngx_http_process_request_headers(ngx_http_request_t *r)
static int ngx_http_process_request_header_line(ngx_http_request_t *r)
{
- int i;
- ngx_table_elt_t *h;
+ int i;
+ ngx_table_elt_t *h;
ngx_test_null(h, ngx_push_table(r->headers_in.headers), NGX_ERROR);
- /* if large client headers are enabled then
- we need to copy header name and value */
-
h->key.len = r->header_name_end - r->header_name_start;
h->value.len = r->header_end - r->header_start;
+ /* if the large client headers are enabled then
+ we need to copy the header name and value */
+
if (ngx_http_large_client_header) {
ngx_test_null(h->key.data, ngx_palloc(r->pool, h->key.len + 1),
NGX_ERROR);
@@ -550,12 +592,12 @@ static int ngx_http_process_request_header_line(ngx_http_request_t *r)
h->value.data[h->value.len] = '\0';
}
- for (i = 0; headers_in[i].len != 0; i++) {
- if (headers_in[i].len != h->key.len) {
+ for (i = 0; headers_in[i].name.len != 0; i++) {
+ if (headers_in[i].name.len != h->key.len) {
continue;
}
- if (ngx_strcasecmp(headers_in[i].data, h->key.data) == 0) {
+ if (ngx_strcasecmp(headers_in[i].name.data, h->key.data) == 0) {
*((ngx_table_elt_t **)
((char *) &r->headers_in + headers_in[i].offset)) = h;
}
@@ -568,167 +610,131 @@ static int ngx_http_process_request_header_line(ngx_http_request_t *r)
}
-static int ngx_http_event_request_handler(ngx_http_request_t *r)
+int ngx_http_finalize_request(ngx_http_request_t *r, int error)
{
- int rc, event;
- ngx_msec_t timeout;
- ngx_event_t *rev, *wev;
- ngx_http_log_ctx_t *ctx;
+ int rc, event;
+ ngx_msec_t timeout;
+ ngx_event_t *rev, *wev;
+ ngx_http_core_loc_conf_t *lcf;
- rev = r->connection->read;
- wev = r->connection->write;
+ rc = error;
- if (rev->timer_set) {
- ngx_del_timer(rev);
- rev->timer_set = 0;
- }
+ if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
- rev->event_handler = ngx_http_block_read;
+ rev = r->connection->read;
- ctx = r->connection->log->data;
- ctx->action = "processing client request";
+ if (rev->timer_set) {
+ ngx_del_timer(rev);
+ } else {
+ rev->timer_set = 1;
+ }
- rc = ngx_http_handler(r);
+ rc = ngx_http_special_response_handler(r, rc);
+ }
- /* handler is still busy */
- if (rc == NGX_WAITING)
- return rc;
+ /* a handler has done its work completely */
- /* handler has done its work but transfer is still not completed */
- if (rc == NGX_AGAIN) {
+ if (rc == NGX_OK) {
- /* STUB: timeouts should be reworked */
- if (r->connection->sent > 0) {
- ngx_log_debug(r->connection->log, "sent: " OFF_FMT _
- r->connection->sent);
- timeout = (ngx_msec_t) (r->connection->sent * 10);
- ngx_log_debug(r->connection->log, "timeout: %d" _ timeout);
- ngx_add_timer(wev, timeout);
+ if (r->keepalive != 0) {
+ return ngx_http_set_keepalive(r);
+ }
- } else {
- ngx_add_timer(wev, 10000);
+ if (r->lingering_close) {
+ return ngx_http_set_lingering_close(r);
}
- wev->event_handler = ngx_http_writer;
+ return ngx_http_close_request(r, 0);
+ }
+
+ /* NGX_AGAIN: a handler has done its work
+ but the transfer is still not completed */
+
+ lcf = (ngx_http_core_loc_conf_t *)
+ ngx_http_get_module_loc_conf(r->main ? r->main : r,
+ ngx_http_core_module);
+ wev = r->connection->write;
+ wev->event_handler = ngx_http_writer;
+ wev->timer_set = 1;
+ ngx_add_timer(wev, lcf->send_timeout);
#if (USE_KQUEUE)
#if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */
- wev->lowat = /* STUB */ NGX_LOWAT;
+ wev->lowat = lcf->send_lowat;
#endif
- if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT) == NGX_ERROR) {
- return ngx_http_close_request(r);
- }
+ if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT) == NGX_ERROR) {
+ return ngx_http_close_request(r, 0);
+ }
- return rc;
+ return rc;
#else
-#if (HAVE_AIO_EVENT) || (HAVE_EDGE_EVENT) /* aio, iocp, epoll */
+ /* aio, iocp, epoll */
- if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
- return rc;
- }
-
-#endif
+ if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
+ return rc;
+ }
#if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */
- if (ngx_event_flags & NGX_HAVE_LOWAT_EVENT) {
- wev->lowat = /* STUB */ NGX_LOWAT;
- }
+ if (ngx_event_flags & NGX_HAVE_LOWAT_EVENT) {
+ wev->lowat = lcf->send_lowat;
+ }
#endif
-#if (HAVE_CLEAR_EVENT) /* kqueue */
-
- if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
- event = NGX_CLEAR_EVENT;
+ /* kqueue */
- } else {
- event = NGX_LEVEL_EVENT;
- }
+ if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
+ event = NGX_CLEAR_EVENT;
-#else /* select, poll, /dev/poll */
+ /* select, poll, /dev/poll */
+ } else {
event = NGX_LEVEL_EVENT;
-
-#endif
-
- if (ngx_add_event(wev, NGX_WRITE_EVENT, event) == NGX_ERROR) {
- return ngx_http_close_request(r);
- }
-
- return rc;
-
-
-#endif /* USE_KQUEUE */
-
}
- if (rc == NGX_ERROR) {
- /* log http request */
- return ngx_http_close_request(r);
+ if (ngx_add_event(wev, NGX_WRITE_EVENT, event) == NGX_ERROR) {
+ return ngx_http_close_request(r, 0);
}
- if (rc >= NGX_HTTP_SPECIAL_RESPONSE)
- return ngx_http_special_response(r, rc);
-
- /* rc == NGX_OK */
+ return rc;
- if (r->keepalive == 0) {
- if (r->lingering_close) {
- return ngx_http_set_lingering_close(r);
-
- } else {
- return ngx_http_close_request(r);
- }
- }
-
- /* keepalive */
-
- return ngx_http_set_keepalive(r);
+#endif /* USE_KQUEUE */
}
-static int ngx_http_writer(ngx_event_t *ev)
+static int ngx_http_writer(ngx_event_t *wev)
{
- int rc;
+ int rc;
ngx_msec_t timeout;
ngx_connection_t *c;
ngx_http_request_t *r;
- ngx_http_core_loc_conf_t *conf;
+ ngx_http_core_loc_conf_t *lcf;
- c = (ngx_connection_t *) ev->data;
+ c = (ngx_connection_t *) wev->data;
r = (ngx_http_request_t *) c->data;
rc = ngx_http_output_filter(r, NULL);
- ngx_log_debug(ev->log, "output filter in writer: %d" _ rc);
+ ngx_log_debug(c->log, "output filter in writer: %d" _ rc);
if (rc == NGX_AGAIN) {
- /* STUB: timeouts should be reworked */
- if (c->sent > 0) {
- conf = (ngx_http_core_loc_conf_t *)
- ngx_http_get_module_loc_conf(r->main ? r->main : r,
- ngx_http_core_module_ctx);
-
- timeout = (ngx_msec_t) (c->sent * conf->send_timeout);
-
- ngx_log_debug(ev->log, "sent: " OFF_FMT _ c->sent);
- ngx_log_debug(ev->log, "timeout: %d" _ timeout);
-
- if (ev->timer_set) {
- ngx_del_timer(ev);
- } else {
- ev->timer_set = 1;
- }
-
- ngx_add_timer(ev, timeout);
+ lcf = (ngx_http_core_loc_conf_t *)
+ ngx_http_get_module_loc_conf(r->main ? r->main : r,
+ ngx_http_core_module);
+ if (wev->timer_set) {
+ ngx_del_timer(wev);
+ } else {
+ wev->timer_set = 1;
}
+ ngx_add_timer(wev, lcf->send_timeout);
+
return rc;
}
@@ -737,20 +743,17 @@ static int ngx_http_writer(ngx_event_t *ev)
/* rc == NGX_OK */
- ngx_log_debug(ev->log, "http writer done");
-
- if (r->keepalive == 0) {
- if (r->lingering_close) {
- return ngx_http_set_lingering_close(r);
+ ngx_log_debug(c->log, "http writer done");
- } else {
- return ngx_http_close_request(r);
- }
+ if (r->keepalive != 0) {
+ return ngx_http_set_keepalive(r);
}
- /* keepalive */
+ if (r->lingering_close) {
+ return ngx_http_set_lingering_close(r);
+ }
- return ngx_http_set_keepalive(r);
+ return ngx_http_close_request(r, 0);
}
@@ -813,30 +816,35 @@ static int ngx_http_read_discarded_body(ngx_event_t *ev)
ngx_log_debug(ev->log, "http read discarded body");
- if (ev->timedout)
+ if (ev->timedout) {
return NGX_ERROR;
+ }
c = (ngx_connection_t *) ev->data;
r = (ngx_http_request_t *) c->data;
lcf = (ngx_http_core_loc_conf_t *)
- ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
+ ngx_http_get_module_loc_conf(r, ngx_http_core_module);
- if (r->discarded_buffer == NULL)
+ if (r->discarded_buffer == NULL) {
ngx_test_null(r->discarded_buffer,
ngx_palloc(r->pool, lcf->discarded_buffer_size),
NGX_ERROR);
+ }
size = r->client_content_length;
- if (size > lcf->discarded_buffer_size)
+ if (size > lcf->discarded_buffer_size) {
size = lcf->discarded_buffer_size;
+ }
n = ngx_event_recv(c, r->discarded_buffer, size);
- if (n == NGX_ERROR)
+ if (n == NGX_ERROR) {
return NGX_ERROR;
+ }
- if (n == NGX_AGAIN)
+ if (n == NGX_AGAIN) {
return NGX_OK;
+ }
r->client_content_length -= n;
/* XXX: what if r->client_content_length == 0 ? */
@@ -854,11 +862,10 @@ static int ngx_http_set_keepalive(ngx_http_request_t *r)
c = (ngx_connection_t *) r->connection;
rev = c->read;
- wev = c->write;
ctx = (ngx_http_log_ctx_t *) c->log->data;
ctx->action = "closing request";
- ngx_http_close_request(r);
+ ngx_http_close_request(r, 0);
if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) {
@@ -876,8 +883,8 @@ static int ngx_http_set_keepalive(ngx_http_request_t *r)
/* pipelined request */
if (h->pos < h->last) {
- /* We do not know here whether pipelined request is complete
- so if large client headers are not enabled
+ /* We do not know here whether a pipelined request is complete
+ so if the large client headers are not enabled
we need to copy the data to the start of c->buffer.
This copy should be rare because clients that support
pipelined requests (Mozilla 1.x, Opera 6.x) are still rare */
@@ -898,6 +905,7 @@ static int ngx_http_set_keepalive(ngx_http_request_t *r)
h->pos = h->last = h->start;
rev->event_handler = ngx_http_keepalive_handler;
+ wev = c->write;
if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
@@ -925,62 +933,60 @@ static int ngx_http_set_keepalive(ngx_http_request_t *r)
}
-static int ngx_http_keepalive_handler(ngx_event_t *ev)
+static int ngx_http_keepalive_handler(ngx_event_t *rev)
{
ssize_t n;
ngx_connection_t *c;
- ngx_http_log_ctx_t *ctx;
+ ngx_http_log_ctx_t *lctx;
- c = (ngx_connection_t *) ev->data;
+ c = (ngx_connection_t *) rev->data;
- ngx_log_debug(ev->log, "http keepalive handler");
+ ngx_log_debug(c->log, "http keepalive handler");
- if (ev->timedout) {
+ if (rev->timedout) {
return NGX_DONE;
}
- /* MSIE closes keepalive connection with RST flag
+ /* MSIE closes a keepalive connection with RST flag
so we ignore ECONNRESET here */
- ev->ignore_econnreset = 1;
+ rev->ignore_econnreset = 1;
ngx_set_socket_errno(0);
n = ngx_event_recv(c, c->buffer->last, c->buffer->end - c->buffer->last);
- ev->ignore_econnreset = 0;
+ rev->ignore_econnreset = 0;
if (n == NGX_AGAIN || n == NGX_ERROR) {
return n;
}
- ctx = (ngx_http_log_ctx_t *) ev->log->data;
- ev->log->handler = NULL;
+ lctx = (ngx_http_log_ctx_t *) rev->log->data;
+ rev->log->handler = NULL;
if (n == 0) {
- ngx_log_error(NGX_LOG_INFO, ev->log, ngx_socket_errno,
- "client %s closed keepalive connection", ctx->client);
+ ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
+ "client %s closed keepalive connection", lctx->client);
return NGX_DONE;
}
c->buffer->last += n;
- ev->log->handler = ngx_http_log_error;
- ctx->action = "reading client request line";
+ rev->log->handler = ngx_http_log_error;
+ lctx->action = "reading client request line";
- return ngx_http_init_request(ev);
+ return ngx_http_init_request(rev);
}
static int ngx_http_set_lingering_close(ngx_http_request_t *r)
{
- int blocked;
- ngx_event_t *rev, *wev;
+ ngx_event_t *rev;
ngx_connection_t *c;
ngx_http_core_loc_conf_t *lcf;
c = r->connection;
rev = c->read;
- wev = c->write;
lcf = (ngx_http_core_loc_conf_t *)
- ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
+ ngx_http_get_module_loc_conf(r, ngx_http_core_module);
r->lingering_time = ngx_time() + lcf->lingering_time / 1000;
r->connection->read->event_handler = ngx_http_lingering_close_handler;
@@ -995,36 +1001,36 @@ static int ngx_http_set_lingering_close(ngx_http_request_t *r)
if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) {
- return ngx_http_close_request(r);
+ return ngx_http_close_request(r, 0);
}
- blocked = 1;
rev->blocked = 0;
-
- } else {
- blocked = 0;
}
- if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
- if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
- return ngx_http_close_request(r);
+#if !(USE_KQUEUE)
+
+ if (c->write->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
+ if (ngx_del_event(c->write, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
+ return ngx_http_close_request(r, 0);
}
}
+#endif
+
if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
ngx_shutdown_socket_n " failed");
- return ngx_http_close_request(r);
+ return ngx_http_close_request(r, 0);
}
-#if (HAVE_AIO_EVENT) /* aio, iocp */
+#if (USE_KQUEUE)
- if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) || blocked) {
+ if (rev->ready) {
return ngx_http_lingering_close_handler(rev);
}
#else
- if (blocked) {
+ if (rev->ready || (ngx_event_flags & NGX_HAVE_AIO_EVENT)) {
return ngx_http_lingering_close_handler(rev);
}
@@ -1034,30 +1040,30 @@ static int ngx_http_set_lingering_close(ngx_http_request_t *r)
}
-static int ngx_http_lingering_close_handler(ngx_event_t *ev)
+static int ngx_http_lingering_close_handler(ngx_event_t *rev)
{
- ssize_t n;
- ngx_msec_t timer;
- ngx_connection_t *c;
- ngx_http_request_t *r;
+ ssize_t n;
+ ngx_msec_t timer;
+ ngx_connection_t *c;
+ ngx_http_request_t *r;
ngx_http_core_loc_conf_t *lcf;
- ngx_log_debug(ev->log, "http lingering close handler");
-
- c = (ngx_connection_t *) ev->data;
+ c = (ngx_connection_t *) rev->data;
r = (ngx_http_request_t *) c->data;
- if (ev->timedout) {
- return ngx_http_close_request(r);
+ ngx_log_debug(c->log, "http lingering close handler");
+
+ if (rev->timedout) {
+ return ngx_http_close_request(r, 0);
}
timer = r->lingering_time - ngx_time();
if (timer <= 0) {
- return ngx_http_close_request(r);
+ return ngx_http_close_request(r, 0);
}
lcf = (ngx_http_core_loc_conf_t *)
- ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
+ ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (r->discarded_buffer == NULL) {
@@ -1072,29 +1078,32 @@ static int ngx_http_lingering_close_handler(ngx_event_t *ev)
} else {
ngx_test_null(r->discarded_buffer,
ngx_palloc(c->pool, lcf->discarded_buffer_size),
- ngx_http_close_request(r));
+ ngx_http_close_request(r, 0));
}
}
- n = ngx_event_recv(c, r->discarded_buffer, lcf->discarded_buffer_size);
+ do {
+ n = ngx_event_recv(c, r->discarded_buffer, lcf->discarded_buffer_size);
- ngx_log_debug(ev->log, "lingering read: %d" _ n);
+ ngx_log_debug(c->log, "lingering read: %d" _ n);
- if (n == NGX_ERROR || n == 0) {
- return ngx_http_close_request(r);
- }
+ if (n == NGX_ERROR || n == 0) {
+ return ngx_http_close_request(r, 0);
+ }
+
+ } while (rev->ready);
timer *= 1000;
if (timer > lcf->lingering_timeout) {
timer = lcf->lingering_timeout;
}
- if (ev->timer_set) {
- ngx_del_timer(ev);
+ if (rev->timer_set) {
+ ngx_del_timer(rev);
} else {
- ev->timer_set = 1;
+ rev->timer_set = 1;
}
- ngx_add_timer(ev, timer);
+ ngx_add_timer(rev, timer);
return NGX_OK;
}
@@ -1106,8 +1115,7 @@ static int ngx_http_close_connection(ngx_event_t *ev)
}
-static int ngx_http_header_parse_error(ngx_http_request_t *r,
- int parse_err, int err)
+static void ngx_http_header_parse_error(ngx_http_request_t *r, int parse_err)
{
ngx_http_log_ctx_t *ctx;
@@ -1126,8 +1134,6 @@ static int ngx_http_header_parse_error(ngx_http_request_t *r,
}
r->connection->log->handler = ngx_http_log_error;
-
- return ngx_http_error(r, err);
}
@@ -1135,10 +1141,11 @@ static size_t ngx_http_log_error(void *data, char *buf, size_t len)
{
ngx_http_log_ctx_t *ctx = (ngx_http_log_ctx_t *) data;
- if (ctx->url)
+ if (ctx->url) {
return ngx_snprintf(buf, len, " while %s, client: %s, URL: %s",
ctx->action, ctx->client, ctx->url);
- else
+ } else {
return ngx_snprintf(buf, len, " while %s, client: %s",
ctx->action, ctx->client);
+ }
}
diff --git a/src/http/ngx_http_header_filter.c b/src/http/ngx_http_header_filter.c
index e7805d6eb..d0e2ae7a0 100644
--- a/src/http/ngx_http_header_filter.c
+++ b/src/http/ngx_http_header_filter.c
@@ -10,26 +10,23 @@
#include <ngx_conf_file.h>
#include <ngx_http.h>
+#include <ngx_http_config.h>
#include <ngx_http_write_filter.h>
+static void ngx_http_header_filter_init(ngx_pool_t *pool,
+ ngx_http_conf_filter_t *cf);
static int ngx_http_header_filter(ngx_http_request_t *r);
ngx_http_module_t ngx_http_header_filter_module_ctx = {
- NGX_HTTP_MODULE,
-
NULL, /* create server config */
NULL, /* init server config */
+
NULL, /* create location config */
NULL, /* merge location config */
- NULL, /* translate handler */
-
- ngx_http_header_filter, /* output header filter */
- NULL, /* next output header filter */
- NULL, /* output body filter */
- NULL /* next output body filter */
+ ngx_http_header_filter_init /* init filters */
};
@@ -295,3 +292,10 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
return ngx_http_write_filter(r, ch);
}
+
+
+static void ngx_http_header_filter_init(ngx_pool_t *pool,
+ ngx_http_conf_filter_t *cf)
+{
+ cf->output_header_filter = ngx_http_header_filter;
+}
diff --git a/src/http/ngx_http_output_filter.c b/src/http/ngx_http_output_filter.c
index ab5553519..73b212f52 100644
--- a/src/http/ngx_http_output_filter.c
+++ b/src/http/ngx_http_output_filter.c
@@ -16,6 +16,8 @@ static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src);
static void *ngx_http_output_filter_create_conf(ngx_pool_t *pool);
static char *ngx_http_output_filter_merge_conf(ngx_pool_t *pool,
void *parent, void *child);
+static void ngx_http_output_filter_init(ngx_pool_t *pool,
+ ngx_http_conf_filter_t *cf);
static ngx_command_t ngx_http_output_filter_commands[] = {
@@ -31,20 +33,13 @@ static ngx_command_t ngx_http_output_filter_commands[] = {
static ngx_http_module_t ngx_http_output_filter_module_ctx = {
- NGX_HTTP_MODULE,
-
NULL, /* create server config */
NULL, /* init server config */
+
ngx_http_output_filter_create_conf, /* create location config */
ngx_http_output_filter_merge_conf, /* merge location config */
- NULL, /* translate handler */
-
- NULL, /* output header filter */
- NULL, /* next output header filter */
- (int (*)(ngx_http_request_t *, ngx_chain_t *))
- ngx_http_output_filter, /* output body filter */
- NULL /* next output body filter */
+ ngx_http_output_filter_init /* output body filter */
};
@@ -58,7 +53,12 @@ ngx_module_t ngx_http_output_filter_module = {
+static int (*next_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
+
+
+#if 0
#define next_filter ngx_http_output_filter_module_ctx.next_output_body_filter
+#endif
#define need_to_copy(r, hunk) \
(((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY) \
@@ -300,6 +300,14 @@ static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src)
}
+static void ngx_http_output_filter_init(ngx_pool_t *pool,
+ ngx_http_conf_filter_t *cf)
+{
+ next_filter = cf->output_body_filter;
+ cf->output_body_filter = NULL;
+}
+
+
static void *ngx_http_output_filter_create_conf(ngx_pool_t *pool)
{
ngx_http_output_filter_conf_t *conf;
diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c
index 6bf62b3f7..123418a83 100644
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -39,6 +39,14 @@ static char error_404_page[] =
;
+static char error_408_page[] =
+"<html>" CRLF
+"<head><title>408 Request Time-out</title></head>" CRLF
+"<body bgcolor=\"white\">" CRLF
+"<center><h1>408 Request Time-out</h1></center>" CRLF
+;
+
+
static char error_414_page[] =
"<html>" CRLF
"<head><title>414 Request-URI Too Large</title></head>" CRLF
@@ -55,35 +63,54 @@ static char error_500_page[] =
;
+static char error_502_page[] =
+"<html>" CRLF
+"<head><title>502 Bad Gateway</title></head>" CRLF
+"<body bgcolor=\"white\">" CRLF
+"<center><h1>502 Bad Gateway</h1></center>" CRLF
+;
+
+
+static char error_504_page[] =
+"<html>" CRLF
+"<head><title>504 Gateway Time-out</title></head>" CRLF
+"<body bgcolor=\"white\">" CRLF
+"<center><h1>504 Gateway Time-out</h1></center>" CRLF
+;
+
+
static ngx_str_t error_pages[] = {
- { 0, NULL}, /* 301 */
- { 0, NULL}, /* 302 */
- { 0, NULL}, /* 303 */
- { 0, NULL}, /* 304 */
-
- { sizeof(error_400_page) - 1, error_400_page },
- { 0, NULL}, /* 401 */
- { 0, NULL}, /* 402 */
- { sizeof(error_403_page) - 1, error_403_page },
- { sizeof(error_404_page) - 1, error_404_page },
- { 0, NULL}, /* 405 */
- { 0, NULL}, /* 406 */
- { 0, NULL}, /* 407 */
- { 0, NULL}, /* 408 */
- { 0, NULL}, /* 409 */
- { 0, NULL}, /* 410 */
- { 0, NULL}, /* 411 */
- { 0, NULL}, /* 412 */
- { 0, NULL}, /* 413 */
- { sizeof(error_414_page) - 1, error_414_page },
- { 0, NULL}, /* 415 */
- { 0, NULL}, /* 416 */
-
- { sizeof(error_500_page) - 1, error_500_page }
+ ngx_null_string, /* 301 */
+ ngx_null_string, /* 302 */
+ ngx_null_string, /* 303 */
+
+ ngx_string(error_400_page),
+ ngx_null_string, /* 401 */
+ ngx_null_string, /* 402 */
+ ngx_string(error_403_page),
+ ngx_string(error_404_page),
+ ngx_null_string, /* 405 */
+ ngx_null_string, /* 406 */
+ ngx_null_string, /* 407 */
+ ngx_string(error_408_page),
+ ngx_null_string, /* 409 */
+ ngx_null_string, /* 410 */
+ ngx_null_string, /* 411 */
+ ngx_null_string, /* 412 */
+ ngx_null_string, /* 413 */
+ ngx_string(error_414_page),
+ ngx_null_string, /* 415 */
+ ngx_null_string, /* 416 */
+
+ ngx_string(error_500_page),
+ ngx_null_string, /* 501 */
+ ngx_string(error_502_page),
+ ngx_null_string, /* 503 */
+ ngx_string(error_504_page)
};
-int ngx_http_special_response(ngx_http_request_t *r, int error)
+int ngx_http_special_response_handler(ngx_http_request_t *r, int error)
{
int err, len;
ngx_hunk_t *message, *tail;
@@ -96,10 +123,10 @@ int ngx_http_special_response(ngx_http_request_t *r, int error)
err = error - NGX_HTTP_MOVED_PERMANENTLY;
} else if (error < NGX_HTTP_INTERNAL_SERVER_ERROR) {
- err = error - NGX_HTTP_BAD_REQUEST + 4;
+ err = error - NGX_HTTP_BAD_REQUEST + 3;
} else {
- err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 4 + 17;
+ err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 3 + 17;
}
if (r->keepalive != 0) {
diff --git a/src/http/ngx_http_write_filter.c b/src/http/ngx_http_write_filter.c
index ea36ab2ce..813b2a6b4 100644
--- a/src/http/ngx_http_write_filter.c
+++ b/src/http/ngx_http_write_filter.c
@@ -16,6 +16,8 @@
static void *ngx_http_write_filter_create_conf(ngx_pool_t *pool);
static char *ngx_http_write_filter_merge_conf(ngx_pool_t *pool,
void *parent, void *child);
+static void ngx_http_write_filter_init(ngx_pool_t *pool,
+ ngx_http_conf_filter_t *cf);
static ngx_command_t ngx_http_write_filter_commands[] = {
@@ -31,19 +33,13 @@ static ngx_command_t ngx_http_write_filter_commands[] = {
ngx_http_module_t ngx_http_write_filter_module_ctx = {
- NGX_HTTP_MODULE,
-
NULL, /* create server config */
NULL, /* init server config */
+
ngx_http_write_filter_create_conf, /* create location config */
ngx_http_write_filter_merge_conf, /* merge location config */
- NULL, /* translate handler */
-
- NULL, /* output header filter */
- NULL, /* next output header filter */
- ngx_http_write_filter, /* output body filter */
- NULL, /* next output body filter */
+ ngx_http_write_filter_init /* init filters */
};
@@ -156,6 +152,13 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
}
+static void ngx_http_write_filter_init(ngx_pool_t *pool,
+ ngx_http_conf_filter_t *cf)
+{
+ cf->output_body_filter = ngx_http_write_filter;
+}
+
+
static void *ngx_http_write_filter_create_conf(ngx_pool_t *pool)
{
ngx_http_write_filter_conf_t *conf;