nginx-0.0.1-2003-11-10-20:17:31 import
diff --git a/src/http/modules/proxy/ngx_http_proxy_cache.c b/src/http/modules/proxy/ngx_http_proxy_cache.c
index 0f56686..3c4f5ca 100644
--- a/src/http/modules/proxy/ngx_http_proxy_cache.c
+++ b/src/http/modules/proxy/ngx_http_proxy_cache.c
@@ -302,6 +302,7 @@
         return;
     }
     
+    p->state->status = NGX_HTTP_SERVICE_UNAVAILABLE;
     ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE);
 }
 
@@ -468,7 +469,7 @@
 
 int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p)
 {
-    time_t                        date, last_modified, expires;
+    time_t                        date, last_modified, expires, t;
     ngx_http_proxy_headers_in_t  *h;
 
     switch (p->upstream->status) {
@@ -509,6 +510,7 @@
                            h->x_accel_expires->value.len);
         if (expires != NGX_ERROR) {
             p->state->reason = NGX_HTTP_PROXY_CACHE_XAE;
+            p->state->expires = expires;
             p->cache->ctx.expires = date + expires;
             return (expires > 0);
         }
@@ -523,6 +525,7 @@
                                           h->expires->value.len);
             if (expires != NGX_ERROR) {
                 p->state->reason = NGX_HTTP_PROXY_CACHE_EXP;
+                p->state->expires = expires - date;
                 p->cache->ctx.expires = expires;
                 return (date < expires);
             }
@@ -531,6 +534,7 @@
 
     if (p->upstream->status == NGX_HTTP_MOVED_PERMANENTLY) {
         p->state->reason = NGX_HTTP_PROXY_CACHE_MVD;
+        p->state->expires = /* STUB: 1 hour */ 60 * 60;
         p->cache->ctx.expires = /* STUB: 1 hour */ 60 * 60;
         return 1;
     }
@@ -544,14 +548,17 @@
         /* FIXME: time_t == int_64_t, we can use fpu */ 
 
         p->state->reason = NGX_HTTP_PROXY_CACHE_LMF;
-        p->cache->ctx.expires = (time_t) (ngx_time()
-             + (((int64_t) (date - last_modified)) * p->lcf->lm_factor) / 100);
+        t = (time_t)
+              ((((int64_t) (date - last_modified)) * p->lcf->lm_factor) / 100);
+        p->state->expires = t;
+        p->cache->ctx.expires = ngx_time() + t;
         return 1;
     }
 
     if (p->lcf->default_expires > 0) {
         p->state->reason = NGX_HTTP_PROXY_CACHE_PDE;
-        p->cache->ctx.expires = p->lcf->default_expires;
+        p->state->expires = p->lcf->default_expires;
+        p->cache->ctx.expires = ngx_time() + p->lcf->default_expires;
         return 1;
     }
 
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
index 4a48250..ad719ca 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -7,7 +7,14 @@
 
 static int ngx_http_proxy_handler(ngx_http_request_t *r);
 
-static int ngx_http_proxy_init(ngx_cycle_t *cycle);
+static char *ngx_http_proxy_log_proxy_state(ngx_http_request_t *r, char *buf,
+                                            uintptr_t data);
+static char *ngx_http_proxy_log_cache_state(ngx_http_request_t *r, char *buf,
+                                            uintptr_t data);
+static char *ngx_http_proxy_log_reason(ngx_http_request_t *r, char *buf,
+                                       uintptr_t data);
+
+static int ngx_http_proxy_pre_conf(ngx_conf_t *cf);
 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
 static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
                                            void *parent, void *child);
@@ -194,6 +201,8 @@
 
 
 ngx_http_module_t  ngx_http_proxy_module_ctx = {
+    ngx_http_proxy_pre_conf,               /* pre conf */
+
     NULL,                                  /* create main configuration */
     NULL,                                  /* init main configuration */
 
@@ -215,6 +224,19 @@
 };
 
 
+
+static ngx_http_log_op_name_t ngx_http_proxy_log_fmt_ops[] = {
+    { ngx_string("proxy"), /* STUB */ 100,
+                           ngx_http_proxy_log_proxy_state },
+    { ngx_string("proxy_cache_state"), sizeof("BYPASS") - 1,
+                                       ngx_http_proxy_log_cache_state },
+    { ngx_string("proxy_reason"), sizeof("BPS") - 1,
+                                  ngx_http_proxy_log_reason },
+    { ngx_null_string, 0, NULL }
+};
+
+
+
 ngx_http_header_t ngx_http_proxy_headers_in[] = {
     { ngx_string("Date"), offsetof(ngx_http_proxy_headers_in_t, date) },
     { ngx_string("Server"), offsetof(ngx_http_proxy_headers_in_t, server) },
@@ -252,7 +274,7 @@
 };
 
 
