美文网首页
2 Flask与HTTP

2 Flask与HTTP

作者: i_1312 | 来源:发表于2019-10-22 00:23 被阅读0次

HTTP(Hypertext Transfer Protocol,超文本传输协议)定义了服务器和客户端之间信息交流的格式和传递方式,它是万维网(World Wide Web)中数据交换的基础。


2.1 请求响应循环


当我们在浏览器中的地址栏中输入某个URL,然后按下Enter时,稍等片刻,浏览器会显示一个页面。这背后到底发生了什么?这背后有一个程序运行着。它负责接收用户的请求,并把对应的内容返回给客户端,显示在用户的浏览器上。事实上,每一个Web应用都包含这种处理模式,即“请求-响应循环(Request-Response Cycle)”:客户端发出请求,服务器端处理请求 并返回响应,如图所示。


图片.png

客户端(Client Side)是指用来提供给用户的与服务器通信的各种软件。客户端通常指Web浏览器(后面简称浏览器),比如 Chrome、Firefox、IE等;服务器端(Server Side)则指为用户提供服务的服务器,也是我们的程序运行的地方。

这是每一个Web程序的基本工作模式,如果再进一步,这个模式又 包含着更多的工作单元,图2-2展示了一个Flask程序工作的实际流程。


图片.png

当用户访问一个URL,浏览器便生成对应的HTTP请求,经由互联网发送到对应的Web服务器。Web服务器接收请求,通过WSGI将HTTP格式的请求数据转换成我们的Flask程序能够使用的Python数据。在程序中,Flask根据请求的URL执行对应的视图函数,获取返回值生成响应。 响应依次经过WSGI转换生成HTTP响应,再经由Web服务器传递,最终被发出请求的客户端接收。浏览器渲染响应中包含的HTML和CSS代 码,并执行JavaScript代码,最终把解析后的页面呈现在用户浏览器的窗口中。


2.2 HTTP请求


URL是一个请求的起源。不论服务器是运行在美国洛杉矶,还是运行在我们自己的电脑上,当我们输入指向服务器所在地址的URL,都会向服务器发送一个HTTP请求。一个标准的URL由很多部分组成,以下 面这个URL为例:

http://heloflask.com/hello?name=Gary
图片.png

这个URL后面的?name=Grey部分是查询字符串(query string)。 URL中的查询字符串用来向指定的资源传递参数。查询字符串从问号? 开始,以键值对的形式写出,多个键值对之间使用&分隔。

2.2.1 请求报文
当我们在浏览器中访问这个URL时,随之产生的是一个发向http://helloflask.com所在服务器的请求。请求的实质是发送到服务器上的一些数据,这种浏览器与服务器之间交互的数据被称为报文(message),请求时浏览器发送的数据被称为请求报文(request message),而服务器返回的数据被称为响应报文(response message)。

请求报文由请求的方法、URL、协议版本、首部字段(header)以 及内容实体组成。前面的请求产生的请求报文示意如表2-2所示。


图片.png

报文由报文首部和报文主体组成,两者由空行分隔,请求报文的主 体一般为空。如果URL中包含查询字符串,或是提交了表单,那么报文 主体将会是查询字符串和表单数据。

HTTP通过方法来区分不同的请求类型。比如,当你直接访问一个 页面时,请求的方法是GET;当你在某个页面填写了表单并提交时,请 求方法则通常为POST。表2-3是常见的几种HTTP方法类型。


图片.png

报文首部包含了请求的各种信息和设置,比如客户端的类型、是否 设置缓存、语言偏好等。

2.2.2 Request对象
Request请求对象封装了从客 户端发来的请求报文,我们能从它获取请求报文中的所有数据。

注意:请求解析和响应封装实际上大部分是由Werkzeug完成的,Flask子类化Werkzeug的请求(Request)和响应(Response)对象并添加了和程序相关的特定功能。

当Flask接收到请求后,请求对象会提供多个属性来获取URL的各个部分,常用的属性。


图片.png

除了URL,请求报文中的其他信息都可以通过request对象提供的属 性和方法获取,其中常用的部分如表所示。


图片.png
Werkzeug的MutliDict类是字典的子类,它主要实现了同一个键对应 多个值的情况。比如一个文件上传字段可能会接收多个文件。这时就可 以通过getlist()方法来获取文件对象列表。而ImmutableMultiDict类继 承了MutliDict类,但其值不可更改。
from flask import Flask, request
app = Flask(__name__)
@app.route('/hello') 
def hello():    
name = request.args.get('name', 'Flask')    # 获取查询参数name的值    
return '<h1>Hello, %s!<h1>' % name         # 插入到返回值中
# 获取请求URL中的查询字符串

上面的示例代码包含安全漏洞,在现实中我们要避免直接将用户传 入的数据直接作为响应返回

需要注意的是,和普通的字典类型不同,当我们从request对象的类 型为MutliDict或ImmutableMultiDict的属性(比如files、form、args)中直接使用键作为索引获取数据时(比如request.args['name']),如果没有对应的键,那么会返回HTTP 400错误响应(Bad Request,表示请求无效),而不是抛出KeyError异常,为了避免这个错误,我们应该使用get()方法获取数据,如果没有对应的值则返回None; get()方法的第二个参数可以设置默认值,比如 requset.args.get('name','Human')。

2.2.3 在Flask中处理请求
URL是指向网络上资源的地址。在Flask中,我们需要让请求的URL 匹配对应的视图函数,视图函数返回值就是URL对应的资源。

