changeset 287:35a6a9df2d25

nginx-0.0.2-2004-03-12-19:57:08 import
author Igor Sysoev <igor@sysoev.ru>
date Fri, 12 Mar 2004 16:57:08 +0000
parents fc8dc489247e
children f81d075ad172
files auto/cc auto/lib/md5/make auto/lib/zlib/make auto/sources src/http/modules/ngx_http_index_handler.c src/http/modules/ngx_http_static_handler.c src/http/modules/proxy/ngx_http_proxy_handler.c src/http/modules/proxy/ngx_http_proxy_handler.h src/http/modules/proxy/ngx_http_proxy_upstream.c src/http/ngx_http.h src/http/ngx_http_core_module.c src/http/ngx_http_headers.c src/http/ngx_http_request.c src/http/ngx_http_request.h
diffstat 14 files changed, 273 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/auto/cc
+++ b/auto/cc
@@ -8,10 +8,16 @@ case $CC in
          #CFLAGS="$CFLAGS -O2 -fomit-frame-pointer"
 
          case $CPU in
+             pentium)
+                 # optimize for Pentium and Athlon
+                 CPU_OPT="-march=pentium"
+             ;;
+
              pentiumpro)
                  # optimize for Pentium Pro, Pentium II and Pentium III
                  CPU_OPT="-march=pentiumpro"
              ;;
+
              pentium4)
                  # optimize for Pentium 4, gcc 3.x
                  CPU_OPT="-march=pentium4"
@@ -85,10 +91,16 @@ case $CC in
          #CFLAGS="$CFLAGS -Ob2"
 
          case $CPU in
+             pentium)
+                 # optimize for Pentium and Athlon
+                 CPU_OPT="-march=pentium"
+             ;;
+
              pentiumpro)
                  # optimize for Pentium Pro, Pentium II and Pentium III
                  CPU_OPT="-mcpu=pentiumpro -march=pentiumpro"
              ;;
+
              pentium4)
                  # optimize for Pentium 4, default
                  CPU_OPT="-march=pentium4"
@@ -148,9 +160,15 @@ case $CC in
 
          case $CPU in
              pentiumpro)
+                 # optimize for Pentium and Athlon
+                 CPU_OPT="-G5"
+             ;;
+
+             pentiumpro)
                  # optimize for Pentium Pro, Pentium II and Pentium III
                  CPU_OPT="-G6"
              ;;
+
              pentium4)
                  # optimize for Pentium 4
                  #CPU_OPT="-G7"
@@ -218,6 +236,14 @@ case $CC in
          CFLAGS="$CFLAGS -s"
 
          case $CPU in
+             pentium)
+                 # optimize for Pentium and Athlon
+                 # register-based arguments passing conventions
+                 CPU_OPT="-5r"
+                 # stack-based arguments passing conventions
+                 #CPU_OPT="-5s"
+             ;;
+
              pentiumpro)
                  # optimize for Pentium Pro, Pentium II and Pentium III
                  # register-based arguments passing conventions
--- a/auto/lib/md5/make
+++ b/auto/lib/md5/make
@@ -48,7 +48,7 @@ case $PLATFORM in
 
             echo "	cd $MD5 \\"                               >> $MAKEFILE
             echo "	&& \$(MAKE) $MD5_OPT \\"                  >> $MAKEFILE
-            echo "		MD5_ASM_OBJ=asm/mx86-elf.o \\"    >> $MAKEFILE
+            echo "		MD5_ASM_OBJ=asm/mx86-sol.o \\"    >> $MAKEFILE
             echo "		CC=$CC CPP=\"$CPP\" libmd5.a"     >> $MAKEFILE
 
             done=YES
--- a/auto/lib/zlib/make
+++ b/auto/lib/zlib/make
@@ -40,17 +40,31 @@ case $PLATFORM in
         done=YES
     ;;
 
+    # FreeBSD: i386
+    # Linux: i686
 
     *:i386 | *:i686)
-        if [ $ZLIB_ASM = pentiumpro ]; then
-            echo "	cd $ZLIB \\"                              >> $MAKEFILE
-            echo "	&& cp contrib/asm686/match.S . \\"        >> $MAKEFILE
-            echo "	&& CC=$CC CFLAGS=\"$ZLIB_OPT -DASMV\" \\" >> $MAKEFILE
-            echo "		./configure \\"                   >> $MAKEFILE
-            echo "	&& \$(MAKE) OBJA=match.o libz.a"          >> $MAKEFILE
+        case $ZLIB_ASM in
+            pentium)
+                echo "	cd $ZLIB \\"                              >> $MAKEFILE
+                echo "	&& cp contrib/asm586/match.S . \\"        >> $MAKEFILE
+                echo "	&& CC=$CC CFLAGS=\"$ZLIB_OPT -DASMV\" \\" >> $MAKEFILE
+                echo "		./configure \\"                   >> $MAKEFILE
+                echo "	&& \$(MAKE) OBJA=match.o libz.a"          >> $MAKEFILE
+
+                done=YES
+            ;;
 
