Nova API服务 之 处理HTTP请求的流程
来源:互联网 发布:淘宝联盟手安卓版 编辑:程序博客网 时间:2024/06/03 19:14
一、回顾
1、Nova API服务的主要功能都在osapi_compute_app_v2应用程序中实现。osapi_compute_app_v2应用程序对应的工
厂方法是APIRouter类的factory方法。APIRouter类的factory方法会返回一个APIRouter对象。当客户端发送HTTP请
求的时候,会调用APIRouter对象的__call__方法。
2、APIRouter继承自Router类,__call__方法便定义在Router类中。Router类的__call__方法的定义是self.router
对象,最终会返回资源对应的Controller对象。
3、servers资源的Controller对象是一个wsgi.Resource对象。因此。当客户端发送HTTP请求后,Nova API服务最终
会调用wsgi.Resource对象的__call__方法。 /nova/api/openstack/wsgi.py
def create_resource(ext_mgr): return wsgi.Resource(Controller(ext_mgr))
二、wsgi.Resource类的初始化方法和__call__方法的定义
1、初始化方法
wsgi.Resource类的初始化方法定义如下:
def __init__(self, controller, action_peek = None, inherits = None,#底层Controller对象self.controller = controller # 反序列化对象default_deserializers = dict(json = JSONDeserializer)default_deserializers.update(deserializers)self.default_deserializers = default_deserializers# 序列化对象self.default_serializers = dict(json = JSONDictSerializer)......Resource类是在资源的底层Controller类的基础上,添加了序列化和反序列化的功能。
序列化:是指将XML或JSON格式的数据转化成字符串格式,以便于在网络间传输
反序列化:将字符串数格式的数据转换为XML或JSON数据格式,以便于显示和处理。 所以,在Resource类中通过两个
成员变量default_deserializers和default_serializers来分别实现数据的反序列化和序列化。
2、__call__方法
Resource类的__call__方法定义如下:
@webob.dec.wsgify(RequestClass=Request) //wsgify装饰器def __call__(self, request): # Identify the action, its arguments, and the requested # content type#获取客户端传入的HTTP请求参数 action_args = self.get_action_args(request.environ)#获取HTTP请求的操作名:post put delete get action = action_args.pop('action', None)#获取客户端传入的报文#content_type:客户端传入的报文格式 body:客户端传入的报文内容 content_type, body = self.get_body(request)#获取服务器返回的报文类型 accept = request.best_match_content_type()#处理HTTP请求 return self._process_stack(request, action, action_args, content_type, body, accept)可以看出,__call__方法最后调用了_process_stack方法。
_process_stack方法的定义如下:
def _process_stack(self, request, action, action_args, content_type, body, accept): #获取处理HTTP请求的方法 try: meth, extensions = self.get_method(request, action, content_type, body) except (AttributeError, TypeError): return Fault(webob.exc.HTTPNotFound()) except KeyError as ex: msg = _("There is no such action: %s") % ex.args[0] return Fault(webob.exc.HTTPBadRequest(explanation=msg)) except exception.MalformedRequestBody: msg = _("Malformed request body") return Fault(webob.exc.HTTPBadRequest(explanation=msg)) if body: msg = _("Action: '%(action)s', calling method: %(meth)s, body: " "%(body)s") % {'action': action, 'body': six.text_type(body, 'utf-8'), 'meth': str(meth)} LOG.debug(strutils.mask_password(msg)) else: LOG.debug("Calling method '%(meth)s'", {'meth': str(meth)}) #反序列化客户端传入的消息 try: contents = {} if self._should_have_body(request): #如果传入客户端消息 # allow empty body with PUT and POST if request.content_length == 0: contents = {'body': None} else: contents = self.deserialize(meth, content_type, body) except exception.InvalidContentType: msg = _("Unsupported Content-Type") return Fault(webob.exc.HTTPUnsupportedMediaType(explanation=msg)) except exception.MalformedRequestBody: msg = _("Malformed request body") return Fault(webob.exc.HTTPBadRequest(explanation=msg)) #更新请求的参数,将传入的消息体内容添加到action_args中 action_args.update(contents)#获取客户端所属的项目ID project_id = action_args.pop("project_id", None) context = request.environ.get('nova.context')#检查客户端请求是否合法 if (context and project_id and (project_id != context.project_id)): msg = _("Malformed request URL: URL's project_id '%(project_id)s'" " doesn't match Context's project_id" " '%(context_project_id)s'") % \ {'project_id': project_id, 'context_project_id': context.project_id} return Fault(webob.exc.HTTPBadRequest(explanation=msg)) #执行HTTP请求的前向扩展方法 response, post = self.pre_process_extensions(extensions, request, action_args)#前向扩展方法没有返回response,说明需要对请求进行进一步处理 if not response: try: with ResourceExceptionHandler():#执行底层Controller对象中 处理HTTP请求 的方法 action_result = self.dispatch(meth, request, action_args) except Fault as ex: response = ex#前向扩展方法没有返回response,处理底层controller对象 方法返回的结果 if not response: resp_obj = None#如果controller对象方法返回结果为字典,则封装成ResponseObject对象 if type(action_result) is dict or action_result is None: resp_obj = ResponseObject(action_result)#如果controller对象方法返回结果为ResponseObject对象 elif isinstance(action_result, ResponseObject): resp_obj = action_result#否则认为返回的结果是response对象 else: response = action_result #如果controller对象方法没有返回response对象,则继续处理resp_obj对象 if resp_obj: #获取controller对象方法 指定的序列化对象 serializers = getattr(meth, 'wsgi_serializers', {})#绑定序列化对象 resp_obj._bind_method_serializers(serializers)#获取controller对象方法默认的HTTP code if hasattr(meth, 'wsgi_code'): resp_obj._default_code = meth.wsgi_code#获取accept报文格式下的序列化方法#如果controller对象方法未指定序列化方法,则使用默认的序列化方法 resp_obj.preserialize(accept, self.default_serializers) #执行HTTP请求的后向扩展方法 response = self.post_process_extensions(post, resp_obj, request, action_args)#如果后向方法没有返回response对象 if resp_obj and not response:#将controller对象方法返回结果 序列化 response = resp_obj.serialize(request, accept, self.default_serializers) if hasattr(response, 'headers'): for hdr, val in response.headers.items(): # Headers must be utf-8 strings response.headers[hdr] = utils.utf8(str(val)) if not request.api_version_request.is_null(): response.headers[API_VERSION_REQUEST_HEADER] = \ request.api_version_request.get_string() response.headers['Vary'] = API_VERSION_REQUEST_HEADER return response(1)、获取HTTP请求的参数,调用deserialize方法将 HTTP请求的消息体反序列化成 字典对象。并且通过检查项目ID
来验证客户是否有执行HTTP请求的权限。
(2)、调用pre_process_extensions方法执行HTTP请求的前向扩展方法。前向扩展方法是为了便于二次开发预留的接
口。在Nova API处理HTTP请求的时候,会首先执行前向扩展方法,然后再执行底层Controller对象中的处理方法。
pre_process_extensions方法返回一个post对象,它是HTTP请求后向扩展方法的列表。后向扩展方法也是预留的二次
开发接口,会在底层的Controller对象的处理方法执行之后执行。
(3)、通过调用dispatch方法运行底层Controller对象的处理方法。底层Controller对象处理方法返回一个字典。
resp_obj = ResponseObject(action_result)将返回的结果封装成ResponseObject对象。
(4)、对ResponseObject对象进行一些配置,需要配置的属性有:序列化对象、默认的HTTP CODE。
(5)、ResponseObject对象的序列化对象和HTTP Code是在底层Controller对象的处理方法中指定。底层Controller对
象的每个处理方法都可以通过装饰器指定序列化对象、反序列化对象和HTTP Code。例如:
指定了index方法的XML序列化对象为MinimalServersTemplate对象,如下代码片段:
指定了create方法的XML序列化对象为 FullServersTemplate对象,xml反序列化对象为CreateDeserializer,默认的
HTTP Code为202。当HTTP请求处理成功时,Nova API服务器会向客户端返回202 的HTTP Code。
(6)、HTTP请求的后向扩展方法,将ResponseObject对象序列化。
总结:由于前向扩展方法和后向扩展方法在Nova中没有使用过,因此HTTP请求的核心工作依然在底层Controller类的
处理方法中定义。_process_stack方法主要是完成了数据的序列化和反序列化工作。
- Nova API服务 之 处理HTTP请求的流程
- Liberty nova-api HTTP请求执行流程
- openstack之nova-api服务流程分析
- openstack之nova-api服务流程分析
- Nova API服务之Nova API服务的启动
- NOVA-API服务的启动流程
- NOVA-API服务的启动流程
- NOVA-API服务启动流程
- NOVA-API服务启动流程
- Openstack Nova API服务流程
- Nova RPC服务 之 Nova Scheduler 的启动流程
- Nova API服务 之 创建虚拟机流程(1)
- Nova API服务 之 创建虚拟机流程(2)
- Nova API服务之 创建虚拟机流程(3)
- openstack nova-api 服务流程介绍
- Servlet之tomcat处理Http请求的流程
- Http请求处理流程
- Http请求处理流程
- POJ 3175 枚举
- Chapter 2 Swarm管理Docker集群
- RBM介绍
- Myeclipse中链接Oracle并实现简单查询-JDBC
- Centos7 安装7z
- Nova API服务 之 处理HTTP请求的流程
- ssoj2867淘淘的柱子朋友
- CSerialPort多线程串口编程工具详解
- MySQL 视图操作
- 【Day35】浅谈PHP拦截器之__set()与__get()的理解与使用方法
- NAT简介及穿透
- Console命令详解
- 对IO学习的总结
- IOS手势处理的那些坑