quartz/content/computer_sci/code_frame_learn/flask/MSGI.md
2024-03-09 16:50:03 +08:00

4.8 KiB
Raw Blame History

title tags date
Web Server Gateway Interface
flask
python
web
http
2024-03-07

Abstract and Pre-knowledge

Note

WSGI 的全程是 Web Server Gateway Interface,中文翻译为 Web 服务器网关接口。它是一种规范,定义了 Web 服务器和 Python Web 应用程序或框架之间的一种简单而通用的接口。

WSGI 规范的目的是使 Python Web 开发人员能够编写可移植和可扩展的 Web 应用程序。WSGI 应用程序可以与任何兼容 WSGI 的 Web 服务器一起使用,而无需进行任何修改。

HTTP Brief Introduction

What's Web application

  1. 浏览器发送一个HTTP请求

  2. 服务器收到请求生成一个HTML文档

  3. 服务器把HTML文档作为HTTP响应的Body发送给浏览器

  4. 浏览器收到HTTP响应从HTTP Body取出HTML文档并显示。

简单的Web应用就是先把HTML用文件保存好用一个现成的HTTP服务器软件接收用户请求从文件中读取HTML返回。

如果要动态生成HTML就需要把上述步骤自己来实现。

但是接受HTTP请求、解析HTTP请求、发送HTTP响应这些涉及到HTTP规范的底层代码正确对待他们的做法是用专门的服务器软件实现我们使用python专注于生成HTML文档。

这些我们不希望接触到的TCPP连接、HTTP原始请求和响应格式需要一个统一的接口让我们专心用python编写web业务。

这个接口就是WSGIWeb Server Gateway Interface。

它是一种规范,定义了 Web 服务器和 Python Web 应用程序或框架之间的一种简单而通用的接口。

Example:

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'<h1>Hello, web!</h1>']

WSGI接口要求Web开发者实现一个函数就可以响应HTTP请求。

这个函数接收两个参数:

  • environ一个包含所有HTTP请求信息的dict对象;
  • start_response一个发送HTTP响应的函数。

application()函数中,调用:

start_response('200 OK', [('Content-Type', 'text/html')])

就发送了HTTP响应的Header注意Header只能发送一次也就是只能调用一次start_response()函数。start_response()函数接收两个参数一个是HTTP响应码一个是一组list表示的HTTP Header每个Header用一个包含两个strtuple表示。

通常情况下,都应该把Content-Type头发送给浏览器。其他很多常用的HTTP Header也应该发送。

然后,函数的返回值b'<h1>Hello, web!</h1>'将作为HTTP响应的Body发送给浏览器。

有了WSGI我们关心的就是如何从environ这个dict对象拿到HTTP请求信息然后构造HTML通过start_response()发送Header最后返回Body。

整个application()函数本身没有涉及到任何解析HTTP的部分也就是说底层代码不需要我们自己编写我们只负责在更高层次上考虑如何响应请求就可以了。

这个application()函数怎么调用?如果我们自己调用,两个参数environstart_response我们没法提供,返回的bytes也没法发给浏览器。

所以application()函数必须由WSGI服务器来调用。有很多符合WSGI规范的服务器我们可以挑选一个来用。但是现在我们只想尽快测试一下我们编写的application()函数真的可以把HTML输出到浏览器所以要赶紧找一个最简单的WSGI服务器把我们的Web应用程序跑起来。

因此我们需要编写以下两个py程序

# hello.py

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'<h1>Hello, web!</h1>']
# server.py
# 从wsgiref模块导入:
from wsgiref.simple_server import make_server
# 导入我们自己编写的application函数:
from hello import application

# 创建一个服务器IP地址为空端口是8000处理函数是application:
httpd = make_server('', 8000, application)
print('Serving HTTP on port 8000...')
# 开始监听HTTP请求:
httpd.serve_forever()

其中,hello.py是实现web应用程序的WSGI处理函数server.py是负责启动WSGI服务器加载application()函数

Conclusion

无论多么复杂的Web应用程序入口都是一个WSGI处理函数。HTTP请求的所有输入信息都可以通过environ获得HTTP响应的输出都可以通过start_response()加上函数返回值作为Body。

复杂的Web应用程序光靠一个WSGI函数来处理还是太底层了我们需要在WSGI之上再抽象出Web框架进一步简化Web开发。

Reference