WSGI:全称是Web Server Gateway Interface,WSGI不是服务器,也不用于与程序交互的API,更不是代码,而只是定义了一个接口,用于描述web server如何与web application通信的规范。
当客户端发送一次请求后,最先处理请求的实际上是 web 服务器就是我们经常说的 nginx、Apache 这类的 web 服务器,然后web服务器再把请求交给web应用程序(如django)处理,这中间的中介就是WSGI,它把 web 服务器和 web 框架 (Django) 连接起来。
for middleware_path in settings.MIDDLEWARE_CLASSES:
···
if hasattr(mw_instance, 'process_request'):
request_middleware.append(mw_instance.process_request)
if hasattr(mw_instance, 'process_view'):
self._view_middleware.append(mw_instance.process_view)
if hasattr(mw_instance, 'process_template_response'):
self._template_response_middleware.insert(0, mw_instance.process_template_response)
if hasattr(mw_instance, 'process_response'):
self._response_middleware.insert(0, mw_instance.process_response)
if hasattr(mw_instance, 'process_exception'):
self._exception_middleware.insert(0, mw_instance.process_exception)
我们可以从源码看出,process request 和 process response的执行加载顺序正好是相反,在循环中,process_request是被append到列表的末尾,而process_request是被insert到最前面的。
(可能有些情况Comment中间件在Session前面,了解加载的顺序就好了)
process_request
举几个中间件的例子
class CommonMiddleware(object):
# 伪代码
def process_request(self, request):
# Check for denied User-Agentsif'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')
host = request.get_host()
if settings.PREPEND_WWW and host and not host.startswith('www.'):
host = 'www.' + host
pass
class XFrameOptionsMiddleware(object):
def process_response(self, request, response):
# Don't set it if it's already in the responseif response.get('X-Frame-Options') is not None:
return response
# Don't set it if they used @xframe_options_exemptif getattr(response, 'xframe_options_exempt', False):
return response
response['X-Frame-Options'] = self.get_xframe_options_value(request,
response)
return response
class CsrfViewMiddleware(object):
def process_response(self, request, response):
if getattr(response, 'csrf_processing_done', False):
return response
if not request.META.get("CSRF_COOKIE_USED", False):
return response
# Set the CSRF cookie even if it's already set, so we renew# the expiry timer.
response.set_cookie(settings.CSRF_COOKIE_NAME,
request.META["CSRF_COOKIE"],
max_age=settings.CSRF_COOKIE_AGE,
domain=settings.CSRF_COOKIE_DOMAIN,
path=settings.CSRF_COOKIE_PATH,
secure=settings.CSRF_COOKIE_SECURE,
httponly=settings.CSRF_COOKIE_HTTPONLY
)
# Content varies with the CSRF cookie, so set the Vary header.
patch_vary_headers(response, ('Cookie',))
response.csrf_processing_done = True
return response