1. 簡述Http協議? - 超文本傳輸協議 - 特色: - 無狀態,請求響應以後,再次發起請求時,不認識。 - 短鏈接,一次請求和一次響應就斷開鏈接。 - 格式: - GET請求:輸入地址回車:https://passport.jd.com/new/login.aspx?ReturnUrl=https%3A%2F%2Fwww.jd.com%2F 請求由兩部分組成:請求頭和請求體,請求頭和請求體經過\r\n\r\n分割,請求頭和請求頭之間經過\r\n分割。 """GET /new/login.aspx?ReturnUrl=https%3A%2F%2Fwww.jd.com%2F http1.1\r\nUser-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36\r\nHost:jd.com\r\n\r\n""" 響應由兩部分組成:響應頭和響應體, b'HTTP/1.1 200 OK\r\nDate: Mon, 05 Nov 2018 01:15:31 GMT\r\nServer: Apache\r\nLast-Modified: Tue, 12 Jan 2010 13:48:00 GMT\r\nETag: "51-47cf7e6ee8400"\r\nAccept-Ranges: bytes\r\nContent-Length: 81\r\nCache-Control: max-age=86400\r\nExpires: Tue, 06 Nov 2018 01:15:31 GMT\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n <html><head> .... </html>' - POST請求: 請求由兩部分組成:請求頭和請求頭 """POST /new/login.aspx?ReturnUrl=https%3A%2F%2Fwww.jd.com%2F http1.1\r\nUser-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36\r\nHost:jd.com\r\n\r\nusername=haoxu666&password=123""" 響應: b'HTTP/1.1 200 OK\r\nDate: Mon, 05 Nov 2018 01:15:31 GMT\r\nServer: Apache\r\nLast-Modified: Tue, 12 Jan 2010 13:48:00 GMT\r\nETag: "51-47cf7e6ee8400"\r\nAccept-Ranges: bytes\r\nContent-Length: 81\r\nCache-Control: max-age=86400\r\nExpires: Tue, 06 Nov 2018 01:15:31 GMT\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n用戶名或密碼錯誤' 2. 你瞭解的請求頭都有什麼? - User-Agent,設備信息。 - Host,當前訪問的主機名稱。 - referrer,作防盜鏈。 - Content-Type: .... 3. 你瞭解的請求方式有哪些? - GET/POST/PUT/PATCH/DELETE/OPTIONS 4. django請求的生命週期/瀏覽器上輸入 http://www.oldboyedu.com 地址回車發生了什麼? - 瀏覽器輸入:http://www.oldboyedu.com 回車 - DNS解析,將域名解析成IP。 - 瀏覽器(socket客戶端),根據IP和端口(80)建立鏈接,發送請求。 - 服務端接收請求 - 實現了wsgi協議的模塊,如:wsgiref接收到用戶請求。 - 而後將請求轉交給django的中間件,執行中間件的process_request(process_view)。 - 路由系統進行路由匹配。 - 匹配成功執行視圖函數,視圖函數進行業務處理(ORM操做數據+模板渲染) - 交給中間件的process_response方法 - wsigref的socket.send,將結果返回給瀏覽器。 - 斷開socket鏈接。 - 瀏覽器斷開鏈接。 詳細:見django請求生命週期圖 5. 什麼是wsgi? wsgi,web服務網關接口,他是一套協議。 實現wsgi協議有: - wsgiref - uwsgi 實現wsgi協議的全部的模塊本質:socket服務端。 6. django中間件的做用?應用場景? 中間件,能夠對全部請求進行批量操做。 應用場景: - 本身玩 - 記錄日誌 - IP黑名單 - 權限系統中的權限校驗 - 解決跨域:編寫一箇中間件,在中間件中定義一個process_response,添加一個響應頭(CORS,跨站資源共享) - 用戶登陸 - csrf_token驗證(django內置功能) 細節: - 5個方法:process_request/process_response + 3 - 執行流程 正常流程: - 全部process_request - 全部process_view - 全部process_response 非正常流程: - django 1.10及之後:平級返回 - django 1.10之前:找到最後的process_response - 寫代碼時,若是忘記方法名稱或方法參數個數,怎麼辦? - 任意導入一個源碼查看,如: # from django.middleware.common import CommonMiddleware MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] - 執行流程是如何實現的? 將中間件的相關方法添加到對應的 5個列表中,之後循環執行(順序、倒序) 源碼:
class BaseHandler(object): def __init__(self): self._request_middleware = None self._view_middleware = None self._template_response_middleware = None self._response_middleware = None self._exception_middleware = None self._middleware_chain = None def load_middleware(self): """ Populate middleware lists from settings.MIDDLEWARE (or the deprecated MIDDLEWARE_CLASSES). Must be called after the environment is fixed (see __call__ in subclasses). """ self._request_middleware = [] self._view_middleware = [] self._template_response_middleware = [] self._response_middleware = [] self._exception_middleware = [] if settings.MIDDLEWARE is None: warnings.warn( "Old-style middleware using settings.MIDDLEWARE_CLASSES is " "deprecated. Update your middleware and use settings.MIDDLEWARE " "instead.", RemovedInDjango20Warning ) handler = convert_exception_to_response(self._legacy_get_response) for middleware_path in settings.MIDDLEWARE_CLASSES: mw_class = import_string(middleware_path) try: mw_instance = mw_class() except MiddlewareNotUsed as exc: if settings.DEBUG: if six.text_type(exc): logger.debug('MiddlewareNotUsed(%r): %s', middleware_path, exc) else: logger.debug('MiddlewareNotUsed: %r', middleware_path) continue if hasattr(mw_instance, 'process_request'): self._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) else: handler = convert_exception_to_response(self._get_response) for middleware_path in reversed(settings.MIDDLEWARE): middleware = import_string(middleware_path) try: mw_instance = middleware(handler) except MiddlewareNotUsed as exc: if settings.DEBUG: if six.text_type(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 ) 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
- 根據字符串的形式導入模塊 + 根據反射找到模塊中的成員 總結: 特色: - 全部請求都要經過中間件 - 5個方法 - 5個方法的執行流程 - 正常 - 不正常(版本區別) 應用場景: - 本身玩: - IP黑名單限制 - 日誌 - 工做場景: - 權限控制 - 跨域 - 登陸 - CSRF 相關知識點: - 流程實現原理:列表+列表翻轉 - 根據字符串的形式導入模塊+反射