diff src/http/modules/ngx_http_ssi_filter.c @ 48:6cfc63e68377 NGINX_0_1_24

nginx 0.1.24 *) Feature: the ngx_http_ssi_filter_module supports the QUERY_STRING and DOCUMENT_URI variables. *) Bugfix: the ngx_http_autoindex_module may some times return the 404 response for existent directory, if this directory was used in "alias" directive. *) Bugfix: the ngx_http_ssi_filter_module ran incorrectly for large responses. *) Bugfix: the lack of the "Referer" header line was always accounted as valid referrer.
author Igor Sysoev <http://sysoev.ru>
date Fri, 04 Mar 2005 00:00:00 +0300
parents 9f3205d496a0
children
line wrap: on
line diff
--- a/src/http/modules/ngx_http_ssi_filter.c
+++ b/src/http/modules/ngx_http_ssi_filter.c
@@ -41,6 +41,8 @@ typedef struct {
     ngx_chain_t       *in;
     ngx_chain_t       *out;
     ngx_chain_t      **last_out;
+    ngx_chain_t       *busy;
+    ngx_chain_t       *free;
 
     ngx_uint_t         state;
     ngx_uint_t         saved_state;
@@ -158,7 +160,7 @@ ngx_module_t  ngx_http_ssi_filter_module
     ngx_http_ssi_filter_commands,          /* module directives */
     NGX_HTTP_MODULE,                       /* module type */
     ngx_http_ssi_filter_init,              /* init module */
-    NULL                                   /* init child */
+    NULL                                   /* init process */
 };
 
 
@@ -212,7 +214,8 @@ ngx_http_ssi_header_filter(ngx_http_requ
     }
 
 
-    if (!(ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_ssi_ctx_t)))) {
+    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_ssi_ctx_t));
+    if (ctx == NULL) {
         return NGX_ERROR;
     }
 
@@ -262,7 +265,7 @@ ngx_http_ssi_body_filter(ngx_http_reques
 
     ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module);
 
