searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

基于装饰器模式的 WSGI Server

2023-09-26 08:34:45
13
0

WSGI

WSGI 是 Web Server Gateway Interface 的缩写。是 Web 服务器如 Apache、Nginx 等与应用服务器(Application)进行交互的约定接口和规范。应用服务器通过实现该接口,可以与任意遵守该规范的 Web Server 通信。

eventlet.wsgi.py

提供基础的文件流读写,HTTP报文头的解析与写入(HttpProtocol实现),并实现了一个简单的 Server包装类(包含了 Server 常见的 socketaddress,keepalive等,并简单的将请求转发给 HttpProtocol来处理)。并在这个文件中,提供启动HTTP Sever 的功能函数,在这个函数中开启事件循环和 socket监听,代码如下(在 Server 函数中):

其中HttpProtocol类维护从socketconn中获得的读写文件实例rfile, wfile,并从中进行读写数据。这个类中handle_one_request函数完成简单的HTTP报文头校验,然后调用handle_one_response方法获取 responsehandle_one_response函数利用self.application函数调用保存的WSGI Application来完成对应的业务逻辑,然后将Application返回的结果result写入HTTP请求头信息,最后写入到wfile中。

 

nova.wsgi.py

包含几个主要的类:ServerApplicationMiddleware 和 Router其中 Server 维护了 hostportprotocolpool_size 等参数,作为一个通用的Socket Server来使用,可以通过指定不同的 protocol来启动不同的 socket 服务。并提供了startstopwait来管理服务器的状态。ServerStart方法可以启动一个eventlet.wsgi.server:

def start(self):
     """Start serving a WSGI application.
     :returns: None
     """
     # The server socket object will be closed after server exits,
     # but the underlying file descriptor will remain open, and will
     # give bad file descriptor error. So duplicating the socket object,
     # to keep file descriptor usable.

     dup_socket = self._socket.dup()
     dup_socket.setsockopt(socket.SOL_SOCKET,
                           socket.SO_REUSEADDR, 1)
     # sockets can hang around forever without keepalive
     dup_socket.setsockopt(socket.SOL_SOCKET,
                           socket.SO_KEEPALIVE, 1)
				...
     wsgi_kwargs = {
         'func': eventlet.wsgi.server,
         'sock': dup_socket,
         'site': self.app,
         'protocol': self._protocol,
         'custom_pool': self._pool,
         'log': self._logger,
         'log_format': CONF.wsgi.wsgi_log_format,
         'debug': False,
         'keepalive': CONF.wsgi.keep_alive,
         'socket_timeout': self.client_socket_timeout
         }

     if self._max_url_len:
         wsgi_kwargs['url_length_limit'] = self._max_url_len

     self._server = utils.spawn(**wsgi_kwargs)

 

Application仅定义了一个 WSGI Application 的接口,主要是__call__函数的接口,Application的子类都要通过wsgify装饰器来装饰__call__方法,使其行为表现的像一个 WSGI Application

Middleware 继承了 Application ,意味着Middleware可以表现的像一个Application。同时也保存了一个 Application 成员引用,Middleware作为 request 处理流程中的中间件。默认 Middleware以函数形式调用,执行__call__函数然后调用 self.application 使用内置 Application。同时值得注意的是,Middleware__call__使用webob.dec.wsgify来进行修饰。webob.dec.wsgify类是一个装饰器,将被装饰函数func进行装饰,使func表现为一个WSGI Application。具体来说,webob.dec.wsgify 中的 __call__函数,也是装饰器实现装饰功能的地方,会将传进的参数req包装为webob.Request对象,

environ = req
         start_response = args[0]
         req = self.RequestClass(environ)
         req.response = req.ResponseClass()
         try:
             args, kw = self._prepare_args(None, None)
             resp = self.call_func(req, *args, **kw)
         except HTTPException as exc:
             resp = exc

然后在self.call_func函数中调用func函数,再将返回结果包装为Response对象:

 if isinstance(resp, bytes):
             body = resp
             resp = req.response
             resp.write(body)
         if resp is not req.response:
             resp = req.response.merge_cookies(resp)
         return resp(environ, start_response)

 

