Api消息參數(shù)的傳遞
在服務(wù)啟動之后春缕,WSGIServer就開始在監(jiān)聽client的請求了
注:關(guān)于服務(wù)的啟動悦陋,在前面幾篇文檔中已有詳細說明么鹤,請移步查看那各app是如何獲取到請求的相關(guān)參數(shù)的呢案狠?比如策略的創(chuàng)建:
@parameter_checker.is_valid_body(dj_constants.SERVICES)
def create(self, req, **kwargs):
"""
create a service
:param req:
:param kwargs:
:return:
"""
context = req.environ['test.context']
services = objects.PlanList.get_all_by_project(context,
context.project_id,
None, None)
這就涉及到plan app的注冊過程
在router.py的APIRouter中磕昼,mapper中plan對應(yīng)的controller是resource類型的對象
class APIRouter(wsgi_common.Router):
@classmethod
def factory(cls, global_conf, **local_conf):
return cls(ProjectMapper())
def __init__(self, mapper):
plans_resources = plans.create_resource()
可以看到create_resource()方法返回的是一個wsgi.py的Resource對象卷雕,而Resource類又繼承自wsgi.py的Application類,Resource實現(xiàn)了Application的__call__方法票从,這個方法會在對象調(diào)用的時候被自動執(zhí)行
def __call__(self, request):
"""WSGI method that controls (de)serialization and method dispatch."""
LOG.info(_LI("%(method)s %(url)s"),
{"method": request.method,
"url": request.url})
# Identify the action, its arguments, and the requested
# content type
action_args = self.get_action_args(request.environ)
action = action_args.pop('action', None)
content_type, body = self.get_body(request)
accept = request.best_match_content_type()
# NOTE(Vek): Splitting the function up this way allows for
# auditing by external tools that wrap the existing
# function. If we try to audit __call__(), we can
# run into troubles due to the @webob.dec.wsgify()
# decorator.
return self._process_stack(request, action, action_args,
content_type, body, accept)
該方法通過解析request漫雕,得到當前請求的http字段(content_type,method類型峰鄙,body等)浸间,_process_stack方法如下
def _process_stack(self, request, action, action_args,
content_type, body, accept):
"""Implement the processing stack."""
# Get the implementing method
try:
meth, extensions = self.get_method(request, action,
content_type, body)
…
# Now, deserialize the request body...
try:
if content_type:
contents = self.deserialize(meth, content_type, body)
else:
contents = {}
…
# Update the action args
action_args.update(contents)
project_id = action_args.pop("project_id", None)
context = request.environ.get('test.context')
if (context and project_id and (project_id != context.project_id)):
msg = _("Malformed request url")
return Fault(webob.exc.HTTPBadRequest(explanation=msg))
# Run pre-processing extensions
response, post = self.pre_process_extensions(extensions,
meth為從控制器中根據(jù)action的值獲取相應(yīng)的方法(例如:cinder.api.v1.volumes.VolumeController.create);extensions為根據(jù)控制器和action的值獲取相應(yīng)的擴展方法吟榴;
def pre_process_extensions(self, extensions, request, action_args):
# List of callables for post-processing extensions
post = []
for ext in extensions:
if inspect.isgeneratorfunction(ext):
response = None
# If it's a generator function, the part before the
# yield is the preprocessing stage
try:
with ResourceExceptionHandler():
gen = ext(req=request, **action_args)
response = next(gen)
except Fault as ex:
response = ex
# We had a response...
if response:
return response, []
上面的代碼中魁蒜,其中ext就是實際調(diào)用的方法名,可以發(fā)現(xiàn)ext(req=request, **action_args)吩翻,最終是從這里將業(yè)務(wù)方法的參數(shù)傳遞進去的
博客:https://tunsuy.github.io/
github:https://github.com/tunsuy