У меня есть экземпляр lighttpd 1.4.35, который прослушивает https-трафик и передает его на внутренний сервер. Т.е.,
.----------. .----------.
client ---https--> | lighttpd | ---http--> | back-end |
<--https--- | | <--http--- | server |
`----------' `----------'
Когда я отправляю HTTP-сообщение на прокси-страницу (через https), внутренний сервер возвращает заголовок Location с http
вместо того https
.
Location: http://lighttpd_url/some_page.htm
Есть ли способ, которым lighttpd может переписать URL-адрес в заголовке местоположения? Я вижу в lighttpd 1.5.x прокси-ядро имеет rewrite-response
директива, и я предполагаю, что это будет выглядеть так:
proxy-core.rewrite-response = (
"Location" => ( "^http://xyz/(.*)" => "https://xyz/$1" ),
)
Но как мне переписать Location
заголовок в lighttpd 1.4.x?
Начиная с версии 1.4.35, mod_proxy не позволяет изменять заголовки ответов. Но мне очень нужен был простой функционал смены Location
заголовки ответов с http на https, поэтому я взломал его в mod_proxy.c.
Вот патч на случай, если он кому-то пригодится. После применения этого патча, а затем повторной сборки и установки из исходного кода вы можете добавить proxy.force_https_location = 1
в ваш файл конфигурации, чтобы включить эту функцию глобально.
--- src/mod_proxy.c-orig 2014-06-26 14:33:50.000000000 -0700
+++ src/mod_proxy.c 2014-06-26 16:08:11.000000000 -0700
@@ -64,6 +64,7 @@
typedef struct {
array *extensions;
unsigned short debug;
+ unsigned short force_https_location;
proxy_balance_t balance;
} plugin_config;
@@ -191,6 +192,7 @@
{ "proxy.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
{ "proxy.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
{ "proxy.balance", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+ { "proxy.force_https_location", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
};
@@ -203,10 +205,12 @@
s = malloc(sizeof(plugin_config));
s->extensions = array_init();
s->debug = 0;
+ s->force_https_location = 0;
cv[0].destination = s->extensions;
cv[1].destination = &(s->debug);
cv[2].destination = p->balance_buf;
+ cv[3].destination = &(s->force_https_location);
buffer_reset(p->balance_buf);
@@ -568,10 +572,13 @@
int key_len;
data_string *ds;
int copy_header;
+ int is_location_header;
ns[0] = '\0';
ns[1] = '\0';
+ is_location_header = 0;
+
if (-1 == http_response_status) {
/* The first line of a Response message is the Status-Line */
@@ -614,6 +621,7 @@
if (0 == strncasecmp(key, "Location", key_len)) {
con->parsed_response |= HTTP_LOCATION;
}
+ is_location_header = 1;
break;
case 10:
if (0 == strncasecmp(key, "Connection", key_len)) {
@@ -635,7 +643,26 @@
ds = data_response_init();
}
buffer_copy_string_len(ds->key, key, key_len);
- buffer_copy_string(ds->value, value);
+
+ if (is_location_header && p->conf.force_https_location) {
+ const unsigned int http_prefix_len = 7; /* strlen("http://") */
+
+ if (0 == strncasecmp(value, "http://", http_prefix_len)) {
+ buffer_copy_string(ds->value, "https://");
+ buffer_append_string(ds->value, value + http_prefix_len);
+
+ if (p->conf.debug) {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "forced Location to https: ", ds->value);
+ }
+ }
+ else {
+ buffer_copy_string(ds->value, value);
+ }
+ }
+ else
+ {
+ buffer_copy_string(ds->value, value);
+ }
array_insert_unique(con->response.headers, (data_unset *)ds);
}
@@ -873,6 +897,7 @@
PATCH(extensions);
PATCH(debug);
PATCH(balance);
+ PATCH(force_https_location);
/* skip the first, the global context */
for (i = 1; i < srv->config_context->used; i++) {
@@ -892,6 +917,8 @@
PATCH(debug);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.balance"))) {
PATCH(balance);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.force_https_location"))) {
+ PATCH(force_https_location);
}
}
}