Django之resquest进入中间件《一》
Posted zengmu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django之resquest进入中间件《一》相关的知识,希望对你有一定的参考价值。
class WSGIHandler(base.BaseHandler): request_class = WSGIRequest def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs)
#在wsgihandler生成实例时,在__init__魔方方法里面就进行了加载中间件 self.load_middleware() def __call__(self, environ, start_response): set_script_prefix(get_script_name(environ)) signals.request_started.send(sender=self.__class__, environ=environ)
#封装成request对象 request = self.request_class(environ) response = self.get_response(request) response._handler_class = self.__class__ status = ‘%d %s‘ % (response.status_code, response.reason_phrase) response_headers = [ *response.items(), *((‘Set-Cookie‘, c.output(header=‘‘)) for c in response.cookies.values()), ] start_response(status, response_headers) if getattr(response, ‘file_to_stream‘, None) is not None and environ.get(‘wsgi.file_wrapper‘): # If `wsgi.file_wrapper` is used the WSGI server does not call # .close on the response, but on the file wrapper. Patch it to use # response.close instead which takes care of closing all files. response.file_to_stream.close = response.close response = environ[‘wsgi.file_wrapper‘](response.file_to_stream, response.block_size) return response
load_middleware函数:
def load_middleware(self): """ Populate middleware lists from settings.MIDDLEWARE. Must be called after the environment is fixed (see __call__ in subclasses). """ self._view_middleware = [] self._template_response_middleware = [] self._exception_middleware = []
# 封装 这个时候就已经把slef._get_response函数绑定到了装饰器的inner函数上面 handler = convert_exception_to_response(self._get_response) for middleware_path in reversed(settings.MIDDLEWARE): middleware = import_string(middleware_path) try:
"""遍历中间件,通过下面的黄色标记并在中间件类上层层包裹上一级中间件,通过类的__call__魔方方法达到动态添加装饰器的效果,
每个中间件中的process_request方法对进来的request进行合法检验; process_response对核心函数self._get_response执行后返回的response进行验证""" mw_instance = middleware(handler) except MiddlewareNotUsed as exc: if settings.DEBUG: if str(exc): logger.debug(‘MiddlewareNotUsed(%r): %s‘, middleware_path, exc) else: logger.debug(‘MiddlewareNotUsed: %r‘, middleware_path) continue if mw_instance is None: raise ImproperlyConfigured( ‘Middleware factory %s returned None.‘ % middleware_path )
#在加载中间件时,将核心对view,response进行检验的钩子函数添加到列表中,为下一步检验做准备 if hasattr(mw_instance, ‘process_view‘): self._view_middleware.insert(0, mw_instance.process_view) if hasattr(mw_instance, ‘process_template_response‘): self._template_response_middleware.append(mw_instance.process_template_response) if hasattr(mw_instance, ‘process_exception‘): self._exception_middleware.append(mw_instance.process_exception) handler = convert_exception_to_response(mw_instance) # We only assign to this when initialization is complete as it is used # as a flag for initialization being complete. self._middleware_chain = handler
进入get_response()函数
def get_response(self, request): """Return an HttpResponse object for the given HttpRequest.""" # Setup default url resolver for this thread set_urlconf(settings.ROOT_URLCONF)
#根据程序上下文 找到 slef._middleware_chain = handler= convert_exception_to_response(middlerinstance)
而且这个handler 是一个装饰器
response = self._middleware_chain(request) response._resource_closers.append(request.close) if response.status_code >= 400: log_response( ‘%s: %s‘, response.reason_phrase, request.path, response=response, request=request, ) return response
当运行self._middleware_chain(request),会先进行上述我们添加的中间件类中的process_request方法对request中的首部关键字进行合法性检验,然后调用核心函数self._get_response():
ps:这与我们在setting中定义的middleware是一致顺序,因为在加载的时候用的reverse函数,和多层装饰器执行顺序一样,是一个后进先出的栈的效果:
总结就是:serverhandler实例化时,就会加载中间件,将核心函数self._get_response()AOP修饰各种中间件函数保存到列表里面为下一步认证做准备,然后通过中间件类的回调方法实现动态添加各种中间件类的process_request方法装饰核心函数-------成为一个多层装饰器。
所以当调用get_response时,会先进行一些列的process_request认证,然后才开始执行核心函数self._get_response()
以上是关于Django之resquest进入中间件《一》的主要内容,如果未能解决你的问题,请参考以下文章
在 django 中间件中使用 HTTP HttpResponsePermanentRedirect 时站点进入重定向循环