-            done=YES
-        fi
+            pentiumpro)
+                echo "	cd $ZLIB \\"                              >> $MAKEFILE
+                echo "	&& cp contrib/asm686/match.S . \\"        >> $MAKEFILE
+                echo "	&& CC=$CC CFLAGS=\"$ZLIB_OPT -DASMV\" \\" >> $MAKEFILE
+                echo "		./configure \\"                   >> $MAKEFILE
+                echo "	&& \$(MAKE) OBJA=match.o libz.a"          >> $MAKEFILE
+
+                done=YES
+            ;;
+        esac
     ;;
 
 esac
--- a/auto/sources
+++ b/auto/sources
@@ -166,8 +166,9 @@ WIN32_SRCS="$CORE_SRCS $EVENT_SRCS \
 
 HTTP_MODULES="ngx_http_module \
             ngx_http_core_module \
-            ngx_http_log_module \
-            ngx_http_cache_module"
+            ngx_http_log_module"
+
+HTTP_FILE_CACHE_MODULE=ngx_http_cache_module
 
 HTTP_FILTER_MODULES="ngx_http_write_filter_module \
             ngx_http_output_filter_module \
@@ -196,9 +197,6 @@ HTTP_SRCS="src/http/ngx_http.c \
             src/http/ngx_http_core_module.c \
             src/http/ngx_http_special_response.c \
             src/http/ngx_http_request.c \
-            src/http/ngx_http_cache.c \
-            src/http/ngx_http_file_cache.c \
-            src/http/ngx_http_busy_lock.c \
             src/http/ngx_http_parse.c \
             src/http/ngx_http_headers.c \
             src/http/ngx_http_header_filter.c \
@@ -214,6 +212,12 @@ HTTP_SRCS="src/http/ngx_http.c \
             src/http/modules/ngx_http_charset_filter.c \
             src/http/modules/ngx_http_not_modified_filter.c"
 
+# STUB
+HTTP_SRCS="$HTTP_SRCS src/http/ngx_http_busy_lock.c"
+
+HTPP_CACHE_SRCS=src/http/ngx_http_cache.c
+HTPP_FILE_CACHE_SRCS=src/http/ngx_http_file_cache.c
+
 
 HTTP_REWRITE_MODULE=ngx_http_rewrite_module
 HTTP_REWRITE_SRCS=src/http/modules/ngx_http_rewrite_handler.c
@@ -234,6 +238,8 @@ HTTP_PROXY_INCS="-I src/http/modules/pro
 HTTP_PROXY_DEPS=src/http/modules/proxy/ngx_http_proxy_handler.h
 HTTP_PROXY_SRCS="src/http/modules/proxy/ngx_http_proxy_handler.c \
             src/http/modules/proxy/ngx_http_proxy_upstream.c \
-            src/http/modules/proxy/ngx_http_proxy_cache.c \
             src/http/modules/proxy/ngx_http_proxy_parse.c \
             src/http/modules/proxy/ngx_http_proxy_header.c"
+
+# STUB
+#            src/http/modules/proxy/ngx_http_proxy_cache.c \
--- a/src/http/modules/ngx_http_index_handler.c
+++ b/src/http/modules/ngx_http_index_handler.c
@@ -46,6 +46,8 @@ static ngx_command_t  ngx_http_index_com
       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 @@ static ngx_command_t  ngx_http_index_com
       offsetof(ngx_http_index_loc_conf_t, index_cache),
       NULL },
 
+#endif
+
       ngx_null_command
 };
 
@@ -125,6 +129,8 @@ int ngx_http_index_handler(ngx_http_requ
                             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,10 +155,9 @@ int ngx_http_index_handler(ngx_http_requ
 
                 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))) {
@@ -237,6 +242,8 @@ int ngx_http_index_handler(ngx_http_requ
         /**/
 
 
+#if (NGX_HTTP_CACHE)
+
         if (ilcf->index_cache) {
 
             if (ctx->cache) {
@@ -271,6 +278,8 @@ int ngx_http_index_handler(ngx_http_requ
             }
         }
 
+#endif
+
         return ngx_http_internal_redirect(r, &ctx->redirect, NULL);
     }
 
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -18,6 +18,8 @@ static ngx_int_t ngx_http_static_init(ng
 
 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 @@ static ngx_command_t  ngx_http_static_co
       offsetof(ngx_http_static_loc_conf_t, redirect_cache),
       NULL },
 
+#endif
+
       ngx_null_command
 };
 
@@ -87,6 +91,8 @@ static ngx_int_t ngx_http_static_handler
         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 @@ static ngx_int_t ngx_http_static_handler
         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 @@ static ngx_int_t ngx_http_static_handler
         redirect_cleanup = NULL;
     }
 
+#if (NGX_HTTP_CACHE)
 
     /* look up an open files cache */
 
@@ -192,6 +201,7 @@ static ngx_int_t ngx_http_static_handler
         redirect = NULL;
     }
 
+#endif
 
     /* open file */
 
