Apache+WSGI中文文件名导致HTTP请求返回500问题解决方法




问题症状

Centos7服务器上搭建了Apache服务,版本httpd-2.4.6-67.el7.centos.6.x86_64,配合mod_wsgi+python+flask搭建web网站。

用flask的render_template渲染html页面,并且用配置文件里的文件名和路径来生成文件下载链接,如果文件路径包含中文,会在请求页面时返回500响应码,而python main.py前台启动没有这个问题,改成英文文件名后Apache+WSGI启动方式也恢复正常。

相关代码如下所示:

# 服务支持页面
@app.route('/services', methods=['GET'])
def services():
    new_dict = {}
    for k, v in base_data['DOWNLOAD_DOC'].items():  ## 内容见下面代码段
        path = os.path.dirname(os.path.realpath(__file__))
        file_path = u"{0}{1}".format(path.decode('utf-8'), v)
        if os.path.exists(file_path):
            filemt = os.stat(file_path).st_ctime
            timeArray = time.localtime(filemt)
            new_dict[k] = {"path": v,
                           "upload_time": time.strftime("%Y-%m-%d", timeArray),
                           "type": os.path.splitext(file_path)[1].split(".")[1]}
    return render_template('/services.html',
                           download_doc_dict=new_dict)
{
  "DOWNLOAD_DOC":{"安装手册": "/static/doc/安装手册.pdf",
    "产品白皮书": "/static/doc/产品白皮书.pdf"},
}

解决方法

网上搜到很多方法都是说修改/etc/apache2/envvars文件,但新版本Apache已经没这个文件了,折腾了好久都没进展,偶然看了下Apache的systemd的启动脚本/usr/lib/systemd/system/httpd.service,发现里面有个EnvironmentFile配置项:

root@minikube website $ systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: active (running) since Fri 2018-04-27 17:34:32 CST; 14min ago
root@minikube website $ cat /usr/lib/systemd/system/httpd.service
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=man:httpd(8)
Documentation=man:apachectl(8)

[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/httpd   ###### 注意这行
ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND
root@minikube website $ cat /etc/sysconfig/httpd
......
#
# This setting ensures the httpd process is started in the "C" locale
# by default.  (Some modules will not behave correctly if
# case-sensitive string comparisons are performed in a different
# locale.)
#
LANG='en_US.UTF-8'   ### 注意这两行
LC_ALL='en_US.UTF-8'

原来是在这里配置的,尝试把原来的LANG=C改成上面两行,之后重启Apache服务,再访问出问题的页面,一切正常了,问题解决。