flask源码分析-WSGI接口(二)

一个web应用的本质

  1. 浏览器发送一个HTTP请求;
  2. 服务器收到请求,生成一个HTML文档;
  3. 服务器把HTML文档作为HTTP响应的Body发送给浏览器;
  4. 浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示。
    思考:HTML文档需要程序员编写代码动态生成,但解析请求和发送响应的代码是不是可以固定下来???

我们一直在编写业务代码,却从未关心过如何发送响应,谁来监听请求?

为了让我们能专注于编写业务,所以底层的解析请求及发送响应需要有一个专门的接口,这个接口就是WSGI。

  • WSGI:全称是Web Server Gateway Interface,WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述web server如何与web application通信的规范,实现了server和application的解耦。当前运行在WSGI协议之上的web框架有Bottle, Flask, Django。
  • uWSGI:是一个web服务器,实现了WSGI协议、uwsgi协议、http协议等
  • uwsgi:是一个uWSGI服务器自有的协议,它用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型描述

图示

在这里插入图片描述

接口定义及测试DEMO展示

首先我们思考一下,我们我们自己去编写一个uWSGI服务器,我们应该怎么让开发web应用的程序员更专注的去编写业务?而不再去操心解析请求和发送响应,我们可能会这么做:要求开发者声明一个函数,服务器负责把请求参数传给这个函数,然后函数返回给服务器一个响应,服务器负责把响应返回给客户端。
WSGI接口定义非常简单,它只要求Web开发者实现一个函数,就可以响应HTTP请求。

  • demo
def application(environ, start_response):
    '''
    :param environ: 一个包含所有HTTP请求信息的dict对象;
    :param start_response:一个发送HTTP响应的函数,接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP Header
    :return:
    '''
    start_response('200 OK', [('Content-Type', 'text/html')])
    return '<h1>Hello, web!</h1>'
  • 开发环境下,我们可以使用Python内置的测试服务器,这个模块叫wsgiref,它是用纯Python编写的WSGI服务器的参考实现,这个模块目前django框架在使用。所谓“参考实现”是指该实现完全符合WSGI标准,但是不考虑任何运行效率,仅供开发和测试使用
#从wsgiref模块导入:
from wsgiref.simple_server import make_server
#创建一个服务器,IP地址为空,端口是8000,处理函数是application:
httpd = make_server('', 8000, application)
print("Serving HTTP on port 8000...")
#开始监听HTTP请求:
httpd.serve_forever()

或者使用Flask开发环境下的一个叫werkzeug的库

from werkzeug.wrappers import Request, Response
@Request.application
def hello(request):
    return Response('Hello World!')
if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 9000, hello)

查看environ参数

在这里插入图片描述
这里可以打断点调试给大家看

  • 总结
    • 通过WSGI定义,我们可以发现,无论多么复杂的框架,只需要提供给uWSGI服务器一个可调用对象,在Python中,可以是一个函数,可以是一个类的实例!
      想开发一个web框架,只需要实现一个可调用的对象,比如Flask中我们创建的app对象,无论这个app对象中间经历多长的流程,终归要返回一个response,其他具体的功能我们在框架内自由发挥即可。
      流程:创建web应用=>交给uWSGI服务器=>开启服务,完事!

寻找框架运行入口

  • Python中什么叫可调用对象?
def application():
    return '<h1>Hello, web!</h1>'
print(callable(application))
print(dir(application))
print(application.__call__())
  • 如何实现让一个类的实例可调用?
class A:
    pass
a = A()
print(callable(a))
class A:
    def __call__(self, *args, **kwargs):
        return '我也可以 像函数一样被调用'
a = A()
print(callable(a))
print(a())
  • 通过前面wsgi的分析,我们知道当你传给给服务器一个可调用对象时,服务器就加上括号调用了,因此现在我们确定了框架的入口,抛开服务器端不管,我们直接去flask框架里找到这个应用的"__call__"方法就可以了.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值