Web开发之旅-Flask如何处理请求

通常分析一个陌生系统时,会首先将系统看成一个黑盒子,不停的改变输入,然后观察输出的变化,这样即使不了解这个黑盒系统的工作原理,也可以使用它,比如使用过很多的Python三方库,我们并不知道它的工作原理,但是我知道它的功能是什么,输入什么就能得到什么就可以了。

一、HTTP如何规定请求和响应

用户只需要在浏览器输入网址,就可以获得相应的内容,浏览器到底给我们的服务器发送了什么东东呢?服务器又返回了什么给浏览器呢?https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Messages给出了标准解释,HTTP消息是服务器和客户端之间交换数据的方式。有两种类型的消息︰请求--由客户端发送用来触发一个服务器上的动作;响应--来自服务器的应答。

Requests是浏览器向服务器发送的,Response是服务器返回给浏览器的。

HTTP请求和响应具有相似的结构,由以下部分组成︰

一行起始行(start line)用于描述要执行的请求,或者是对应的状态,成功或失败。这个起始行总是单行的。

一个可选的HTTP头集合(headers)指明请求或描述消息正文。

一个空行指示所有关于请求的元数据已经发送完毕。

一个可选的包含请求相关数据的正文(比如HTML表单内容),或者响应相关的文档。正文(body)的大小有起始行的HTTP头来指定。

start line和 HTTP headers统称为request header,而其有效负载被称为body。

(一)request部分

1.start line

start line有3个内容:

(1)请求方式:

一个HTTP 方法,一个动词(像GET, PUT 或者POST) 或者一个名词(像HEAD 或者OPTIONS), 描述要执行的动作.例如, GET 表示要获取资源,POST 表示向服务器推送数据(创建或修改资源,或者产生要返回的临时文件)。

(2)请求目标:

通常是一个URL,或者是协议、端口和域名的绝对路径,通常以请求的环境为特征。请求的格式因不同的HTTP 方法而异。它可以是:

一个绝对路径,末尾跟上一个' ? '和查询字符串。这是最常见的形式,称为原始形式(origin form),被GET,POST,HEAD和OPTIONS方法所使用。

POST / HTTP 1.1

GET /background.png HTTP/1.0

HEAD /test.html?query=alibaba HTTP/1.1

OPTIONS /anypage.html HTTP/1.0

一个完整的URL,被称为绝对形式(absolute form),主要在GET连接到代理时使用。

GET http://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1

由域名和可选端口(以':'为前缀)组成的URL的authority component,称为authority form。仅在使用CONNECT建立HTTP隧道时才使用。

CONNECT developer.mozilla.org:80 HTTP/1.1

星号形式(asterisk form),一个简单的星号('*'),配合OPTIONS方法使用,代表整个服务器。

OPTIONS * HTTP/1.1

(3)HTTP版本

定义了剩余报文的结构,作为对期望的响应版本的指示符。

2.headers

整个header(包括值)由一行组成,这一行可以相当长。结构形式比较像是Python里的字典。请求头里面的内容很多,但是可以分为3个组:

(1)General headers

适用于整个报文

(2)Request headers

例如User-Agent,Accept-Type,通过进一步的定义(例如Accept-Language),或者给定上下文(例如Referer),或者进行有条件的限制(例如If-None) 来修改请求。

(3)Entity headers

例如Content-Length,适用于请求的body。显然,如果请求中没有任何body,则不会发送这样的头文件。

3.body

请求的最后一部分是它的body。不是所有的请求都有一个body:例如获取资源的请求,GET,HEAD,DELETE和OPTIONS,通常它们不需要body。有些请求将数据发送到服务器以便更新数据:常见的的情况是POST请求(包含HTML表单数据)。

Body大致可分为两类:

(1)Single-resource bodies,由一个单文件组成。该类型body 由两个header 定义:Content-Type 和Content-Length.

(2)Multiple-resource bodies,由多部分body组成,每一部分包含不同的信息位。通常提交表单时是这种类型。

(二)response部分

1.start line

响应的start line被称为状态行,同样包含3个信息:

(1)协议版本

通常为HTTP/1.1

(2)状态码(status code)

表明请求是成功或失败。常见的状态码是200,404,或302。

(3)状态文本(status text)

一个简短的,纯粹的信息,通过状态码的文本描述,帮助人们理解该HTTP消息。

一个典型的状态行:HTTP/1.1 200 OK

2.headers

响应的headers和请求的headers结构相同:

3.body

不是所有的响应都有body:具有状态码(如201 或204) 的响应,通常不会有body。

Body大致可分为三类:

(1)Single-resource bodies

由已知长度的单个文件组成。该类型body 由两个header 定义:Content-Type和Content-Length。

(2)Single-resource bodies

由未知长度的单个文件组成,通过将Transfer-Encoding 设置为chunked 来使用chunks 编码。

(3)Multiple-resource bodies

由多部分body 组成,每部分包含不同的信息段。但这是比较少见的。

二、Flask处理请求

现在我们终于清楚了浏览器到底发了什么东东过来,服务器应该如何做出相应的操作呢?

1.start line

请求路由:它是由app.route这个装饰器来处理的,讲它用在一个函数前就把那个函数变成了处理对应路由的视图函数,例如@app.route('/user')这个装饰器规定了用户访问/user的视图函数,但是我们的user很多,那就需要定义@app.route('/user/1')、@app.route('/user/2').....这很明显不科学啊,那么我们就要定义一个动态的路由,让这些路由都由一个视图函数来处理,安装下面的方法就可以定义动态的路由,当访问/user/john和访问/user/tom都是由show_user_profile这个视图函数来处理,john和tom被当成参数传给了视图函数:

Flask规定了5种动态路由参数类型:

这样就能处理各种各样的请求路由了。

请求方法:它也是由app.route这个装饰器来实现的,只需要传入第二个命名参数methods就可以了,这个参数接收的是一个列表,想要这个视图函数能够处理哪种请求就填入相应的方法就行了。

HTTP版本这个由Flask自行处理就行了,不用我们操心。

2.headers

headers里面通常会包含很多我们感兴趣的内容,可以通过request对象获取这些内容。浏览器本次发来请求Flask会将它的内容放入request对象中,这里就要介绍4个重要的对象:

要调用request中的内容很简单:

3.body

当用户上传表单或者上传文件时,body里面就包含了相应的内容,取出相应内容同样很简单,NewArticleForm这个类可能不太理解,在后面讲到表单时会详细说,先看看如何获得内容:

下面这个是获取上传的文件:

总之:Flask先构造出相应的URL,当用户请求相应的URL时,通过request对象就可以获取到相应的内容。下一篇文章介绍Flask如何给浏览器发送响应。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180826G01OUK00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券