nginx-0.0.2-2004-03-12-19:57:08 import
diff --git a/src/http/modules/ngx_http_index_handler.c b/src/http/modules/ngx_http_index_handler.c
index 029843e..d5ecd41 100644
--- a/src/http/modules/ngx_http_index_handler.c
+++ b/src/http/modules/ngx_http_index_handler.c
@@ -46,6 +46,8 @@
       0,
       NULL },
 
+#if (NGX_HTTP_CACHE)
+
     { ngx_string("index_cache"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE3,
       ngx_http_set_cache_slot,
@@ -53,6 +55,8 @@
       offsetof(ngx_http_index_loc_conf_t, index_cache),
       NULL },
 
+#endif
+
       ngx_null_command
 };
 
@@ -125,6 +129,8 @@
                             sizeof(ngx_http_index_ctx_t),
                             NGX_HTTP_INTERNAL_SERVER_ERROR);
 
+#if (NGX_HTTP_CACHE)
+
         if (ilcf->index_cache) {
             ctx->cache = ngx_http_cache_get(ilcf->index_cache, NULL,
                                             &r->uri, &crc);
@@ -149,11 +155,10 @@
 
                 return ngx_http_internal_redirect(r, &ctx->redirect, NULL);
             }
-
-        } else {
-            ctx->cache = NULL;
         }
 
+#endif
+
         len = clcf->doc_root.len + r->uri.len + ilcf->max_index_len;
         if (!(ctx->path.data = ngx_palloc(r->pool, len))) {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -237,6 +242,8 @@
         /**/
 
 
+#if (NGX_HTTP_CACHE)
+
         if (ilcf->index_cache) {
 
             if (ctx->cache) {
@@ -271,6 +278,8 @@
             }
         }
 
+#endif
+
         return ngx_http_internal_redirect(r, &ctx->redirect, NULL);
     }
 
diff --git a/src/http/modules/ngx_http_static_handler.c b/src/http/modules/ngx_http_static_handler.c
index 6997471..6925a03 100644
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -18,6 +18,8 @@
 
 static ngx_command_t  ngx_http_static_commands[] = {
 
+#if (NGX_HTTP_CACHE)
+
     { ngx_string("redirect_cache"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE3,
       ngx_http_set_cache_slot,
@@ -25,6 +27,8 @@
       offsetof(ngx_http_static_loc_conf_t, redirect_cache),
       NULL },
 
+#endif
+
       ngx_null_command
 };
 
@@ -87,6 +91,8 @@
         return rc;
     }
 
+#if (NGX_HTTP_CACHE)
+
     /*
      * there is a valid cached open file, i.e by the index handler,
      * and it should be already registered in r->cleanup
@@ -96,6 +102,8 @@
         return ngx_http_send_cached(r);
     }
 
+#endif
+
     log = r->connection->log;
 
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
@@ -138,6 +146,7 @@
         redirect_cleanup = NULL;
     }
 
+#if (NGX_HTTP_CACHE)
 
     /* look up an open files cache */
 
@@ -192,6 +201,7 @@
         redirect = NULL;
     }
 
+#endif
 
     /* open file */
 
@@ -302,6 +312,8 @@
 
         r->headers_out.location->value = location;
 
+#if (NGX_HTTP_CACHE)
+
         if (slcf->redirect_cache) {
             if (redirect) {
                 if (location.len == redirect->data.value.len
@@ -345,6 +357,8 @@
 
         }
 
+#endif
+
         return NGX_HTTP_MOVED_PERMANENTLY;
     }
 
@@ -365,6 +379,8 @@
 #endif
 
 
+#if (NGX_HTTP_CACHE)
+
     if (clcf->open_files) {
 
 #if (NGX_USE_HTTP_FILE_CACHE_UNIQ)
@@ -416,6 +432,7 @@
         return ngx_http_send_cached(r);
     }
 
+#endif
 
     ctx = log->data;
     ctx->action = "sending response to client";
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
index 68e9032..669a970 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -81,6 +81,20 @@
       offsetof(ngx_http_proxy_loc_conf_t, send_timeout),
       NULL },
 
