nginx-0.0.3-2004-04-14-21:44:28 import
diff --git a/src/http/modules/ngx_http_gzip_filter.c b/src/http/modules/ngx_http_gzip_filter.c
index c62a9ea..2034595 100644
--- a/src/http/modules/ngx_http_gzip_filter.c
+++ b/src/http/modules/ngx_http_gzip_filter.c
@@ -96,10 +96,8 @@
 
 static ngx_conf_enum_t  ngx_http_gzip_proxied[] = {
     { ngx_string("off"), NGX_HTTP_GZIP_PROXIED_OFF },
-#if 0
     { ngx_string("nocachable"), NGX_HTTP_GZIP_PROXIED_NOCACHABLE },
     { ngx_string("poor_cachable"), NGX_HTTP_GZIP_PROXIED_POOR_CACHABLE },
-#endif
     { ngx_string("on"), NGX_HTTP_GZIP_PROXIED_ON },
     { ngx_null_string, 0 }
 };
@@ -223,6 +221,7 @@
 
 static int ngx_http_gzip_header_filter(ngx_http_request_t *r)
 {
+    time_t                 date, expires;
     ngx_http_gzip_ctx_t   *ctx;
     ngx_http_gzip_conf_t  *conf;
 
@@ -250,9 +249,67 @@
     }
 
 
-    /* TODO: proxied */
-    if (r->headers_in.via && conf->proxied == NGX_HTTP_GZIP_PROXIED_OFF) {
-        return ngx_http_next_header_filter(r);
+    if (r->headers_in.via && conf->proxied != NGX_HTTP_GZIP_PROXIED_ON) {
+
+        if (conf->proxied == NGX_HTTP_GZIP_PROXIED_OFF) {
+            return ngx_http_next_header_filter(r);
+        }
+
+        if (r->headers_out.expires) {
+            expires = ngx_http_parse_time(r->headers_out.expires->value.data,
+                                          r->headers_out.expires->value.len);
+            if (expires == NGX_ERROR) {
+                return ngx_http_next_header_filter(r);
+            }
+
+            if (r->headers_out.date) {
+                date = ngx_http_parse_time(r->headers_out.date->value.data,
+                                           r->headers_out.date->value.len);
+                if (date == NGX_ERROR) {
+                    return ngx_http_next_header_filter(r);
+                }
+
+            } else {
+                date = ngx_cached_time;
+            }
+
+            if (expires >= date) {
+                return ngx_http_next_header_filter(r);
+            }
+
+        } else if (r->headers_out.cache_control) {
+
+            if (conf->proxied == NGX_HTTP_GZIP_PROXIED_NOCACHABLE) {
+                if (ngx_strstr(r->headers_out.cache_control->value.data,
+                               "no-cache") == NULL)
+                {
+                    return ngx_http_next_header_filter(r);
+                }
+
+            } else {  /* NGX_HTTP_GZIP_PROXIED_POOR_CACHABLE */
+
+                /* STUB: should be one cycle for all values */
+
+                if (ngx_strstr(r->headers_out.cache_control->value.data,
+                               "no-cache") == NULL
+                    && ngx_strstr(r->headers_out.cache_control->value.data,
+                                  "private") == NULL
+                    && ngx_strstr(r->headers_out.cache_control->value.data,
+                                  "no-store") == NULL)
+                {
+                    return ngx_http_next_header_filter(r);
+                }
+            }
+
+        } else if (conf->proxied == NGX_HTTP_GZIP_PROXIED_NOCACHABLE) {
+            return ngx_http_next_header_filter(r);
+
+        } else {  /* NGX_HTTP_GZIP_PROXIED_POOR_CACHABLE */
+
+            if (r->headers_out.last_modified || r->headers_out.etag) {
+                return ngx_http_next_header_filter(r);
+            }
+        }
     }
 
 
@@ -533,7 +590,7 @@
                     trailer->crc32 = ctx->crc32;
                     trailer->zlen = ctx->zin;
 #else
-                    /* STUB */
+                    /* STUB */ Oops !
 #endif
 
                     ctx->zstream.avail_in = 0;
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
index 0fd89c1..d7cbf96 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -262,6 +262,7 @@
     { ngx_string("Expires"), offsetof(ngx_http_proxy_headers_in_t, expires) },
     { ngx_string("Cache-Control"),
                         offsetof(ngx_http_proxy_headers_in_t, cache_control) },
+    { ngx_string("ETag"), offsetof(ngx_http_proxy_headers_in_t, etag) },
     { ngx_string("X-Accel-Expires"),
                       offsetof(ngx_http_proxy_headers_in_t, x_accel_expires) },
 
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h
index 853aa76..55eee74 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -114,6 +114,7 @@
 
     ngx_table_elt_t                 *expires;
     ngx_table_elt_t                 *cache_control;
+    ngx_table_elt_t                 *etag;
     ngx_table_elt_t                 *x_accel_expires;
 
     ngx_table_elt_t                 *connection;
diff --git a/src/http/modules/proxy/ngx_http_proxy_header.c b/src/http/modules/proxy/ngx_http_proxy_header.c
index 8c24a06..cb13034 100644
--- a/src/http/modules/proxy/ngx_http_proxy_header.c
+++ b/src/http/modules/proxy/ngx_http_proxy_header.c
@@ -20,6 +20,8 @@
     h = headers_in->headers.elts;
     for (i = 0; i < headers_in->headers.nelts; i++) {
 
+        /* ignore some headers */
+
         if (&h[i] == headers_in->connection) {
             continue;
         }
@@ -51,12 +53,18 @@
             }
         }
 
+
+        /* "Content-Type" is handled specially */
+
         if (&h[i] == headers_in->content_type) {
             r->headers_out.content_type = &h[i];
             r->headers_out.content_type->key.len = 0;
             continue;
         }
 
+
+        /* copy some header pointers and set up r->headers_out */
+
         if (!(ho = ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
         {
             return NGX_ERROR;
@@ -64,9 +72,30 @@
 
         *ho = h[i];
 
+        if (&h[i] == headers_in->expires) {
+            r->headers_out.expires = ho;
+            continue;
+        }
+
+        if (&h[i] == headers_in->cache_control) {
+            r->headers_out.cache_control = ho;
+            continue;
+        }
+
+        if (&h[i] == headers_in->etag) {
+            r->headers_out.etag = ho;
+            continue;
+        }
+
+        if (&h[i] == headers_in->last_modified) {
+            r->headers_out.last_modified = ho;
+            /* TODO: update r->headers_out.last_modified_time */
+            continue;
+        }
+
         /*
-         * ngx_http_header_filter() does not handle specially
-         * the following headers if they are set:
+         * ngx_http_header_filter() passes the following headers as is
+         * and does not handle them specially if they are set:
          *     r->headers_out.server,
          *     r->headers_out.date,
          *     r->headers_out.content_length
diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c
index 41946bf..60c9e8f 100644
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c
@@ -338,9 +338,7 @@
 
     r->connection->read->event_handler = ngx_http_proxy_check_broken_connection;
 
-    if (ngx_event_flags & (NGX_USE_CLEAR_EVENT|NGX_HAVE_KQUEUE_EVENT)) {
-
-        /* kqueue allows to detect when client closes prematurely connection */
+    if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
 
         r->connection->write->event_handler =
                                         ngx_http_proxy_check_broken_connection;
@@ -627,11 +625,6 @@
 
     if (rc == NGX_AGAIN) {
         ngx_add_timer(c->write, p->lcf->connect_timeout);
-
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
-                       "http proxy connect handler: " PTR_FMT,
-                       c->write->event_handler);
-
         return;
     }