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

中间件

一、剖析:

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

在这里插入图片描述

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

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

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

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

from flask import Flaskapp = Flask(__name__)class MyMiddleware:def __init__(self, old_wsgi_app):# 服务端启动时,自动执行self.old_wsgi_app = old_wsgi_appdef __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 + bresult = add(2, 3)
print(result)  
  1. **方法(method)是属于某个类的函数。**它定义在类的内部,并且可以访问类的属性和其他方法。**方法通过对类的实例进行调用来执行相应的操作。**每个方法的第一个参数通常都是 self,它表示方法所属的实例对象。

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

class Circle:def __init__(self, radius):self.radius = radiusdef area(self):return 3.14 * self.radius * self.radiuscircle = Circle(5)
circle_area = circle.area()
print(circle_area)  # 输出:78.5

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

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

举个例子:

在这里插入图片描述

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

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

或者这样也能证明:

from types import MethodType, FunctionTypeclass 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.rhkb.cn/news/217021.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【抄作业】ImportError :cannot import name xxxxxx ,原博主Activewaste

前情介绍 网上关于这种问题的解决方案一大堆,但是绝大多数都是不适用,或者说解决不了问题,我根据别人所遇到的和我自己遇到的,对这个问题整理了一下,希望能解决这个问题。 问题分析 一、缺少这个module或者func或者p…

【C++】C++中的String类详解及模拟实现示例

文章目录 string类简介string类的基本用法string类的常用方法string类的优势 string类的模拟实现存储结构头文件string.h源文件string.cpp源文件test.cpp string类简介 string类简介在C编程中,字符串是一种非常常见的数据类型,用于存储文本信息。C标准库…

我的网站服务器被入侵了该怎么办?

最近有用户咨询到德迅云安全,说自己再用的网站服务器遇到了入侵情况,询问该怎么处理入侵问题,有什么安全方案可以解决服务器被入侵的问题。下面,我们就来简单讲下服务器遇到入侵了,该从哪方面入手处理,在预…

全球化需要先搬离中国?中国公司出海不应失去“模式自信”

中国企业出海近期热闹非凡,其中以短剧为代表的文化内容产业和跨境电商产业都吸引了大量关注。例如亚马逊在12月12日公布一组最新数据,亚马逊过去一年销售额超过1000万美金的中国卖家数量,同比增长接近30%。中国跨境电商平台在刚刚过去的“黑五…

机器学习算法应用场景与评价指标

一、应用场景 机器学习的算法选择大部分依赖于具体的问题类型和数据特征。下面是一些典型的场景以及对应的常用算法: 1.二元分类问题 当你的目标变量只有两个类别时,如垃圾邮件过滤(垃圾邮件/非垃圾邮件)、患者疾病诊断&#x…

医院污水处理设备远程监控超标报警解决方案

行业背景 近年来,我国医疗机构建设得到了巨大的发展。根据《2022年我国卫生健康事业发展统计公报》,2022年末,全国医疗卫生机构总数达1032918个。截至2022年10月,根据全国排污许可证管理信息平台,共有 13316家医院核发…

UE引擎 LandscapeGrass 实现机制分析(UE5.2)

前言 随着电脑和手机硬件性能越来越高,游戏越来越追求大世界,而大世界非常核心的一环是植被,目前UE5引擎提供给植被生成的主流两种方式为 手刷植被和LandscapeGrass(WeightMap程序化植被)。当然UE5.3推出新一代PCGFramework 节点程序化生成框…

Halcon reduce_domain和scale_image的作用

在Halcon中,reduce_domain是用于缩小图像域(Image Domain)的操作。 它的作用是通过指定一个感兴趣区域(ROI,Region of Interest),将图像数据限制在该区域内,从而实现对图像进行裁剪…

领导力的3个常见误区,你可能中了其中之一

什么是领导力? 领导力是组织和团队成功的关键。在一个不断变化的商业环境中,理解领导力的本质至关重要。这篇文章将揭示有关领导力的三个常见误解,帮助读者更清晰地认识领导者的角色。 关于领导力的常见误解 人们对领导力的理解经常受到错…

