• Django 分析(一)Requst、Middleware 和 Response 数据流


    0. 前言

    • 通过 Django 编写 HTTP 接口时,我们需要指定 URL、Model 和 Views 函数(或者指定 RESTBaseView 对象解析参数和编写逻辑)
    • 编写逻辑时的基本思路就是解析 Request 对象 → 逻辑处理 → 返回 Response 对象
    • RESTBaseView 对象封装了这一逻辑,我们只需要指定参数、解析方、处理逻辑和返回值即可

    1. 基本概念 

    1.1 WSGI

    • WSGI:是 python web 开发的标准,类似于协议
      • 它是服务器程序和应用程序的一个约定,规定了各自使用的接口和功能,以便二和互相配合
      • WSGI 处理程序充当服务器(Apache、Nginx 等)和应用程序(Django)之间的守门员
    • Python web开发中,服务端程序可分为2个部分:
      • 服务器程序(用来接收、整理客户端发送的请求)
      • 应用程序(处理服务器程序传递过来的请求)
    • 在开发应用程序的时候,我们会把常用的功能封装起来,成为各种框架,比如Flask、Django 和 Tornado(使用某框架进行 web 开发,相当于开发服务端的应用程序,处理后台逻辑)
    • 但是,服务器程序和应用程序互相配合才能给用户提供服务,而不同应用程序(不同框架)会有不同的函数、功能
    • 此时,我们就需要一个标准,让服务器程序和应用程序都支持这个标准,那么,二者就能很好的配合了

    1.2 中间件

    • 中间件被用在 Django 项目中的许多关键功能中,例如:
      • 使用 CSRF 中间件来防止跨站请求伪造攻击
      • 处理会话数据
      • 身份验证和授权是使用中间件完成的
    • 服务器和应用程序之间是中间件,可以将中间件视为一系列双向过滤器:
      • 要么对来自用户的数据进行预处理,然后发送给应用
      • 要么在应用将响应负载返回给用户之前,对结果数据进行一些最终的调整
    MIDDLEWARE_CLASSES = (
        'django.middleware.common.CommonMiddleware',
        'session_pyclient.account.django_middleware.AccountSessionMiddleware',
        # 'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'django.middleware.security.SecurityMiddleware',
    )
    • 中间件可以定义五个方法,分别是:(主要的是 process_request 和 process_response)

    process_request(self,request)
    process_view(self, request, view_func, view_args, view_kwargs)
    process_template_response(self,request,response)
    process_exception(self, request, exception)
    process_response(self, request, response) 
    • 以上方法的返回值可以是 None 或一个 HttpResponse 对象:
      • 如果是 None,则继续按照 Django 定义的规则向后继续执行
      • 如果是 HttpResponse 对象,则直接将该对象返回给用户
    from django.utils.deprecation import MiddlewareMixin
    
    
    class MD1(MiddlewareMixin):
    
        def process_request(self, request):
            print("MD1里面的 process_request")
    
        def process_response(self, request, response):
            print("MD1里面的 process_response")
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print("-" * 80)
            print("MD1 中的process_view")
            print(view_func, view_func.__name__)
    
    
    class MD2(MiddlewareMixin):
        def process_request(self, request):
            print("MD2里面的 process_request")
            pass
    
        def process_response(self, request, response):
            print("MD2里面的 process_response")
            return response
    
        def process_view(self, request, view_func, view_args, view_kwargs):
            print("-" * 80)
            print("MD2 中的process_view")
            print(view_func, view_func.__name__) 
    • process_request:有一个参数,就是 request,这个 request 和 Views 函数中的 request 是一样的
      • 中间件的 process_request 方法是在执行 Views 函数之前执行的
      • 当配置多个中间件时,会按照 MIDDLEWARE 中的注册顺序,也就是列表的索引值,从前到后依次执行的。
      • 不同中间件之间传递的 request 都是同一个对象
      • 返回值可以是 None 也可以是 HttpResponse 对象。返回值是 None 的话,按正常流程继续走,交给下一个中间件处理
      • 如果是 HttpResponse 对象,Django 将不执行视图函数,而将相应对象返回给浏览器
    • process_response:有两个参数,一个是 request,一个是 response。
      • request 就是上述例子中一样的对象,response 是 Views 函数返回的 HttpResponse 对象。该方法的返回值也必须是 HttpResponse 对象
      • 中间件的 process_response 方法是按照 MIDDLEWARE 中的注册顺序倒序执行的
      • 该方法的返回值也必须是 HttpResponse 对象
    • process_view:该方法有四个参数:
      • request 是HttpRequest对象
      • view_func:是Django即将使用的 Views 函数
      • view_args:是将传递给 Views 的位置参数的列表
      • view_kwargs:是将传递给 Views 的关键字参数的字典。 view_args 和 view_kwargs 都不包含第一个 Views 参数(request)
      • process_view 方法是在 process_request 之后,视图函数之前执行的,执行顺序按照 MIDDLEWARE 中的注册顺序从前到后顺序执行的
      • Django 会在调用 Views 函数之前调用 process_view 方法。它应该返回 None 或一个 HttpResponse 对象
        • 如果返回 None,Django 将继续处理这个请求,执行任何其他中间件的 process_view 方法,然后在执行相应的 Views
        • 如果它返回一个 HttpResponse 对象,Django 不会调用适当的 Views 函数。 它将执行中间件的 process_response 方法并将应用到该 HttpResponse 并返回结果
    • process_exception:有两个参数,一个是 request,一个是 exception。exception 是视图函数异常产生的 Exception 对象
      • 这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个 None 也可以是一个 HttpResponse 对象
        • 如果是 HttpResponse 对象,Django 将调用模板和中间件中的 process_response 方法,并返回给浏览器,否则将默认处理异常
        • 如果返回一个 None,则交给下一个中间件的 process_exception 方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行
    • process_template_response:用的比较少,暂不介绍
    • 基本过程如下:

    2. 数据流

    • 启动一个 Django 项目的时候,需要执行 'runserver' 的操作,而 ruserver 是使用 Django 自带的的 Web Server,主要用于开发和调试中,而在正式的环境中,一般会使用 Nginx+uwsgi 模式
    • 无论是哪种方式,当启动一个项目,都会做两件事:
      • 首先创建一个WSGIServer类的实例,接受用户的请求
      • 然后当一个用户的 HTTP 请求到达的时,为用户初始化一个 WSGIHandler,用于处理用户请求与响应,这个 Handler 是处理整个 Request 的核心
    • Handler 从请求到相应处理流程如下:

    3. 参考文献

  • 相关阅读:
    开源的UML建模工具
    leetcode 559. Maximum Depth of N-ary Tree
    leetcode 9. Palindrome Number
    暗网 tor溯源困难根因——用户的请求会在分布全球的主机随机跳转三次,最终才到达服务器,这就造成了溯源的极其困难
    leetcode 374. Guess Number Higher or Lower
    RDP协议暴力破解
    清华大学 pip 源
    暴力破解研究论文
    利用ModSecurity防御暴力破解
    IRC BOT原来是利用IRC下发C&C命令——在xx云环境遇到了,恶意软件开的是6666端口
  • 原文地址:https://www.cnblogs.com/wangao1236/p/10900301.html
Copyright © 2020-2023  润新知