-static ngx_str_t cache_reason[] = {
+static ngx_str_t cache_reasons[] = {
     ngx_string("BPS"),
     ngx_string("XAE"),
     ngx_string("CTL"),
@@ -453,12 +475,6 @@
 }
 
 
-size_t ngx_http_proxy_log_state(void *data, char *buf, size_t len)
-{
-    return 0;
-}
-
-
 size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len)
 {
     ngx_http_proxy_ctx_t *p = data;
@@ -482,6 +498,121 @@
 }
 
 
+static char *ngx_http_proxy_log_proxy_state(ngx_http_request_t *r, char *buf,
+                                            uintptr_t data)
+{
+    ngx_http_proxy_ctx_t  *p;
+
+    p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
+
+    if (p == NULL) {
+        *buf = '-';
+        return buf + 1;
+    }
+
+    if (p->state->cache_state == 0) {
+        *buf++ = '-';
+
+    } else {
+        buf = ngx_cpymem(buf, cache_states[p->state->cache_state - 1].data,
+                         cache_states[p->state->cache_state - 1].len);
+    }
+
+    *buf++ = '/';
+
+    *buf++ = 'X';
+
+    *buf++ = '/';
+
+    *buf++ = 'X';
+
+    *buf++ = ' ';
+
+    if (p->state->status == 0) {
+        *buf++ = '-';
+
+    } else {
+        buf += ngx_snprintf(buf, 4, "%d", p->state->status);
+    }
+
+    *buf++ = '/';
+
+    if (p->state->reason == 0) {
+        *buf++ = '-';
+
+    } else {
+        buf = ngx_cpymem(buf, cache_reasons[p->state->reason - 1].data,
+                         cache_reasons[p->state->reason - 1].len);
+    }
+
+    *buf++ = '/';
+
+    if (p->state->reason >= NGX_HTTP_PROXY_CACHE_XAE) {
+        *buf++ = '-';
+
+    } else {
+        buf += ngx_snprintf(buf, NGX_TIME_LEN, TIME_FMT, p->state->expires);
+    }
+
+    return buf;
+}
+
+
+static char *ngx_http_proxy_log_cache_state(ngx_http_request_t *r, char *buf,
+                                            uintptr_t data)
+{
+    ngx_http_proxy_ctx_t  *p;
+
+    p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
+
+    if (p == NULL || p->state->cache_state == 0) {
+        *buf = '-';
+        return buf + 1;
+    }
+
+    return ngx_cpymem(buf, cache_states[p->state->cache_state - 1].data,
+                      cache_states[p->state->cache_state - 1].len);
+}
+
+
+static char *ngx_http_proxy_log_reason(ngx_http_request_t *r, char *buf,
+                                       uintptr_t data)
+{
+    ngx_http_proxy_ctx_t  *p;
+
+    p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
+
+    if (p == NULL || p->state->reason == 0) {
+        *buf = '-';
+        return buf + 1;
+    }
+
+    return ngx_cpymem(buf, cache_reasons[p->state->reason - 1].data,
+                      cache_reasons[p->state->reason - 1].len);
+}
+
+
+static int ngx_http_proxy_pre_conf(ngx_conf_t *cf)
+{
+    ngx_http_log_op_name_t  *op;
+
+    for (op = ngx_http_proxy_log_fmt_ops; op->name.len; op++) { /* void */ }
+    op->op = NULL;
+
+    op = ngx_http_log_fmt_ops;
+
+    for (op = ngx_http_log_fmt_ops; op->op; op++) {
+        if (op->name.len == 0) {
+            op = (ngx_http_log_op_name_t *) op->op;
+        }
+    }
+
+    op->op = (ngx_http_log_op_pt) ngx_http_proxy_log_fmt_ops;
+
+    return NGX_OK;
+}
+
+
 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
 {
     ngx_http_proxy_loc_conf_t  *conf;
diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c
index 0ec2fee..d404993 100644
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c
@@ -305,6 +305,13 @@
         }
     }
 
+    /* add one more state */
+
+    if (!(p->state = ngx_push_array(&p->states))) {
+        ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
+        return;
+    }
+
     p->status = 0;
     p->status_count = 0;
 }
@@ -344,6 +351,7 @@
         return;
     }
 
+    p->state->status = NGX_HTTP_SERVICE_UNAVAILABLE;
     ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE);
 }
 
@@ -407,11 +415,6 @@
 
     p->request_sent = 0;
 
-    if (!(p->state = ngx_push_array(&p->states))) {
-        ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
-        return;
-    }
-
     if (rc == NGX_AGAIN) {
         ngx_add_timer(c->write, p->lcf->connect_timeout);
         return;
@@ -636,6 +639,7 @@
     /* rc == NGX_OK */
 
     p->upstream->status = p->status;
+    p->state->status = p->status;
 
     if (p->status == NGX_HTTP_INTERNAL_SERVER_ERROR) {