解决nginx在记录post数据时 中文字符转成16进制的问题【转载】
1. 问题描述
nginx 在获取post数据时候,如果是中文,则转换成16进制显示在日志文件中,如下图所示。
日志格式为: log_format postdata '$remote_addr | $request_body | $resp_body';
此篇文章记录下解决此次问题的过程。
最新版本解决方式
适合nginx 1.11.8
以上版本
在nginx 1.11.8
以上版本中log_format
增加了escape=json
参数,在配置日志格式时加上此参数可以不转义变量内容,官方文档-参数说明
日志配置
log_format postdata '$remote_addr | $request_body | $resp_body';
log_format postdata escape=json '$remote_addr | $request_body | $resp_body';
日志输出
第一条日志是不加escape=json
参数后,log_format
输出的
第二条日志是加上escape=json
参数后,log_format
输出的
2. 软件版本
- 系统
centos 6.7 X86_64
- nginx
1.11.5
- lua-nginx-module
0.10.7
- PHP
5.6.27
测试环境部署见:Nginx 使用lua-nginx-module 来获取post请求中得request和response信息
3. 收集信息
收集信息-阶段1:
在遇到此类问题的时候,我们大多是使用搜索引擎搜索答案,因为这样来的更快一些。当遇到这个问题的时候,我感觉也无从下手,随即在google中搜索答案,没过多久,便找到了同类人,也遇到了这个问题
此次搜索关键字: nginx log 中文 16进制
出处:https://groups.google.com/forum/#!topic/openresty/PYvvfj5RKCg
这个里面提到了:
为什么会出现这个问题?
解决办法
当时情况,在大量的搜索结果下,刚开始没注意到这里面的问题,认为这个是openresty的解决办法。就继续搜索信息了。
收集信息-阶段2:
经过上面得信息,我们可以得知,nginx现在是把中文字符转换成16进制。
所以关键字变成了:nginx 不支持中文
从这个关键字便发现了下面得信息
来自: http://navyaijm.blog.51cto.com/4647068/1082169
从这里面获得了:
- 通过降级nginx来解决问题
这位博主通过过降级nginx 程序来达到支持中文得效果,当时目测这文章是2012年得,比较久远,而且还需要降级,就没有尝试这类方法。
信息收集-阶段3:
这次搜索解决答案也有一段时间了,突然想起了阶段1时发现得解决方法,里面有个命令可以关闭nginx转换16进制得命令。随即搜索关键字改成:
nginx log escape characters
通过这个关键字找到了下列有用信息。
来自: http://mailman.nginx.org/pipermail/nginx/2008-January/003051.html
从这里面获得了:
- 在2008年得时候,通过这个path,让不可打印得字符转成16进制。
- attachment.bin 文件记录了是哪个源代码文件的补丁。
通过查看这个文件,发现了 ngx_http_log_escape
这函数是转换16进制的。要知道nginx源代码已经被很多国人都阅读过,肯定有相关的解释。
随即关键字变成了: nginx ngx_http_log_escape
通过搜索发现了下列的源码解释
static uintptr_t
ngx_http_log_escape(u_char *dst, u_char *src, size_t size)
{
ngx_uint_t n;
/* 这是十六进制字符表 */
static u_char hex[] = "0123456789ABCDEF";
/* 这是ASCII码表,每一位表示一个符号,其中值为1表示此符号需要转换,值为0表示不需要转换 */
static uint32_t escape[] = {
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
0x00000004, /* 0000 0000 0000 0000 0000 0000 0000 0100 */
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
0x10000000, /* 0001 0000 0000 0000 0000 0000 0000 0000 */
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
};
if (dst == NULL) {
/* find the number of the characters to be escaped */
n = 0;
while (size) {
if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
n++;
}
src++;
size--;
}
return (uintptr_t) n;
/* 返回需要转换的字符总数*/
}
while (size) {
/* escape[*src >> 5],escape每一行保存了32个符号,
所以右移5位,即除以32就找到src对应的字符保存在escape的行,
(1 << (*src & 0x1f))此符号在escape一行中的位置,
相&结果就是判断src符号位是否为1,需不需要转换 */
if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
*dst++ = '\\';
*dst++ = 'x';
/* 一个字符占一个字节8位,每4位转成一个16进制表示 */
/* 高4位转换成16进制 */
*dst++ = hex[*src >> 4];
/* 低4位转换成16进制*/
*dst++ = hex[*src & 0xf];
src++;
} else {
/* 不需要转换的字符直接赋值 */
*dst++ = *src++;
}
size--;
}
return (uintptr_t) dst;
}
感谢大神:http://blog.csdn.net/l09711/article/details/46712325
从上面解释来看,我们只需要*src不转换16进制就可以。
4. 解决方法
源码文件为:src/http/modules/ngx_http_log_module.c
修改源码如下图所示,
然后重新编译,安装nginx
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_flv_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_realip_module --http-client-body-temp-path=/var/tmp/nginx/client/ --http-proxy-temp-path=/var/tmp/nginx/proxy/ --http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi --http-scgi-temp-path=/var/tmp/nginx/scgi --with-pcre --add-module=../lua-nginx-module-0.10.7
/usr/local/nginx/sbin/nginx -s stop
make -j2 && make install
/usr/local/nginx/sbin/nginx
再次post 数据到nginx里
查看日志会发现中文不在转换16进制了。
第1-2行,是没有修改源码前,向nginx url post数据,中文被转换成16进制。
第3-5行,修改源码后,中文就不会转换为16进制了。也没有什么乱码。
至此,遇到得问题已解决,在修改源码得情况下,目前还没有发现什么影响之处,如由朋友发现,请联系我lework[@]yeah.net
5. 总结
在遇到错误得时候,我们往往不知道该怎么搜索此类答案,我想大家应该都会把错误信息放在搜索引擎中搜索,关键字要随着搜索得到的信息从而不断变化,才能往根源得问题靠近。在搜索引擎给出的大量信息,要懂得抓取有用的信息,不能忽视已经给出问题答案的信息,即使信息比较久远。像阶段1得情况,我如果仔细阅读上面得解答信息,应该会很快得找到问题所在的根源。
作者:lework
链接:https://www.jianshu.com/p/8f8c2b5ca2d1
來源:简书
解决nginx在记录post数据时 中文字符转成16进制的问题【转载】的更多相关文章
- C#把汉字转换成16进制(HEX)并向串口发送数据
报警器实例:(有发送,无返回获取) using System; using System.Collections.Generic; using System.Linq; using System.Te ...
- C#将文件转成16进制码流写入数据库存起来,访问的时候再还原成PDF文件。
转自https://blog.csdn.net/liubowei_0312/article/details/53378146 适合将文件写入数据库,远程访问的时候还原1.首先把文件转成十六进制文件流 ...
- C# 发送16进制串口数据
一个困扰两天的问题:需要通过串口向设备发送的数据:0A010 7e 08 00 11 00 00 7e 76 7f我先将每个16进制字符转换成10进制,再将其转换成ASCII码对应的字符. /// & ...
- Android--字符串和16进制相互转化(解决中文乱码)
import java.io.ByteArrayOutputStream; /** * Created by Administrator on 2016/2/2. * -----------16进制和 ...
- PHP 通过Socket收发16进制数据
最近在php下做关于Socket通讯的相关内容,发现网络上好多人在了解如何进行16进制收发,研究了下,代码如下,欢迎拍砖. <?php $sendStr = '30 32 30 3 ...
- JDBC插入数据时中文变为问号的解决方法
JDBC插入数据时中文变为问号的解决方法 制作人:全心全意 出现中文变问号的代码: String url = "jdbc:mysql://localhost:3306/test"; ...
- curl提交数据时中文乱码
1.使用curl提交数据时中文乱码解决: <?php $testJSON=array('name'=>'中文字符串','value'=>'test'); foreach ( $tes ...
- Dos中查看mysql数据时 中文乱码
使用jsp页面查看数据时可以正确显示中文,但是dos窗口查看数据时中文显示乱码. 上网查了一下原因:之所以会显示乱码,就是因为MySQL客户端输出窗口显示中文时使用的字符编码不对造成的,可以使用如下的 ...
- mysql 恢复数据时中文乱码
mysql恢复数据时中文乱码,解决办法. 用source命令导入mysql数据库怎么设置中文编码 1.导出数据时指定编码在导出mysql sql执行文件的时候,指定一下编码格式: mysqldump ...
随机推荐
- Python中的global和nonlocal
在Python中,一个变量的scope范围从小到大分成4部分:Local Scope(也可以看成是当前函数形成的scope),Enclosing Scope(简单来说,就是外层函数形成的scope), ...
- Java中I/O流之Object流
Java 中的 object 流:直接将 Object 对象写入或读出 1. serializable 接口:序列化,可以被序列化的,若确实需要将某个类的对象写在硬盘上或网络上,想把他们序列化成一个字 ...
- Alpha 冲刺2
队名:日不落战队 安琪(队长) 今天完成的任务 组织第二次站立式会议. 完成40%个人信息前端界面. 明天的计划 完成剩下的60%个人信息前端界面. 还剩下的任务 个人信息修改前端界面. 遇到的困难 ...
- 面试中常用排序算法的python实现和性能分析
这篇是关于排序的,把常见的排序算法和面试中经常提到的一些问题整理了一下.这里面大概有3个需要提到的问题: 虽然专业是数学,但是自己还是比较讨厌繁琐的公式,所以基本上文章所有的逻辑,我都尽可能的用大白话 ...
- set类型没有单独取值功能 通过循环取值
set类型没有单独取值功能 通过循环取值
- 【bzoj5107】[CodePlus2017]找爸爸 dp
题目描述 给出两个基因串,你需要在其中插入任意个空格,使得两个串长度相同.如果两个串的某同一位置都是字母则获得某给定收益,对于每个串的每个长度为k的连续空格段要付出a(k-1)+b的损失.求最大净收益 ...
- 【bzoj1334】[Baltic2008]Elect 背包dp
题目描述 N个政党要组成一个联合内阁,每个党都有自己的席位数. 现在希望你找出一种方案,你选中的党的席位数要大于总数的一半,并且联合内阁的席位数越多越好. 对于一个联合内阁,如果某个政党退出后,其它党 ...
- HTML5语义元素总结
HTML5语义元素 语义=意义 语义元素=元素的意义 什么事语义元素? 一个语义元素能够清楚的描述其意义给浏览器和开发者. 无语义 元素实例:div.span.无需考虑内容. 语义 元素实例:fo ...
- 进程池-限制同一时间在CPU上运行的进程数
if __name__=='__main__' : 为了区分你是主动执行这个脚本,还是从别的地方把它当做一个模块去调用. 如果是主动执行,则执行.如果是调用的,则不执行主体. 1. 串行:切记切记: ...
- [NOI2017]蔬菜 贪心
题面: [NOI2017]蔬菜 题解: 首先每天蔬菜会变质这点并不好处理,我们考虑让时间倒流,从后向前处理,这样的话就相当于每天都会得到一定量的蔬菜. 这样做有什么好处呢? 我们可以发现一个性质:如果 ...