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 相关知识点: - 流程实现原理:列表+列表翻转 - 根据字符串的形式导入模块+反射