字符串过滤掉所有最邻近的“<”和“>”之间的字符
Flask
overview
背景
Flask以及它所使用的wsgi库werkzeug和模板引擎jinja2都是由Armin Ronacher和他的团队开发的。实际上Armin Ronacher早就开发出来了werkzeug开源库,旨在为框架封装一个良好的底层的API接口,但过了一段时间,Armin发现还是自己来先做一个吧,然后Flask就诞生了。
任务
分析从发起HTTP请求到响应请求之间的流程
涉及源代码文件:
- Flask源码
- app.py
- werkzeug源码
- serving.py
python基本库源码
- SocketServer.py
- BaseHTTPServer.py
- 先来看一个最小的Flask应用:
from flask import Flask
app = Flask(__name__) @app.route('/')
def hello_world():
return 'Hello World!' if __name__ == '__main__':
app.run()
显而易见,app.run
是核心代码。我们来看一下app.py
中相关的代码:
<app.py>
def run(self, host=None, port=None, debug=None, **options):
from werkzeug.serving import run_simple
run_simple(host, port, self, **options) <serving.py>
def run_simple(hostname, port, application, ...,
request_handler=None, static_files=None, ...):
srv = make_server(hostname, port, application, threaded,
processes, request_handler,
passthrough_errors, ssl_context,
fd=fd)
srv.serve_forever() def make_server(host=None, port=None, app=None, threaded=False, processes=1,
request_handler=None, passthrough_errors=False,
ssl_context=None, fd=None):
return BaseWSGIServer(host, port, app, request_handler,
passthrough_errors, ssl_context, fd=fd)
可以看到实际上是make了一个BaseWSGIServer,这个server开始监听连接。下边来研究一下这个BaseWSGIServer。
BaseWSGIServer继承自python基本库BaseHTTPServer.py中的HTTPServer, HTTPServer继承自SocketServer.py中的TCPServer。
<serving.py>
class BaseWSGIServer(HTTPServer, object):
def __init__(self, host, port, app, handler=None, ...):
if handler is None:
handler = WSGIRequestHandler
HTTPServer.__init__(self, (host, int(port)), handler)
self.app = app class HTTPServer(SocketServer.TCPServer):
def server_bind(self):
.... class TCPServer(BaseServer):
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
"""Constructor. May be extended, do not override."""
BaseServer.__init__(self, server_address, RequestHandlerClass)
self.socket = socket.socket(self.address_family,
self.socket_type)
if bind_and_activate:
try:
self.server_bind()
self.server_activate()
except:
self.server_close()
raise <SocketServer.py>
class BaseServer:
def __init__(self, server_address, RequestHandlerClass):
"""Constructor. May be extended, do not override."""
self.server_address = server_address
self.RequestHandlerClass = RequestHandlerClass
self.__is_shut_down = threading.Event()
self.__shutdown_request = False def serve_forever(self, poll_interval=0.5):
self.__is_shut_down.clear()
try:
while not self.__shutdown_request:
r, w, e = _eintr_retry(select.select, [self], [], [],
poll_interval)
if self in r:
self._handle_request_noblock()
finally:
self.__shutdown_request = False
self.__is_shut_down.set() def finish_request(self, request, client_address):
# 这里非常重要,就是实例化请求处理类
self.RequestHandlerClass(request, client_address, self)
从这些代码可以看出,HTTP建立于TCP之上。BaseServer最需要注意的是在构造的时候设置了请求处理类RequestHandlerClass。也就是在BaseWSGIServer构造的时候设置了请求处理类。根据上边的了解,我们知道在app.run()的时候就把请求处理类设置好了,注意这里只是设置了请求处理类,并没有真正的去构建一个处理实例。那么它是在什么时候实例化呢?实际上它是在http请求真正到来的时候才会被实例化。随后我们会继续通过代码看到这个请求处理类在实例化的时候就会自动去处理这个请求。
我们先来简单说一下一个请求的基本处理逻辑。
1.首先一个连接进来,BaseServer监听到连接,调用self._handle_request_noblock()处理
2.self._handle_request_noblock()最终找到finish_request方法
3.finish_request方法实例化请求处理类RequestHandlerClass
在BaseWSGIServer
的构造函数中,我们看到如果我们不自己实现请求处理句柄的话,就会使用werkzeug
库提供的WSGIRequestHandler
。我们再来看一下这个类到底是一个什么东西。
<serving.py>
class WSGIRequestHandler(BaseHTTPRequestHandler, object):
def handle(self):
rv = BaseHTTPRequestHandler.handle(self)
return rv
def handle_one_request(self):
self.raw_requestline = self.rfile.readline()
if not self.raw_requestline:
self.close_connection = 1
elif self.parse_request(): # 从tcp到http中间的处理逻辑
return self.run_wsgi() # 真正的处理,随后我们会拿出来研究一下
def run_wsgi(self):
pass <BaseHTTPServer.py>
class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler):
def parse_request(self):
...
def handle(self):
self.handle_one_request() <SocketServer.py>
class StreamRequestHandler(BaseRequestHandler):
def setup(self):
...
def finish(self):
... class BaseRequestHandler:
def __init__(self, request, client_address, server):
self.request = request
self.client_address = client_address
self.server = server # 这个非常重要,设置了request的server,我们随后会看到
self.setup()
try:
self.handle()
finally:
self.finish()
一层一层的继承下来,实际上就是继承的python基本库里的基本请求处理类。这个类在实例化的时候会调用handle函数处理,handle函数我们在WSGIRequestHandler中复写了,handle函数会调用我们在WSGIRequestHandler中复写的handle_one_request函数。好了,终于找到头了。我们看一下这个run_wsgi是怎么处理的。函数稍微长一些,我们拣逻辑性的重要代码分析一下。
def run_wsgi(self):
def write(data):
...
self.wfile.write(data) # 回复响应数据
def start_response(status, response_headers, exc_info=None):
...
return write
def execute(app):
application_iter = app(environ, start_response)
for data in application_iter:
write(data)
execute(self.server.app)
代码很清楚,就是调用了app来处理请求,然后app匹配url找到视图view,真正的处理。你说app是怎么来的?我们上边研究过了,它是在请求到来的时候,由server传递给请求处理类的。也就是说只有当请求连接的时候,才会实例化处理类,处理类在实例化的时候就会配置它的server。就是下边的代码。
<SocketServer.py>
class BaseServer:
def finish_request(self, request, client_address):
# 这里非常重要,就是实例化请求处理类
self.RequestHandlerClass(request, client_address, self) class BaseRequestHandler:
def __init__(self, request, client_address, server):
self.server = server <serving.py>
class BaseWSGIServer(HTTPServer, object):
def __init__(self, host, port, app, handler=None, ...):
self.app = app
好了,以上的流程我们都清楚了。下边就开始研究app(environ, start_response)
的奇妙了。
https://blog.csdn.net/u010007589/article/details/70338066
https://blog.csdn.net/u010007589/article/details/50542251
字符串过滤掉所有最邻近的“<”和“>”之间的字符的更多相关文章
- 【编程题目】在一个字符串中找到第一个只出现一次的字符。如输入 abaccdeff,则输出 b。
第 17 题(字符串):题目:在一个字符串中找到第一个只出现一次的字符.如输入 abaccdeff,则输出 b. 思路:此题非常容易. 最开始是想开辟一块空间存储每个字符出现的次数. 但转念一想,似乎 ...
- 一个字符串中可能包含a~z中的多个字符,如有重复,如String data="aavzcadfdsfsdhshgWasdfasdf",求出现次数最多的那个字母及次数,如有多个重复的则都求出。
主要掌握String中的方法 char[] toCharArray() 将此字符串转换为一个新的字符数组. int indexOf(String str) 返回 ...
- C#返回字符串的字节长度,一个中文算两个字符的代码
如下代码段是关于C#返回字符串的字节长度,一个中文算两个字符的代码. public static int GetLength(string str) { if (str.Length == 0) re ...
- Oracle把逗号分割的字符串转换为可放入in的条件语句的字符数列
Oracle把逗号分割的字符串转换为可放入in的条件语句的字符数列 前台传来的字符串:'589,321' SELECT*FROM TAB_A T1 WHERE T1.CODE IN ( SEL ...
- 剑指offer-第五章优化时间和空间效率(在字符串中第一次出现切只出现一次的字符)
题目:在字符串中第一次出现切只出现一次的字符 思路:用HashMap来存放对应的char值和该char出现的次数.做一次变量就可以得到第一个只出现一次的字符. Java代码: import java. ...
- 使你的C/C++代码支持Unicode(CRT字符串处理的所有API列表,甚至有WEOF字符存在)
悉Microsoft支持Unicode的方式. 它的主要目的是方便你查询相关的数据类型和函数,以及修正相应的拼写错误. I18nGuy 主页 XenCraft (Unicode 咨询公司) Engli ...
- JS中substring()方法(用于提取字符串中介于两个指定下标之间的字符)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 【leetcode-03】给定一个字符串,请你找出其中不含有重复字符的最长子串的长度
开个新坑,leetcode上面做题目.下面是题目描述: <!-- 给定一个字符串,请你找出其中不含有重复字符的最长子串的长度. 示例 1: 输入: "abcabcbb" 输出 ...
- 2016/1/12 第一题 输出 i 出现次数 第二题 用for循环和if条件句去除字符串中空格 第三题不用endwith 实现尾端字符查询
import java.util.Scanner; public class Number { private static Object i; /* *第一题 mingrikejijavabu中字符 ...
随机推荐
- 如何调试makefile变量
六.七年前写过一篇<跟我一起写Makefile>,直到今天,还有一些朋友问我一些Makefile的问题,老实说,我有一段时间没有用Makefile了,生疏了.回顾,这几年来大家问题我的问题 ...
- 【SDOI2014】【BZOJ3529】数表
Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼.1 < =j < =m)的数值为 能同一时候整除i和j的全部自然数之和.给定a,计算数表中不 ...
- Java String首字母大写
一種寫法參考 public String upperFirstChar(String input) { if (input == null || "".equals(input)) ...
- 如何通过sql的insert语句插入大量字符串到oracle的clob字段?
当通过insert语句直接插入大量字符串(主要是html的内容),超过4000字符时候,就会报: ORA-01489: 字符串连接的结果过长 虽然字段是clob,足以存储,但是通过这种直接插入的时候, ...
- Android中五种常用的menu
Android Menu在手机的应用中起着导航的作用,作者总结了5种常用的Menu. 1.左右推出的Menu 前段时间比较流行,我最早是在海豚浏览器中看到的,当时耳目一新.最早使用左右推出菜单的,听说 ...
- html与表格(table)相关的属性
<table> 标签定义 HTML 表格.简单的 HTML 表格由 table 元素以及一个或多个 tr.th 或 td 元素组成.tr 元素定义表格行,th 元素定义表头,td 元素定义 ...
- AndroidStudio创建项目时一直处于building“project name”gradle project info的解决办法
AndroidStudio创建项目,最后一步finish后,一直长时间处于building“project name”gradle project info,界面就一直停留在如图所示: 谷歌自家的产品 ...
- Go 源码学习之--net/http
其实自己不是很会看源码,但是学习优秀的源码是提升自己代码能力的一种方式,也可以对自己以后写代码有一个很好的影响,所以决定在之后的时间内,要有一个很好的习惯,阅读优秀的源码.刚开始自己会觉得看源码很痛苦 ...
- 4-4-串的KMP匹配算法-串-第4章-《数据结构》课本源码-严蔚敏吴伟民版
课本源码部分 第4章 串 - KMP匹配算法 ——<数据结构>-严蔚敏.吴伟民版 源码使用说明 链接☛☛☛ <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码 ...
- Java中List详解
List是Java中比较常用的集合类,关于List接口有很多实现类,本文就来简单介绍下其中几个重点的实现ArrayList.LinkedList和Vector之间的关系和区别. List List 是 ...