问题描述当自定义日志输出格式需要输出http请求中url参数时如果参数中包含中文是会进行url encode的所以输出都是编码后的字符串比如我配置的12345log_format test_log escapejson{ timestamp: $msec, request: $request,name: $arg_name,uuid: $http_uuid,remoteAddr: $remote_addr };请求 http://192.168.108.130:80/lua?name我是中文arg_name输出时就会是这样子12{ “timestamp”: “1740829638.783”, “request”: “GET/lua?name%E6%88%91%E6%98%AF%E4%B8%AD%E6%96%87 HTTP/1.1”,“name”: “%E6%88%91%E6%98%AF%E4%B8%AD%E6%96%87”,“uuid”: “-”,“remoteAddr”: “192.168.108.1” }所以目的是需要把它url decode再输出方法1-lua首先需要安装Lua具体可以网上找教程文章看下这里只提及简要流程安装lua所需模块包括lua-nginx-modulengx_devel_kit123456789101112131415161718./configure--prefix/usr/local/nginx\--pid-path/var/run/nginx/nginx.pid \--lock-path/var/lock/nginx.lock \--error-log-path/var/log/nginx/error.log \--http-log-path/var/log/nginx/access.log \--with-http_gzip_static_module \--http-client-body-temp-path/var/temp/nginx/client\--http-proxy-temp-path/var/temp/nginx/proxy\--http-fastcgi-temp-path/var/temp/nginx/fastcgi\--http-uwsgi-temp-path/var/temp/nginx/uwsgi\--http-scgi-temp-path/var/temp/nginx/scgi\--with-http_stub_status_module \--with-http_ssl_module \--with-file-aio \--with-http_realip_module \--with-openssl/usr/local/software/openssl-1.1.1w \--add-module/usr/local/software/lua-nginx-module-0.10.27rc1 \--add-module/usr/local/software/ngx_devel_kit-0.3.3然后 make注意如果无需替换原nginx目录的内容则只需要make不需要make install然后编译后的objs目录里把nginx可执行文件copy过去即可可以先把原来nginx可执行文件备份下另外需要本地先安装luajit比如我安装的 luajit2-2.1-20240626另外有可能会报错 resty 相关的错误网上文章有提到用lua_load_resty_core off;解决但是我实际测试无效故按照错误提示又下载了相关的包lua-resty-corelua-resty-lrucachenginx.conf 中添加配置lua_package_path “/usr/local/software/lua-resty-core-0.1.29/lib/?.lua;”;安装完成之后可以测试下lua12345location/lua{default_typetext/plain;content_by_luangx.say(hello, lua);}之后加上我们的url解析配置1set$decoded_arg_name;12345678910111213location/lua{default_typetext/plain;content_by_luangx.say(hello, lua);access_by_lua_block {localargs ngx.req.get_uri_args()ifargs.namethenlocaldecoded_name ngx.unescape_uri(args.name)ngx.var.decoded_arg_name decoded_namengx.log(ngx.ERR,Decoded name: , decoded_name)# 打印日志调试用end}}完整nginx配置代码如下1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677#user nobody;worker_processes 1;#error_log logs/error.log;#error_log logs/error.log notice;#error_log logs/error.log info;#pid logs/nginx.pid;events {worker_connections 1024;}http {include mime.types;default_type application/octet-stream;#log_format main $remote_addr - $remote_user [$time_local] $request # $status $body_bytes_sent $http_referer # $http_user_agent $http_x_forwarded_for;log_format test_log escapejson{ timestamp: $msec, request: $request,name: $decoded_arg_name,uuid: $http_uuid,remoteAddr: $remote_addr };#access_log logs/access.log main;access_log logs/test_access.log test_log;sendfile on;#tcp_nopush on;lua_load_resty_core off;lua_package_path/usr/local/software/lua-resty-core-0.1.29/lib/?.lua;;#keepalive_timeout 0;keepalive_timeout 65;#gzip on;server {listen 80;server_name localhost;set$decoded_arg_name;#charset koi8-r;charset utf-8;#access_log logs/host.access.log main;location / {root html;index index.html index.htm;}location/lua{default_typetext/plain;content_by_luangx.say(hello, lua);access_by_lua_block {localargs ngx.req.get_uri_args()ifargs.namethenlocaldecoded_name ngx.unescape_uri(args.name)ngx.var.decoded_arg_name decoded_namengx.log(ngx.ERR,Decoded name: , decoded_name)end}}#error_page 404 /404.html;# redirect server error pages to the static page /50x.html#error_page 500 502 503 504/50x.html;location /50x.html {root html;}}}但加上上面这一部还不够lua的输出日志如果是非ascii码会输出为十六进制字符串像是1{ “timestamp”: “1740835690.677”, “request”: “POST/lua?name%E6%88%91%E6%98%AF%E4%B8%AD%E6%96%87 HTTP/1.1”,“name”: “\xE6\x88\x91\xE6\x98\xAF\xE4\xB8\xAD\xE6\x96\x87”,“uuid”: “testuuid”,“remoteAddr”: “192.168.108.1” }对于这个问题偏新版的nginx可以通过加上 escapejson解决12345log_format test_log escapejson{ timestamp: $msec, request: $request,name: $decoded_arg_name,uuid: $http_uuid,remoteAddr: $remote_addr };至此打印的日志则是中文了1{ “timestamp”: “1740834963.209”, “request”: “POST/lua?name%E6%88%91%E6%98%AF%E4%B8%AD%E6%96%87 HTTP/1.1”,“name”: “我是中文”,“uuid”: “testuuid”,“remoteAddr”: “192.168.108.1” }方法2-set-misc-nginx-module在nginx中添加此模块下载模块包 set-misc-nginx-module-0.33 解压后configure命令如下12345678910111213141516171819./configure--prefix/usr/local/nginx\--pid-path/var/run/nginx/nginx.pid \--lock-path/var/lock/nginx.lock \--error-log-path/var/log/nginx/error.log \--http-log-path/var/log/nginx/access.log \--with-http_gzip_static_module \--http-client-body-temp-path/var/temp/nginx/client\--http-proxy-temp-path/var/temp/nginx/proxy\--http-fastcgi-temp-path/var/temp/nginx/fastcgi\--http-uwsgi-temp-path/var/temp/nginx/uwsgi\--http-scgi-temp-path/var/temp/nginx/scgi\--with-http_stub_status_module \--with-http_ssl_module \--with-file-aio \--with-http_realip_module \--with-openssl/usr/local/software/openssl-1.1.1w \--add-module/usr/local/software/lua-nginx-module-0.10.27rc1 \--add-module/usr/local/software/ngx_devel_kit-0.3.3 \--add-module/usr/local/software/set-misc-nginx-module-0.33以上添加模块的lua相关的两个模块可能可以不用加但我测试的时候没有去掉这里可以看大家需求然后 make注意如果无需替换原nginx目录的内容则只需要make不需要make install然后编译后的objs里把nginx可执行文件copy过去即可可以先把原来nginx可执行文件备份更改 nginx.conf12set$decoded_arg_name;set_unescape_uri $decoded_arg_name $arg_name;再同样加上 escapejson其他什么的都不用配置了实现效果是一样的。