+    { ngx_string("proxy_set_x_real_ip"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_proxy_loc_conf_t, set_x_real_ip),
+      NULL },
+
+    { ngx_string("proxy_add_x_forwarded_for"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_proxy_loc_conf_t, add_x_forwarded_for),
+      NULL },
+
     { ngx_string("proxy_header_buffer_size"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_size_slot,
@@ -109,6 +123,8 @@
       offsetof(ngx_http_proxy_loc_conf_t, busy_buffers_size),
       NULL },
 
+#if (NGX_HTTP_FILE_CACHE)
+
     { ngx_string("proxy_cache_path"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
       ngx_conf_set_path_slot,
@@ -116,6 +132,8 @@
       offsetof(ngx_http_proxy_loc_conf_t, cache_path),
       ngx_garbage_collector_http_cache_handler },
 
+#endif
+
     { ngx_string("proxy_temp_path"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
       ngx_conf_set_path_slot,
@@ -311,6 +329,7 @@
 
     ngx_memzero(p->state, sizeof(ngx_http_proxy_state_t));
 
+#if (NGX_HTTP_FILE_CACHE)
 
     if (!p->lcf->cache
         || (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD))
@@ -337,6 +356,14 @@
     }
 
     return ngx_http_proxy_get_cached_response(p);
+
+#else
+
+    p->state->cache_state = NGX_HTTP_PROXY_CACHE_PASS;
+
+    return ngx_http_proxy_request_upstream(p);
+
+#endif
 }
 
 
@@ -404,12 +431,20 @@
         rev->timedout = 0;
         p->busy_lock.time++;
         p->state->bl_time = p->busy_lock.time;
+
+#if (NGX_HTTP_FILE_CACHE)
+
         if (p->state->cache_state < NGX_HTTP_PROXY_CACHE_MISS) {
             ngx_http_proxy_upstream_busy_lock(p);
 
         } else {
             ngx_http_proxy_cache_busy_lock(p);
         }
+#else
+
+        ngx_http_proxy_upstream_busy_lock(p);
+
+#endif
 
         return;
     }
@@ -738,6 +773,10 @@
     conf->request_buffer_size = NGX_CONF_UNSET;
     conf->connect_timeout = NGX_CONF_UNSET;
     conf->send_timeout = NGX_CONF_UNSET;
+
+    conf->set_x_real_ip = NGX_CONF_UNSET;
+    conf->add_x_forwarded_for = NGX_CONF_UNSET;
+
     conf->header_buffer_size = NGX_CONF_UNSET;
     conf->read_timeout = NGX_CONF_UNSET;
     conf->busy_buffers_size = NGX_CONF_UNSET;
@@ -776,6 +815,11 @@
     ngx_conf_merge_msec_value(conf->connect_timeout,
                               prev->connect_timeout, 60000);
     ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 30000);
+
+    ngx_conf_merge_value(conf->set_x_real_ip, prev->set_x_real_ip, 0);
+    ngx_conf_merge_value(conf->add_x_forwarded_for,
+                         prev->add_x_forwarded_for, 0);
+
     ngx_conf_merge_size_value(conf->header_buffer_size,
                               prev->header_buffer_size, 4096);
     ngx_conf_merge_msec_value(conf->read_timeout, prev->read_timeout, 30000);
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h
index 62d0548..44fb662 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -56,19 +56,22 @@
 
     ssize_t                          max_temp_file_size;
     ssize_t                          temp_file_write_size;
-    int                              cyclic_temp_file;
+    ngx_flag_t                       cyclic_temp_file;
 
-    int                              cache;
+    ngx_flag_t                       cache;
 
-    int                              pass_server;
-    int                              pass_x_accel_expires;
+    ngx_flag_t                       set_x_real_ip;
+    ngx_flag_t                       add_x_forwarded_for;
 
-    int                              ignore_expires;
+    ngx_flag_t                       pass_server;
+    ngx_flag_t                       pass_x_accel_expires;
+
+    ngx_flag_t                       ignore_expires;
     int                              lm_factor;
     time_t                           default_expires;
 
-    int                              next_upstream;
-    int                              use_stale;
+    u_int                            next_upstream;
+    u_int                            use_stale;
 
     ngx_path_t                      *cache_path;
     ngx_path_t                      *temp_path;