1.路由匹配
为了便于将请求分发到对应的视图函数,程序实例中存储了一个路
由表(app.url_map),其中定义了URL规则和视图函数的映射关系。当请求发来后,Flask会根据请求报文中的URL(path部分)来尝试与这个表中的所有URL规则进行匹配,调用匹配成功的视图函数。如果没有找到匹配的URL规则,说明程序中没有处理这个URL的视图函数,Flask会自动返回404错误响应(Not Found,表示资源未找到)。

当请求的URL与某个视图函数的URL规则匹配成功时,对应的视图 函数就会被调用。使用flask routes命令可以查看程序中定义的所有路由信息,我们可以看到每个路由对应的端点 (Endpoint)、HTTP方法(Methods)和URL规则(Rule),其中static 端点是Flask添加的特殊路由,用来访问静态文件。

2.设置监听的HTTP方法

每一个 路由除了包含URL规则外,还设置了监听的HTTP方法。GET是最常用 的HTTP方法,所以视图函数默认监听的方法类型就是GET,HEAD、OPTIONS方法的请求由Flask处理,而像DELETE、PUT等方法一般不会 在程序中实现,在后面我们构建Web API时才会用到这些方法。

我们可以在app.route()装饰器中使用methods参数传入一个包含监听的HTTP方法的可迭代对象。比如,下面的视图函数同时监听GET请求和POST请求:

@app.route('/hello', methods=['GET', 'POST']) 
def hello():    
    return '<h1>Hello, Flask!</h1>'

当某个请求的方法不符合要求时,请求将无法被正常处理。比如, 在提交表单时通常使用POST方法,而如果提交的目标URL对应的视图 函数只允许GET方法,这时Flask会自动返回一个405错误响应(Method Not Allowed,表示请求方法不允许.

3.URL处理

URL中的变量部分默认类型为字符串,但Flask提供了一些转换器可以在URL规则里使用,<int:year>表示为year变量添加了一个int转换器, Flask在解析这个URL变量时会将其转换为整型。


图片.png

转换器通过特定的规则指定,即“<转换器:变量名>”。<int:year> 把year的值转换为整数.但是如果用户输入的是英文字母,就会出现转换错误,抛出ValueError 异常,我们还需要手动验证;使用了转换器后,如果URL中传入的变量 不是数字,那么会直接返回404错误响应。

默认的行为不仅仅是转换变量类型,还包括URL匹配。唯一特别的是any转换,你需要在转换器后添加括号来 给出可选值,即“<any(value1,value2,...):变量名>”,比如:

@app.route('/colors/<any(blue, white, red):color>') 
def three_colors(color):    
return '<p>Love is patient and kind. Love is not jealous </p>'

2.2.4 请求钩子
有时我们需要对请求进行预处理(preprocessing)和后处理 (postprocessing),这时可以使用Flask提供的一些请求钩子(Hook),它们可以用来注册在请求处理的不同阶段执行的处理函数 (或称为回调函数,即Callback)。这些请求钩子使用装饰器实现,通过程序实例app调用


图片.png

这些钩子使用起来和app.route()装饰器基本相同,每个钩子可以 注册任意多个处理函数,函数名并不是必须和钩子名称相同,下面是一 个基本示例:

@app.before_request 
def do_something():

请求钩子的一些常见应用场景:
·before_first_request:在玩具程序中,运行程序前我们需要进行一 些程序的初始化操作,比如创建数据库表,添加管理员用户。这些工作 可以放到使用before_first_request装饰器注册的函数中。
·before_request:比如网站上要记录用户最后在线的时间,可以通 过用户最后发送的请求时间来实现。为了避免在每个视图函数都添加更新在线时间的代码,我们可以仅在使用before_request钩子注册的函数中调用这段代码。
·after_request:我们经常在视图函数中进行数据库操作,比如更\新、插入等,之后需要将更改提交到数据库中。提交更改的代码就可以 放到after_request钩子注册的函数中。

图片.png

另一种常见的应用是建立数据库连接,通常会有多个视图函数需要建立和关闭数据库连接,这些操作基本相同。一个理想的解决方法是在 请求之前(before_request)建立连接,在请求之后(teardown_request) 关闭连接。通过在使用相应的请求钩子注册的函数中添加代码就可以实现。这很像单元测试中的setUp()方法和tearDown()方法。

相关文章

  • 2 Flask与HTTP

    HTTP(Hypertext Transfer Protocol,超文本传输协议)定义了服务器和客户端之间信息交流...

  • 2.Flask与HTTP

    2.2.2 Requests对象 from flask import request request主要的...

  • flask备课

    学习 Flask 函数 模块 类 与 实例 装饰器 http://www.bjhee.com/flask-4.ht...

  • flask web development pdf

    http://flask.pocoo.org/docs/0.10/.latex/Flask.pdf

  • 课堂笔记

    Flask课堂笔记 1. HTTP通信与Web框架 1.1 流程 客户端将请求打包成HTTP的请求报文(HTTP协...

  • Flask扩展-学习

    Flask扩展详细说明文档 http://flask.pocoo.org/extensions/ Flask表单w...

  • Python全栈快餐教程(1) - 用Flask处理HTTP请求

    Python全栈快餐教程(1) - 用Flask处理HTTP请求 初识Flask Flask是最流行的Python...

  • [Flask]文件上传Demo

    参考flask官方文档:http://flask.pocoo.org/docs/0.12/patterns/fil...

  • 2018-08-06

    Flask_restful 开发指南 http://flask-restful.readthedocs.io/en...

  • Flask框架学习

    Flask框架学习http://www.pythondoc.com/flask-mega-tutorial/hel...

网友评论

      本文标题:2 Flask与HTTP

      本文链接:https://www.haomeiwen.com/subject/blcfvctx.html