字符串过滤掉所有最邻近的“<”和“>”之间的字符
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中字符 ...
随机推荐
- 【转】DRY原则的误区
很多编程的人,喜欢鼓吹各种各样的“原则”,比如KISS原则,DRY原则…… 总有人把这些所谓原则奉为教条或者秘方,以为兢兢业业地遵循这些,空喊几个口号,就可以写出好的代码.同时,他们对违反这些原则的人 ...
- 使用Kotlin开发Android应用
1.Kotlin介绍 [Kotlin](https://kotlinlang.org/) Kotlin是一门基于JVM的编程语言,它正成长为Android开发中用于替代Java语言的继承者.Java是 ...
- 永久代 PermGen 简述
永久代(PermGen) 绝大部分 Java 程序员应该都见过 “java.lang.OutOfMemoryError: PermGen space “这个异常.这里的 “PermGen space” ...
- 使用layui 和 jquery 问题小结
问题 1 在使用 layui 2.2.5 之前,可以引入最新版的 jquery ,使用更好的性能.也可以使用layui 的jquery内部版本.如果引入要在引入layui.js 之前引入 2 使用 s ...
- Ubuntu 14.04 静态IP设置, ping通win7
ubuntu 14.04以后不支持 /etc/init.d/networing restart命令,使用ifdown et0 和ifup eth0 使用echo $?查看上一次命令执行的结果 ifdo ...
- 幽灵漏洞(Ghost gethost)
幽灵漏斗简介: 编号CVE-2015-0235的GHOST(幽灵)漏洞是Qualys研究员发现的一个Linux服务上非常严重的安全漏洞,可以被利用来远程代码执行及本地权限提升. 漏洞简要描述 该漏洞存 ...
- 用原生JavaScript写AJAX
//原生js写ajax就像打电话 //打电话分下面4步//1.拿出手机//2.拨号//3.说话//4.听对方说话 //ajax也分下面4步//1.创建ajax对象//2.连接到服务器//3.发送请求( ...
- Eclipse_Configure
原文链接:http://android.eoe.cn/topic/android_sdk 1. 下载Eclipse 在前面我们配置好了JDK环境后,就可以开始配置Android的集成开发环境了,官方G ...
- 转【Python】同时向控制台和文件输出日志logging
#-*- coding:utf-8 -*-import logging # 配置日志信息logging.basicConfig(level=logging.DEBUG, format='%(ascti ...
- 临摹一个像素风格高楼shader
原始效果地址:http://glslsandbox.com/e#40050.0 是一个的城市高楼感的shader,比较像素风 可以拿来做游戏背景,或者基于这个思路做一些别的效果 这个是我后来找的版本, ...