@@ -302,6 +312,8 @@ static ngx_int_t ngx_http_static_handler
 
         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 @@ static ngx_int_t ngx_http_static_handler
 
         }
 
+#endif
+
         return NGX_HTTP_MOVED_PERMANENTLY;
     }
 
@@ -365,6 +379,8 @@ static ngx_int_t ngx_http_static_handler
 #endif
 
 
+#if (NGX_HTTP_CACHE)
+
     if (clcf->open_files) {
 
 #if (NGX_USE_HTTP_FILE_CACHE_UNIQ)
@@ -416,6 +432,7 @@ static ngx_int_t ngx_http_static_handler
         return ngx_http_send_cached(r);
     }
 
+#endif
 
     ctx = log->data;
     ctx->action = "sending response to client";
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -81,6 +81,20 @@ static ngx_command_t  ngx_http_proxy_com
       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 @@ static ngx_command_t  ngx_http_proxy_com
       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 @@ static ngx_command_t  ngx_http_proxy_com
       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 @@ static int ngx_http_proxy_handler(ngx_ht
 
     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 @@ static int ngx_http_proxy_handler(ngx_ht
     }
 
     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 @@ void ngx_http_proxy_busy_lock_handler(ng
         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 @@ static void *ngx_http_proxy_create_loc_c
     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 @@ static char *ngx_http_proxy_merge_loc_co
     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);
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -56,19 +56,22 @@ typedef struct {
 
     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 @@ typedef struct {
 #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);
--- 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 *upstream_header_errors[] = 
 
 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 @@ static ngx_chain_t *ngx_http_proxy_creat
           + 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 @@ static ngx_chain_t *ngx_http_proxy_creat
     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 @@ static ngx_chain_t *ngx_http_proxy_creat
             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 @@ void ngx_http_proxy_upstream_busy_lock(n
         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 @@ static void ngx_http_proxy_process_upstr
             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 @@ static void ngx_http_proxy_process_upstr
 
             return;
         }
+
+#endif
     }
 
     if (p->status == NGX_HTTP_NOT_FOUND
@@ -841,10 +916,14 @@ static void ngx_http_proxy_process_upstr
 
             /* 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 @@ static void ngx_http_proxy_process_body(
     }
 
     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 @@ static void ngx_http_proxy_process_body(
             }
         }
 
+#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 @@ static void ngx_http_proxy_next_upstream
 
         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;
         }
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -9,7 +9,10 @@
 typedef struct ngx_http_request_s  ngx_http_request_t;
 typedef struct ngx_http_cleanup_s  ngx_http_cleanup_t;
 
+#if (NGX_HTTP_CACHE)
+#endif
 #include <ngx_http_cache.h>
+
 #include <ngx_http_request.h>
 #include <ngx_http_config.h>
 #include <ngx_http_busy_lock.h>
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -211,6 +211,8 @@ static ngx_command_t  ngx_http_core_comm
       0,
       NULL },
 
+#if (NGX_HTTP_CACHE)
+
     { ngx_string("open_file_cache"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE4,
       ngx_http_set_cache_slot,
@@ -218,6 +220,8 @@ static ngx_command_t  ngx_http_core_comm
       offsetof(ngx_http_core_loc_conf_t, open_files),
       NULL },
 
+#endif
+
       ngx_null_command
 };
 
--- a/src/http/ngx_http_headers.c
+++ b/src/http/ngx_http_headers.c
@@ -29,6 +29,11 @@ ngx_http_header_t  ngx_http_headers_in[]
 
     { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive) },
 
+#if (NGX_HTTP_PROXY)
+    { ngx_string("X-Forwarded-For"),
+                           offsetof(ngx_http_headers_in_t, x_forwarded_for) },
+#endif
+
     { ngx_null_string, 0 }
 };
 
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1485,12 +1485,16 @@ void ngx_http_close_request(ngx_http_req
             continue;
         }
 
+#if (NGX_HTTP_CACHE)
+
         if (cleanup[i].cache) {
             ngx_http_cache_unlock(cleanup[i].data.cache.hash,
                                   cleanup[i].data.cache.cache, log);
             continue;
         }
 
+#endif
+
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http cleanup fd: %d",
                        cleanup[i].data.file.fd);
 
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -93,15 +93,22 @@ typedef struct {
     ngx_table_elt_t  *if_modified_since;
     ngx_table_elt_t  *user_agent;
     ngx_table_elt_t  *referer;
+    ngx_table_elt_t  *content_length;
 
-    ngx_table_elt_t  *content_length;
+    ngx_table_elt_t  *range;
+
+#if (NGX_HTTP_GZIP)
     ngx_table_elt_t  *accept_encoding;
-    ngx_table_elt_t  *range;
+#endif
 
     ngx_table_elt_t  *authorization;
 
     ngx_table_elt_t  *keep_alive;
 
+#if (NGX_HTTP_PROXY)
+    ngx_table_elt_t  *x_forwarded_for;
+#endif
+
     size_t            host_name_len;
     ssize_t           content_length_n;
     size_t            connection_type;