Python CGIHTTPServer是否会将URL中的加号(+)解码为空格?表单提交QUERY_STRING异常问题咨询
Python CGIHTTPServer对URL加号(+)的解码行为解析
我来帮你理清这个问题的来龙去脉:
1. 你看到的行为是CGIHTTPServer的固有逻辑,但不符合表单编码规范
你观察到的现象是Python 2.7版本CGIHTTPServer的正常表现,但从HTTP表单编码的标准来看,这个处理是不严谨的。
背后的细节:
- 当浏览器处理
GET表单(默认用application/x-www-form-urlencoded编码)时,会遵循规则:- 空格被编码成
+ - 特殊字符(包括
+本身)会被转成%XX格式(比如+→%2B,=→%3D)
- 空格被编码成
- 但你提供的CGIHTTPServer代码里,用的是
urllib.unquote()(第167行),而不是专门处理表单编码的urllib.unquote_plus():urllib.unquote()只会解码%XX格式的字符,不会把+转换成空格urllib.unquote_plus()才会同时处理%XX解码和+转空格的逻辑
你看到QUERY_STRING是aaa++=,本质是浏览器发送的编码内容(比如PlainText=+aaa+%2B+%3D)被CGIHTTPServer解码后,%2B变回了+,而原本代表空格的+被保留了下来,所以最终参数值变成了aaa++=。
2. 如何正确获取输入的空格?
有两个可行的解决办法:
办法一:在CGI脚本中手动修正
在你的encry.sh里,先把所有+替换成空格,再解码%XX格式的字符。比如用bash结合Python来处理:
# 先替换+为空格,再解码URL编码字符 decoded_query=$(echo "$QUERY_STRING" | sed 's/+/ /g' | python -c "import urllib, sys; print urllib.unquote(sys.stdin.read().strip())") # 提取PlainText参数的值 plain_text=$(echo "$decoded_query" | grep -oP 'PlainText=\K.*')
办法二:修改CGIHTTPServer的实现
找到系统里的/usr/lib64/python2.7/CGIHTTPServer.py,做两处修改:
- 第87行:把
urllib.unquote改成urllib.unquote_pluscollapsed_path = _url_collapse_path(urllib.unquote_plus(self.path)) - 第167行:同样把
urllib.unquote改成urllib.unquote_plusuqrest = urllib.unquote_plus(rest)
修改前记得备份原文件,避免影响其他依赖该模块的程序。
3. 后续版本是否修复了这个问题?
是的,这个问题在Python 3中已经被彻底修复:
- Python 3里没有单独的
CGIHTTPServer模块,功能整合到了http.server中 - 处理URL和查询字符串时,默认使用
urllib.parse.unquote_plus(),会自动把+转换成空格,完全符合HTTP表单编码规范
另外提醒一下:Python 2.7早在2020年就停止维护了,无论是安全性还是兼容性都没有保障,建议尽快迁移到Python 3版本。
内容的提问来源于stack exchange,提问作者Qiu Yangfan
相关产品推荐
相关产品推荐

