]> git.kaiwu.me - nginx.git/commitdiff
handle big responses for "size" and "test" image_filters
authorIgor Sysoev <igor@sysoev.ru>
Fri, 8 May 2009 14:25:51 +0000 (14:25 +0000)
committerIgor Sysoev <igor@sysoev.ru>
Fri, 8 May 2009 14:25:51 +0000 (14:25 +0000)
src/http/modules/ngx_http_image_filter_module.c
src/http/ngx_http_request.c
src/http/ngx_http_request.h
src/http/ngx_http_special_response.c

index 10fefc5490ba6ec3e8d00c543e9cbdd1fc2c7034..c68ecb510928fa8ea6ff998740965de25a55b85d 100644 (file)
@@ -7,7 +7,8 @@
 #include <ngx_config.h>
 #include <ngx_core.h>
 #include <ngx_http.h>
-#include "gd.h"
+
+#include <gd.h>
 
 
 #define NGX_HTTP_IMAGE_OFF       0
@@ -20,7 +21,8 @@
 #define NGX_HTTP_IMAGE_START     0
 #define NGX_HTTP_IMAGE_READ      1
 #define NGX_HTTP_IMAGE_PROCESS   2
-#define NGX_HTTP_IMAGE_DONE      3
+#define NGX_HTTP_IMAGE_PASS      3
+#define NGX_HTTP_IMAGE_DONE      4
 
 
 #define NGX_HTTP_IMAGE_NONE      0
@@ -55,6 +57,8 @@ typedef struct {
 } ngx_http_image_filter_ctx_t;
 
 
+static ngx_int_t ngx_http_image_send(ngx_http_request_t *r,
+    ngx_http_image_filter_ctx_t *ctx, ngx_chain_t *in);
 static ngx_uint_t ngx_http_image_test(ngx_http_request_t *r, ngx_chain_t *in);
 static ngx_int_t ngx_http_image_read(ngx_http_request_t *r, ngx_chain_t *in);
 static ngx_buf_t *ngx_http_image_process(ngx_http_request_t *r);
@@ -247,9 +251,9 @@ ngx_http_image_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
 
                 if (out.buf) {
                     out.next = NULL;
-                    in = &out;
+                    ctx->phase = NGX_HTTP_IMAGE_DONE;
 
-                    break;
+                    return ngx_http_image_send(r, ctx, &out);
                 }
             }
 
@@ -264,7 +268,9 @@ ngx_http_image_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
         r->headers_out.content_type = *ct;
 
         if (conf->filter == NGX_HTTP_IMAGE_TEST) {
-            break;
+            ctx->phase = NGX_HTTP_IMAGE_PASS;
+
+            return ngx_http_image_send(r, ctx, in);
         }
 
         ctx->phase = NGX_HTTP_IMAGE_READ;
@@ -296,24 +302,44 @@ ngx_http_image_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
         }
 
         out.next = NULL;
-        in = &out;
+        ctx->phase = NGX_HTTP_IMAGE_PASS;
 
-        break;
+        return ngx_http_image_send(r, ctx, &out);
 
-    default: /* NGX_HTTP_IMAGE_DONE */
+    case NGX_HTTP_IMAGE_PASS:
 
         return ngx_http_next_body_filter(r, in);
+
+    default: /* NGX_HTTP_IMAGE_DONE */
+
+        rc = ngx_http_next_body_filter(r, NULL);
+
+        /* NGX_ERROR resets any pending data */
+        return (rc == NGX_OK) ? NGX_ERROR : rc;
     }
+}
+
 
-    ctx->phase = NGX_HTTP_IMAGE_DONE;
+static ngx_int_t
+ngx_http_image_send(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx,
+    ngx_chain_t *in)
+{
+    ngx_int_t  rc;
 
     rc = ngx_http_next_header_filter(r);
 
     if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
-        return rc;
+        return NGX_ERROR;
+    }
+
+    rc = ngx_http_next_body_filter(r, in);
+
+    if (ctx->phase == NGX_HTTP_IMAGE_DONE) {
+        /* NGX_ERROR resets any pending data */
+        return (rc == NGX_OK) ? NGX_ERROR : rc;
     }
 
-    return ngx_http_next_body_filter(r, in);
+    return rc;
 }
 
 
index 9cdd92ddd59f7e479b7f1aed4a72a837fba494a0..32f120c8e9cbb349712980a8eacc94090c7a1ca0 100644 (file)
@@ -1815,6 +1815,11 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
                    "http finalize request: %d, \"%V?%V\" %d",
                    rc, &r->uri, &r->args, r == c->data);
 
+    if (rc == NGX_OK && r->filter_finalize) {
+        c->error = 1;
+        return;
+    }
+
     if (rc == NGX_DECLINED) {
         r->content_handler = NULL;
         r->write_event_handler = ngx_http_core_run_phases;
index 23a88463037c889b02b05b97400894d3049480d8..4fef7c36cab74b4609407f81c32e94e9d0731b48 100644 (file)
@@ -478,6 +478,7 @@ struct ngx_http_request_s {
     unsigned                          discard_body:1;
     unsigned                          internal:1;
     unsigned                          error_page:1;
+    unsigned                          filter_finalize:1;
     unsigned                          post_action:1;
     unsigned                          request_complete:1;
     unsigned                          request_output:1;
index 7d3fd43e9944e77f40ac5526af2264b01c6e9a9b..8f0a2078d3eb8d199517d0b274b43f639712bb5d 100644 (file)
@@ -455,11 +455,21 @@ ngx_http_filter_finalize_request(ngx_http_request_t *r, ngx_int_t error)
     /* clear the modules contexts */
     ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
 
+    r->filter_finalize = 1;
+
     rc = ngx_http_special_response_handler(r, error);
 
     /* NGX_ERROR resets any pending data */
 
-    return (rc == NGX_OK) ? NGX_ERROR : rc;
+    switch (rc) {
+
+    case NGX_OK:
+    case NGX_DONE:
+        return NGX_ERROR;
+
+    default:
+        return rc;
+    }
 }