@@ -194,26 +197,31 @@
 #define NGX_HTTP_PROXY_PARSE_NO_HEADER       20
 
 
-#define NGX_HTTP_PROXY_FT_ERROR              2
-#define NGX_HTTP_PROXY_FT_TIMEOUT            4
-#define NGX_HTTP_PROXY_FT_INVALID_HEADER     8
-#define NGX_HTTP_PROXY_FT_HTTP_500           16
-#define NGX_HTTP_PROXY_FT_HTTP_404           32
-#define NGX_HTTP_PROXY_FT_BUSY_LOCK          64
-#define NGX_HTTP_PROXY_FT_MAX_WAITING        128
+#define NGX_HTTP_PROXY_FT_ERROR              0x02
+#define NGX_HTTP_PROXY_FT_TIMEOUT            0x04
+#define NGX_HTTP_PROXY_FT_INVALID_HEADER     0x08
+#define NGX_HTTP_PROXY_FT_HTTP_500           0x10
+#define NGX_HTTP_PROXY_FT_HTTP_404           0x20
+#define NGX_HTTP_PROXY_FT_BUSY_LOCK          0x40
+#define NGX_HTTP_PROXY_FT_MAX_WAITING        0x80
 
 
 int ngx_http_proxy_request_upstream(ngx_http_proxy_ctx_t *p);
 
+#if (NGX_HTTP_FILE_CACHE)
+
 int ngx_http_proxy_get_cached_response(ngx_http_proxy_ctx_t *p);
 int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p);
 int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p);
 int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p);
 
+void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p);
+
+#endif
+
 void ngx_http_proxy_check_broken_connection(ngx_event_t *wev);
 
 void ngx_http_proxy_busy_lock_handler(ngx_event_t *rev);
-void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p);
 void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p);
 
 size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len);
diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c
index a65b864..67dabe9 100644
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c
@@ -38,6 +38,8 @@
 
 static char  http_version[] = " HTTP/1.0" CRLF;
 static char  host_header[] = "Host: ";
+static char  x_real_ip_header[] = "X-Real-IP: ";
+static char  x_forwarded_for_header[] = "X-Forwarded-For: ";
 static char  connection_close_header[] = "Connection: close" CRLF;
 
 
@@ -116,6 +118,27 @@
           + sizeof(connection_close_header) - 1
           + 2;                          /* 2 is for "\r\n" at the header end */
 
