Django源碼分析之server
乍見
Django內置的server基本包括兩部分:django.core.servers和django.core.handlers
相識
servers.basehttp是Django自身提供的一個用於開發測試的server模塊,其中提供的WSGIServer、ServerHandler、WSGIRequestHandler其實都是屬於WSGI server,django只不過是對python內置的WSGI模塊simple_server做的一層包裝。
handlers package包括base.py和wsgi.py兩個模塊。
base.py中只定義了一個BaseHandler類,它復雜一些基礎的功能,比如加載中間件,處理異常,獲取響應數據等
wsgi.py才是主角,其中最重要的就是WSGIHandler類,它繼承了base.py中的BaseHandler,只添加了一個__call__方法,那為什麽添加這個方法呢?
django.core.wsgi
import django
from django.core.handlers.wsgi import WSGIHandler
def get_wsgi_application():
"""
The public interface to Django‘s WSGI support. Should return a WSGI
callable.
Allows us to avoid making django.core.handlers.WSGIHandler public API, in
case the internal WSGI implementation changes or moves in the future.
"""
django.setup()
return WSGIHandler()
可見我們啟動server時傳入的application其實是WSGIHandler的一個實例,而根據WSGI規範,這個application必須要是callable,python中的callable包括函數、方法以及任何定義了__call__方法的對象
回到handlers.wsgi
class WSGIHandler(base.BaseHandler):
initLock = Lock()
request_class = WSGIRequest
def __call__(self, environ, start_response):
# Set up middleware if needed. We couldn‘t do this earlier, because
# settings weren‘t available.
if self._request_middleware is None:
with self.initLock:
try:
# Check that middleware is still uninitialized.
if self._request_middleware is None:
self.load_middleware()
except:
# Unload whatever middleware we got
self._request_middleware = None
raise
set_script_prefix(get_script_name(environ))
signals.request_started.send(sender=self.__class__, environ=environ)
try:
request = self.request_class(environ)
except UnicodeDecodeError:
logger.warning(‘Bad Request (UnicodeDecodeError)‘,
exc_info=sys.exc_info(),
extra={
‘status_code‘: 400,
}
)
response = http.HttpResponseBadRequest()
else:
response = self.get_response(request)
response._handler_class = self.__class__
status = ‘%s %s‘ % (response.status_code, response.reason_phrase)
response_headers = [(str(k), str(v)) for k, v in response.items()]
for c in response.cookies.values():
response_headers.append((str(‘Set-Cookie‘), str(c.output(header=‘‘))))
start_response(force_str(status), response_headers)
if getattr(response, ‘file_to_stream‘, None) is not None and environ.get(‘wsgi.file_wrapper‘):
response = environ[‘wsgi.file_wrapper‘](response.file_to_stream)
return response
由於__call__是一個請求的入口,它需要調用BaseHandler中定義的方法去執行加載中間件等一系列操作和異常處理,除此之外,WSGIHandler還會處理cookie、觸發signal等。
至於如何返回響應,具體可看handlers.base模塊,大概就是找出請求的path,通過匹配路由,找到並執行用戶定義的view方法,執行中間件處理方法,最後返回響應。當然,還有一系列的異常處理。
回想
這部分的內容需要對WSGi協議有個大致的了解,可以參考:http://xiaorui.cc/2016/04/16/%E6%89%93%E9%80%A0mvc%E6%A1%86%E6%9E%B6%E4%B9%8Bwsgi%E5%8D%8F%E8%AE%AE%E7%9A%84%E4%BC%98%E7%BC%BA%E7%82%B9%E5%8F%8A%E6%8E%A5%E5%8F%A3%E5%AE%9E%E7%8E%B0/
Django源碼分析之server