值得注意的是,Middleware可以利用`wsgify'装饰器来实现装饰器模式,在源代码中,可能还同时作为责任链模式的实现,用于链式处理请求。Router类负责将url映射到对应的controller,并完成请求分发。

nova.api.openstack.wsgi.py

该文件中包含了Resource类、Controller类、actionControllerMetaclass类以及Request类。其中Resource类继承自wsgi.Application,包含一个controller成员变量。负责根据请求从路由信息中找到对应的method去执行。这当中涉及到action的路由问题。具体的会调用Resource__call__方法,在该方法中调用_process_task方法查找具体的method来执行。ControllerMetaclass类主要工作是完成actionmethod的映射构建。Controller类看不出他的作用,作为一个Controller的基类。

0条评论
0 / 1000
张运昌
3文章数
0粉丝数
张运昌
3 文章 | 0 粉丝
张运昌
3文章数
0粉丝数
张运昌
3 文章 | 0 粉丝
原创

基于装饰器模式的 WSGI Server

2023-09-26 08:34:45
13
0

WSGI

WSGI 是 Web Server Gateway Interface 的缩写。是 Web 服务器如 Apache、Nginx 等与应用服务器(Application)进行交互的约定接口和规范。应用服务器通过实现该接口,可以与任意遵守该规范的 Web Server 通信。

eventlet.wsgi.py

提供基础的文件流读写,HTTP报文头的解析与写入(HttpProtocol实现),并实现了一个简单的 Server包装类(包含了 Server 常见的 socketaddress,keepalive等,并简单的将请求转发给 HttpProtocol来处理)。并在这个文件中,提供启动HTTP Sever 的功能函数,在这个函数中开启事件循环和 socket监听,代码如下(在 Server 函数中):

其中HttpProtocol类维护从socketconn中获得的读写文件实例rfile, wfile,并从中进行读写数据。这个类中handle_one_request函数完成简单的HTTP报文头校验,然后调用handle_one_response方法获取 responsehandle_one_response函数利用self.application函数调用保存的WSGI Application来完成对应的业务逻辑,然后将Application返回的结果result写入HTTP请求头信息,最后写入到wfile中。

 

nova.wsgi.py

包含几个主要的类:ServerApplicationMiddleware 和 Router其中 Server 维护了 hostportprotocolpool_size 等参数,作为一个通用的Socket Server来使用,可以通过指定不同的 protocol来启动不同的 socket 服务。并提供了startstopwait来管理服务器的状态。ServerStart方法可以启动一个eventlet.wsgi.server:

def start(self):
     """Start serving a WSGI application.
     :returns: None
     """
     # The server socket object will be closed after server exits,
     # but the underlying file descriptor will remain open, and will
     # give bad file descriptor error. So duplicating the socket object,
     # to keep file descriptor usable.

     dup_socket = self._socket.dup()
     dup_socket.setsockopt(socket.SOL_SOCKET,
                           socket.SO_REUSEADDR, 1)
     # sockets can hang around forever without keepalive
     dup_socket.setsockopt(socket.SOL_SOCKET,
                           socket.SO_KEEPALIVE, 1)
				...
     wsgi_kwargs = {
         'func': eventlet.wsgi.server,
         'sock': dup_socket,
         'site': self.app,
         'protocol': self._protocol,
         'custom_pool': self._pool,
         'log': self._logger,
         'log_format': CONF.wsgi.wsgi_log_format,
         'debug': False,
         'keepalive': CONF.wsgi.keep_alive,
         'socket_timeout': self.client_socket_timeout
         }

     if self._max_url_len:
         wsgi_kwargs['url_length_limit'] = self._max_url_len

     self._server = utils.spawn(**wsgi_kwargs)

 

Application仅定义了一个 WSGI Application 的接口,主要是__call__函数的接口,Application的子类都要通过wsgify装饰器来装饰__call__方法,使其行为表现的像一个 WSGI Application

Middleware 继承了 Application ,意味着Middleware可以表现的像一个Application。同时也保存了一个 Application 成员引用,Middleware作为 request 处理流程中的中间件。默认 Middleware以函数形式调用,执行__call__函数然后调用 self.application 使用内置 Application。同时值得注意的是,Middleware__call__使用webob.dec.wsgify来进行修饰。webob.dec.wsgify类是一个装饰器,将被装饰函数func进行装饰,使func表现为一个WSGI Application。具体来说,webob.dec.wsgify 中的 __call__函数,也是装饰器实现装饰功能的地方,会将传进的参数req包装为webob.Request对象,

environ = req
         start_response = args[0]
         req = self.RequestClass(environ)
         req.response = req.ResponseClass()
         try:
             args, kw = self._prepare_args(None, None)
             resp = self.call_func(req, *args, **kw)
         except HTTPException as exc:
             resp = exc

然后在self.call_func函数中调用func函数,再将返回结果包装为Response对象:

 if isinstance(resp, bytes):
             body = resp
             resp = req.response
             resp.write(body)
         if resp is not req.response:
             resp = req.response.merge_cookies(resp)
         return resp(environ, start_response)

 

值得注意的是,Middleware可以利用`wsgify'装饰器来实现装饰器模式,在源代码中,可能还同时作为责任链模式的实现,用于链式处理请求。Router类负责将url映射到对应的controller,并完成请求分发。

nova.api.openstack.wsgi.py

该文件中包含了Resource类、Controller类、actionControllerMetaclass类以及Request类。其中Resource类继承自wsgi.Application,包含一个controller成员变量。负责根据请求从路由信息中找到对应的method去执行。这当中涉及到action的路由问题。具体的会调用Resource__call__方法,在该方法中调用_process_task方法查找具体的method来执行。ControllerMetaclass类主要工作是完成actionmethod的映射构建。Controller类看不出他的作用,作为一个Controller的基类。

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0