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,
}
+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)
{
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"),
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;
}
}
+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
off_t content_length_n;
ngx_array_t cache_control;
+ ngx_array_t cookies;
unsigned connection_close:1;
unsigned chunked:1;
} 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);
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) {
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;