Welcome! Log In Create A New Profile

Advanced

[PATCH] Added support for client_scheme_in_redirect directive

Kyle Ibrahim
March 15, 2015 07:08AM
Currently, there is no way way to control the scheme which will be used in
nginx-issued redirects. This is a problem when the client is potentially
using a different scheme than nginx due to a SSL terminating load balancer.
As some client requests may have started over http and some over https,
we'd like to way to dynamically set the proper client scheme.

This is a patch which adds a directive `client_scheme_in_redirect` to
complement `server_name_in_redirect` and `port_in_redirect`.

A suggested documentation block is included in the commit.

# HG changeset patch
# User Kyle Ibrahim <kibrahim@getpantheon.com>
# Date 1426414581 25200
# Sun Mar 15 03:16:21 2015 -0700
# Node ID 9785f13c006025f180b354bdeac2de5d8cc9af8e
# Parent 79b473d5381d85f79ab71b7aa85ecf9be1caf9fb
Added support for client_scheme_in_redirect directive

Syntax: client_scheme_in_redirect scheme;
Default: --
Context: http, server, location

The client_scheme_in_redirect directive defines the scheme in redirects
issued by nginx. When not specified, the scheme will be https if the
current connection is
over ssl and http otherwise. The scheme value can contain variables.

diff -r 79b473d5381d -r 9785f13c0060 contrib/vim/syntax/nginx.vim
--- a/contrib/vim/syntax/nginx.vim Fri Mar 13 16:43:01 2015 +0300
+++ b/contrib/vim/syntax/nginx.vim Sun Mar 15 03:16:21 2015 -0700
@@ -96,6 +96,7 @@
syn keyword ngxDirective client_header_buffer_size
syn keyword ngxDirective client_header_timeout
syn keyword ngxDirective client_max_body_size
+syn keyword ngxDirective client_scheme_in_redirect
syn keyword ngxDirective connection_pool_size
syn keyword ngxDirective create_full_put_path
syn keyword ngxDirective daemon
diff -r 79b473d5381d -r 9785f13c0060 src/http/ngx_http_core_module.c
--- a/src/http/ngx_http_core_module.c Fri Mar 13 16:43:01 2015 +0300
+++ b/src/http/ngx_http_core_module.c Sun Mar 15 03:16:21 2015 -0700
@@ -72,6 +72,8 @@
void *conf);
static char *ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static char *ngx_http_client_scheme_in_redirect(ngx_conf_t *cf,
+ ngx_command_t *cmd, void *conf);
#if (NGX_HTTP_GZIP)
static ngx_int_t ngx_http_gzip_accept_encoding(ngx_str_t *ae);
static ngx_uint_t ngx_http_gzip_quantity(u_char *p, u_char *last);
@@ -560,6 +562,13 @@
offsetof(ngx_http_core_loc_conf_t, reset_timedout_connection),
NULL },

