]> git.kaiwu.me - nginx.git/commitdiff
Upstream: added the "$upstream_cookie_<name>" variables.
authorVladimir Homutov <vl@nginx.com>
Tue, 29 Apr 2014 08:28:41 +0000 (12:28 +0400)
committerVladimir Homutov <vl@nginx.com>
Tue, 29 Apr 2014 08:28:41 +0000 (12:28 +0400)
src/http/ngx_http.h
src/http/ngx_http_parse.c
src/http/ngx_http_upstream.c
src/http/ngx_http_upstream.h
src/http/ngx_http_variables.c

index d4dc1bd94e9db3983c5e896ef6d2ed31d73fdab4..0acc234942cfe9281399131883e04313085a3bed 100644 (file)
@@ -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,
index 02b4a0fd1092821050960397815f499dd321206e..f28786946bfbea3a3202ad7737a30db3f058182a 100644 (file)
@@ -1984,6 +1984,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)
 {
index af77e50e7a02d350c64d7e3673bdf73cee354d0c..a64538309f0ccea7936ff12445c1ea0ca615cdaa 100644 (file)
@@ -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
index b8998ced86e6e0d364209bb44495b415a544b3b7..50b3e6367d90fc13ed33132b8110563f1901bd56 100644 (file)
@@ -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);
 
index f618622976f8d1a9e9e7fb15384b4a188b88d81a..5bd6b96bd15e2d47b781f3b5f522bd9d4a667fa7 100644 (file)
@@ -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;