[PATCH] Support X-Forwarded-Proto in redirects
Lukas Vacek
lucas.vacek at gmail.com
Mon Mar 19 19:53:46 UTC 2018
# HG changeset patch
# User Lukas Vacek <lucas.vacek at gmail.com>
# Date 1521488415 -3600
# Mon Mar 19 20:40:15 2018 +0100
# Node ID 0f9ed8bb5c9505f7a77271eed54e7b01b9b65a81
# Parent 413189f03c8d13d0d20bd5e44fa0e48e693badef
Support X-Forwarded-Proto in redirects
This patch adds a new configuration option x_forwarded_proto_in_redirect
(default off) to fill schema from X-Forwarded-Proto HTTP header in
URLs generated by nginx.
This is handy when running nginx behind SSL off-loading reverse proxy.
diff -r 413189f03c8d -r 0f9ed8bb5c95 src/http/ngx_http_core_module.c
--- a/src/http/ngx_http_core_module.c Mon Mar 19 16:42:56 2018 +0300
+++ b/src/http/ngx_http_core_module.c Mon Mar 19 20:40:15 2018 +0100
@@ -576,6 +576,13 @@
offsetof(ngx_http_core_loc_conf_t, port_in_redirect),
NULL },
+ { ngx_string("x_forwarded_proto_in_redirect"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_core_loc_conf_t, x_forwarded_proto_in_redirect),
+ NULL },
+
{ ngx_string("msie_padding"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
@@ -3401,6 +3408,7 @@
clcf->absolute_redirect = NGX_CONF_UNSET;
clcf->server_name_in_redirect = NGX_CONF_UNSET;
clcf->port_in_redirect = NGX_CONF_UNSET;
+ clcf->x_forwarded_proto_in_redirect = NGX_CONF_UNSET;
clcf->msie_padding = NGX_CONF_UNSET;
clcf->msie_refresh = NGX_CONF_UNSET;
clcf->log_not_found = NGX_CONF_UNSET;
@@ -3669,6 +3677,8 @@
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);
+ ngx_conf_merge_value(conf->x_forwarded_proto_in_redirect,
+ prev->x_forwarded_proto_in_redirect, 0);
ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1);
ngx_conf_merge_value(conf->msie_refresh, prev->msie_refresh, 0);
ngx_conf_merge_value(conf->log_not_found, prev->log_not_found, 1);
diff -r 413189f03c8d -r 0f9ed8bb5c95 src/http/ngx_http_core_module.h
--- a/src/http/ngx_http_core_module.h Mon Mar 19 16:42:56 2018 +0300
+++ b/src/http/ngx_http_core_module.h Mon Mar 19 20:40:15 2018 +0100
@@ -385,6 +385,8 @@
ngx_flag_t absolute_redirect; /* absolute_redirect */
ngx_flag_t server_name_in_redirect; /* server_name_in_redirect */
ngx_flag_t port_in_redirect; /* port_in_redirect */
+ ngx_flag_t x_forwarded_proto_in_redirect;
+ /* x_forwarded_proto_in_redirect */
ngx_flag_t msie_padding; /* msie_padding */
ngx_flag_t msie_refresh; /* msie_refresh */
ngx_flag_t log_not_found; /* log_not_found */
diff -r 413189f03c8d -r 0f9ed8bb5c95 src/http/ngx_http_header_filter_module.c
--- a/src/http/ngx_http_header_filter_module.c Mon Mar 19 16:42:56 2018 +0300
+++ b/src/http/ngx_http_header_filter_module.c Mon Mar 19 20:40:15 2018 +0100
@@ -158,7 +158,7 @@
{
u_char *p;
size_t len;
- ngx_str_t host, *status_line;
+ ngx_str_t proto, host, *status_line;
ngx_buf_t *b;
ngx_uint_t status, i, port;
ngx_chain_t out;
@@ -343,12 +343,44 @@
}
}
- port = ngx_inet_get_port(c->local_sockaddr);
+ proto.data = (u_char *)"http";
+ proto.len = 4;
- len += sizeof("Location: https://") - 1
+#if (NGX_HTTP_SSL)
+ if (c->ssl) {
+ proto.data = (u_char *)"https";
+ proto.len = 5;
+ }
+#endif
+ if (clcf->x_forwarded_proto_in_redirect) {
+ part = &r->headers_in.headers.part;
+ header = part->elts;
+
+ for (i = 0; /* void */; i++) {
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ header = part->elts;
+ i = 0;
+ }
+
+ if (ngx_strcasecmp(header[i].key.data,
+ (u_char *)"X-Forwarded-Proto") == 0) {
+ proto = header[i].value;
+ break;
+ }
+ }
+ }
+
+ len += sizeof("Location: ") - 1 + proto.len + sizeof("://") - 1
+ host.len
+ r->headers_out.location->value.len + 2;
+ port = ngx_inet_get_port(c->local_sockaddr);
+
if (clcf->port_in_redirect) {
#if (NGX_HTTP_SSL)
@@ -368,6 +400,7 @@
} else {
ngx_str_null(&host);
+ ngx_str_null(&proto);
port = 0;
}
@@ -518,14 +551,9 @@
p = b->last + sizeof("Location: ") - 1;
- b->last = ngx_cpymem(b->last, "Location: http",
- sizeof("Location: http") - 1);
-
-#if (NGX_HTTP_SSL)
- if (c->ssl) {
- *b->last++ ='s';
- }
-#endif
+ b->last = ngx_cpymem(b->last, "Location: ", sizeof("Location: ") - 1);
+
+ b->last = ngx_copy(b->last, proto.data, proto.len);
*b->last++ = ':'; *b->last++ = '/'; *b->last++ = '/';
b->last = ngx_copy(b->last, host.data, host.len);
diff -r 413189f03c8d -r 0f9ed8bb5c95 src/http/v2/ngx_http_v2_filter_module.c
--- a/src/http/v2/ngx_http_v2_filter_module.c Mon Mar 19 16:42:56 2018 +0300
+++ b/src/http/v2/ngx_http_v2_filter_module.c Mon Mar 19 20:40:15 2018 +0100
@@ -319,11 +319,45 @@
}
}
+ ngx_str_t proto;
+ proto.data = (u_char* )"http";
+ proto.len = 4;
+
+#if (NGX_HTTP_SSL)
+ if (fc->ssl) {
+ proto.data = (u_char* )"https";
+ proto.len = 5;
+ }
+#endif
+
+ if (clcf->x_forwarded_proto_in_redirect) {
+ part = &r->headers_in.headers.part;
+ header = part->elts;
+
+ for (i = 0; /* void */; i++) {
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ header = part->elts;
+ i = 0;
+ }
+
+ if (ngx_strcasecmp(header[i].key.data,
+ (u_char *)"X-Forwarded-Proto") == 0) {
+ proto = header[i].value;
+ break;
+ }
+ }
+ }
+
+ location.len = proto.len + sizeof("://") - 1 + host.len +
+ + r->headers_out.location->value.len;
+
port = ngx_inet_get_port(fc->local_sockaddr);
- location.len = sizeof("https://") - 1 + host.len
- + r->headers_out.location->value.len;
-
if (clcf->port_in_redirect) {
#if (NGX_HTTP_SSL)
@@ -346,13 +380,7 @@
return NGX_ERROR;
}
- p = ngx_cpymem(location.data, "http", sizeof("http") - 1);
-
-#if (NGX_HTTP_SSL)
- if (fc->ssl) {
- *p++ = 's';
- }
-#endif
+ p = ngx_cpymem(location.data, proto.data, proto.len);
*p++ = ':'; *p++ = '/'; *p++ = '/';
p = ngx_cpymem(p, host.data, host.len);
More information about the nginx-devel
mailing list