changeset 2819:43fe53832da7

handle big responses for "size" and "test" image_filters
author Igor Sysoev <igor@sysoev.ru>
date Fri, 08 May 2009 14:25:51 +0000
parents 7e02df612521
children 5eb4e2d2e9fa
files 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
diffstat 4 files changed, 54 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/modules/ngx_http_image_filter_module.c
+++ b/src/http/modules/ngx_http_image_filter_module.c
@@ -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_requ
 
                 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_requ
         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_requ
         }
 
         out.next = NULL;
-        in = &out;
+        ctx->phase = NGX_HTTP_IMAGE_PASS;
+
+        return ngx_http_image_send(r, ctx, &out);
 
-        break;
+    case NGX_HTTP_IMAGE_PASS:
+
+        return ngx_http_next_body_filter(r, in);
 
     default: /* NGX_HTTP_IMAGE_DONE */
 
-        return ngx_http_next_body_filter(r, in);
+        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;
     }
 
-    return ngx_http_next_body_filter(r, in);
+    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 rc;
 }
 
 
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1815,6 +1815,11 @@ ngx_http_finalize_request(ngx_http_reque
                    "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;
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -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;
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -455,11 +455,21 @@ ngx_http_filter_finalize_request(ngx_htt
     /* 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;
+    }
 }