aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/http/ngx_http.h2
-rw-r--r--src/http/ngx_http_parse.c51
-rw-r--r--src/http/ngx_http_upstream.c58
-rw-r--r--src/http/ngx_http_upstream.h3
-rw-r--r--src/http/ngx_http_variables.c19
5 files changed, 130 insertions, 3 deletions
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index d4dc1bd94..0acc23494 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -105,6 +105,8 @@ ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
ngx_uint_t allow_underscores);
ngx_int_t ngx_http_parse_multi_header_lines(ngx_array_t *headers,
ngx_str_t *name, ngx_str_t *value);
+ngx_int_t ngx_http_parse_set_cookie_lines(ngx_array_t *headers,
+ ngx_str_t *name, ngx_str_t *value);
ngx_int_t ngx_http_arg(ngx_http_request_t *r, u_char *name, size_t len,
ngx_str_t *value);
void ngx_http_split_args(ngx_http_request_t *r, ngx_str_t *uri,
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
index 02b4a0fd1..f28786946 100644
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -1985,6 +1985,57 @@ ngx_http_parse_multi_header_lines(ngx_array_t *headers, ngx_str_t *name,
ngx_int_t
+ngx_http_parse_set_cookie_lines(ngx_array_t *headers, ngx_str_t *name,
+ ngx_str_t *value)
+{
+ ngx_uint_t i;
+ u_char *start, *last, *end;
+ ngx_table_elt_t **h;
+
+ h = headers->elts;
+
+ for (i = 0; i < headers->nelts; i++) {
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, headers->pool->log, 0,
+ "parse header: \"%V: %V\"", &h[i]->key, &h[i]->value);
+
+ if (name->len >= h[i]->value.len) {
+ continue;
+ }
+
+ start = h[i]->value.data;
+ end = h[i]->value.data + h[i]->value.len;
+
+ if (ngx_strncasecmp(start, name->data, name->len) != 0) {
+ continue;
+ }
+
+ for (start += name->len; start < end && *start == ' '; start++) {
+ /* void */
+ }
+
+ if (start == end || *start++ != '=') {
+ /* the invalid header value */
+ continue;
+ }
+
+ while (start < end && *start == ' ') { start++; }
+
+ for (last = start; last < end && *last != ';'; last++) {
+ /* void */
+ }
+
+ value->len = last - start;
+ value->data = start;
+
+ return i;
+ }
+
+ return NGX_DECLINED;
+}
+
+
+ngx_int_t
ngx_http_arg(ngx_http_request_t *r, u_char *name, size_t len, ngx_str_t *value)
{
u_char *p, *last;
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index af77e50e7..a64538309 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -216,7 +216,8 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
ngx_http_upstream_rewrite_refresh, 0, 0 },
{ ngx_string("Set-Cookie"),
- ngx_http_upstream_process_set_cookie, 0,
+ ngx_http_upstream_process_set_cookie,
+ offsetof(ngx_http_upstream_headers_in_t, cookies),
ngx_http_upstream_rewrite_set_cookie, 0, 1 },
{ ngx_string("Content-Disposition"),
@@ -3731,11 +3732,28 @@ static ngx_int_t
ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
ngx_uint_t offset)
{
-#if (NGX_HTTP_CACHE)
- ngx_http_upstream_t *u;
+ ngx_array_t *pa;
+ ngx_table_elt_t **ph;
+ ngx_http_upstream_t *u;
u = r->upstream;
+ pa = &u->headers_in.cookies;
+
+ if (pa->elts == NULL) {
+ if (ngx_array_init(pa, r->pool, 1, sizeof(ngx_table_elt_t *)) != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ ph = ngx_array_push(pa);
+ if (ph == NULL) {
+ return NGX_ERROR;
+ }
+
+ *ph = h;
+#if (NGX_HTTP_CACHE)
if (!(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_SET_COOKIE)) {
u->cacheable = 0;
}
@@ -4657,6 +4675,40 @@ ngx_http_upstream_header_variable(ngx_http_request_t *r,
}
+ngx_int_t
+ngx_http_upstream_cookie_variable(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ ngx_str_t *name = (ngx_str_t *) data;
+
+ ngx_str_t cookie, s;
+
+ if (r->upstream == NULL) {
+ v->not_found = 1;
+ return NGX_OK;
+ }
+
+ s.len = name->len - (sizeof("upstream_cookie_") - 1);
+ s.data = name->data + sizeof("upstream_cookie_") - 1;
+
+ if (ngx_http_parse_set_cookie_lines(&r->upstream->headers_in.cookies,
+ &s, &cookie)
+ == NGX_DECLINED)
+ {
+ v->not_found = 1;
+ return NGX_OK;
+ }
+
+ v->len = cookie.len;
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+ v->data = cookie.data;
+
+ return NGX_OK;
+}
+
+
#if (NGX_HTTP_CACHE)
ngx_int_t
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index b8998ced8..50b3e6367 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -248,6 +248,7 @@ typedef struct {
off_t content_length_n;
ngx_array_t cache_control;
+ ngx_array_t cookies;
unsigned connection_close:1;
unsigned chunked:1;
@@ -363,6 +364,8 @@ typedef struct {
} ngx_http_upstream_param_t;
+ngx_int_t ngx_http_upstream_cookie_variable(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
ngx_int_t ngx_http_upstream_header_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index f61862297..5bd6b96bd 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -613,6 +613,17 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
return NULL;
}
+ if (ngx_strncmp(name->data, "upstream_cookie_", 16) == 0) {
+
+ if (ngx_http_upstream_cookie_variable(r, vv, (uintptr_t) name)
+ == NGX_OK)
+ {
+ return vv;
+ }
+
+ return NULL;
+ }
+
if (ngx_strncmp(name->data, "arg_", 4) == 0) {
if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) {
@@ -2528,6 +2539,14 @@ ngx_http_variables_init_vars(ngx_conf_t *cf)
continue;
}
+ if (ngx_strncmp(v[i].name.data, "upstream_cookie_", 16) == 0) {
+ v[i].get_handler = ngx_http_upstream_cookie_variable;
+ v[i].data = (uintptr_t) &v[i].name;
+ v[i].flags = NGX_HTTP_VAR_NOCACHEABLE;
+
+ continue;
+ }
+
if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) {
v[i].get_handler = ngx_http_variable_argument;
v[i].data = (uintptr_t) &v[i].name;