]> git.kaiwu.me - nginx.git/commitdiff
nginx-0.0.1-2003-06-02-19:24:30 import
authorIgor Sysoev <igor@sysoev.ru>
Mon, 2 Jun 2003 15:24:30 +0000 (15:24 +0000)
committerIgor Sysoev <igor@sysoev.ru>
Mon, 2 Jun 2003 15:24:30 +0000 (15:24 +0000)
37 files changed:
src/core/ngx_conf_file.c
src/core/ngx_conf_file.h
src/core/ngx_connection.h
src/core/ngx_core.h
src/core/ngx_hunk.h
src/core/ngx_modules.c
src/event/ngx_event.h
src/event/ngx_event_accept.c
src/http/modules/ngx_http_charset_filter.c [new file with mode: 0644]
src/http/modules/ngx_http_chunked_filter.c [new file with mode: 0644]
src/http/modules/ngx_http_index_handler.c
src/http/modules/ngx_http_index_handler.h [deleted file]
src/http/modules/ngx_http_log_handler.c
src/http/modules/ngx_http_log_handler.h [new file with mode: 0644]
src/http/modules/ngx_http_range_filter.c [new file with mode: 0644]
src/http/modules/ngx_http_static_handler.c
src/http/ngx_http.h
src/http/ngx_http_cache.c
src/http/ngx_http_core_module.c
src/http/ngx_http_event.c
src/http/ngx_http_filter.h [new file with mode: 0644]
src/http/ngx_http_get_time.c
src/http/ngx_http_header_filter.c
src/http/ngx_http_output_filter.c
src/http/ngx_http_output_filter.h [deleted file]
src/http/ngx_http_parse.c
src/http/ngx_http_request.h
src/http/ngx_http_script.c [new file with mode: 0644]
src/http/ngx_http_script.h [new file with mode: 0644]
src/http/ngx_http_special_response.c
src/http/ngx_http_write_filter.c
src/http/ngx_http_write_filter.h [deleted file]
src/os/unix/ngx_files.h
src/os/unix/ngx_freebsd_init.c
src/os/unix/ngx_freebsd_init.h
src/os/unix/ngx_freebsd_sendfile_chain.c
src/os/win32/ngx_files.h

index 54d4f387b26cf45b7e16b95a8da1c94423f41794..241c7a89744ef7fb977ce5eaed8441a038dc5336 100644 (file)
@@ -32,7 +32,7 @@ char *ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
 
         /* open configuration file */
 
-        fd = ngx_open_file(filename->data, NGX_FILE_RDONLY);
+        fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN);
         if (fd == NGX_INVALID_FILE) {
             ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,
                           ngx_open_file_n " %s failed", filename->data);