如何使用bash写脚本

本章主要介绍如何使用bash写脚本。 了解通配符了解变量了解返回值和数值运算数值的对比判断语句循环语句 grep的用法是“grep 关键字 file”,意思是从file中过滤出含有关键字的行。 例如,grep root /var/log/messages,意思是从/var/log/me…

在做题中学习(33):只出现一次的数字 II

137. 只出现一次的数字 II - 力扣(LeetCode) 思路: 1.首先想到出现三次的数,它们仨的任意一位都是相同的(1/0) 2.可以发现出现三次的数的某一位和a某一位在所有情况下%3最后的结果都和a的那一位相同&…

【PyTorch】卷积神经网络

文章目录 1. 理论介绍1.1. 从全连接层到卷积层1.1.1. 背景1.1.2. 从全连接层推导出卷积层 1.2. 卷积层1.2.1. 图像卷积1.2.2. 填充和步幅1.2.3. 多通道 1.3. 池化层(又称汇聚层)1.3.1. 背景1.3.2. 池化运算1.3.3. 填充和步幅1.3.4. 多通道 1.4. 卷积神经…

抖店商品卡流量怎么做?附实操玩法解析及案例分享!

我是电商珠珠 在抖店中,我们会看到一些店铺从来都不直播,官方账号的作品很少,但是他的店铺GMV依旧过万。 其实这就是抖音的货架电商所带来的优势,抖音现在主要由两部分组成,一部分是内容场,就是咱们平时刷…

SpringBoot整合MongoDB详解

SpringBoot——整合MongoDB详解 注意: MongoDB默认是本机访问 需要开启远程访问 window修改如下 linux 修改如下 /usr/local/mongodb4/mongodb.conf 详细内容 dbpath/data/mongodb4/mongo #数据文件保存地址 logpath/data/mongodb4/log/mongod.log #日志保存地址…

架构设计系列之基础:初探软件架构设计

11 月开始突发奇想,想把自己在公司内部做的技术培训、平时的技术总结等等的内容分享出来,于是就开通了一个 Wechat 订阅号(灸哥漫谈),开始同步发送内容。 今天(12 月 10 日)也同步在 CSDN 上开通…

mysql字段设计规范:使用unsigned(无符号的)存储非负值

如果一个字段存储的是数值,并且是非负数,要设置为unsigned(无符号的)。 例如: 备注:对于类型是 FLOAT、 DOUBLE和 DECIMAL的,UNSIGNED属性已经废弃了,可能在mysql的未来某个版本去…

AI隆重软件,AI原创文章隆重软件

随着信息量的急剧增加,许多写作者、网站管理员和内容创作者们纷纷感受到了文章降重的压力。原始文本的降重,需要保留关键信息的同时避免重复,这是一项既繁琐又耗时的任务。 改写软件的批量降重功能 147SEO改写软件在降重领域的卓越表现主要体…

常见SSL证书都有哪些格式

常见Web服务软件 常见的Web服务软件,通常都基于OpenSSL和Java两种基础密码库。 Tomcat、Weblogic、JBoss等Web服务软件,一般使用Java提供的密码库。通过Java Development Kit(JDK)工具包中的Keytool工具,生成Java Ke…

android studio 按键点击事件的实现方法

一、onClick属性&#xff1a; 1&#xff09;、在activity_main.xml中设置button的onClick属性&#xff1a; <Buttonandroid:id"id/button"android:layout_width"wrap_content"android:layout_height"wrap_content"android:text"开灯&q…

SpringCloud系列(三)| 集成Nacos注册中心

好了万事具备&#xff0c;接下来我们就开始搭建我们SpringCloud项目。本章节我们先来搭建我们SpringCloud项目框架&#xff0c;然后开发两个服务&#xff0c;把他们注册到Nacos注册中心中。上一章节我们已经介绍了Nacos是可以作为注册中心和配置中心的&#xff0c;这一章节我们…