--- title: Web Server Gateway Interface tags: - flask - python - web - http date: 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](computer_sci/web/http/http_introduction.md) # 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业务。 这个接口就是WSGI:Web Server Gateway Interface。 它是一种规范,定义了 Web 服务器和 Python Web 应用程序或框架之间的一种简单而通用的接口。 Example: ```python def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [b'

Hello, web!

'] ``` **WSGI接口要求Web开发者实现一个函数**,就可以响应HTTP请求。 这个函数接收两个参数: * environ:一个包含所有HTTP请求信息的`dict`对象; * start_response:一个发送HTTP响应的函数。 在`application()`函数中,调用: ```python start_response('200 OK', [('Content-Type', 'text/html')]) ``` 就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次`start_response()`函数。`start_response()`函数接收两个参数,一个是HTTP响应码,一个是一组`list`表示的HTTP Header,每个Header用一个包含两个`str`的`tuple`表示。 通常情况下,都应该把`Content-Type`头发送给浏览器。其他很多常用的HTTP Header也应该发送。 然后,函数的返回值`b'

Hello, web!

'`将作为HTTP响应的Body发送给浏览器。 有了WSGI,我们关心的就是如何从`environ`这个`dict`对象拿到HTTP请求信息,然后构造HTML,通过`start_response()`发送Header,最后返回Body。 整个`application()`函数本身没有涉及到任何解析HTTP的部分,也就是说,底层代码不需要我们自己编写,我们只负责在更高层次上考虑如何响应请求就可以了。 这个`application()`函数怎么调用?如果我们自己调用,两个参数`environ`和`start_response`我们没法提供,返回的`bytes`也没法发给浏览器。 **所以`application()`函数必须由WSGI服务器来调用**。有很多符合WSGI规范的服务器,我们可以挑选一个来用。但是现在,我们只想尽快测试一下我们编写的`application()`函数真的可以把HTML输出到浏览器,所以,要赶紧找一个最简单的WSGI服务器,把我们的Web应用程序跑起来。 因此我们需要编写以下两个py程序: ```python # hello.py def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [b'

Hello, web!

'] ``` ```python # 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 * https://www.liaoxuefeng.com/wiki/1016959663602400/1017805733037760 * https://www.liaoxuefeng.com/wiki/1016959663602400/1017806472608512