Wsgiref 包——符合 WSGI 标准的 Web 服务实现(一)

引子

在前几篇文章:SocketServer——网络通信服务器BaseHTTPServer——实现Web服务器SimpleHTTPServer——一个简单的HTTP服务器,我们介绍了Python标准库对于网络通信的支持,并且还介绍了标准库中的一些模块,例如TCPServerUDPServerBaseHTTPServer等。这些模块能够实现基础的网路通信服务,例如TCP/UDP层的通信、HTTP应用层的通信。

上述模块对于网络通信的实现,基本的流程是:

  • 创建一个服务器。例如TCP服务器、UDP服务器、HTTP服务器。服务器可以监听和接收请求;
  • 创建请求处理程序。请求处理程序可以解析到达的请求,并发回一个响应。

以上流程基本上反映了Python标准库中关于网络通信的基本过程。服务器类和请求处理类的解耦,意味着很多应用可以使用某个现有的服务器类,而不需要其他任何的修改,只需要提供一个可以处理这些应用的请求处理类即可。但随着近些年网络编程越来越复杂,对于服务器网络通信提出了较大的挑战。以Web编程为例,挑战主要在于:

  1. 服务器不再仅仅提供简单的、静态的HTML页面,更多的是要与丰富的Web应用进行相互通信。如果将请求处理程序的构建放在服务器端实现,那对于每个Web应用构建一个请求处理程序显然不现实;
  2. 如果将请求处理程序的构建放在开发Web应用的过程中,那无疑增加了Web应用程序开发的难度和复杂度,也是不太理想的。

为了解决这些问题,常用的做法是提供一个中间层,通常称为网关接口网关接口在服务器和应用中间承担一个“翻译官”的角色。只要应用程序符合网关接口的标准,那么服务器就只要做好服务器的角色,应用程序只要做好应用程序的作用,服务器和应用程序之间的通信全靠网关接口来协调。常用的网关接口有CGIWSGI,本文就以WSGI网关接口来对此进行说明。

WSGI网关接口

WSGI (Python Web Server Gateway Interface, Python Web服务器网关接口)是一个Web服务器和Web应用程序之间的标准化接口,用于增进应用程序在不同的Web服务器和框架之间的可移植性。关于该标准的官方说明可以参考PEP333

WSGI的主要作用是在Web服务器和Web应用程序承担“翻译官”的角色。对于这一角色可以这样理解:

  1. Web服务器的责任在于监听和接收请求。在处理请求的时候调用WSGI提供的标准化接口,将请求的信息转给WSGI
  2. WSGI的责任在于“中转”请求和响应信息。WSGI接收到Web服务器提供的请求信息后可以做一些处理,之后通过标准化接口调用Web应用,并将请求信息传递给Web应用。同时,WSGI还将会处理Web应用返回的响应信息,并通过服务器返回给客户端;
  3. Web应用的责任在于接收请求信息,并且生成响应。

根据以上分析,要实现符合WSGI标准的Web服务,服务器和应用程序的设计就要符合WSGI规范。

WSGI规范

WSGI规范如下:

  • 服务器的请求处理程序中要调用符合WSGI规范的网关接口;
  • 网关接口调用应用程序,并且要定义start_response(status, headers)函数,用于返回响应;
  • 应用程序中实现一个函数或者一个可调用对象webapp(environ, start_response)。其中environ是环境设置的字典,由服务器和WSGI网关接口设置,start_response是由网关接口定义的函数。

在Python标准库中,wsgiref包就是符合WSGI标准的Web服务实现。后面简单对wsgiref包进行介绍,以此来对符合WSGI标准的Web服务的实现过程进行梳理。

wsgiref包

wsgiref包为实现WSGI标准提供了一个参考,它可以作为独立的服务器测试和调试应用程序。在实际的生产环境中尽量不要使用。wsgiref包含有以下模块:

  • simple_server模块 ——simple_server模块实现了可以运行单个WSGI应用的简单的HTTP服务器。
  • headers模块 ——管理响应首部的模块。
  • handlers模块 ——符合WSGI标准的Web服务网关接口实现。该模块包含了一些处理程序对象,用来设置WSGI执行环境,以便应用程序能够在其他的Web服务器中运行。
  • validate模块 ——“验证包装”模块,确保应用程序和服务器都能够按照WSGI标准进行操作。
  • util模块 ——一些有用的工具集。

以上模块暂时不做详细的介绍。本文剩余内容将simple_server模块单独拿出来,以其中的测试例子简单说明符合WSGI标准的Web服务器的实现过程。

simple_server——一个简单的符合WSGI规范的服务器

wsgiref包的simple_server模块实现了一个符合WSGI规范的服务器。测试代码如下:

1. 创建HTTP服务器

上述测试代码中httpd = make_server(”, 8000, demo_app)创建了一个HTTP服务器。

其中make_server函数用来创建服务器:

make_server函数使用WSGIServer类构建符合WSGI规范的HTTP服务器,使用WSGIRequestHandler类作为处理请求的类,使用demo_app作为一个Web应用。该函数返回一个服务器实例,并开始监听请求。可以通过httpd.socket.getsockname()获取服务器地址和端口号。

2. 使用webbrowser模块创建请求

紧接着,测试例子导入webbrowser模块,使用函数创建了一个请求。

3. 服务器处理请求

服务器通过handle_request()方法处理请求。关于处理请求的过程简单介绍如下:

  • handle_request()方法通过调用get_requestverify_requestprocess_requestfinish_request等方法创建一个请求处理实例(该过程可以参考TCPServer、HTTPServer的实现过程);
  • 请求处理实例调用handle()方法处理请求。handle()WSGIRequestHandler类中进行了重写。代码如下:

上面handle()函数先解析了请求,之后创建了一个WSGI网关类实例handler,这个实例可以作为服务器和应用程序之间的接口存在。

4. WSGI网关的请求处理过程

WSGI网关的定义在handlers模块。上一步骤中通过调用WSGI网关类实例handlerrun方法,WSGI网关开始处理请求。

run方法的代码如下:

run方法的主要功能有:

  • 通过setup_environ()方法创建WSGI相关的环境;
  • 调用WSGI应用的函数或者WSGI应用的可调用对象。本测试例子中的WSGI应用是一个简单的函数,其作用是将请求的environ信息打印出来。
  • 调用finish_response()方法将WSGI应用返回的数据作为响应发回。

5. 关闭服务器

请求结束后,服务器会调用一系列函数关闭请求连接。之后测试代码调用server_close()方法关闭服务器。

1 2 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部