问题描述:开发项目 前端antd pro,后端django。在本地进行开发时,路由一切正常,但是将其部署到服务器后,有几个url不能正常访问。
一个斜杠引发的血案
由于前端的请求需要经过uwsgi转发到后台django,首先查看uwsgi日志,发现如下记录:
[pid: 9313|app: 0|req: 2/2] 127.0.0.1 () {48 vars in 913 bytes} [Tue Jul 2 14:38:20 2019] GET /get_user_list => generated 0 bytes in 1 msecs (HTTP/1.0 301) 3 headers in 120 bytes (1 switches on core 0)
主要注意(HTTP/1.0 301),说明该请求被重定向了。
最后经过分析,发现请求在经过真正的后台路由之前,会经过一系列的django中间件处理,如果其中有什么错误的话,该请求就会被重定向。
修改中间件源码(主要是输出一些调试信息),主要是中间件的process_request(self, request)函数。最后发现,在最后面决定是否重定向的时候,path与request.get_full_path()之间相差一个斜杠,从而导致了重定向。。。。
def process_request(self, request):
"""
Check for denied User-Agents and rewrite the URL based on
settings.APPEND_SLASH and settings.PREPEND_WWW
"""
# Check for denied User-Agents
if 'HTTP_USER_AGENT' in request.META:
for user_agent_regex in settings.DISALLOWED_USER_AGENTS:
if user_agent_regex.search(request.META['HTTP_USER_AGENT']):
raise PermissionDenied('Forbidden user agent')
# Check for a redirect based on settings.PREPEND_WWW
host = request.get_host()
must_prepend = settings.PREPEND_WWW and host and not host.startswith('www.')
redirect_url = ('%s://www.%s' % (request.scheme, host)) if must_prepend else ''
# Check if a slash should be appended
if self.should_redirect_with_slash(request):
path = self.get_full_path_with_slash(request)
else:
path = request.get_full_path()
# Return a redirect if necessary
if redirect_url or path != request.get_full_path():
redirect_url += path
return self.response_redirect_class(redirect_url)
为什么在本地进行开发时没有错误呢???
因为本地使用的django1.8,而服务器上使用的是django1.11.20,它们中间件的代码不一样,从而引发了关于一条斜杠的惨案。
在django1.8中,访问/xxx会被重定向到/xxx/上,而1.11版本则也会重定向到/xxx/,但返回的却是空。
1.8:
[02/Jul/2019 17:42:15]"GET /get_user_list?offset=0&limit=15 HTTP/1.1" 301 0
[02/Jul/2019 17:42:16]"GET /get_user_list/?offset=0&limit=15 HTTP/1.1" 200 1344
1.11
[pid: 15633|app: 0|req: 5/5] 127.0.0.1 () {48 vars in 913 bytes} [Tue Jul 2 18:04:10 2019] GET /get_user_list => generated 0 bytes in 0 msecs (HTTP/1.0 301) 5 headers in 163 bytes (1 switches on core 0)