summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES21
-rw-r--r--CHANGES.ru22
-rw-r--r--auto/cc/sunc2
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_string.c22
-rw-r--r--src/core/ngx_string.h17
-rw-r--r--src/event/ngx_event_connect.h48
-rw-r--r--src/http/modules/ngx_http_memcached_module.c16
-rw-r--r--src/http/modules/ngx_http_upstream_ip_hash_module.c3
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/modules/perl/ngx_http_perl_module.c24
-rw-r--r--src/http/ngx_http_upstream.c2
-rw-r--r--src/http/ngx_http_upstream_round_robin.c59
-rw-r--r--src/http/ngx_http_upstream_round_robin.h7
-rw-r--r--src/http/ngx_http_variables.c47
-rw-r--r--src/mail/ngx_mail_proxy_module.c8
16 files changed, 244 insertions, 58 deletions
diff --git a/CHANGES b/CHANGES
index 0af6f8890..11bd3d879 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,25 @@
+Changes with nginx 0.5.30 30 Jul 2007
+
+ *) Feature: the $args variable can be set with the "set" directive.
+
+ *) Feature: the $is_args variable.
+
+ *) Bugfix: if a client has closed connection to mail proxy then nginx
+ might not close connection to backend.
+
+ *) Bugfix: now nginx escapes space in $memcached_key variable.
+
+ *) Bugfix: a segmentation fault might occur in worker process when the
+ HTTPS protocol was used in the "proxy_pass" directive.
+
+ *) Bugfix: the perl $$ variable value in ngx_http_perl_module was equal
+ to the master process identification number.
+
+ *) Bugfix: fix building on Solaris/amd64 by Sun Studio 11 and early
+ versions; bug appeared in 0.5.29.
+
+
Changes with nginx 0.5.29 23 Jul 2007
*) Feature: $nginx_version variable.
diff --git a/CHANGES.ru b/CHANGES.ru
index 2a120995d..edf6b3558 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,26 @@
+Изменения в nginx 0.5.30 30.07.2007
+
+ *) Добавление: переменную $args можно устанавливать с помощью set.
+
+ *) Добавление: переменная $is_args.
+
+ *) Исправление: если клиент в почтовом прокси-сервере закрывал
+ соединение, то nginx мог не закрывать соединение с бэкендом.
+
+ *) Исправление: теперь nginx экранирует пробел в переменной
+ $memcached_key.
+
+ *) Исправление: при использовании протокола HTTPS в директиве
+ proxy_pass в рабочем процессе мог произойти segmentation fault.
+
+ *) Исправление: значение perl'овой переменной $$ модуля
+ ngx_http_perl_module было равно номеру главного процесса.
+
+ *) Исправление: nginx не собирался на Solaris/amd64 Sun Studio 11 и
+ более ранними версиями; ошибка появилась в 0.5.29.
+
+
Изменения в nginx 0.5.29 23.07.2007
*) Добавление: переменная $nginx_version.
diff --git a/auto/cc/sunc b/auto/cc/sunc
index f7eb8800d..d464c6e11 100644
--- a/auto/cc/sunc
+++ b/auto/cc/sunc
@@ -39,7 +39,7 @@ if [ "$ngx_sunc_ver" -ge 1424 ]; then
else
ngx_sparc32="-xarch=v8plus"
ngx_sparc64="-xarch=v9"
- ngx_amd64="-amd64"
+ ngx_amd64="-xarch=amd64"
fi
case "$NGX_MACHINE" in
diff --git a/src/core/nginx.h b/src/core/nginx.h
index dfc4d0a95..868817322 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VERSION "0.5.29"
+#define NGINX_VERSION "0.5.30"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
index 6a927b03b..a07dbebeb 100644
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -1059,7 +1059,27 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
};
- static uint32_t *map[] = { uri, args, html, refresh };
+ /* " ", %00-%1F */
+
+ static uint32_t memcached[] = {
+ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
+
+ /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
+ 0x00000001, /* 0000 0000 0000 0000 0000 0000 0000 0001 */
+
+ /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
+ 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
+
+ /* ~}| {zyx wvut srqp onml kjih gfed cba` */
+ 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
+
+ 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
+ 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
+ 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
+ 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
+ };
+
+ static uint32_t *map[] = { uri, args, html, refresh, memcached };
escape = map[type];
diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h
index 9e0b06394..b4a96c543 100644
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -150,12 +150,13 @@ size_t ngx_utf_length(u_char *p, size_t n);
u_char *ngx_utf_cpystrn(u_char *dst, u_char *src, size_t n);
-#define NGX_ESCAPE_URI 0
-#define NGX_ESCAPE_ARGS 1
-#define NGX_ESCAPE_HTML 2
-#define NGX_ESCAPE_REFRESH 3
+#define NGX_ESCAPE_URI 0
+#define NGX_ESCAPE_ARGS 1
+#define NGX_ESCAPE_HTML 2
+#define NGX_ESCAPE_REFRESH 3
+#define NGX_ESCAPE_MEMCACHED 4
-#define NGX_UNESCAPE_URI 1
+#define NGX_UNESCAPE_URI 1
uintptr_t ngx_escape_uri(u_char *dst, u_char *src, size_t size,
ngx_uint_t type);
@@ -164,11 +165,11 @@ void ngx_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type);
void ngx_sort(void *base, size_t n, size_t size,
int (*cmp)(const void *, const void *));
-#define ngx_qsort qsort
+#define ngx_qsort qsort
-#define ngx_value_helper(n) #n
-#define ngx_value(n) ngx_value_helper(n)
+#define ngx_value_helper(n) #n
+#define ngx_value(n) ngx_value_helper(n)
#endif /* _NGX_STRING_H_INCLUDED_ */
diff --git a/src/event/ngx_event_connect.h b/src/event/ngx_event_connect.h
index f8a7de944..6cad04279 100644
--- a/src/event/ngx_event_connect.h
+++ b/src/event/ngx_event_connect.h
@@ -13,50 +13,56 @@
#include <ngx_event.h>
-#define NGX_PEER_KEEPALIVE 1
-#define NGX_PEER_NEXT 2
-#define NGX_PEER_FAILED 4
+#define NGX_PEER_KEEPALIVE 1
+#define NGX_PEER_NEXT 2
+#define NGX_PEER_FAILED 4
typedef struct ngx_peer_connection_s ngx_peer_connection_t;
typedef ngx_int_t (*ngx_event_get_peer_pt)(ngx_peer_connection_t *pc,
void *data);
-#if (NGX_SSL)
-typedef void (*ngx_event_save_peer_pt)(ngx_peer_connection_t *pc, void *data);
-#endif
typedef void (*ngx_event_free_peer_pt)(ngx_peer_connection_t *pc, void *data,
ngx_uint_t state);
+#if (NGX_SSL)
+
+typedef ngx_int_t (*ngx_event_set_peer_session_pt)(ngx_peer_connection_t *pc,
+ void *data);
+typedef void (*ngx_event_save_peer_session_pt)(ngx_peer_connection_t *pc,
+ void *data);
+#endif
struct ngx_peer_connection_s {
- ngx_connection_t *connection;
+ ngx_connection_t *connection;
- struct sockaddr *sockaddr;
- socklen_t socklen;
- ngx_str_t *name;
+ struct sockaddr *sockaddr;
+ socklen_t socklen;
+ ngx_str_t *name;
- ngx_uint_t tries;
+ ngx_uint_t tries;
- ngx_event_get_peer_pt get;
- ngx_event_free_peer_pt free;
- void *data;
+ ngx_event_get_peer_pt get;
+ ngx_event_free_peer_pt free;
+ void *data;
#if (NGX_SSL)
- ngx_ssl_session_t *ssl_session;
- ngx_event_save_peer_pt save_session;
+ ngx_event_set_peer_session_pt set_session;
+ ngx_event_save_peer_session_pt save_session;
#endif
#if (NGX_THREADS)
- ngx_atomic_t *lock;
+ ngx_atomic_t *lock;
#endif
- int rcvbuf;
+ int rcvbuf;
+
+ ngx_log_t *log;
- ngx_log_t *log;
+ unsigned cached:1;
- unsigned cached:1;
- unsigned log_error:2; /* ngx_connection_log_error_e */
+ /* ngx_connection_log_error_e */
+ unsigned log_error:2;
};
diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c
index ffd872b44..f7205418c 100644
--- a/src/http/modules/ngx_http_memcached_module.c
+++ b/src/http/modules/ngx_http_memcached_module.c
@@ -226,6 +226,7 @@ static ngx_int_t
ngx_http_memcached_create_request(ngx_http_request_t *r)
{
size_t len;
+ uintptr_t escape;
ngx_buf_t *b;
ngx_chain_t *cl;
ngx_http_memcached_ctx_t *ctx;
@@ -242,10 +243,9 @@ ngx_http_memcached_create_request(ngx_http_request_t *r)
return NGX_ERROR;
}
- len = sizeof("get ") - 1 + vv->len + sizeof(CRLF) - 1;
- if (vv->len) {
- len += 1 + vv->len;
- }
+ escape = 2 * ngx_escape_uri(NULL, vv->data, vv->len, NGX_ESCAPE_MEMCACHED);
+
+ len = sizeof("get ") - 1 + vv->len + escape + sizeof(CRLF) - 1;
b = ngx_create_temp_buf(r->pool, len);
if (b == NULL) {
@@ -268,7 +268,13 @@ ngx_http_memcached_create_request(ngx_http_request_t *r)
ctx->key.data = b->last;
- b->last = ngx_copy(b->last, vv->data, vv->len);
+ if (escape == 0) {
+ b->last = ngx_copy(b->last, vv->data, vv->len);
+
+ } else {
+ b->last = (u_char *) ngx_escape_uri(b->last, vv->data, vv->len,
+ NGX_ESCAPE_MEMCACHED);
+ }
ctx->key.len = b->last - ctx->key.data;
diff --git a/src/http/modules/ngx_http_upstream_ip_hash_module.c b/src/http/modules/ngx_http_upstream_ip_hash_module.c
index ba1cd53ff..3ef424921 100644
--- a/src/http/modules/ngx_http_upstream_ip_hash_module.c
+++ b/src/http/modules/ngx_http_upstream_ip_hash_module.c
@@ -198,9 +198,6 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data)
pc->sockaddr = peer->sockaddr;
pc->socklen = peer->socklen;
pc->name = &peer->name;
-#if (NGX_SSL)
- pc->ssl_session = peer->ssl_session;
-#endif
/* ngx_unlock_mutex(iphp->rrp.peers->mutex); */
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index 1f263b271..8933e2c62 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '0.5.29';
+our $VERSION = '0.5.30';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
index b8352f056..248f57823 100644
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -67,6 +67,7 @@ static char *ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static void ngx_http_perl_cleanup_perl(void *data);
#endif
+static ngx_int_t ngx_http_perl_init_worker(ngx_cycle_t *cycle);
static void ngx_http_perl_exit(ngx_cycle_t *cycle);
@@ -126,7 +127,7 @@ ngx_module_t ngx_http_perl_module = {
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
- NULL, /* init process */
+ ngx_http_perl_init_worker, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
@@ -1004,6 +1005,27 @@ ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
+static ngx_int_t
+ngx_http_perl_init_worker(ngx_cycle_t *cycle)
+{
+ ngx_http_perl_main_conf_t *pmcf;
+
+ pmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_perl_module);
+
+ {
+
+ dTHXa(pmcf->perl);
+ PERL_SET_CONTEXT(pmcf->perl);
+
+ /* set worker's $$ */
+
+ sv_setiv(GvSV(gv_fetchpv("$", TRUE, SVt_PV)), (I32) ngx_pid);
+
+ }
+
+ return NGX_OK;
+}
+
static void
ngx_http_perl_exit(ngx_cycle_t *cycle)
{
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index c1bae266c..d01941a86 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -657,7 +657,7 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
c->sendfile = 0;
u->output.sendfile = 0;
- if (ngx_ssl_set_session(c, u->peer.ssl_session) != NGX_OK) {
+ if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK) {
ngx_http_upstream_finalize_request(r, u,
NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c
index b54e7a72d..af90d1d59 100644
--- a/src/http/ngx_http_upstream_round_robin.c
+++ b/src/http/ngx_http_upstream_round_robin.c
@@ -152,7 +152,10 @@ ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r,
r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer;
r->upstream->peer.tries = rrp->peers->number;
#if (NGX_HTTP_SSL)
- r->upstream->peer.save_session = ngx_http_upstream_save_round_robin_peer;
+ r->upstream->peer.set_session =
+ ngx_http_upstream_set_round_robin_peer_session;
+ r->upstream->peer.save_session =
+ ngx_http_upstream_save_round_robin_peer_session;
#endif
return NGX_OK;
@@ -328,9 +331,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
pc->sockaddr = peer->sockaddr;
pc->socklen = peer->socklen;
pc->name = &peer->name;
-#if (NGX_SSL)
- pc->ssl_session = peer->ssl_session;
-#endif
/* ngx_unlock_mutex(rrp->peers->mutex); */
@@ -408,29 +408,72 @@ ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
#if (NGX_HTTP_SSL)
-void
-ngx_http_upstream_save_round_robin_peer(ngx_peer_connection_t *pc, void *data)
+ngx_int_t
+ngx_http_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc,
+ void *data)
{
ngx_http_upstream_rr_peer_data_t *rrp = data;
+ ngx_int_t rc;
ngx_ssl_session_t *ssl_session;
ngx_http_upstream_rr_peer_t *peer;
+ peer = &rrp->peers->peer[rrp->current];
+
+ /* TODO: threads only mutex */
+ /* ngx_lock_mutex(rrp->peers->mutex); */
+
+ ssl_session = peer->ssl_session;
+
+ rc = ngx_ssl_set_session(pc->connection, ssl_session);
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
+ "set session: %p:%d",
+ ssl_session, ssl_session ? ssl_session->references : 0);
+
+ /* ngx_unlock_mutex(rrp->peers->mutex); */
+
+ return rc;
+}
+
+
+void
+ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc,
+ void *data)
+{
+ ngx_http_upstream_rr_peer_data_t *rrp = data;
+
+ ngx_ssl_session_t *old_ssl_session, *ssl_session;
+ ngx_http_upstream_rr_peer_t *peer;
+
ssl_session = ngx_ssl_get_session(pc->connection);
if (ssl_session == NULL) {
return;
}
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
+ "save session: %p:%d", ssl_session, ssl_session->references);
+
peer = &rrp->peers->peer[rrp->current];
+ /* TODO: threads only mutex */
/* ngx_lock_mutex(rrp->peers->mutex); */
+
+ old_ssl_session = peer->ssl_session;
peer->ssl_session = ssl_session;
+
/* ngx_unlock_mutex(rrp->peers->mutex); */
- if (pc->ssl_session) {
+ if (old_ssl_session) {
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
+ "old session: %p:%d",
+ old_ssl_session, old_ssl_session->references);
+
/* TODO: may block */
- ngx_ssl_free_session(pc->ssl_session);
+
+ ngx_ssl_free_session(old_ssl_session);
}
}
diff --git a/src/http/ngx_http_upstream_round_robin.h b/src/http/ngx_http_upstream_round_robin.h
index 5d952217b..2e2bf132f 100644
--- a/src/http/ngx_http_upstream_round_robin.h
+++ b/src/http/ngx_http_upstream_round_robin.h
@@ -30,7 +30,7 @@ typedef struct {
ngx_uint_t down; /* unsigned down:1; */
#if (NGX_SSL)
- ngx_ssl_session_t *ssl_session;
+ ngx_ssl_session_t *ssl_session; /* local to a process */
#endif
} ngx_http_upstream_rr_peer_t;
@@ -68,7 +68,10 @@ void ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc,
void *data, ngx_uint_t state);
#if (NGX_HTTP_SSL)
-void ngx_http_upstream_save_round_robin_peer(ngx_peer_connection_t *pc,
+ngx_int_t
+ ngx_http_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc,
+ void *data);
+void ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc,
void *data);
#endif
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index af54d29b0..913746079 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -13,6 +13,8 @@
static ngx_int_t ngx_http_variable_request(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static void ngx_http_variable_request_set(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
static void ngx_http_variable_request_set_size(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r,
@@ -39,6 +41,8 @@ static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_scheme(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r,
@@ -155,9 +159,14 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
offsetof(ngx_http_request_t, args),
NGX_HTTP_VAR_NOCACHABLE, 0 },
- { ngx_string("args"), NULL, ngx_http_variable_request,
+ { ngx_string("args"),
+ ngx_http_variable_request_set,
+ ngx_http_variable_request,
offsetof(ngx_http_request_t, args),
- NGX_HTTP_VAR_NOCACHABLE, 0 },
+ NGX_HTTP_VAR_CHANGABLE|NGX_HTTP_VAR_NOCACHABLE, 0 },
+
+ { ngx_string("is_args"), NULL, ngx_http_variable_is_args,
+ 0, NGX_HTTP_VAR_NOCACHABLE, 0 },
{ ngx_string("request_filename"), NULL,
ngx_http_variable_request_filename, 0,
@@ -501,6 +510,19 @@ ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v,
static void
+ngx_http_variable_request_set(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ ngx_str_t *s;
+
+ s = (ngx_str_t *) ((char *) r + data);
+
+ s->len = v->len;
+ s->data = v->data;
+}
+
+
+static void
ngx_http_variable_request_set_size(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
@@ -860,6 +882,27 @@ ngx_http_variable_scheme(ngx_http_request_t *r,
static ngx_int_t
+ngx_http_variable_is_args(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ v->valid = 1;
+ v->no_cachable = 0;
+ v->not_found = 0;
+
+ if (r->args.len == 0) {
+ v->len = 0;
+ v->data = NULL;
+ return NGX_OK;
+ }
+
+ v->len = 1;
+ v->data = (u_char *) "?";
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
ngx_http_variable_document_root(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c
index 894c01d04..ae2fc4c38 100644
--- a/src/mail/ngx_mail_proxy_module.c
+++ b/src/mail/ngx_mail_proxy_module.c
@@ -866,9 +866,11 @@ ngx_mail_proxy_handler(ngx_event_t *ev)
c->log->action = "proxying";
- if ((s->connection->read->eof || s->proxy->upstream.connection->read->eof)
- && s->buffer->pos == s->buffer->last
- && s->proxy->buffer->pos == s->proxy->buffer->last)
+ if ((s->connection->read->eof && s->buffer->pos == s->buffer->last)
+ || (s->proxy->upstream.connection->read->eof
+ && s->proxy->buffer->pos == s->proxy->buffer->last)
+ || (s->connection->read->eof
+ && s->proxy->upstream.connection->read->eof))
{
action = c->log->action;
c->log->action = NULL;