-    if (ctx == NULL || (in == NULL && ctx->in == NULL)) {
+    if (ctx == NULL || (in == NULL && ctx->in == NULL && ctx->busy == NULL)) {
         return ngx_http_next_body_filter(r, in);
     }
 
@@ -279,19 +282,21 @@ ngx_http_ssi_body_filter(ngx_http_reques
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http ssi filter");
 
-    b = NULL;
-
-    while (ctx->in) {
+    while (ctx->in || ctx->buf) {
 
-        ctx->buf = ctx->in->buf;
-        ctx->in = ctx->in->next;
-        ctx->pos = ctx->buf->pos;
+        if (ctx->buf == NULL ){
+            ctx->buf = ctx->in->buf;
+            ctx->in = ctx->in->next;
+            ctx->pos = ctx->buf->pos;
+        }
 
         if (ctx->state == ssi_start_state) {
             ctx->copy_start = ctx->pos;
             ctx->copy_end = ctx->pos;
         }
 
+        b = NULL;
+
         while (ctx->pos < ctx->buf->last) {
 
             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -313,32 +318,60 @@ ngx_http_ssi_body_filter(ngx_http_reques
                                "saved: %d", ctx->saved);
 
                 if (ctx->saved) {
-                    if (!(b = ngx_calloc_buf(r->pool))) {
-                        return NGX_ERROR;
+
+                    if (ctx->free) {
+                        cl = ctx->free;
+                        ctx->free = ctx->free->next;
+                        b = cl->buf;
+                        ngx_memzero(b, sizeof(ngx_buf_t));
+
+                    } else {
+                        b = ngx_calloc_buf(r->pool);
+                        if (b == NULL) {
+                            return NGX_ERROR;
+                        }
+
+                        cl = ngx_alloc_chain_link(r->pool);
+                        if (cl == NULL) {
+                            return NGX_ERROR;
+                        }
+
+                        cl->buf = b;
                     }
 
                     b->memory = 1;
                     b->pos = ngx_http_ssi_string;
                     b->last = ngx_http_ssi_string + ctx->saved;
 
-                    if (!(cl = ngx_alloc_chain_link(r->pool))) {
-                        return NGX_ERROR;
-                    }
-
-                    cl->buf = b;
                     *ctx->last_out = cl;
                     ctx->last_out = &cl->next;
 
                     ctx->saved = 0;
                 }
 
-                if (!(b = ngx_calloc_buf(r->pool))) {
-                    return NGX_ERROR;
+                if (ctx->free) {
+                    cl = ctx->free;
+                    ctx->free = ctx->free->next;
+                    b = cl->buf;
+
+                } else {
+                    b = ngx_alloc_buf(r->pool);
+                    if (b == NULL) {
+                        return NGX_ERROR;
+                    }
+
+                    cl = ngx_alloc_chain_link(r->pool);
+                    if (cl == NULL) {
+                        return NGX_ERROR;
+                    }
+
+                    cl->buf = b;
                 }
 
                 ngx_memcpy(b, ctx->buf, sizeof(ngx_buf_t));
 
                 b->last_buf = 0;
+                b->recycled = 0;
                 b->pos = ctx->copy_start;
                 b->last = ctx->copy_end;
 
@@ -353,11 +386,6 @@ ngx_http_ssi_body_filter(ngx_http_reques
                     }
                 }
 
-                if (!(cl = ngx_alloc_chain_link(r->pool))) {
-                    return NGX_ERROR;
-                }
-
-                cl->buf = b;
                 cl->next = NULL;
                 *ctx->last_out = cl;
                 ctx->last_out = &cl->next;
@@ -461,14 +489,30 @@ ngx_http_ssi_body_filter(ngx_http_reques
 
             /* rc == NGX_HTTP_SSI_ERROR */
 
-ssi_error:
+    ssi_error:
 
             if (conf->silent_errors) {
                 continue;
             }
 
-            if (!(b = ngx_calloc_buf(r->pool))) {
-                return NGX_ERROR;
+            if (ctx->free) {
+                cl = ctx->free;
+                ctx->free = ctx->free->next;
+                b = cl->buf;
+                ngx_memzero(b, sizeof(ngx_buf_t));
+
+            } else {
+                b = ngx_calloc_buf(r->pool);
+                if (b == NULL) {
+                    return NGX_ERROR;
+                }
+
+                cl = ngx_alloc_chain_link(r->pool);
+                if (cl == NULL) {
+                    return NGX_ERROR;
+                }
+
+                cl->buf = b;
             }
 
             b->memory = 1;
@@ -476,11 +520,6 @@ ssi_error:
             b->last = ngx_http_ssi_error_string
                       + sizeof(ngx_http_ssi_error_string) - 1;
 
-            if (!(cl = ngx_alloc_chain_link(r->pool))) {
-                return NGX_ERROR;
-            }
-
-            cl->buf = b;
             cl->next = NULL;
             *ctx->last_out = cl;
             ctx->last_out = &cl->next;
@@ -488,24 +527,85 @@ ssi_error:
             continue;
         }
 
-        ctx->buf->pos = ctx->buf->last;
+        if (ctx->buf->recycled || ctx->buf->last_buf) {
+            if (b == NULL) {
+
+                if (ctx->free) {
+                    cl = ctx->free;
+                    ctx->free = ctx->free->next;
+                    b = cl->buf;
+                    ngx_memzero(b, sizeof(ngx_buf_t));
+
+                } else {
+                    b = ngx_calloc_buf(r->pool);
+                    if (b == NULL) {
+                        return NGX_ERROR;
+                    }
 
-        if (b && ctx->buf->last_buf) {
-            b->last_buf = 1;
+                    cl = ngx_alloc_chain_link(r->pool);
+                    if (cl == NULL) {
+                        return NGX_ERROR;
+                    }
+
+                    cl->buf = b;
+                }
+
+                cl->next = NULL;
+                *ctx->last_out = cl;
+                ctx->last_out = &cl->next;
+            }
+
+            b->last_buf = ctx->buf->last_buf;
+            b->flush = ctx->buf->recycled;
+            b->shadow = ctx->buf;
         }
 
+        ctx->buf = NULL;
+
         ctx->saved = ctx->looked;
     }
 
-    if (ctx->out == NULL) {
+    if (ctx->out == NULL && ctx->busy == NULL) {
         return NGX_OK;
     }
 
     rc = ngx_http_next_body_filter(r, ctx->out);
 
+    if (ctx->busy == NULL) {
+        ctx->busy = ctx->out;
+
+    } else {
+        for (cl = ctx->busy; cl->next; cl = cl->next) { /* void */ }
+        cl->next = ctx->out;
+    }
+
     ctx->out = NULL;
     ctx->last_out = &ctx->out;
 
+    while (ctx->busy) {
+
+        b = ctx->busy->buf;
+
+        if (ngx_buf_size(b) != 0) {
+            break;
+        }
+
+#if (NGX_HAVE_WRITE_ZEROCOPY)
+        if (b->zerocopy_busy) {
+            break;
+        }
+#endif
+
+        if (b->shadow) {
+            b->shadow->pos = b->shadow->last;
+        }
+
+        cl = ctx->busy;
+        ctx->busy = cl->next;
+        cl->next = ctx->free;
+        ctx->free = cl;
+    }
+
     return rc;
 }
 
@@ -530,16 +630,20 @@ ngx_http_ssi_parse(ngx_http_request_t *r
 
             /* the tight loop */
 
-            for ( /* void */ ; p < last; ch = *(++p)) {
-                if (ch != '<') {
-                    continue;
+            for ( ;; ) {
+                if (ch == '<') {
+                    copy_end = p;
+                    looked = 1;
+                    state = ssi_tag_state;
+
+                    goto tag_started;
                 }
 
-                copy_end = p;
-                looked = 1;
-                state = ssi_tag_state;
+                if (++p == last) {
+                    break;
+                }
 
-                goto tag_started;
+                ch = *p;
             }
 
             ctx->pos = p;
@@ -552,7 +656,8 @@ ngx_http_ssi_parse(ngx_http_request_t *r
 
             return NGX_AGAIN;
 
-tag_started:
+        tag_started:
+
             continue;
         }
 
@@ -715,7 +820,8 @@ tag_started:
                 break;
 
             default:
-                if (!(ctx->param = ngx_array_push(&ctx->params))) {
+                ctx->param = ngx_array_push(&ctx->params);
+                if (ctx->param == NULL) {
                     return NGX_ERROR;
                 }
 
@@ -1041,80 +1147,45 @@ static ngx_int_t
 ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
     ngx_str_t **params)
 {
-    u_char            ch;
-    ngx_uint_t        i, n;
-    ngx_buf_t        *b;
-    ngx_str_t        *var, *value;
-    ngx_chain_t      *cl;
-    ngx_list_part_t  *part;
-    ngx_table_elt_t  *header;
+    ngx_buf_t                  *b;
+    ngx_str_t                  *var, *value;
+    ngx_chain_t                *cl;
+    ngx_http_variable_value_t  *v;
 
     var = params[NGX_HTTP_SSI_ECHO_VAR];
     value = NULL;
 
-    if (var->len > 5 && ngx_strncmp(var->data, "HTTP_", 5) == 0) {
-
-        part = &r->headers_in.headers.part;
-        header = part->elts;
-
-        for (i = 0; /* void */ ; i++) {
-
-            if (i >= part->nelts) {
-                if (part->next == NULL) {
-                    break;
-                }
-
-                part = part->next;
-                header = part->elts;
-                i = 0; 
-            }
-
-            for (n = 0; n + 5 < var->len && n < header[i].key.len; n++)
-            {
-                ch = header[i].key.data[n];
-
-                if (ch >= 'a' && ch <= 'z') {
-                    ch &= ~0x20;
-
-                } else if (ch == '-') {
-                    ch = '_';
-                }
+    v = ngx_http_get_variable(r, var);
 
-                if (var->data[n + 5] != ch) {
-                    break;
-                }
-            }
-
-            if (n + 5 == var->len) {
-                value = &header[i].value;
-                break;
-            }
-        }
-
-    } else if (var->len == sizeof("REMOTE_ADDR") - 1
-               && ngx_strncmp(var->data, "REMOTE_ADDR",
-                              sizeof("REMOTE_ADDR") - 1) == 0)
-    {
-        value = &r->connection->addr_text;
-    }
-
-
-    if (value == NULL) {
-        value = params[NGX_HTTP_SSI_ECHO_DEFAULT];
-    }
-
-    if (value == NULL) {
-        value = &ngx_http_ssi_none;
-
-    } else if (value->len == 0) {
-        return NGX_OK;
-    }
-
-    if (!(b = ngx_calloc_buf(r->pool))) {
+    if (v == NULL) {
         return NGX_HTTP_SSI_ERROR;
     }
 
-    if (!(cl = ngx_alloc_chain_link(r->pool))) {
+    if (v == NGX_HTTP_VARIABLE_NOT_FOUND) {
+        value = params[NGX_HTTP_SSI_ECHO_DEFAULT];
+
+        if (value == NULL) {
+            value = &ngx_http_ssi_none;
+
+        } else if (value->len == 0) {
+            return NGX_OK;
+        }
+
+    } else {
+        value = &v->text;
+
+        if (value->len == 0) {
+            return NGX_OK;
+        }
+    }
+
+    b = ngx_calloc_buf(r->pool);
+    if (b == NULL) {
+        return NGX_HTTP_SSI_ERROR;
+    }
+
+    cl = ngx_alloc_chain_link(r->pool);
+    if (cl == NULL) {
         return NGX_HTTP_SSI_ERROR;
     }
 
@@ -1136,7 +1207,8 @@ ngx_http_ssi_create_conf(ngx_conf_t *cf)
 {
     ngx_http_ssi_conf_t  *conf;
 
-    if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssi_conf_t)))) {
+    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssi_conf_t));
+    if (conf == NULL) {
         return NGX_CONF_ERROR;
     }