@@ -142,7 +142,7 @@ ngx_log_debug(cf->log, "command '%s'" _ cmd->name.data);
                     if (cmd->type & argument_number[cf->args->nelts - 1]) {
                         valid = 1;
 
-                    } else if (cmd->type & NGX_CONF_ANY1) {
+                    } else if (cmd->type & NGX_CONF_1MORE) {
 
                         if (cf->args->nelts != 1) {
                             valid = 1;
index b3f1d6304c1dd9f5925304885ea97170dc131db1..20747b62430514fd2850b5df71b6645f3133d213 100644 (file)
@@ -24,7 +24,7 @@
 #define NGX_CONF_TAKE2       0x00000004
 #define NGX_CONF_ARGS_NUMBER 0x0000ffff
 #define NGX_CONF_ANY         0x00010000
-#define NGX_CONF_ANY1        0x00020000
+#define NGX_CONF_1MORE       0x00020000
 #define NGX_CONF_BLOCK       0x00040000
 #define NGX_CONF_FLAG        0x00080000
 
index 59bf33307b683a49d5516047803da901773c4948..c3e9e0902f08f051bfa0e9ade99cdaabcaf45bc3 100644 (file)
@@ -61,6 +61,7 @@ struct ngx_connection_s {
 
     unsigned          pipeline:1;
     unsigned          unexpected_eof:1;
+    unsigned          tcp_nopush:1;
 };
 
 
index e8b3117001f44f3c3d510d14eeefddd4c283c6f5..a612200d1c9c4076fb2bc53df6ea2f131fee756d 100644 (file)
@@ -18,6 +18,7 @@ typedef struct ngx_event_s       ngx_event_t;
 #include <ngx_array.h>
 #include <ngx_string.h>
 #include <ngx_file.h>
+#include <ngx_inet.h>
 #include <ngx_conf_file.h>
 #include <ngx_os_init.h>
 #include <ngx_connection.h>
index c097289d89482c87f06991c5ab620a1f19395dc4..c0e0dbf7b6bef57c25a3968a9eb2f424be7c4a2f 100644 (file)
@@ -71,11 +71,9 @@ ngx_hunk_t *ngx_create_temp_hunk(ngx_pool_t *pool, int size,
                                  int before, int after);
 
 #define ngx_alloc_hunk(pool) ngx_palloc(pool, sizeof(ngx_hunk_t))
-#define ngx_alloc_chain_entry(pool) ngx_palloc(pool, sizeof(ngx_chain_t))
+#define ngx_calloc_hunk(pool) ngx_pcalloc(pool, sizeof(ngx_hunk_t))
 
-/* STUB */
-#define ngx_create_chain_entry(pool) ngx_palloc(pool, sizeof(ngx_chain_t))
-/**/
+#define ngx_alloc_chain_entry(pool) ngx_palloc(pool, sizeof(ngx_chain_t))
 
 #define ngx_add_hunk_to_chain(chain, h, pool, error)                         \
             do {                                                             \
index 8f57db399c08f2993979a815b6ae4aaf698211c8..27d150cd2b2be9bf328d6e0efd1448d1142a7f0f 100644 (file)
@@ -29,10 +29,16 @@ extern ngx_module_t  ngx_http_write_filter_module;
 extern ngx_module_t  ngx_http_output_filter_module;
 extern ngx_module_t  ngx_http_header_filter_module;
 
+extern ngx_module_t  ngx_http_chunked_filter_module;
+extern ngx_module_t  ngx_http_range_filter_module;
+extern ngx_module_t  ngx_http_charset_filter_module;
+
 extern ngx_module_t  ngx_http_index_module;
 extern ngx_module_t  ngx_http_static_module;
 extern ngx_module_t  ngx_http_proxy_module;
 
+extern ngx_module_t  ngx_http_log_module;
+
 
 ngx_module_t *ngx_modules[] = {
 
@@ -64,13 +70,17 @@ ngx_module_t *ngx_modules[] = {
     &ngx_http_output_filter_module,
     &ngx_http_header_filter_module,
 
+    &ngx_http_chunked_filter_module,
     /* &ngx_http_gzip_filter_module, */
-    /* &ngx_http_range_filter_module, */
+    &ngx_http_range_filter_module,
     /* &ngx_http_ssi_filter_module, */
+    &ngx_http_charset_filter_module,
 
     &ngx_http_index_module,
     /* &ngx_http_static_module, */
     /* &ngx_http_proxy_module, */
 
+    &ngx_http_log_module,
+
     NULL
 };
index 928d2cf4bce060092195c4ad8ad5f1667e11e1f0..08119a30bdc520b12595dad2ccdc289c7337f0b8 100644 (file)
@@ -5,17 +5,6 @@
 #include <ngx_config.h>
 #include <ngx_core.h>
 
-#if 0
-#include <ngx_types.h>
-#include <ngx_time.h>
-#include <ngx_socket.h>
-#include <ngx_log.h>
-#include <ngx_alloc.h>
-#include <ngx_array.h>
-#include <ngx_conf_file.h>
-#endif
-
-
 
 #define NGX_INVALID_INDEX  0x80000000
 
@@ -310,10 +299,6 @@ extern int                   ngx_event_flags;
 #endif
 
 
-#if !(HAVE_EPOLL)
-#define  ngx_edge_add_event(ev)  NGX_ERROR
-#endif
-
 
 #define NGX_EVENT_MODULE      0x544E5645  /* "EVNT" */
 
index dacd7e427636d8ac8c25d24ebc0daf56abd51c45..77ba8edfadc48793796d210617e8eac1805716ca 100644 (file)
@@ -1,10 +1,8 @@
 
 #include <ngx_config.h>
 #include <ngx_core.h>
-
-#include <nginx.h>
-
 #include <ngx_event.h>
+#include <nginx.h>
 
 
 void ngx_event_accept(ngx_event_t *ev)
@@ -30,9 +28,11 @@ void ngx_event_accept(ngx_event_t *ev)
 
     do {
 
-        /* Create the pool before accept() to avoid copy the sockaddr.
-           Although accept() can fail it's uncommon case
-           and the pool can be got from the free pool list */
+        /*
+         * Create the pool before accept() to avoid copy the sockaddr.
+         * Although accept() can fail it's uncommon case
+         * and the pool can be got from the free pool list
+         */
 
         pool = ngx_create_pool(ls->pool_size, ev->log);
         if (pool == NULL) {
@@ -168,7 +168,7 @@ void ngx_event_accept(ngx_event_t *ev)
         ngx_memcpy(c->log, ev->log, sizeof(ngx_log_t));
         rev->log = wev->log = c->log;
 
-        /* STUB: x86: MT: lock xadd, MP: lock xadd, shared */
+        /* TODO: x86: MT: lock xadd, MP: lock xadd, shared */
         c->number = ngx_connection_counter++;
 
         ngx_log_debug(ev->log, "accept: %d, %d" _ s _ c->number);
diff --git a/src/http/modules/ngx_http_charset_filter.c b/src/http/modules/ngx_http_charset_filter.c
new file mode 100644 (file)
index 0000000..baf6d9a
--- /dev/null
@@ -0,0 +1,124 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+    ngx_str_t  default_charset;
+} ngx_http_charset_loc_conf_t;
+
+
+static void *ngx_http_charset_create_loc_conf(ngx_pool_t *pool);
+static char *ngx_http_charset_merge_loc_conf(ngx_pool_t *pool,
+                                             void *parent, void *child);
+static int ngx_http_charset_filter_init(ngx_pool_t *pool);
+
+
+static ngx_command_t  ngx_http_charset_filter_commands[] = {
+
+    {ngx_string("default_charset"),
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     ngx_conf_set_str_slot,
+     NGX_HTTP_LOC_CONF_OFFSET,
+     offsetof(ngx_http_charset_loc_conf_t, default_charset),
+     NULL},
+
+    ngx_null_command
+};
+
+
+static ngx_http_module_t  ngx_http_charset_filter_module_ctx = {
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_charset_create_loc_conf,      /* create location configuration */
+    ngx_http_charset_merge_loc_conf        /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_charset_filter_module = {
+    NGX_MODULE,
+    &ngx_http_charset_filter_module_ctx,   /* module context */
+    ngx_http_charset_filter_commands,      /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_charset_filter_init           /* init module */
+};
+
+
+static int (*next_header_filter) (ngx_http_request_t *r);
+#if 0
+static int (*next_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
+#endif
+
+
+static int ngx_http_charset_header_filter(ngx_http_request_t *r)
+{
+    ngx_http_charset_loc_conf_t  *lcf;
+
+    lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module);
+
+    if (r->headers_out.status == NGX_HTTP_MOVED_PERMANENTLY
+        && r->headers_out.status == NGX_HTTP_MOVED_TEMPORARILY)
+    {
+        /* do not set charset for the redirect because NN 4.x uses this
+           charset instead of the next page charset */
+        r->headers_out.charset.len = 0;
+
+    } else if (r->headers_out.charset.len == 0) {
+        r->headers_out.charset = lcf->default_charset;
+    }
+
+    return next_header_filter(r);
+}
+
+
+#if 0
+static int ngx_http_charset_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+    ngx_log_debug(r->connection->log, "CHARSET BODY");
+    return next_body_filter(r, in);
+}
+#endif
+
+
+static int ngx_http_charset_filter_init(ngx_pool_t *pool)
+{
+    next_header_filter = ngx_http_top_header_filter;
+    ngx_http_top_header_filter = ngx_http_charset_header_filter;
+
+#if 0
+    next_body_filter = ngx_http_top_body_filter;
+    ngx_http_top_body_filter = ngx_http_charset_body_filter;
+#endif
+
+    return NGX_OK;
+}
+
+
+static void *ngx_http_charset_create_loc_conf(ngx_pool_t *pool)
+{
+    ngx_http_charset_loc_conf_t  *lcf;
+
+    ngx_test_null(lcf,
+                  ngx_pcalloc(pool, sizeof(ngx_http_charset_loc_conf_t)),
+                  NGX_CONF_ERROR);
+
+    return lcf;
+}
+
+
+static char *ngx_http_charset_merge_loc_conf(ngx_pool_t *pool,
+                                             void *parent, void *child)
+{
+    ngx_http_charset_loc_conf_t *prev = parent;
+    ngx_http_charset_loc_conf_t *conf = child;
+
+    ngx_conf_merge_str_value(conf->default_charset,
+                             prev->default_charset, "koi8-r");
+
+    return NGX_CONF_OK;
+}
diff --git a/src/http/modules/ngx_http_chunked_filter.c b/src/http/modules/ngx_http_chunked_filter.c
new file mode 100644 (file)
index 0000000..75a0cdf
--- /dev/null
@@ -0,0 +1,129 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+static int ngx_http_chunked_filter_init(ngx_pool_t *pool);
+
+
+static ngx_http_module_t  ngx_http_chunked_filter_module_ctx = {
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    NULL,                                  /* create location configuration */
+    NULL,                                  /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_chunked_filter_module = {
+    NGX_MODULE,
+    &ngx_http_chunked_filter_module_ctx,   /* module context */
+    NULL,                                  /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_chunked_filter_init           /* init module */
+};
+
+
+static int (*next_header_filter) (ngx_http_request_t *r);
+static int (*next_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
+
+
+static int ngx_http_chunked_header_filter(ngx_http_request_t *r)
+{
+    if (r->headers_out.content_length == -1) {
+        if (r->http_version < NGX_HTTP_VERSION_11) {
+            r->keepalive = 0;
+
+        } else {
+            r->chunked = 1;
+        }
+    }
+
+    return next_header_filter(r);
+}
+
+
+static int ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+    char         *chunk;
+    size_t        size, len;
+    ngx_hunk_t   *h;
+    ngx_chain_t  *out, *ce, *te, **le;
+
+    if (in == NULL || !r->chunked) {
+        return next_body_filter(r, in);
+    }
+
+    ngx_test_null(out, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
+    le = &out->next;
+
+    size = 0;
+    ce = in;
+
+    for ( ;; ) {
+
+        if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
+            size += ce->hunk->last - ce->hunk->pos;
+        } else {
+            size += (size_t) (ce->hunk->file_last - ce->hunk->file_pos);
+        }
+
+        ngx_test_null(te, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
+        te->hunk = ce->hunk;
+        *le = te;
+        le = &te->next;
+
+        if (ce->next == NULL) {
+            break;
+        }
+
+        ce = ce->next;
+    }
+
+    ngx_test_null(chunk, ngx_palloc(r->pool, 11), NGX_ERROR);
+    len = ngx_snprintf(chunk, 11, "%x" CRLF, size);
+
+    ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
+    h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
+    h->pos = chunk;
+    h->last = chunk + len;
+
+    out->hunk = h;
+
+    ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
+
+    if (ce->hunk->type & NGX_HUNK_LAST) {
+        ce->hunk->type &= ~NGX_HUNK_LAST;
+        h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_MEMORY|NGX_HUNK_LAST;
+        h->pos = CRLF "0" CRLF CRLF;
+        h->last = h->pos + 7;
+
+    } else {
+        h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_MEMORY;
+        h->pos = CRLF;
+        h->last = h->pos + 2;
+    }
+
+    ngx_test_null(te, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
+    te->hunk = h;
+    te->next = NULL;
+    *le = te;
+
+    return next_body_filter(r, out);
+}
+
+
+static int ngx_http_chunked_filter_init(ngx_pool_t *pool)
+{
+    next_header_filter = ngx_http_top_header_filter;
+    ngx_http_top_header_filter = ngx_http_chunked_header_filter;
+
+    next_body_filter = ngx_http_top_body_filter;
+    ngx_http_top_body_filter = ngx_http_chunked_body_filter;
+
+    return NGX_OK;
+}
index c9ad911120df09dcc105ed0e94fd14cfa8fab3c4..cc7c92790e79457948bf650159e6dffec49586d9 100644 (file)
@@ -1,5 +1,16 @@
 
-#include <ngx_http_index_handler.h>
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+    ngx_array_t  indices;
+    size_t       max_index_len;
+} ngx_http_index_conf_t;
+
+
+#define NGX_HTTP_DEFAULT_INDEX   "index.html"
 
 
 static int ngx_http_index_test_dir(ngx_http_request_t *r);
@@ -14,7 +25,7 @@ static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
 static ngx_command_t ngx_http_index_commands[] = {
 
     {ngx_string("index"),
-     NGX_HTTP_LOC_CONF|NGX_CONF_ANY1,
+     NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
      ngx_http_index_set_index,
      NGX_HTTP_LOC_CONF_OFFSET,
      0,
@@ -46,8 +57,8 @@ ngx_module_t  ngx_http_index_module = {
 
 
 /*
-   Try to open first index file before the test of the directory existence
-   because the valid requests should be many more then invalid ones.
+   Try to open the first index file before the directory existence test
+   because the valid requests should be many more than invalid ones.
    If open() failed then stat() should be more quickly because some data
    is already cached in the kernel.
    Besides Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR).
@@ -57,7 +68,7 @@ ngx_module_t  ngx_http_index_module = {
 
 int ngx_http_index_handler(ngx_http_request_t *r)
 {
-    int                        i, rc, test_dir;
+    int                        i, rc, test_dir, path_not_found;
     char                      *name, *file;
     ngx_str_t                  redirect, *index;
     ngx_err_t                  err;
@@ -80,6 +91,7 @@ int ngx_http_index_handler(ngx_http_request_t *r)
     r->path.len = file - r->path.data;
 
     test_dir = 1;
+    path_not_found = 1;
 
     index = icf->indices.elts;
     for (i = 0; i < icf->indices.nelts; i++) {
@@ -92,7 +104,7 @@ int ngx_http_index_handler(ngx_http_request_t *r)
             name = index[i].data;
         }
 
-        fd = ngx_open_file(name, NGX_FILE_RDONLY);
+        fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN);
         if (fd == NGX_INVALID_FILE) {
             err = ngx_errno;
 
@@ -100,7 +112,7 @@ ngx_log_error(NGX_LOG_DEBUG, r->connection->log, err,
               "DEBUG: " ngx_open_file_n " %s failed", name);
 
             if (err == NGX_ENOTDIR) {
-                r->path_not_found = 1;
+                path_not_found = 1;
 
             } else if (err == NGX_EACCES) {
                 r->path_err = err;
@@ -108,7 +120,7 @@ ngx_log_error(NGX_LOG_DEBUG, r->connection->log, err,
             }
 
             if (test_dir) {
-                if (r->path_not_found) {
+                if (path_not_found) {
                     r->path_err = err;
                     return NGX_HTTP_NOT_FOUND;
                 }
diff --git a/src/http/modules/ngx_http_index_handler.h b/src/http/modules/ngx_http_index_handler.h
deleted file mode 100644 (file)
index 3d2f6f0..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef _NGX_HTTP_INDEX_HANDLER_H_INCLUDED_
-#define _NGX_HTTP_INDEX_HANDLER_H_INCLUDED_
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-#define NGX_HTTP_DEFAULT_INDEX   "index.html"
-
-
-typedef struct {
-    ngx_array_t  indices;
-    size_t       max_index_len;
-} ngx_http_index_conf_t;
-
-
-extern ngx_module_t  ngx_http_index_module;
-
-
-#endif /* _NGX_HTTP_INDEX_HANDLER_H_INCLUDED_ */
index 44df4530288deb5375398114c1a12c6cfc481584..f61461ce71ce279f5c913924f0c8478a4f798561 100644 (file)
@@ -1,38 +1,82 @@
 
 #include <ngx_config.h>
 #include <ngx_core.h>
-#include <ngx_string.h>
-#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;
+typedef struct {
+    ngx_file_t  file;
+} ngx_http_log_conf_t;
+
+
+static void *ngx_http_log_create_conf(ngx_pool_t *pool);
+static char *ngx_http_log_merge_conf(ngx_pool_t *p, void *parent, void *child);
+static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
+                                                                   void *conf);
+
+static ngx_command_t ngx_http_log_commands[] = {
+
+    {ngx_string("access_log"),
+     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+     ngx_http_log_set_log,
+     NGX_HTTP_LOC_CONF_OFFSET,
+     0,
+     NULL},
+
+    ngx_null_command
+};
+
+
+ngx_http_module_t  ngx_http_log_module_ctx = {
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_log_create_conf,              /* create location configration */
+    ngx_http_log_merge_conf                /* merge location configration */
+};
+
+
+ngx_module_t  ngx_http_log_module = {
+    NGX_MODULE,
+    &ngx_http_log_module_ctx,              /* module context */
+    ngx_http_log_commands,                 /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    NULL,                                  /* init module */
+};
+
 
 
 static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+                          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
 
 
 int ngx_http_log_handler(ngx_http_request_t *r)
 {
-    size_t    len;
-    char     *line, *p;
-    ngx_tm_t  tm;
+    char                 *line, *p;
+    size_t                len;
+    ngx_tm_t              tm;
+    ngx_http_log_conf_t  *lcf;
 
     ngx_log_debug(r->connection->log, "log handler");
 
-    /* 10:%con, 1:%pipe, 22:%date, 2:"%r", 3:%status, 20:%bytes,
-       6*" ", 2/1: "\r\n" */
+    lcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);
+
+    /* 10:%con, 1:%pipe, 22:%date, 2:"%r", 3:%status, 20:%bytes, 2:%user-agent,
+       7*" ", 2/1: "\r\n" */
 #if (WIN32)
-    len = 10 + 1 + 22 + 2 + 3 + 20 + 6 + 2;
+    len = 10 + 1 + 22 + 2 + 3 + 20 + 2 + 7 + 2;
 #else
-    len = 10 + 1 + 22 + 2 + 3 + 20 + 6 + 1;
+    len = 10 + 1 + 22 + 2 + 3 + 20 + 2 + 7 + 1;
 #endif
 
     len += r->connection->addr_text.len;
     len += r->request_line.len;
+    if (r->headers_in.user_agent) {
+        len += r->headers_in.user_agent->value.len;
+    }
 
     ngx_test_null(line, ngx_palloc(r->pool, len), NGX_ERROR);
     p = line;
@@ -79,13 +123,80 @@ int ngx_http_log_handler(ngx_http_request_t *r)
 
     p += ngx_snprintf(p, 21, OFF_FMT, r->connection->sent);
 
+    *p++ = ' ';
+
+    *p++ = '"';
+    if (r->headers_in.user_agent) {
+        ngx_memcpy(p, r->headers_in.user_agent->value.data,
+                   r->headers_in.user_agent->value.len);
+        p += r->headers_in.user_agent->value.len;
+    }
+    *p++ = '"';
+
 #if (WIN32)
     *p++ = CR; *p++ = LF;
 #else
     *p++ = LF;
 #endif
 
-    write(1, line, p - line);
+    write(lcf->file.fd, line, p - line);
 
     return NGX_OK;
 }
+
+
+static void *ngx_http_log_create_conf(ngx_pool_t *pool)
+{
+    ngx_http_log_conf_t  *conf;
+
+    ngx_test_null(conf, ngx_pcalloc(pool, sizeof(ngx_http_log_conf_t)),
+                  NGX_CONF_ERROR);
+
+    return conf;
+}
+
+
+static char *ngx_http_log_merge_conf(ngx_pool_t *p, void *parent, void *child)
+{
+    ngx_http_log_conf_t *prev = parent;
+    ngx_http_log_conf_t *conf = child;
+
+    /* STUB */
+    *conf = *prev;
+
+    return NGX_CONF_OK;
+}
+
+
+static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
+                                  void *conf)
+{
+    ngx_http_log_conf_t *lcf = conf;
+
+    int         len;
+    ngx_err_t   err;
+    ngx_str_t  *value;
+
+    value = cf->args->elts;
+
+    lcf->file.name.len = value[1].len;
+    lcf->file.name.data = value[1].data;
+
+    lcf->file.fd = ngx_open_file(lcf->file.name.data,
+                                 NGX_FILE_RDWR,
+                                 NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND);
+
+    if (lcf->file.fd == NGX_INVALID_FILE) {
+        err = ngx_errno;
+        len = ngx_snprintf(ngx_conf_errstr, sizeof(ngx_conf_errstr) - 1,
+                          ngx_open_file_n " \"%s\" failed (%d: ",
+                          lcf->file.name.data, err);
+        len += ngx_strerror_r(err, ngx_conf_errstr + len,
+                              sizeof(ngx_conf_errstr) - len - 1);
+        ngx_conf_errstr[len++] = ')';
+        ngx_conf_errstr[len++] = '\0';
+        return ngx_conf_errstr;
+    }
+
+    return NGX_CONF_OK;
+}
diff --git a/src/http/modules/ngx_http_log_handler.h b/src/http/modules/ngx_http_log_handler.h
new file mode 100644 (file)
index 0000000..2bda1f0
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _NGX_HTTP_LOG_HANDLER_H_INCLUDED_
+#define _NGX_HTTP_LOG_HANDLER_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+    int   dummy;
+} ngx_http_log_conf_t;
+
+
+typedef enum {
+
+    NGX_HTTP_LOG_HANDLER = 0,
+
+#if 0
+    /* the ngx_str_t field of the request */
+    NGX_HTTP_LOG_REQUEST_STR_FIELD,
+
+    /* the ngx_str_t field of the r->headers_in */
+    NGX_HTTP_LOG_REQUEST_HEADER_IN_FIELD,
+
+    /* the ngx_str_t field of the r->headers_out */
+    NGX_HTTP_LOG_REQUEST_HEADER_OUT_FIELD,
+#endif
+
+} ngx_http_log_code_e;
+
+
+typedef struct {
+    int      type;
+    int      size;
+    char  *(*handler) (ngx_http_request_t *r, char *p);
+    int      offset;
+} ngx_http_log_code_t;
+
+
+#endif /* _NGX_HTTP_LOG_HANDLER_H_INCLUDED_ */
diff --git a/src/http/modules/ngx_http_range_filter.c b/src/http/modules/ngx_http_range_filter.c
new file mode 100644 (file)
index 0000000..d2696fd
--- /dev/null
@@ -0,0 +1,362 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+    ngx_str_t  boundary_header;
+} ngx_http_range_filter_ctx_t;
+
+
+static int ngx_http_range_filter_init(ngx_pool_t *pool);
+
+
+static ngx_http_module_t  ngx_http_range_filter_module_ctx = {
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    NULL,                                  /* create location configuration */
+    NULL,                                  /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_range_filter_module = {
+    NGX_MODULE,
+    &ngx_http_range_filter_module_ctx,     /* module context */
+    NULL,                                  /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_range_filter_init             /* init module */
+};
+
+
+static int (*next_header_filter) (ngx_http_request_t *r);
+static int (*next_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
+
+
+static int ngx_http_range_header_filter(ngx_http_request_t *r)
+{
+    int                           rc, boundary, len, i;
+    char                         *p;
+    off_t                         start, end;
+    ngx_http_range_t             *range;
+    ngx_http_range_filter_ctx_t  *ctx;
+
+    if (r->main
+        || r->http_version < NGX_HTTP_VERSION_10
+        || r->headers_out.status != NGX_HTTP_OK
+        || r->headers_out.content_length == -1
+        /* STUB: we currently support ranges for file hunks only */
+        || r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY
+        || r->headers_in.range == NULL
+        || r->headers_in.range->value.len < 7
+        || ngx_strncasecmp(r->headers_in.range->value.data, "bytes=", 6) != 0)
+    {
+        return next_header_filter(r);
+    }
+
+    ngx_init_array(r->headers_out.ranges, r->pool, 5, sizeof(ngx_http_range_t),
+                   NGX_ERROR);
+
+    rc = 0;
+    p = r->headers_in.range->value.data + 6;
+
+    for ( ;; ) {
+        start = end = 0;
+
+        while (*p == ' ') { p++; }
+
+        if (*p < '0' || *p > '9') {
+            rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
+            break;
+        }
+
+        while (*p >= '0' && *p <= '9') {
+            start = start * 10 + *p++ - '0';
+        }
+
+        while (*p == ' ') { p++; }
+
+        if (*p++ != '-') {
+            rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
+            break;
+        }
+
+        if (start >= r->headers_out.content_length) {
+            rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
+            break;
+        }
+
+        while (*p == ' ') { p++; }
+
+        if (*p == ',' || *p == '\0') {
+            ngx_test_null(range, ngx_push_array(&r->headers_out.ranges),
+                          NGX_ERROR);
+            range->start = start;
+            range->end = r->headers_out.content_length;
+
+            if (*p++ == ',') {
+                continue;
+            }
+
+            break;
+        }
+
+        if (*p < '0' || *p > '9') {
+            rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
+            break;
+        }
+
+        while (*p >= '0' && *p <= '9') {
+            end = end * 10 + *p++ - '0';
+        }
+
+        while (*p == ' ') { p++; }
+
+        if (*p != ',' && *p != '\0') {
+            rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
+            break;
+        }
+
+        if (end >= r->headers_out.content_length || start >= end) {
+            rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
+            break;
+        }
+
+        ngx_test_null(range, ngx_push_array(&r->headers_out.ranges), NGX_ERROR);
+        range->start = start;
+        range->end = end + 1;
+
+        if (*p++ == ',') {
+            continue;
+        }
+
+        break;
+    }
+
+    if (rc) {
+        r->headers_out.status = rc;
+        r->headers_out.ranges.nelts = 0;
+
+        ngx_test_null(r->headers_out.content_range,
+                      ngx_push_table(r->headers_out.headers),
+                      NGX_ERROR);
+
+        ngx_test_null(r->headers_out.content_range->value.data,
+                      ngx_palloc(r->pool, 8 + 20 + 1),
+                      NGX_ERROR);
+
+        r->headers_out.content_range->value.len = 
+                        ngx_snprintf(r->headers_out.content_range->value.data,
+                                     8 + 20 + 1, "bytes */" OFF_FMT,
+                                     r->headers_out.content_length);
+
+        r->headers_out.content_length = -1;
+
+        return rc;
+
+    } else {
+        r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT;
+
+        if (r->headers_out.ranges.nelts == 1) {
+            ngx_test_null(r->headers_out.content_range,
+                          ngx_push_table(r->headers_out.headers),
+                          NGX_ERROR);
+
+            ngx_test_null(r->headers_out.content_range->value.data,
+                          ngx_palloc(r->pool, 6 + 20 + 1 + 20 + 1 + 20 + 1),
+                          NGX_ERROR);
+
+            r->headers_out.content_range->value.len = 
+                         ngx_snprintf(r->headers_out.content_range->value.data,
+                                      6 + 20 + 1 + 20 + 1 + 20 + 1,
+                                      "bytes " OFF_FMT "-" OFF_FMT "/" OFF_FMT,
+                                      range->start, range->end - 1,
+                                      r->headers_out.content_length);
+
+            r->headers_out.content_length = range->end - range->start;
+
+        } else {
+
+#if 0
+            /* TODO: what if no content_type ?? */
+            ngx_test_null(r->headers_out.content_type,
+                          ngx_push_table(r->headers_out.headers),
+                          NGX_ERROR);
+#endif
+
+            ngx_http_create_ctx(r, ctx, ngx_http_range_filter_module,
+                               sizeof(ngx_http_range_filter_ctx_t), NGX_ERROR);
+
+            len = 4 + 10 + 2 + 14 + r->headers_out.content_type->value.len
+                                  + 2 + 21 + 1;
+
+            if (r->headers_out.charset.len) {
+                len += 10 + r->headers_out.charset.len;
+            }
+
+            ngx_test_null(ctx->boundary_header.data, ngx_palloc(r->pool, len),
+                          NGX_ERROR);
+
+            boundary = ngx_next_temp_number(0);
+
+            if (r->headers_out.charset.len) {
+                ctx->boundary_header.len =
+                         ngx_snprintf(ctx->boundary_header.data, len,
+                                      CRLF "--%010u" CRLF
+                                      "Content-Type: %s; charset=%s" CRLF
+                                      "Content-Range: bytes ",
+                                      boundary,
+                                      r->headers_out.content_type->value.data,
+                                      r->headers_out.charset.data);
+
+                r->headers_out.charset.len = 0;
+
+            } else {
+                ctx->boundary_header.len =
+                         ngx_snprintf(ctx->boundary_header.data, len,
+                                      CRLF "--%010u" CRLF
+                                      "Content-Type: %s" CRLF
+                                      "Content-Range: bytes ",
+                                      boundary,
+                                      r->headers_out.content_type->value.data);
+            }
+
+            ngx_test_null(r->headers_out.content_type->value.data,
+                          ngx_palloc(r->pool, 31 + 10 + 1),
+                          NGX_ERROR);
+
+            r->headers_out.content_type->value.len =
+                      ngx_snprintf(r->headers_out.content_type->value.data,
+                                   31 + 10 + 1,
+                                   "multipart/byteranges; boundary=%010u",
+                                   boundary);
+
+            /* the last "CRLF--BOUNDARY--CRLF" */
+            len = 4 + 10 + 4;
+
+            range = r->headers_out.ranges.elts;
+            for (i = 0; i < r->headers_out.ranges.nelts; i++) {
+                 ngx_test_null(range[i].content_range.data,
+                               ngx_palloc(r->pool, 20 + 1 + 20 + 1 + 20 + 5),
+                               NGX_ERROR);
+
+                 range[i].content_range.len = 
+                        ngx_snprintf(range[i].content_range.data,
+                                     20 + 1 + 20 + 1 + 20 + 5,
+                                     OFF_FMT "-" OFF_FMT "/" OFF_FMT CRLF CRLF,
+                                     range[i].start, range[i].end - 1,
+                                     r->headers_out.content_length);
+
+                 len += ctx->boundary_header.len + range[i].content_range.len
+                        + range[i].end - range[i].start;
+            }
+
+            r->headers_out.content_length = len;
+        }
+    }
+
+    return next_header_filter(r);
+}
+
+
+static int ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+    int                           i;
+    ngx_hunk_t                   *h;
+    ngx_chain_t                  *out, *hce, *rce, *dce, **le;
+    ngx_http_range_t             *range;
+    ngx_http_range_filter_ctx_t  *ctx;
+
+    if (r->headers_out.ranges.nelts == 0) {
+        return next_body_filter(r, in);
+    }
+
+    /* the optimized version for the static files only
+       that are passed in the single file hunk */
+
+    if (in
+        && in->hunk->type & NGX_HUNK_FILE
+        && in->hunk->type & NGX_HUNK_LAST)
+    {
+        if (r->headers_out.ranges.nelts == 1) {
+            range = r->headers_out.ranges.elts;
+            in->hunk->file_pos = range->start;
+            in->hunk->file_last = range->end;
+
+            return next_body_filter(r, in);
+        }
+
+        ctx = ngx_http_get_module_ctx(r, ngx_http_range_filter_module);
+        le = &out;
+
+        range = r->headers_out.ranges.elts;
+        for (i = 0; i < r->headers_out.ranges.nelts; i++) {
+
+            ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
+            h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_MEMORY;
+            h->pos = ctx->boundary_header.data;
+            h->last = ctx->boundary_header.data + ctx->boundary_header.len;
+
+            ngx_test_null(hce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
+            hce->hunk = h;
+
+            ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
+            h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
+            h->pos = range[i].content_range.data;
+            h->last = range[i].content_range.data + range[i].content_range.len;
+
+            ngx_test_null(rce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
+            rce->hunk = h;
+
+            ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
+            h->type = NGX_HUNK_FILE;
+            h->file_pos = range[i].start;
+            h->file_last = range[i].end;
+            h->file = in->hunk->file;
+
+            ngx_test_null(dce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
+            dce->hunk = h;
+            dce->next = NULL;
+
+            *le = hce;
+            hce->next = rce;
+            rce->next = dce;
+            le = &dce->next;
+        }
+
+        ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
+        h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP|NGX_HUNK_LAST;
+        ngx_test_null(h->pos, ngx_palloc(r->pool, 4 + 10 + 4), NGX_ERROR);
+        h->last = ngx_cpymem(h->pos, ctx->boundary_header.data, 4 + 10);
+        *h->last++ = '-'; *h->last++ = '-';
+        *h->last++ = CR; *h->last++ = LF;
+
+        ngx_test_null(hce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
+        hce->hunk = h;
+        hce->next = NULL;
+        *le = hce;
+
+        return next_body_filter(r, out);
+    }
+
+    /* TODO: several incoming hunks of proxied responses
+             and memory hunks on platforms that have no sendfile() */
+
+    return next_body_filter(r, in);
+}
+
+
+static int ngx_http_range_filter_init(ngx_pool_t *pool)
+{
+    next_header_filter = ngx_http_top_header_filter;
+    ngx_http_top_header_filter = ngx_http_range_header_filter;
+
+    next_body_filter = ngx_http_top_body_filter;
+    ngx_http_top_body_filter = ngx_http_range_body_filter;
+
+    return NGX_OK;
+}
index bc88fc920da24ddd12394e96034ac697e8849b40..8ea6a0a00c47fc9bb17032034f1bd75faa782292 100644 (file)
@@ -2,10 +2,6 @@
 #include <ngx_config.h>
 #include <ngx_core.h>
 #include <ngx_http.h>
-#include <ngx_http_config.h>
-#include <ngx_http_core_module.h>
-#include <ngx_http_output_filter.h>
-
 
 
 int ngx_http_static_handler(ngx_http_request_t *r)
@@ -32,7 +28,8 @@ int ngx_http_static_handler(ngx_http_request_t *r)
     ctx->action = "sending response";
 
     if (r->file.fd == NGX_INVALID_FILE) {
-        r->file.fd = ngx_open_file(r->file.name.data, NGX_FILE_RDONLY);
+        r->file.fd = ngx_open_file(r->file.name.data,
+                                   NGX_FILE_RDONLY, NGX_FILE_OPEN);
 
         if (r->file.fd == NGX_INVALID_FILE) {
             err = ngx_errno;
@@ -129,6 +126,10 @@ int ngx_http_static_handler(ngx_http_request_t *r)
 
 
     rc = ngx_http_send_header(r);
+    if (rc == NGX_ERROR || rc > NGX_OK) {
+        ngx_http_finalize_request(r, rc);
+        return NGX_OK;
+    }
 
     if (r->header_only) {
         if (rc == NGX_AGAIN) {
index 81a859d40ca6645067e8a65c065328ad497568f1..4a6e3ced297e62f9dae2bdce1e1d73d99ec735cb 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <ngx_http_request.h>
 #include <ngx_http_config.h>
+#include <ngx_http_filter.h>
 #include <ngx_http_core_module.h>
 
 
index f9e36f5973e7443a149cbbd192dc0af051accf75..0c563206ca5d696e0947a60a27747a71bf7297a3 100644 (file)
@@ -1,5 +1,12 @@
 
 
+/*
+ * small file in malloc()ed memory, mmap()ed file, file descriptor only,
+ * file access time only (to estimate can pages pages still be in memory),
+ * translated URI (ngx_http_index_hanlder),
+ * compiled script (ngx_http_ssi_filter).
+ */
+
 
 #define NGX_HTTP_CACHE_ENTRY_DELETED  0x00000001
 #define NGX_HTTP_CACHE_ENTRY_MMAPED   0x00000002
@@ -7,6 +14,9 @@
 /* "/" -> "/index.html" in ngx_http_index_handler */
 #define NGX_HTTP_CACHE_ENTRY_URI      0x00000004
 
+/* complied script */
+#define NGX_HTTP_CACHE_ENTRY_SCRIPT   0x00000008
+
 #define NGX_HTTP_CACHE_FILTER_FLAGS   0xFFFF0000
 
 
@@ -42,7 +52,7 @@ int ngx_http_cache_get(ngx_http_cache_hash_t *cache_hash,
     int                           hi;
     ngx_http_cache_hash_entry_t  *entry;
 
-    h->crc = ngx_crc32(uri->data, uri->len);
+    h->crc = ngx_crc(uri->data, uri->len);
 
     hi = h->crc % cache_hash->size;
     entry = cache_hash[hi].elts;
@@ -61,3 +71,23 @@ int ngx_http_cache_get(ngx_http_cache_hash_t *cache_hash,
 
     return NGX_ERROR;
 }
+
+
+/* 32-bit crc16 */
+
+int ngx_crc(char *data, size_t len)
+{
+    u_int32_t  sum;
+
+    for (sum = 0; len; len--) {
+        /*
+         * gcc 2.95.2 x86 compiles that operator into the single rol opcode.
+         * msvc 6.0sp2 compiles it into four opcodes.
+         */
+        sum = sum >> 1 | sum << 31;
+
+        sum += *data++;
+    }
+
+    return sum;
+}
index 46f9686e3bbe799094e4334b0c0d14e819d02239..b390c9438f05dec079d12444ba64d9b869c661b3 100644 (file)
@@ -6,8 +6,6 @@
 #include <ngx_listen.h>
 
 #include <ngx_http.h>
-#include <ngx_http_output_filter.h>
-
 #include <nginx.h>
 
 
@@ -97,14 +95,18 @@ static ngx_command_t  ngx_http_core_commands[] = {
      NULL},
 
     {ngx_string("listen"),
+#if 0
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
+#else
+     NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
+#endif
      ngx_set_listen,
      NGX_HTTP_SRV_CONF_OFFSET,
      0,
      NULL},
 
     {ngx_string("server_name"),
-     NGX_HTTP_SRV_CONF|NGX_CONF_ANY1,
+     NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
      ngx_set_server_name,
      NGX_HTTP_SRV_CONF_OFFSET,
      0,
@@ -195,12 +197,16 @@ ngx_module_t  ngx_http_core_module = {
 void ngx_http_handler(ngx_http_request_t *r)
 {
     int                        rc, i;
+    ngx_http_log_ctx_t        *lcx;
     ngx_http_handler_pt       *h;
     ngx_http_core_loc_conf_t  *clcf, **clcfp;
     ngx_http_core_srv_conf_t  *cscf;
 
     r->connection->unexpected_eof = 0;
 
+    lcx = r->connection->log->data;
+    lcx->action = NULL;
+
     r->keepalive = 1;
 
     if (r->headers_in.content_length_n > 0) {
@@ -337,7 +343,8 @@ ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data);
 #else
 
     if (r->file.fd == NGX_INVALID_FILE) {
-        r->file.fd = ngx_open_file(r->file.name.data, NGX_FILE_RDONLY);
+        r->file.fd = ngx_open_file(r->file.name.data,
+                                   NGX_FILE_RDONLY, NGX_FILE_OPEN);
     }
 
     if (r->file.fd == NGX_INVALID_FILE) {
@@ -367,6 +374,8 @@ ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data);
                               r->file.name.data);
             }
 
+            r->file.fd = NGX_INVALID_FILE;
+
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
 
@@ -382,6 +391,8 @@ ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data);
             ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
                           ngx_close_file_n " \"%s\" failed", r->file.name.data);
         }
+
+        r->file.fd = NGX_INVALID_FILE;
 #endif
 
         /* BROKEN: need to include server name */
@@ -782,12 +793,13 @@ static char *ngx_http_core_merge_srv_conf(ngx_pool_t *pool,
     ngx_http_listen_t        *l;
     ngx_http_server_name_t   *n;
 
-    /* TODO: it does not merge, it init only */
+    /* TODO: it does not merge, it inits only */
 
     if (conf->listen.nelts == 0) {
         ngx_test_null(l, ngx_push_array(&conf->listen), NGX_CONF_ERROR);
         l->addr = INADDR_ANY;
-        l->port = 8000;
+        /* STUB: getuid() should be cached */
+        l->port = (getuid() == 0) ? 80 : 8000;
         l->family = AF_INET;
     }
 
@@ -871,8 +883,7 @@ static char *ngx_http_core_merge_loc_conf(ngx_pool_t *pool,
     int               i, key;
     ngx_http_type_t  *t;
 
-    ngx_conf_merge_str_value(conf->doc_root,
-                             prev->doc_root, "html");
+    ngx_conf_merge_str_value(conf->doc_root, prev->doc_root, "html");
 
     if (conf->types == NULL) {
         if (prev->types) {
index 9d41584d3c77ab230f7f71b79d2f1ff2b4e2d3e3..d65fdde486eacdf408fa45fe55077848fd28a30a 100644 (file)
@@ -1,21 +1,8 @@
 
 #include <ngx_config.h>
 #include <ngx_core.h>
-#include <ngx_string.h>
-#include <ngx_files.h>
-#include <ngx_log.h>
-#include <ngx_alloc.h>
-#include <ngx_array.h>
-#include <ngx_table.h>
-#include <ngx_hunk.h>
-#include <ngx_connection.h>
 #include <ngx_event.h>
-#include <ngx_event_timer.h>
-#include <ngx_inet.h>
 #include <ngx_http.h>
-#include <ngx_http_config.h>
-#include <ngx_http_core_module.h>
-#include <ngx_http_output_filter.h>
 
 
 static void ngx_http_init_request(ngx_event_t *ev);
@@ -63,12 +50,13 @@ static ngx_http_header_t headers_in[] = {
     { ngx_string("Content-Length"),
                             offsetof(ngx_http_headers_in_t, content_length) },
 
+    { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range) },
 #if 0
+    { ngx_string("If-Range"), offsetof(ngx_http_headers_in_t, if_range) },
+#endif
 
     { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) },
 
-#endif
-
     { ngx_null_string, 0 }
 };
 
@@ -289,6 +277,13 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
 
         /* the request line has been parsed successfully */
 
+        /* STUB: we need to handle such URIs */
+        if (r->complex_uri || r->unusual_uri) {
+            ngx_http_header_parse_error(r, NGX_HTTP_PARSE_INVALID_REQUEST);
+            ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+            return;
+        }
+
         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
 
         if (r->http_version >= NGX_HTTP_VERSION_10
@@ -402,7 +397,7 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
         if (r->args.data[0] == '\0') { r->args.data = NULL; }
 #endif
 
-        if (r->http_version == NGX_HTTP_VERSION_9) {
+        if (r->http_version < NGX_HTTP_VERSION_10) {
             rev->event_handler = ngx_http_block_read;
             ngx_http_handler(r);
             return;
@@ -1436,9 +1431,14 @@ 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->action && ctx->url) {
         return ngx_snprintf(buf, len, " while %s, client: %s, URL: %s",
                             ctx->action, ctx->client, ctx->url);
+
+    } else if (ctx->action == NULL && ctx->url) {
+        return ngx_snprintf(buf, len, ", client: %s, URL: %s",
+                            ctx->client, ctx->url);
+
     } else {
         return ngx_snprintf(buf, len, " while %s, client: %s",
                             ctx->action, ctx->client);
diff --git a/src/http/ngx_http_filter.h b/src/http/ngx_http_filter.h
new file mode 100644 (file)
index 0000000..6e0c3fc
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _NGX_HTTP_FILTER_H_INCLUDED_
+#define _NGX_HTTP_FILTER_H_INCLUDED_
+
+
+#define NGX_HTTP_FILTER_NEED_IN_MEMORY      1
+#define NGX_HTTP_FILTER_SSI_NEED_IN_MEMORY  2
+#define NGX_HTTP_FILTER_NEED_TEMP           4
+
+
+int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk);
+int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in);
+
+
+extern int (*ngx_http_top_header_filter) (ngx_http_request_t *r);
+extern int (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
+
+
+#endif /* _NGX_HTTP_FILTER_H_INCLUDED_ */
index c83a5ba2ae542ead94e287e10e428ced53f091c1..45df008d183e7621ab70bf40e64a67f6f0b4c8ab 100644 (file)
@@ -1,8 +1,6 @@
 
-#include <nginx.h>
-
 #include <ngx_config.h>
-#include <ngx_types.h>
+#include <ngx_core.h>
 
 
 size_t ngx_http_get_time(char *buf, time_t t)
index cbdbf23dfacfa0572a0ef1202578dc6422306599..583b56dc0020a979397c932a3dc5cd635cb63f62 100644 (file)
@@ -1,11 +1,8 @@
 
 #include <ngx_config.h>
 #include <ngx_core.h>
-
-#include <nginx.h>
-
 #include <ngx_http.h>
-#include <ngx_http_write_filter.h>
+#include <nginx.h>
 
 
 static int ngx_http_header_filter_init(ngx_pool_t *pool);
@@ -52,7 +49,11 @@ static ngx_str_t http_codes[] = {
 #endif
 
     ngx_string("301 Moved Permanently"),
+#if 0
     ngx_string("302 Moved Temporarily"),
+#else
+    ngx_string("302 Found"),
+#endif
     ngx_null_string,  /* "303 See Other" */
     ngx_string("304 Not Modified"),
 
@@ -87,11 +88,12 @@ static ngx_str_t http_codes[] = {
 
 static int ngx_http_header_filter(ngx_http_request_t *r)
 {
-    int               len, status, text, i;
-    time_t            ims;
-    ngx_hunk_t       *h;
-    ngx_chain_t      *ch;
-    ngx_table_elt_t  *header;
+    int                len, status, i;
+    time_t             ims;
+    ngx_hunk_t        *h;
+    ngx_chain_t       *ch;
+    ngx_table_elt_t   *header;
+    ngx_http_range_t  *range;
 
     if (r->http_version < NGX_HTTP_VERSION_10) {
         return NGX_OK;
@@ -170,20 +172,23 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
         len += 37;
     }
 
+    if (r->headers_out.content_range && r->headers_out.content_range->value.len)
+    {
+        len += 15 + r->headers_out.content_range->value.len + 2;
+    }
+
     if (r->headers_out.content_length >= 0) {
         /* "Content-Length: ... \r\n", 2^64 is 20 characters */
         len += 48;
     }
 
-    text = 0;
     if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
         r->headers_out.content_type->key.len = 0;
         len += 16 + r->headers_out.content_type->value.len;
-        if (ngx_strncasecmp(r->headers_out.content_type->value.data,
-                                                            "text/", 5) == 0) {
-            text = 1;
-            /* "; charset=koi8-r" */
-            len += 16;
+
+        if (r->headers_out.charset.len) {
+            /* "; charset= ... " */
+            len += 10 + r->headers_out.charset.len;
         }
     }
 
@@ -210,6 +215,11 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
         len += 46;
     }
 
+    if (r->chunked) {
+        /* "Transfer-Encoding: chunked\r\n" */
+        len += 28;
+    }
+
     if (r->keepalive == 0) {
         /* "Connection: close\r\n" */
         len += 19;
@@ -253,6 +263,15 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
         *(h->last++) = CR; *(h->last++) = LF;
     }
 
+
+    if (r->headers_out.content_range && r->headers_out.content_range->value.len)
+    {
+        h->last = ngx_cpymem(h->last, "Content-Range: ", 15);
+        h->last = ngx_cpymem(h->last, r->headers_out.content_range->value.data,
+                             r->headers_out.content_range->value.len);
+        *(h->last++) = CR; *(h->last++) = LF;
+    }
+
     /* 2^64 is 20 characters  */
     if (r->headers_out.content_length >= 0) {
         h->last += ngx_snprintf(h->last, 49,
@@ -263,10 +282,12 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
     if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
         h->last = ngx_cpymem(h->last, "Content-Type: ", 14);
         h->last = ngx_cpymem(h->last, r->headers_out.content_type->value.data,
-                   r->headers_out.content_type->value.len);
+                             r->headers_out.content_type->value.len);
 
-        if (text) {
-            h->last = ngx_cpymem(h->last, "; charset=koi8-r", 16);
+        if (r->headers_out.charset.len) {
+            h->last = ngx_cpymem(h->last, "; charset=", 10);
+            h->last = ngx_cpymem(h->last, r->headers_out.charset.data,
+                                 r->headers_out.charset.len);
         }
 
         *(h->last++) = CR; *(h->last++) = LF;
@@ -299,6 +320,10 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
         *(h->last++) = CR; *(h->last++) = LF;
     }
 
+    if (r->chunked) {
+        h->last = ngx_cpymem(h->last, "Transfer-Encoding: chunked" CRLF, 28);
+    }
+
     if (r->keepalive == 0) {
         h->last = ngx_cpymem(h->last, "Connection: close" CRLF, 19);
 
index 2db9b523ffc79c558c99cd36f1a04366e7a48202..c0c4dd4cfb9fe4833f1b11d0df8aebf98877d038 100644 (file)
@@ -1,15 +1,20 @@
 
 #include <ngx_config.h>
-
 #include <ngx_core.h>
-#include <ngx_files.h>
-#include <ngx_string.h>
-#include <ngx_hunk.h>
-#include <ngx_conf_file.h>
-
 #include <ngx_http.h>
-#include <ngx_http_config.h>
-#include <ngx_http_output_filter.h>
+
+
+typedef struct {
+    size_t        hunk_size;
+} ngx_http_output_filter_conf_t;
+
+
+typedef struct {
+    ngx_hunk_t   *hunk;         /* the temporary hunk to copy */
+    ngx_chain_t  *incoming;
+    ngx_chain_t   in;           /* one chain entry for input */
+    ngx_chain_t   out;          /* one chain entry for output */
+} ngx_http_output_filter_ctx_t;
 
 
 static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src);
diff --git a/src/http/ngx_http_output_filter.h b/src/http/ngx_http_output_filter.h
deleted file mode 100644 (file)
index 2f34600..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef _NGX_HTTP_OUTPUT_FILTER_H_INCLUDED_
-#define _NGX_HTTP_OUTPUT_FILTER_H_INCLUDED_
-
-
-#include <ngx_hunk.h>
-#include <ngx_conf_file.h>
-#include <ngx_http.h>
-
-
-#define NGX_HTTP_FILTER_NEED_IN_MEMORY      1
-#define NGX_HTTP_FILTER_SSI_NEED_IN_MEMORY  2
-#define NGX_HTTP_FILTER_NEED_TEMP           4
-
-
-typedef struct {
-    size_t        hunk_size;
-} ngx_http_output_filter_conf_t;
-
-
-typedef struct {
-    ngx_hunk_t   *hunk;         /* the temporary hunk to copy */
-    ngx_chain_t  *incoming;
-    ngx_chain_t   in;           /* one chain entry for input */
-    ngx_chain_t   out;          /* one chain entry for output */
-} ngx_http_output_filter_ctx_t;
-
-
-int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk);
-
-
-extern ngx_module_t  ngx_http_output_filter_module;
-
-
-#endif /* _NGX_HTTP_OUTPUT_FILTER_H_INCLUDED_ */
index a7784a36d8fca2c6dae0698d08e5c1deeaae95e3..e02805be83cd29fa3667297033458c40b1a9d113 100644 (file)
@@ -175,7 +175,7 @@ int ngx_parse_http_request_line(ngx_http_request_t *r)
             }
             break;
 
-        /* check "/." or "//" */
+        /* check "/.", "//", and "%" in URI */
         case sw_after_slash_in_uri:
             switch (ch) {
             case CR:
@@ -193,6 +193,7 @@ int ngx_parse_http_request_line(ngx_http_request_t *r)
                 state = sw_http_09;
                 break;
             case '.':
+            case '%':
                 r->complex_uri = 1;
                 state = sw_uri;
                 break;
@@ -211,7 +212,7 @@ int ngx_parse_http_request_line(ngx_http_request_t *r)
             }
             break;
 
-        /* check slash in URI */
+        /* check "/" and "%" in URI */
         case sw_check_uri:
             switch (ch) {
             case CR:
@@ -235,6 +236,10 @@ int ngx_parse_http_request_line(ngx_http_request_t *r)
                 r->uri_ext = NULL;
                 state = sw_after_slash_in_uri;
                 break;
+            case '%':
+                r->complex_uri = 1;
+                state = sw_uri;
+                break;
             case '?':
                 r->args_start = p;
                 state = sw_uri;
index 15898e8681999006c58717dfb82de587954e6d47..a4ecb6bf1bef3e443921f48dac10c3d8a69fea9f 100644 (file)
@@ -40,6 +40,7 @@
 
 
 #define NGX_HTTP_OK                     200
+#define NGX_HTTP_PARTIAL_CONTENT        206
 
 #define NGX_HTTP_SPECIAL_RESPONSE       300
 #define NGX_HTTP_MOVED_PERMANENTLY      301
@@ -52,6 +53,7 @@
 #define NGX_HTTP_NOT_ALLOWED            405
 #define NGX_HTTP_REQUEST_TIME_OUT       408
 #define NGX_HTTP_REQUEST_URI_TOO_LARGE  414
+#define NGX_HTTP_RANGE_NOT_SATISFIABLE  416
 
 #define NGX_HTTP_INTERNAL_SERVER_ERROR  500
 #define NGX_HTTP_NOT_IMPLEMENTED        501
@@ -79,6 +81,8 @@ typedef struct {
     ngx_table_elt_t  *connection;
     ngx_table_elt_t  *if_modified_since;
     ngx_table_elt_t  *content_length;
+    ngx_table_elt_t  *range;
+
     ngx_table_elt_t  *accept_encoding;
 
     ngx_table_elt_t  *user_agent;
@@ -99,6 +103,13 @@ typedef struct {
 } ngx_http_request_body_t;
 
 
+typedef struct {
+    off_t      start;
+    off_t      end;
+    ngx_str_t  content_range;
+} ngx_http_range_t;
+
+
 typedef struct {
     int               status;
     ngx_str_t         status_line;
@@ -108,11 +119,14 @@ typedef struct {
     ngx_table_elt_t  *content_type;
     ngx_table_elt_t  *location;
     ngx_table_elt_t  *last_modified;
+    ngx_table_elt_t  *content_range;
+
+    ngx_str_t         charset;
+    ngx_array_t       ranges;
 
     ngx_table_t      *headers;
 
     off_t             content_length;
-    char             *charset;
     char             *etag;
     time_t            date_time;
     time_t            last_modified_time;
@@ -140,7 +154,7 @@ struct ngx_http_request_s {
 
     int  (*handler)(ngx_http_request_t *r);
 
-    time_t  lingering_time;
+    time_t               lingering_time;
 
     int                  method;
     int                  http_version;
@@ -161,46 +175,44 @@ struct ngx_http_request_s {
     ngx_str_t           *server_name;
     ngx_array_t         *virtual_names;
 
-    int         filter;
 
-    char       *discarded_buffer;
+    char                *discarded_buffer;
 
-    ngx_str_t   path;
-    int         path_err;
+    ngx_str_t            path;
+    int                  path_err;
 
-    unsigned  proxy:1;
-    unsigned  cachable:1;
-    unsigned  pipeline:1;
-    unsigned  keepalive:1;
-    unsigned  lingering_close:1;
+    /* URI is not started with '/' - "GET http://" */
+    unsigned             unusual_uri:1;
+    /* URI with "/.", "%" and on Win32 with "//" */
+    unsigned             complex_uri:1;
+    unsigned             header_timeout_set:1;
 
-    unsigned  header_read:1;
-    unsigned  header_timeout_set:1;
-
-    unsigned  logging:1;
-
-    unsigned  header_only:1;
-    unsigned  unusual_uri:1;  /* URI is not started with '/' - "GET http://" */
-    unsigned  complex_uri:1;  /* URI with "/." or with "//" (WIN32) */
-    unsigned  path_not_found:1;
-#ifdef NGX_EVENT
-    unsigned  write_level_event:1;
-#endif
-
-    int    state;
-    char  *uri_start;
-    char  *uri_end;
-    char  *uri_ext;
-    char  *args_start;
-    char  *request_start;
-    char  *request_end;
-    char  *header_name_start;
-    char  *header_name_end;
-    char  *header_start;
-    char  *header_end;
-#ifdef NGX_EVENT
-    int  (*state_handler)(ngx_http_request_t *r);
+    unsigned             proxy:1;
+#if 0
+    unsigned             cachable:1;
 #endif
+    unsigned             pipeline:1;
+
+    unsigned             chunked:1;
+    unsigned             header_only:1;
+    unsigned             keepalive:1;
+    unsigned             lingering_close:1;
+
+    /* TODO: use filter or bits ???? */
+    int                  filter;
+
+    /* used to parse HTTP headers */
+    int                  state;
+    char                *uri_start;
+    char                *uri_end;
+    char                *uri_ext;
+    char                *args_start;
+    char                *request_start;
+    char                *request_end;
+    char                *header_name_start;
+    char                *header_name_end;
+    char                *header_start;
+    char                *header_end;
 };
 
 
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
new file mode 100644 (file)
index 0000000..19e582a
--- /dev/null
@@ -0,0 +1,49 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+char *ngx_http_script_copy(ngx_http_request_t *r,
+                           ngx_http_script_code_t *code,
+                           char *p, size_t len)
+{
+    return ngx_cpymem(p, code->offset, code->len < len ? code->len : len);
+}
+
+
+char *ngx_http_script_header_in(ngx_http_request_t *r,
+                                ngx_http_script_code_t *code,
+                                char *p, size_t len)
+{
+    ngx_str_t *s;
+
+    s = (ngx_str_t *) (((char *) r->headers_in) + code->offset);
+
+    return ngx_cpymem(p, s->data, s->len < len ? s->len : len);
+}
+
+
+/* the log script codes */
+
+char *ngx_http_script_request_line(ngx_http_request_t *r, char *p, size_t len)
+{
+    return ngx_cpymem(p, r->request_line.data,
+                      r->request_line.len < len ? r->request_line.len : len);
+}
+
+
+char *ngx_http_script_status(ngx_http_request_t *r, char *p, size_t len)
+{
+    p += ngx_snprintf(p, len, "%d", r->headers_out.status);
+
+    return p;
+}
+
+
+char *ngx_http_script_sent(ngx_http_request_t *r, char *p, size_t len)
+{
+    p += ngx_snprintf(p, len, OFF_FMT, r->connection->sent);
+
+    return p;
+}
diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h
new file mode 100644 (file)
index 0000000..d3fd5fb
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _NGX_HTTP_SCRIPT_H_INCLUDED_
+#define _NGX_HTTP_SCRIPT_H_INCLUDED_
+
+
+typedef struct {
+    handler;
+    offset / data;
+    size;
+} ngx_http_script_code_t;
+
+
+#endif /* _NGX_HTTP_SCRIPT_H_INCLUDED_ */
index 1b71352da9adc427a6601b05295fb65ece5a39e6..9a5dea1f85f276095059563845c12b700fa2b1ea 100644 (file)
@@ -1,11 +1,8 @@
 
 #include <ngx_config.h>
 #include <ngx_core.h>
-
-#include <nginx.h>
-
 #include <ngx_http.h>
-#include <ngx_http_output_filter.h>
+#include <nginx.h>
 
 
 static char error_tail[] =
@@ -15,6 +12,14 @@ static char error_tail[] =
 ;
 
 
+static char error_302_page[] =
+"<html>" CRLF
+"<head><title>302 Found</title></head>" CRLF
+"<body bgcolor=\"white\">" CRLF
+"<center><h1>302 Found</h1></center>" CRLF
+;
+
+
 static char error_400_page[] =
 "<html>" CRLF
 "<head><title>400 Bad Request</title></head>" CRLF
@@ -63,6 +68,14 @@ static char error_414_page[] =
 ;
 
 
+static char error_416_page[] =
+"<html>" CRLF
+"<head><title>416 Requested Range Not Satisfiable</title></head>" CRLF
+"<body bgcolor=\"white\">" CRLF
+"<center><h1>416 Requested Range Not Satisfiable</h1></center>" CRLF
+;
+
+
 static char error_500_page[] =
 "<html>" CRLF
 "<head><title>500 Internal Server Error</title></head>" CRLF
@@ -88,8 +101,9 @@ static char error_504_page[] =
 
 
 static ngx_str_t error_pages[] = {
+    ngx_null_string,             /* 300 */
     ngx_null_string,             /* 301 */
-    ngx_null_string,             /* 302 */
+    ngx_string(error_302_page),
     ngx_null_string,             /* 303 */
 
     ngx_string(error_400_page),
@@ -108,7 +122,7 @@ static ngx_str_t error_pages[] = {
     ngx_null_string,             /* 413 */
     ngx_string(error_414_page),
     ngx_null_string,             /* 415 */
-    ngx_null_string,             /* 416 */
+    ngx_string(error_416_page),
 
     ngx_string(error_500_page),
     ngx_null_string,             /* 501 */
@@ -120,35 +134,22 @@ static ngx_str_t error_pages[] = {
 
 int ngx_http_special_response_handler(ngx_http_request_t *r, int error)
 {
-    int          err, len;
+    int          err;
     ngx_hunk_t  *message, *tail;
 
-    len = 0;
-
     r->headers_out.status = error;
 
     if (error < NGX_HTTP_BAD_REQUEST) {
         /* 3XX */
         err = error - NGX_HTTP_MOVED_PERMANENTLY;
 
-    } else {
-        ngx_test_null(r->headers_out.content_type,
-                      ngx_push_table(r->headers_out.headers),
-                      NGX_HTTP_INTERNAL_SERVER_ERROR);
-
-        r->headers_out.content_type->key.len = 12;
-        r->headers_out.content_type->key.data = "Content-Type";
-        r->headers_out.content_type->value.len = 9;
-        r->headers_out.content_type->value.data = "text/html";
-
-        if (error < NGX_HTTP_INTERNAL_SERVER_ERROR) {
-            /* 4XX */
-            err = error - NGX_HTTP_BAD_REQUEST + 3;
+    } else if (error < NGX_HTTP_INTERNAL_SERVER_ERROR) {
+        /* 4XX */
+        err = error - NGX_HTTP_BAD_REQUEST + 4;
 
-        } else {
-            /* 5XX */
-            err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 3 + 17;
-        }
+    } else {
+        /* 5XX */
+        err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 4 + 17;
     }
 
     if (r->keepalive != 0) {
@@ -169,11 +170,21 @@ int ngx_http_special_response_handler(ngx_http_request_t *r, int error)
         }
     }
 
-    if (error_pages[err].len == 0) {
-        r->headers_out.content_length = -1;
-    } else {
+    if (error_pages[err].len) {
         r->headers_out.content_length = error_pages[err].len
-                                        + len + sizeof(error_tail);
+                                        + sizeof(error_tail);
+
+        ngx_test_null(r->headers_out.content_type,
+                      ngx_push_table(r->headers_out.headers),
+                      NGX_HTTP_INTERNAL_SERVER_ERROR);
+
+        r->headers_out.content_type->key.len = 12;
+        r->headers_out.content_type->key.data = "Content-Type";
+        r->headers_out.content_type->value.len = 9;
+        r->headers_out.content_type->value.data = "text/html";
+
+    } else {
+        r->headers_out.content_length = -1;
     }
 
     if (ngx_http_send_header(r) == NGX_ERROR) {
index 1844438870ca7e22383a3557a9eff7f6685bcc59..59d4a69250736c04d5169c265cc0e1fc67870ffd 100644 (file)
@@ -1,16 +1,17 @@
 
 #include <ngx_config.h>
-
 #include <ngx_core.h>
-#include <ngx_hunk.h>
-#include <ngx_conf_file.h>
-#include <ngx_connection.h>
+#include <ngx_http.h>
 
-#include <ngx_event_write.h>
 
-#include <ngx_http.h>
-#include <ngx_http_config.h>
-#include <ngx_http_write_filter.h>
+typedef struct {
+    size_t        buffer_output;
+} ngx_http_write_filter_conf_t;
+
+
+typedef struct {
+    ngx_chain_t  *out;
+} ngx_http_write_filter_ctx_t;
 
 
 static void *ngx_http_write_filter_create_conf(ngx_pool_t *pool);
@@ -96,7 +97,7 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
     /* add the new chain to the existent one */
 
     for (/* void */; in; in = in->next) {
-        ngx_test_null(ce, ngx_palloc(r->pool, sizeof(ngx_chain_t)), NGX_ERROR);
+        ngx_test_null(ce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
 
         ce->hunk = in->hunk;
         ce->next = NULL;
diff --git a/src/http/ngx_http_write_filter.h b/src/http/ngx_http_write_filter.h
deleted file mode 100644 (file)
index 492d4d8..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _NGX_HTTP_WRITE_FILTER_H_INCLUDED_
-#define _NGX_HTTP_WRITE_FILTER_H_INCLUDED_
-
-
-#include <ngx_hunk.h>
-#include <ngx_http.h>
-
-
-typedef struct {
-    size_t        buffer_output;
-} ngx_http_write_filter_conf_t;
-
-
-typedef struct {
-    ngx_chain_t  *out;
-} ngx_http_write_filter_ctx_t;
-
-
-int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in);
-
-
-extern ngx_module_t  ngx_http_write_filter_module;
-
-
-#endif /* _NGX_HTTP_WRITE_FILTER_H_INCLUDED_ */
index 37d136af7395f198fc20fbacf720fcfe87973e0c..e2af7222c3a6455a32b0923f53d04a7249d47961 100644 (file)
 
 
 
-#define ngx_open_file            open
+#define ngx_open_file(name, access, create)                                 \
+                                 open(name, access|create, 0644)
 #define ngx_open_file_n          "open()"
 
+#define NGX_FILE_RDONLY          O_RDONLY
+#define NGX_FILE_RDWR            O_RDWR
+#define NGX_FILE_CREATE_OR_OPEN  O_CREAT
+#define NGX_FILE_OPEN            0
+#define NGX_FILE_APPEND          O_APPEND
+
+
 #define ngx_close_file           close
 #define ngx_close_file_n         "close()"
 
+
 #define ngx_open_tempfile(name, persistent)                                 \
                                  open(name, O_CREAT|O_EXCL|O_RDWR, 0600)
 #define ngx_open_tempfile_n      "open()"
 
+
 ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset);
 #define ngx_read_file_n          "read()"
 
-#define NGX_FILE_RDONLY          O_RDONLY
 
 ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset);
 
index cacc4579f91a8e31e795a0871710b81ba275aa9a..e01f9b613aaa87893ba1647b75ff661c188c1cce 100644 (file)
@@ -9,6 +9,7 @@ int ngx_freebsd_kern_osreldate;
 int ngx_freebsd_hw_ncpu;
 int ngx_freebsd_net_inet_tcp_sendspace;
 int ngx_freebsd_sendfile_nbytes_bug;
+int ngx_freebsd_tcp_nopush_flush;
 
 /* FreeBSD 5.0 */
 int ngx_freebsd_kern_ipc_zero_copy_send;
@@ -39,6 +40,8 @@ sysctl_t sysctls[] = {
      &ngx_freebsd_net_inet_tcp_sendspace,
      sizeof(int)},
 
+     /* FreeBSD 5.0 */
+
     {"kern.ipc.zero_copy.send",
      &ngx_freebsd_kern_ipc_zero_copy_send,
      sizeof(int)},
@@ -49,7 +52,7 @@ sysctl_t sysctls[] = {
 
 int ngx_os_init(ngx_log_t *log)
 {
-    int        i;
+    int        i, version;
     size_t     size;
     ngx_err_t  err;
 
@@ -81,9 +84,11 @@ int ngx_os_init(ngx_log_t *log)
         return NGX_ERROR;
     }
 
+    version = ngx_freebsd_kern_osreldate;
+
     ngx_log_error(NGX_LOG_INFO, log, 0,
                   "kern.osreldate: %d, built on %d",
-                  ngx_freebsd_kern_osreldate, __FreeBSD_version);
+                  version, __FreeBSD_version);
 
 
 #if (HAVE_FREEBSD_SENDFILE)
@@ -91,12 +96,12 @@ int ngx_os_init(ngx_log_t *log)
     /* The determination of the sendfile() nbytes bug is complex enough.
        There're two sendfile() syscalls: a new 393 has no bug while
        an old 336 has the bug in some versions and has not in others.
-       libc_r wrapper also emulates the bug in some versions.
+       Besides libc_r wrapper also emulates the bug in some versions.
        There's no way to say exactly if a given FreeBSD version has bug.
-       Here is the algorithm that work at least for RELEASEs
+       Here is the algorithm that works at least for RELEASEs
        and for syscalls only (not libc_r wrapper). */
 
-    /* detect was the new sendfile() version available at the compile time
+    /* detect the new sendfile() version available at the compile time
        to allow an old binary to run correctly on an updated FreeBSD system. */
 
 #if (__FreeBSD__ == 4 && __FreeBSD_version >= 460102) \
@@ -115,6 +120,11 @@ int ngx_os_init(ngx_log_t *log)
 #endif /* HAVE_FREEBSD_SENDFILE */
 
 
+    if ((version < 500000 && version >= 440003) || version >= 500017) {
+        ngx_freebsd_tcp_nopush_flush = 1;
+    }
+
+
     for (i = 0; sysctls[i].name; i++) {
         *sysctls[i].value = 0;
         size = sysctls[i].size;
index cc450f91456d487fadd383a4906c4c8feeab3a65..967951d8d9924291dd6b368af4695656a0d174c1 100644 (file)
@@ -20,6 +20,8 @@ extern int ngx_freebsd_kern_osreldate;
 extern int ngx_freebsd_hw_ncpu;
 extern int ngx_freebsd_net_inet_tcp_sendspace;
 extern int ngx_freebsd_sendfile_nbytes_bug;
+extern int ngx_freebsd_tcp_nopush_flush;
+extern int ngx_freebsd_kern_ipc_zero_copy_send;
 
 
 #endif /* _NGX_FREEBSD_INIT_H_INCLUDED_ */
index bdb7250c908c22771a95e81d1dfc082dd716a762..cd21ed904363c8ff408773c1037644b52a192083 100644 (file)
@@ -13,9 +13,9 @@
    and the first part of the file in one packet but also sends 4K pages
    in the full packets.
 
-   The turning TCP_NOPUSH off flushes any pending data at least in FreeBSD 4.2,
-   although there's special fix in src/sys/netinet/tcp_usrreq.c just before
-   FreeBSD 4.5.
+   Until FreeBSD 4.5 the turning TCP_NOPUSH off does not not flush
+   the pending data that less than MSS and the data sent with 5 second delay.
+   So we use TCP_NOPUSH on FreeBSD 4.5+ only.
 */
 
 
@@ -105,14 +105,15 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
 
         if (file) {
 
-            if (tcp_nopush == 0) {
+            if (!c->tcp_nopush && ngx_freebsd_tcp_nopush_flush) {
+                c->tcp_nopush = 1;
                 tcp_nopush = 1;
                 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NOPUSH,
                                (const void *) &tcp_nopush,
                                sizeof(int)) == -1)
                 {
                     ngx_log_error(NGX_LOG_CRIT, c->log, ngx_errno,
-                                  "setsockopt(TCP_NO_PUSH) failed");
+                                  "setsockopt(TCP_NOPUSH) failed");
                     return NGX_CHAIN_ERROR;
                 }
             }
@@ -221,14 +222,18 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
 
     } while ((tail && tail == ce) || eintr);
 
-    if (tcp_nopush == 1) {
+    /* STUB: should be in app code, no need to clear TCP_NOPUSH
+             if the conneciton close()d or shutdown()ed */
+
+    if (c->tcp_nopush) {
+        c->tcp_nopush = 0;
         tcp_nopush = 0;
         if (setsockopt(c->fd, IPPROTO_TCP, TCP_NOPUSH,
                        (const void *) &tcp_nopush,
                        sizeof(int)) == -1)
         {
             ngx_log_error(NGX_LOG_CRIT, c->log, ngx_errno,
-                          "setsockopt(!TCP_NO_PUSH) failed");
+                          "setsockopt(!TCP_NOPUSH) failed");
             return NGX_CHAIN_ERROR;
         }
     }
index 0fdad0f75f4bb948c5baaa779fe318911821e902..08525b992c60f3bb6938c6fac185a01102953604 100644 (file)
 
 
 
-#define ngx_open_file(name, flags)                                          \
+#define ngx_open_file(name, access, create)                                 \
             CreateFile(name, flags,                                         \
                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,  \
-                       NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL)
+                       NULL, create, FILE_FLAG_BACKUP_SEMANTICS, NULL)
 /*
                        NULL, OPEN_EXISTING, 0, NULL)
 */
+#define ngx_open_file_n             "CreateFile()"
+
+#define NGX_FILE_RDONLY             GENERIC_READ
+#define NGX_FILE_RDWR               GENERIC_READ|GENERIC_WRITE
+#define NGX_FILE_CREATE_OR_OPEN     OPEN_ALWAYS
+#define NGX_FILE_OPEN               OPEN_EXISTING
+
 
 #define ngx_open_tempfile(name, persistent)                                 \
             CreateFile(name,                                                \
 
 
 
-#define ngx_open_file_n             "CreateFile()"
-
-#define NGX_FILE_RDONLY             GENERIC_READ
-
 #define ngx_close_file              CloseHandle
 #define ngx_close_file_n            "CloseHandle()"