我有一个 lighttpd 1.4.35 实例,用于监听 https 流量并将其反向代理到后端服务器。例如,
.----------. .----------.
client ---https--> | lighttpd | ---http--> | back-end |
<--https--- | | <--http--- | server |
`----------' `----------'
当我向代理页面(通过 https)执行 HTTP 发布时,后端服务器返回带有http
而不是 的位置标头https
。
Location: http://lighttpd_url/some_page.htm
lighttpd 有没有办法重写 location 标头中的 URL?我看到在 lighttpd 1.5.x 中,proxy-core 有一个rewrite-response
指令,我猜它应该是这样的:
proxy-core.rewrite-response = (
"Location" => ( "^http://xyz/(.*)" => "https://xyz/$1" ),
)
但是如何Location
在 lighttpd 1.4.x 中重写标头?
答案1
从 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);
}
}
}