我现在已经花了太多的时间/天来谷歌搜索这个问题,我几乎已经在chatgpt上寻求答案了,所以现在我需要征求一些意见。
我在 php-fpm 服务器(wordpress)前面有一个 nginx 反向代理。我正在使用 sub_filter 更改响应中的一些值。
这适用于某些 json 响应,但不适用于其他响应。
以下是 nginx.conf 的相关部分:
# Reverse proxy
server {
... # certificates, logging etc. removed for simplicity
root /var/www/html;
index index.php index.html index.htm;
...
location / {
gzip off;
... # proxy_set_header stuff removed
proxy_set_header Accept-Encoding "";
proxy_pass http://127.0.0.1:8082;
sub_filter_once off;
sub_filter_types *;
sub_filter "target_vlue" "replacement_value";
}
}
# Application http
server {
... # listen, logging etc removed
location ~ \.php$ {
gzip off;
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass test-wordpress:9000; #its docker
}
}
我有双服务器设置,原因是 - 与此无关。
注意 gzip 关闭;和接受编码“”;在 php-pfm 中,压缩被关闭:
9dedac8fdba4:/var/www/html# php -i |grep zlib
zlib.output_compression => Off => Off
zlib.output_compression_level => -1 => -1
zlib.output_handler => no value => no value
我检查了响应中的Content-Type标头是application/json; charset=utf-8 ,并且我检查了 application/json 是 sub_filter 类型配置的一部分。
进一步调试
sub_filter不起作用的json是由Wordpress(插件)生成的。它很大,但这里是一个片段:
{
"success": true,
"data": {
"responses": {
"app_site_editor_template_types": {
"success": true,
"code": 200,
"data": [
{
"type": "header",
...
"urls": {
...
"thumbnail": "https://<TARGET_VALUE>/wp-content/plugins/elementor/assets/images/app/site-editor/header.svg", // <-- Here target_value is not changed by subfiler
"EXTRA_DEBUG_TEST": "DEADBEEF" // <--- My test, also not changed
}
},
...
正如评论所说,“TARGET_VALUE”并未如希望的那样被 sub_filter 更改。如果我更改 sub_filter 来替换“DEADBEEF”,那也不起作用。所以它不是价值本身。我已经编辑了插件 .php 以注入 json 的额外“EXTRA_DEBUG_TEST”部分。如果我将此 JSON 的简单部分放入 .php 文件中并通过相同的服务器设置请求该文件,那么这些值将按预期替换:
{
"status": "success",
"message": "This is a simple JSON response",
"items": [
1,
2,
3,
4,
5
],
"url": "https://<TARGET_VALUE>", // <-- sub_filter catches and changes this
"url2": "https://<TARGET_VALUE>/wp-content/plugins/elementor/assets/images/app/site-editor/header.svg", // <-- sub_filter catches and changes this
}
注意:第二个 json 是使用的整个 debug-json。有人知道这里发生了什么事吗?
编辑:它不是 json。我编辑了插件 .php 以返回一个非常简单的 json 对象:
{
"success": true,
"data": {
"responses": [ "https://<TARGET_VALUE>/wp-admin" ]
}
}
sub_filter 仍然没有替换 target_value。
Wordpress 插件是 Elementor 和 Elementor-pro。我的问题与主题编辑器功能特别相关。它是一个专业功能,它调用 admin-ajax.php 来获取一些编辑器配置值。触发的动作是:
$ajax->register_ajax_action( 'app_site_editor_template_types', [ $this, 'get_template_types' ] );
实现看起来没问题。但罪魁祸首是在 Elementor 核心中,特别是在 elementor/core/common/modules/ajax/module.php 中,我们有这个 gem:
private function send_success() {
// things left out
if ( function_exists( 'gzencode' ) ) {
$response = gzencode( $json );
header( 'Content-Type: application/json; charset=utf-8' );
header( 'Content-Encoding: gzip' );
header( 'Content-Length: ' . strlen( $response ) );
echo $response; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} else {
echo $json; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
wp_die( '', '', [ 'response' => null ] );
}
此函数包装了对 admin-ajax.php 的调用。正如我们所看到的,它很高兴地忽略任何 HTTP 标头和 PHP 配置,并无论如何压缩输出 JSON。这就是为什么 nginx 或 php 配置更改没有任何效果。