+ { ngx_string("client_scheme_in_redirect"),
+
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_http_client_scheme_in_redirect,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
{ ngx_string("server_name_in_redirect"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
@@ -3642,6 +3651,7 @@
clcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
clcf->resolver_timeout = NGX_CONF_UNSET_MSEC;
clcf->reset_timedout_connection = NGX_CONF_UNSET;
+ clcf->client_scheme_in_redirect = NGX_CONF_UNSET_PTR;
clcf->server_name_in_redirect = NGX_CONF_UNSET;
clcf->port_in_redirect = NGX_CONF_UNSET;
clcf->msie_padding = NGX_CONF_UNSET;
@@ -3898,6 +3908,8 @@

ngx_conf_merge_value(conf->reset_timedout_connection,
prev->reset_timedout_connection, 0);
+ ngx_conf_merge_ptr_value(conf->client_scheme_in_redirect,
+ prev->client_scheme_in_redirect, NULL);
ngx_conf_merge_value(conf->server_name_in_redirect,
prev->server_name_in_redirect, 0);
ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect,
1);
@@ -5066,6 +5078,38 @@
return NGX_CONF_OK;
}

+static char *
+ngx_http_client_scheme_in_redirect(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
+{
+ ngx_http_core_loc_conf_t *clcf = conf;
+
+ ngx_str_t *value;
+ ngx_http_compile_complex_value_t ccv;
+
+ if (clcf->client_scheme_in_redirect != NGX_CONF_UNSET_PTR) {
+ return "is duplicate";
+ }
+
+ value = cf->args->elts;
+
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+ ccv.cf = cf;
+ ccv.value = &value[1];
+ ccv.complex_value = ngx_palloc(cf->pool,
+ sizeof(ngx_http_complex_value_t));
+ if (ccv.complex_value == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ clcf->client_scheme_in_redirect = ccv.complex_value;
+
+ return NGX_CONF_OK;
+}

#if (NGX_HTTP_GZIP)

diff -r 79b473d5381d -r 9785f13c0060 src/http/ngx_http_core_module.h
--- a/src/http/ngx_http_core_module.h Fri Mar 13 16:43:01 2015 +0300
+++ b/src/http/ngx_http_core_module.h Sun Mar 15 03:16:21 2015 -0700
@@ -399,6 +399,7 @@
ngx_flag_t tcp_nopush; /* tcp_nopush */
ngx_flag_t tcp_nodelay; /* tcp_nodelay */
ngx_flag_t reset_timedout_connection; /* reset_timedout_connection
*/
+ ngx_http_complex_value_t *client_scheme_in_redirect; /*
client_scheme_in_redirect */
ngx_flag_t server_name_in_redirect; /* server_name_in_redirect */
ngx_flag_t port_in_redirect; /* port_in_redirect */
ngx_flag_t msie_padding; /* msie_padding */
diff -r 79b473d5381d -r 9785f13c0060
src/http/ngx_http_header_filter_module.c
--- a/src/http/ngx_http_header_filter_module.c Fri Mar 13 16:43:01 2015
+0300
+++ b/src/http/ngx_http_header_filter_module.c Sun Mar 15 03:16:21 2015
-0700
@@ -152,7 +152,7 @@
{
u_char *p;
size_t len;
- ngx_str_t host, *status_line;
+ ngx_str_t client_scheme, host, *status_line;
ngx_buf_t *b;
ngx_uint_t status, i, port;
ngx_chain_t out;
@@ -317,6 +317,15 @@
{
r->headers_out.location->hash = 0;

+ if (clcf->client_scheme_in_redirect) {
+ if (ngx_http_complex_value(r, clcf->client_scheme_in_redirect,
&client_scheme) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ } else {
+ ngx_str_null(&client_scheme);
+ }
+
if (clcf->server_name_in_redirect) {
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
host = cscf->server_name;
@@ -352,7 +361,12 @@
break;
}

- len += sizeof("Location: https://") - 1
+ if (client_scheme.len) {
+ len += client_scheme.len;
+ } else {
+ len += sizeof("https") - 1;
+ }
+ len += sizeof("Location: ://") - 1
+ host.len
+ r->headers_out.location->value.len + 2;

@@ -374,6 +388,7 @@
}

} else {
+ ngx_str_null(&client_scheme);
ngx_str_null(&host);
port = 0;
}
@@ -521,14 +536,19 @@

p = b->last + sizeof("Location: ") - 1;

- b->last = ngx_cpymem(b->last, "Location: http",
- sizeof("Location: http") - 1);
+ b->last = ngx_cpymem(b->last, "Location: ",
+ sizeof("Location: ") - 1);

+ if (client_scheme.len) {
+ b->last = ngx_copy(b->last, client_scheme.data,
client_scheme.len);
+ } else {
+ b->last = ngx_cpymem(b->last, "http", sizeof("http") - 1);
#if (NGX_HTTP_SSL)
- if (c->ssl) {
- *b->last++ ='s';
+ if (c->ssl) {
+ *b->last++ ='s';
+ }
+#endif
}
-#endif

*b->last++ = ':'; *b->last++ = '/'; *b->last++ = '/';
b->last = ngx_copy(b->last, host.data, host.len);
diff -r 79b473d5381d -r 9785f13c0060 src/http/ngx_http_spdy_filter_module.c
--- a/src/http/ngx_http_spdy_filter_module.c Fri Mar 13 16:43:01 2015 +0300
+++ b/src/http/ngx_http_spdy_filter_module.c Sun Mar 15 03:16:21 2015 -0700
@@ -99,7 +99,7 @@
size_t len;
u_char *p, *buf, *last;
ngx_buf_t *b;
- ngx_str_t host;
+ ngx_str_t client_scheme, host;
ngx_uint_t i, j, count, port;
ngx_chain_t *cl;
ngx_list_part_t *part, *pt;
@@ -217,6 +217,15 @@
{
r->headers_out.location->hash = 0;

+ if (clcf->client_scheme_in_redirect) {
+ if (ngx_http_complex_value(r, clcf->client_scheme_in_redirect,
&client_scheme) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ } else {
+ ngx_str_null(&client_scheme);
+ }
+
if (clcf->server_name_in_redirect) {
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
host = cscf->server_name;
@@ -252,8 +261,14 @@
break;
}

+ if (client_scheme.len) {
+ len += client_scheme.len;
+ } else {
+ len += ngx_http_spdy_nv_vsize("https");
+ }
+
len += ngx_http_spdy_nv_nsize("location")
- + ngx_http_spdy_nv_vsize("https://")
+ + ngx_http_spdy_nv_vsize("://")
+ host.len
+ r->headers_out.location->value.len;

@@ -275,6 +290,7 @@
}

} else {
+ ngx_str_null(&client_scheme);
ngx_str_null(&host);
port = 0;
}
@@ -411,13 +427,16 @@

p = last + NGX_SPDY_NV_VLEN_SIZE;

- last = ngx_cpymem(p, "http", sizeof("http") - 1);
-
+ if (client_scheme.len) {
+ last = ngx_cpymem(p, client_scheme.data, client_scheme.len);
+ } else {
+ last = ngx_cpymem(p, "http", sizeof("http") - 1);
#if (NGX_HTTP_SSL)
- if (c->ssl) {
- *last++ ='s';
+ if (c->ssl) {
+ *last++ ='s';
+ }
+#endif
}
-#endif

*last++ = ':'; *last++ = '/'; *last++ = '/';
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[PATCH] Added support for client_scheme_in_redirect directive

Kyle Ibrahim 495 March 15, 2015 07:08AM

Re: [PATCH] Added support for client_scheme_in_redirect directive

Maxim Dounin 227 March 18, 2015 12:24PM

Re: [PATCH] Added support for client_scheme_in_redirect directive

Kyle Ibrahim 300 March 18, 2015 02:08PM

Re: [PATCH] Added support for client_scheme_in_redirect directive

Maxim Dounin 285 March 19, 2015 02:42PM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 314
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 500 on July 15, 2024
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready