(十五)Flask覆写wsgi_app函数实现自定义中间件

中间件

一、剖析:

在前面讲session部分提到过:请求一进来,Flask会自动调用应用程序对象【Flask(__name__)】的__call__方法,这个方法负责处理请求并返回响应(其实如下图:其内部就是wsgi_app方法)。它是WSGI规范所要求的。

在这里插入图片描述

wsgi_app方法内部,Flask会根据路由规则和视图函数来确定如何处理请求,并生成相应的响应。最终,wsgi_app方法会将响应返回给Web服务器,供其发送给客户端(前面详细讲过,后面还会再细细剖析)。

所以,这里就有一个坑可以让我们操作,即我们可以通过覆写wsgi_app方法,实现自己的中间件逻辑,例如身份验证、日志记录等。

而且这个坑牛逼之处在于:我们可以借由它实现在最开始的开始和最后的最后做操作!!!多加理解,底下会详细讲解。

结合实战讲解—通过覆写wsgi_app函数实现一个简单的中间件:

from flask import Flask

app = Flask(__name__)


class MyMiddleware:
    def __init__(self, old_wsgi_app):
        # 服务端启动时,自动执行
        self.old_wsgi_app = old_wsgi_app

    def __call__(self, environ, start_response):
        # 每次有用户请求到来时执行
        # 在请求到达视图函数之前执行的代码
        print("Before request")

        # 调用原始的wsgi_app函数处理请求
        response = self.old_wsgi_app(environ, start_response)

        # 在响应发送给客户端之前执行的代码
        print("After request")

        return response


@app.route('/')
def home():
    return "Hello, GuHanZhe~"


# 设置自定义中间件实例为应用程序对象的wsgi_app属性
app.wsgi_app = MyMiddleware(app.wsgi_app)

if __name__ == '__main__':
    app.run()

在上述示例中,我定义了一个名为MyMiddleware的类,它接受一个Flask应用程序对象的wsgi_app方法作为参数。该类实现了__call__方法,这是一个wsgi应用程序必须具备的方法。在__call__方法中,大家可以编写自己的中间件逻辑。

__call__方法中,大家可以首先执行在请求到达视图函数之前需要执行的代码,然后调用原始的wsgi_app方法处理请求,并将响应保存在response变量中。最后,在响应发送给客户端之前,大家可以执行一些在响应阶段需要执行的代码。

通过创建自定义中间件实例,并将其设置为Flask应用程序对象的wsgi_app属性,就可以使用自定义的中间件了。

请注意,自定义中间件类必须实现__call__方法,并且接受environstart_response参数,这是遵守WSGI规范。

而且看Flask的wsgi_app函数源码,也是如此:

在这里插入图片描述

需要注意的是:在print("Before request")部分做操作时,只有原生的请求相关的数据environ,所以就只能对原生的environ做操作! request和session是都没有的!!!

二、应用点:

通过覆写wsgi_app函数实现的自定义中间件可以有如下几种在开发时的应用点:

  1. 可以对请求进行预处理:通过覆写wsgi_app函数,可以在请求到达视图函数之前执行一些代码逻辑,例如身份验证、参数解析、请求日志记录等。这样可以方便地对请求进行预处理,并根据需要做出相应的处理。

  2. 可以对响应进行后处理:同样地,在覆写wsgi_app函数时,还可以在响应发送给客户端之前执行一些代码逻辑,例如响应的加工、错误处理、响应日志记录等。这样可以方便地对响应进行后处理,以满足特定的需求。

  3. 可以实现自定义中间件功能:通过覆写wsgi_app函数,可以实现自定义的中间件功能。中间件是一种可重用的组件,可以用于添加额外的逻辑或修改请求/响应的行为。可以根据具体需求编写自己的中间件,并将其插入Flask应用程序对象的处理流程中。

  4. 可以实现多个中间件的串联:Flask允许使用多个中间件,并且这些中间件可以按照特定的顺序串联起来。通过覆写wsgi_app函数,可以轻松地将多个中间件组合起来,形成一个中间件链条。每个中间件都可以独立地处理请求和响应,并将处理结果传递给下一个中间件。

  5. 可以修改请求和响应:通过覆写wsgi_app函数,可以自由地修改请求和响应对象。这包括添加、删除或修改请求头部信息,修改请求体内容,修改响应状态码,添加响应头部信息等。这样可以实现更加灵活和定制化的请求/响应处理。

总而言之,覆写wsgi_app函数实现中间件提供了对请求和响应进行预处理和后处理的能力,同时也允许编写自定义的中间件功能。这样可以增强Flask应用程序的功能和灵活性,满足特定的需求。

就比如要做IP黑名单,就可以在before里直接写逻辑(environ里有请求IP信息),这样就可以在最开始的开始直接限制!

拓展:

(1)在Python中,当一个对象后面能加括号,那么这个对象可能是什么?

  1. 函数:一个函数是可调用的对象。通过在函数名后加上括号,可以执行该函数并传递相应的参数。

  2. 方法:方法是属于类的函数。通过在实例或类名后加上括号,可以调用该方法并传递相应的参数。

  3. 类:类本身也是可调用的对象。通过在类名后加上括号,可以创建类的实例。

  4. 对象:某个类的实例对象也可以是可调用的对象。通过在对象名后加上括号,可以调用该对象所属类中定义的特殊方法,例如__call__()方法。

(2)在Python中,函数和方法分别是什么?

首先,要认识到在Python中,函数(function)和方法(method)是两种不同的概念。这也是为啥我给的问题是“函数和方法分别是什么?”

  1. 函数(function)是一段封装了特定功能的可重用代码块。它接收输入参数,执行特定的操作,并返回结果。 函数可以在任何地方定义和使用,不依赖于任何类或对象。它们通常用于模块化代码、提高代码的复用性和可维护性。

    例如,下面是一个简单的函数示例:

def add(a, b):
    return a + b


result = add(2, 3)
print(result)  
  1. **方法(method)是属于某个类的函数。**它定义在类的内部,并且可以访问类的属性和其他方法。**方法通过对类的实例进行调用来执行相应的操作。**每个方法的第一个参数通常都是 self,它表示方法所属的实例对象。

    例如,下面是一个简单的类和方法示例:

class Circle:
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14 * self.radius * self.radius

circle = Circle(5)
circle_area = circle.area()
print(circle_area)  # 输出:78.5

在上面的示例中,area()Circle 类的一个方法,它可以通过 circle.area() 的方式进行调用。

需要注意的是,对于一个类里面的函数,它究竟真是函数还是方法,取决于谁调用它!!!

举个例子:

在这里插入图片描述

上图中Test.index执行的话,此时index作为函数,意思是执行类里面的函数;

而下面是通过类的实例调用,所以此时是方法。

或者这样也能证明:

from types import MethodType, FunctionType

class Test(object):
    def index(self):
        pass


# print(Test.index)
print(isinstance(Test.index, FunctionType))

test = Test()
# print(test.index)
print(isinstance(test.index, MethodType))

在这里插入图片描述

总结:函数是独立的可调用代码块,而方法是属于类的函数,需要通过类的实例进行调用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/226166.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【重磅来袭!!!工程师必备初始化建工程软件】

重磅来袭!!!工程师必备初始化软件 每个工程建立前,你是否为了要建立各种文件夹而烦恼?你是否为了因为工程每次文件夹不统一找不到文件而烦扰?来咯,Project Initial V1_0软件只需输入工程名称&am…

安装you-get(mac)

1、首先要有python环境 2、更新pip python -m pip install --upgrade pip 3、安装you-get pip install you-get;

keep-alive 是 Vue 的一个内置组件,用于缓存其他组件的实例,以避免重复渲染和销毁,它可以在需要频繁切换的组件之间提供性能优化

目录 keep-alive 使用 keep-alive 的示例代码: 手动清除组件缓存的示例代码: keep-alive 组件有以下几个优点: keep-alive 的原理: 使用 keep-alive 组件,你可以包裹需要缓存的组件,然后这些组件在切…

基于ssm安徽新华学院实验中心管理系统论文

摘 要 本安徽新华学院实验中心管理系统的设计目标是实现安徽新华学院实验中心的信息化管理,提高管理效率,使得安徽新华学院实验中心管理工作规范化、科学化、高效化。 本文重点阐述了安徽新华学院实验中心管理系统的开发过程,以实际运用为开…

Pytest+Allure生成自动化测试报告!

前言 在自动化测试中,有unittestHTMLTestRunner自动化测试报告,但是生成的测试报告不够美观详细,今天我们来学习一下PytestAllure生成自动化测试报告。 一:安装python中的allure依赖库 在dos窗口中,输入下面三个命令…

AntDesignBlazor示例——创建查询条件

本示例是AntDesign Blazor的入门示例,在学习的同时分享出来,以供新手参考。 示例代码仓库:https://gitee.com/known/AntDesignDemo 1. 学习目标 重构项目文件结构添加日期查询条件实现查询业务逻辑 2. 重构项目结构 在实现列表查询条件功…

【PCB设计】嘉立创EDA器件3D模型导入AD的方法