+    if (p->lcf->set_x_real_ip) {
+                                                          /* 2 is for "\r\n" */
+        len += sizeof(x_real_ip_header) - 1 + INET_ADDRSTRLEN - 1 + 2;
+    }
+
+
+    if (p->lcf->add_x_forwarded_for) {
+        if (r->headers_in.x_forwarded_for) {
+            len += r->headers_in.x_forwarded_for->key.len
+                   + 2                                      /* 2 is ofr ": " */
+                   + r->headers_in.x_forwarded_for->value.len
+                   + 2                                      /* 2 is ofr ", " */
+                   + INET_ADDRSTRLEN - 1
+                   + 2;                                   /* 2 is for "\r\n" */
+        } else {
+            len += sizeof(x_forwarded_for_header) - 1 + INET_ADDRSTRLEN - 1 + 2;
+                                                          /* 2 is for "\r\n" */
+        }
+    }
+
+
     header = (ngx_table_elt_t *) r->headers_in.headers->elts;
     for (i = 0; i < r->headers_in.headers->nelts; i++) {
 
@@ -156,19 +179,57 @@
     h->last = ngx_cpymem(h->last, http_version, sizeof(http_version) - 1);
 
 
-    /* "Host" header */
+    /* the "Host" header */
 
     h->last = ngx_cpymem(h->last, host_header, sizeof(host_header) - 1);
     h->last = ngx_cpymem(h->last, uc->host_header.data, uc->host_header.len);
     *(h->last++) = CR; *(h->last++) = LF;
 
 
-    /* "Connection: close" header */
+    /* the "Connection: close" header */
 
     h->last = ngx_cpymem(h->last, connection_close_header,
                          sizeof(connection_close_header) - 1);
 
 
+    /* the "X-Real-IP" header */
+
+    if (p->lcf->set_x_real_ip) {
+        h->last = ngx_cpymem(h->last, x_real_ip_header,
+                             sizeof(x_real_ip_header) - 1);
+        h->last = ngx_cpymem(h->last, r->connection->addr_text.data,
+                             r->connection->addr_text.len);
+        *(h->last++) = CR; *(h->last++) = LF;
+    }
+
+
+    /* the "X-Forwarded-For" header */
+
+    if (p->lcf->add_x_forwarded_for) {
+        if (r->headers_in.x_forwarded_for) {
+            h->last = ngx_cpymem(h->last,
+                                 r->headers_in.x_forwarded_for->key.data,
+                                 r->headers_in.x_forwarded_for->key.len);
+
+            *(h->last++) = ':'; *(h->last++) = ' ';
+
+            h->last = ngx_cpymem(h->last,
+                                 r->headers_in.x_forwarded_for->value.data,
+                                 r->headers_in.x_forwarded_for->value.len);
+
+            *(h->last++) = ','; *(h->last++) = ' ';
+
+        } else {
+            h->last = ngx_cpymem(h->last, x_forwarded_for_header,
+                                 sizeof(x_forwarded_for_header) - 1);
+        }
+
+        h->last = ngx_cpymem(h->last, r->connection->addr_text.data,
+                             r->connection->addr_text.len);
+        *(h->last++) = CR; *(h->last++) = LF;
+    }
+
+
     for (i = 0; i < r->headers_in.headers->nelts; i++) {
 
         if (&header[i] == r->headers_in.host) {
@@ -183,6 +244,12 @@
             continue;
         }
 
+        if (&header[i] == r->headers_in.x_forwarded_for
+            && p->lcf->add_x_forwarded_for)
+        {
+            continue;
+        }
+
         h->last = ngx_cpymem(h->last, header[i].key.data, header[i].key.len);
 
         *(h->last++) = ':'; *(h->last++) = ' ';
@@ -377,12 +444,16 @@
         ft_type = NGX_HTTP_PROXY_FT_MAX_WAITING;
     }
 
+#if (NGX_HTTP_CACHE)
+
     if (p->stale && (p->lcf->use_stale & ft_type)) {
         ngx_http_proxy_finalize_request(p,
                                         ngx_http_proxy_send_cached_response(p));
         return;
     }
 
+#endif
+
     p->state->status = NGX_HTTP_SERVICE_UNAVAILABLE;
     ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE);
 }
@@ -692,6 +763,8 @@
             return;
         }
 
+#if (NGX_HTTP_CACHE)
+
         if (p->upstream->peer.tries == 0
             && p->stale
             && (p->lcf->use_stale & NGX_HTTP_PROXY_FT_HTTP_500))
@@ -701,6 +774,8 @@
 
             return;
         }
+
+#endif
     }
 
     if (p->status == NGX_HTTP_NOT_FOUND
@@ -841,10 +916,14 @@
 
             /* TODO: hook to process the upstream header */
 
+#if (NGX_HTTP_CACHE)
+
             if (p->cachable) {
                 p->cachable = ngx_http_proxy_is_cachable(p);
             }
 
+#endif
+
             ngx_http_proxy_send_response(p);
             return;
 
@@ -1118,6 +1197,9 @@
     }
 
     if (p->upstream->peer.connection) {
+
+#if (NGX_HTTP_FILE_CACHE)
+
         if (ep->upstream_done && p->cachable) {
             if (ngx_http_proxy_update_cache(p) == NGX_ERROR) {
                 ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
@@ -1136,6 +1218,8 @@
             }
         }
 
+#endif
+
         if (ep->upstream_done || ep->upstream_eof || ep->upstream_error) {
             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
                            "http proxy upstream exit");
@@ -1214,12 +1298,17 @@
 
         if (p->upstream->peer.tries == 0 || !(p->lcf->next_upstream & ft_type))
         {
+
+#if (NGX_HTTP_CACHE)
+
             if (p->stale && (p->lcf->use_stale & ft_type)) {
                 ngx_http_proxy_finalize_request(p,
                                        ngx_http_proxy_send_cached_response(p));
                 return;
             }
 
+#endif
+
             ngx_http_proxy_finalize_request(p, status);
             return;
         }