嘉立创EDA器件3D模型导入AD的方法 一、嘉立创EDA导出3D模型二、CAD编辑3D模型三、AD中加载3D模型 一、嘉立创EDA导出3D模型 在嘉立创EDA中找到对应的元器件,并生成PCB,选择导出3D文件 导出元件step模型 二、CAD编辑3D模型 用FreeCAD打开模型 删除…

JAVA全栈开发 MySql详解

一、数据库 1.数据储存在哪里? 硬盘、网盘、U盘、光盘、内存(临时存储) 数据持久化 使用文件来进行存储,数据库也是一种文件,像excel ,xml 这些都可以进行数据的存储,但大量数据操作&#x…

学习设计模式的一个好网址

常用设计模式有哪些? (refactoringguru.cn)https://refactoringguru.cn/design-patterns

elasticsearch-head 启动教程

D:\elasticsearch-head-master>grunt server ‘grunt’ 不是内部或外部命令,也不是可运行的程序 或批处理文件。 npm install -g grunt-clinpm install

经历需求放缓,裁员1.7万人后,亚马逊股票还值得投资吗?

来源:猛兽财经 作者:猛兽财经 亚马逊再次实现增长 尽管在疫情期间,很多电子商务公司都发展的很迅猛,但根据Statista的数据,亚马逊(AMZN)依然保持着对竞争对手的碾压,亚马逊目前约占美国电子商务市场总份额…

全志XR806蓝牙透传(单向)测试

评测三 蓝牙透传(单向) 有时无线透传在无法布线时有很方便的效用,不妨试试蓝牙透传,效果如下: 具体是无线数据->串口数据,串口数据->无线数据,目前前者实现了,后者还有些问题未解决, 实现…

每日一练:插入排序

1. 概念及原理 插入排序是一种简单直观的排序算法,其基本思想是将一个元素插入到已经排序好的部分,然后不断地重复这个过程,直到整个数组有序。下面是插入排序的算法原理: 初始状态: 数组被分为已排序和未排序两个部分…

2、RocketMQ源码分析(二)

RocketMQ的底层通信模块remoting remoting是RocketMQ的底层通信模块,RocketMQ底层通讯是使用Netty来实现的。本文通过对remoting源码进行分析,来说明remoting如何实现高性能通信的。 二、Remoting 通信模块结构 remoting 的网络通信是基于 Netty 实现&…

基于OpenCV+CNN+IOT+微信小程序智能果实采摘指导系统——深度学习算法应用(含pytho、JS工程源码)+数据集+模型(四)

目录 前言总体设计系统整体结构图系统流程图 运行环境Python环境TensorFlow 环境Jupyter Notebook环境Pycharm 环境微信开发者工具OneNET云平台 模块实现1. 数据预处理2. 创建模型并编译3. 模型训练及保存1)模型训练2)模型保存 4. 上传结果1)…

刷题学习记录(文件上传)

[GXYCTF 2019]BabyUpload 知识点&#xff1a;文件上传.htaccessMIME绕过 题目直接给题目标签提示文件上传的类型 思路&#xff1a;先上传.htaccess文件&#xff0c;在上传木马文件&#xff0c;最后蚁剑连接 上传.htaccess文件 再上传一个没有<?的shell 但是要把image/pn…

生态学、种间关系、进化

这里写自定义目录标题 参考资料种间关系Lynn Margulis共生体在进化过程中形成了一种互帮互助的机制 捕食&#xff1a;收割理论 进化思想史 参考资料 Symbiotic Communications: Where Marconi Meets Darwin 普通生态学(孙儒泳)高等教育出版社1998普通生态学(尚玉昌)北京大学出…

AUTOSAR 入门

前言 AUTOSAR是什么Vector DaVinci 工具功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个注脚注释也是必…

Weblogic CVE-2023-21839(metasploit版)

Step1&#xff1a;用docker搭建环境 Step2&#xff1a;docker查看映射端口 Step3&#xff1a;访问特定端口&#xff0c;然后靶标应用。 Step4&#xff1a;用metasploit进行攻击&#xff1a; 首先&#xff0c;打开metasploit&#xff0c;然后查询需要攻击的板块&#xff0…

【绘图工具】-- Excalidraw 介绍

1、Excalidraw 的来源 Excalidraw 的作者 vjeux 是 facebook 团队的成员&#xff0c;项目在开始阶段就是就是以开源的方式推进&#xff08;现在也开源&#xff0c;只是商业版本才收费&#xff09;&#xff0c;当时作者在 Twitter 上发了一些推文介绍了&#xff0c;然后引起了许…