def handle_request(self, env, start_response): trans_id_suffix = self.trans_id_suffix trans_id_extra = env.get('HTTP_X_TRANS_ID_EXTRA') if trans_id_extra: trans_id_suffix += '-' + trans_id_extra[:32] trans_id = generate_trans_id(trans_id_suffix) env['swift.trans_id'] = trans_id self.logger.txn_id = trans_id try: # catch any errors in the pipeline resp = self._app_call(env) except: # noqa self.logger.exception(_('Error: An error occurred')) resp = HTTPServerError(request=Request(env), body='An error occurred', content_type='text/plain') resp.headers['X-Trans-Id'] = trans_id resp.headers['X-Openstack-Request-Id'] = trans_id return resp(env, start_response) # make sure the response has the trans_id if self._response_headers is None: self._response_headers = [] self._response_headers.append(('X-Trans-Id', trans_id)) self._response_headers.append(('X-Openstack-Request-Id', trans_id)) start_response(self._response_status, self._response_headers, self._response_exc_info) return resp
def handle_request(self, env, start_response): trans_id = generate_trans_id(self.trans_id_suffix) env['swift.trans_id'] = trans_id self.logger.txn_id = trans_id try: # catch any errors in the pipeline resp = self._app_call(env) except (Exception, Timeout), err: self.logger.exception(_('Error: %s'), err) resp = HTTPServerError(request=Request(env), body='An error occurred', content_type='text/plain') resp.headers['X-Trans-Id'] = trans_id return resp(env, start_response)
def handle_request(self, env, start_response): trans_id = generate_trans_id(self.trans_id_suffix) env['swift.trans_id'] = trans_id self.logger.txn_id = trans_id try: # catch any errors in the pipeline resp = self._app_call(env) except (Exception, Timeout) as err: self.logger.exception(_('Error: %s'), err) resp = HTTPServerError(request=Request(env), body='An error occurred', content_type='text/plain') resp.headers['X-Trans-Id'] = trans_id return resp(env, start_response) # make sure the response has the trans_id if self._response_headers is None: self._response_headers = [] self._response_headers.append(('X-Trans-Id', trans_id)) start_response(self._response_status, self._response_headers, self._response_exc_info) return resp
def handle_request(self, req): """ Entry point for proxy server. Should return a WSGI-style callable (such as swob.Response). :param req: swob.Request object """ try: self.logger.set_statsd_prefix('proxy-server') if req.content_length and req.content_length < 0: self.logger.increment('errors') return HTTPBadRequest(request=req, body='Invalid Content-Length') try: if not check_utf8(req.path_info): self.logger.increment('errors') return HTTPPreconditionFailed( request=req, body='Invalid UTF8 or contains NULL') except UnicodeError: self.logger.increment('errors') return HTTPPreconditionFailed( request=req, body='Invalid UTF8 or contains NULL') try: controller, path_parts = self.get_controller(req.path) p = req.path_info if isinstance(p, unicode): p = p.encode('utf-8') except ValueError: self.logger.increment('errors') return HTTPNotFound(request=req) if not controller: self.logger.increment('errors') return HTTPPreconditionFailed(request=req, body='Bad URL') if self.deny_host_headers and \ req.host.split(':')[0] in self.deny_host_headers: return HTTPForbidden(request=req, body='Invalid host header') self.logger.set_statsd_prefix('proxy-server.' + controller.server_type.lower()) controller = controller(self, **path_parts) if 'swift.trans_id' not in req.environ: # if this wasn't set by an earlier middleware, set it now trans_id = generate_trans_id(self.trans_id_suffix) req.environ['swift.trans_id'] = trans_id self.logger.txn_id = trans_id req.headers['x-trans-id'] = req.environ['swift.trans_id'] controller.trans_id = req.environ['swift.trans_id'] self.logger.client_ip = get_remote_client(req) try: handler = getattr(controller, req.method) getattr(handler, 'publicly_accessible') except AttributeError: allowed_methods = getattr(controller, 'allowed_methods', set()) return HTTPMethodNotAllowed( request=req, headers={'Allow': ', '.join(allowed_methods)}) if 'swift.authorize' in req.environ: # We call authorize before the handler, always. If authorized, # we remove the swift.authorize hook so isn't ever called # again. If not authorized, we return the denial unless the # controller's method indicates it'd like to gather more # information and try again later. resp = req.environ['swift.authorize'](req) if not resp: # No resp means authorized, no delayed recheck required. del req.environ['swift.authorize'] else: # Response indicates denial, but we might delay the denial # and recheck later. If not delayed, return the error now. if not getattr(handler, 'delay_denial', None): return resp # Save off original request method (GET, POST, etc.) in case it # gets mutated during handling. This way logging can display the # method the client actually sent. req.environ['swift.orig_req_method'] = req.method return handler(req) except HTTPException as error_response: return error_response except (Exception, Timeout): self.logger.exception(_('ERROR Unhandled exception in request')) return HTTPServerError(request=req)
def handle_request(self, req): """ Entry point for proxy server. Should return a WSGI-style callable (such as swob.Response). :param req: swob.Request object """ try: self.logger.set_statsd_prefix('proxy-server') if req.content_length and req.content_length < 0: self.logger.increment('errors') return HTTPBadRequest(request=req, body='Invalid Content-Length') try: if not check_utf8(req.path_info): self.logger.increment('errors') return HTTPPreconditionFailed( request=req, body='Invalid UTF8 or contains NULL') except UnicodeError: self.logger.increment('errors') return HTTPPreconditionFailed( request=req, body='Invalid UTF8 or contains NULL') try: controller, path_parts = self.get_controller(req) p = req.path_info if isinstance(p, six.text_type): p = p.encode('utf-8') except APIVersionError: self.logger.increment('errors') return HTTPBadRequest(request=req) except ValueError: self.logger.increment('errors') return HTTPNotFound(request=req) if not controller: self.logger.increment('errors') return HTTPPreconditionFailed(request=req, body='Bad URL') if self.deny_host_headers and \ req.host.split(':')[0] in self.deny_host_headers: return HTTPForbidden(request=req, body='Invalid host header') self.logger.set_statsd_prefix('proxy-server.' + controller.server_type.lower()) controller = controller(self, **path_parts) if 'swift.trans_id' not in req.environ: # if this wasn't set by an earlier middleware, set it now trans_id_suffix = self.trans_id_suffix trans_id_extra = req.headers.get('x-trans-id-extra') if trans_id_extra: trans_id_suffix += '-' + trans_id_extra[:32] trans_id = generate_trans_id(trans_id_suffix) req.environ['swift.trans_id'] = trans_id self.logger.txn_id = trans_id req.headers['x-trans-id'] = req.environ['swift.trans_id'] controller.trans_id = req.environ['swift.trans_id'] self.logger.client_ip = get_remote_client(req) try: handler = getattr(controller, req.method) getattr(handler, 'publicly_accessible') except AttributeError: allowed_methods = getattr(controller, 'allowed_methods', set()) return HTTPMethodNotAllowed( request=req, headers={'Allow': ', '.join(allowed_methods)}) old_authorize = None if 'swift.authorize' in req.environ: # We call authorize before the handler, always. If authorized, # we remove the swift.authorize hook so isn't ever called # again. If not authorized, we return the denial unless the # controller's method indicates it'd like to gather more # information and try again later. resp = req.environ['swift.authorize'](req) if not resp and not req.headers.get('X-Copy-From-Account') \ and not req.headers.get('Destination-Account'): # No resp means authorized, no delayed recheck required. old_authorize = req.environ['swift.authorize'] else: # Response indicates denial, but we might delay the denial # and recheck later. If not delayed, return the error now. if not getattr(handler, 'delay_denial', None): return resp # Save off original request method (GET, POST, etc.) in case it # gets mutated during handling. This way logging can display the # method the client actually sent. req.environ['swift.orig_req_method'] = req.method try: if old_authorize: req.environ.pop('swift.authorize', None) return handler(req) finally: if old_authorize: req.environ['swift.authorize'] = old_authorize except HTTPException as error_response: return error_response except (Exception, Timeout): self.logger.exception(_('ERROR Unhandled exception in request')) return HTTPServerError(request=req)
def handle_request(self, req): """ Entry point for proxy server. Should return a WSGI-style callable (such as swob.Response). :param req: swob.Request object """ try: #设置日志的前缀为proxy-server self.logger.set_statsd_prefix('proxy-server') #如果请求长度为负数,报错 if req.content_length and req.content_length < 0: self.logger.increment('errors') return HTTPBadRequest(request=req, body='Invalid Content-Length') try: #如果路径信息不是有效的utf-8编码,报错 if not check_utf8(req.path_info): self.logger.increment('errors') return HTTPPreconditionFailed( request=req, body='Invalid UTF8 or contains NULL') except UnicodeError: #解码utf-8失败,报错 self.logger.increment('errors') return HTTPPreconditionFailed( request=req, body='Invalid UTF8 or contains NULL') try: #1、根据请求的路径信息,获取对应的控制器对象,并返回路径字典 controller, path_parts = self.get_controller(req) p = req.path_info if isinstance(p, six.text_type): p = p.encode('utf-8') except APIVersionError: self.logger.increment('errors') return HTTPBadRequest(request=req) except ValueError: self.logger.increment('errors') return HTTPNotFound(request=req) if not controller: self.logger.increment('errors') return HTTPPreconditionFailed(request=req, body='Bad URL') if self.deny_host_headers and \ req.host.split(':')[0] in self.deny_host_headers: return HTTPForbidden(request=req, body='Invalid host header') self.logger.set_statsd_prefix('proxy-server.' + controller.server_type.lower()) #2、生成控制器对象 controller = controller(self, **path_parts) #如果没有在请求的env中设置swift.trans_id,那么现在设置 if 'swift.trans_id' not in req.environ: # if this wasn't set by an earlier middleware, set it now trans_id_suffix = self.trans_id_suffix trans_id_extra = req.headers.get('x-trans-id-extra') if trans_id_extra: trans_id_suffix += '-' + trans_id_extra[:32] trans_id = generate_trans_id(trans_id_suffix) req.environ['swift.trans_id'] = trans_id self.logger.txn_id = trans_id req.headers['x-trans-id'] = req.environ['swift.trans_id'] controller.trans_id = req.environ['swift.trans_id'] self.logger.client_ip = get_remote_client(req) try: #3、根据请求方法,获取对应的函数指针handler handler = getattr(controller, req.method) getattr(handler, 'publicly_accessible') except AttributeError: allowed_methods = getattr(controller, 'allowed_methods', set()) return HTTPMethodNotAllowed( request=req, headers={'Allow': ', '.join(allowed_methods)}) old_authorize = None #4、如果请求的env中有鉴权方法,调用该鉴权方法,进行鉴权 if 'swift.authorize' in req.environ: # We call authorize before the handler, always. If authorized, # we remove the swift.authorize hook so isn't ever called # again. If not authorized, we return the denial unless the # controller's method indicates it'd like to gather more # information and try again later. resp = req.environ['swift.authorize'](req) if not resp and not req.headers.get('X-Copy-From-Account') \ and not req.headers.get('Destination-Account'): # No resp means authorized, no delayed recheck required. old_authorize = req.environ['swift.authorize'] else: # 返回resp代表鉴权失败,但是我们可能延迟后重新检查,如果没有设置延迟检查,则返回失败 # Response indicates denial, but we might delay the denial # and recheck later. If not delayed, return the error now. if not getattr(handler, 'delay_denial', None): return resp # Save off original request method (GET, POST, etc.) in case it # gets mutated during handling. This way logging can display the # method the client actually sent. req.environ['swift.orig_req_method'] = req.method try: #将鉴权方法从请求的env中取出,以免后续再次调用 if old_authorize: req.environ.pop('swift.authorize', None) #5、调用处理请求的方法,处理请求 return handler(req) finally: if old_authorize: req.environ['swift.authorize'] = old_authorize except HTTPException as error_response: return error_response except (Exception, Timeout): self.logger.exception(_('ERROR Unhandled exception in request')) return HTTPServerError(request=req)
def handle_request(self, req): """ Entry point for proxy server. Should return a WSGI-style callable (such as swob.Response). :param req: swob.Request object """ try: self.logger.set_statsd_prefix('proxy-server') # content_length存在且小于0,返回错误。 if req.content_length and req.content_length < 0: self.logger.increment('errors') return HTTPBadRequest(request=req, body='Invalid Content-Length') try: if not check_utf8(req.path_info): self.logger.increment('errors') return HTTPPreconditionFailed( request=req, body='Invalid UTF8 or contains NULL') except UnicodeError: self.logger.increment('errors') return HTTPPreconditionFailed( request=req, body='Invalid UTF8 or contains NULL') try: # 根据 path获取相应的 controller, 如: # 1. AccountController. 2. ContainerController # 3. ECObjectController 4. ReplicatedObjectController # 5. InfoController # path_parts is a dict : (version=version, # account_name=account, # container_name=container, # object_name=obj) controller, path_parts = self.get_controller(req) except APIVersionError: self.logger.increment('errors') return HTTPBadRequest(request=req) except ValueError: self.logger.increment('errors') return HTTPNotFound(request=req) if not controller: self.logger.increment('errors') return HTTPPreconditionFailed(request=req, body='Bad URL') if self.deny_host_headers and \ req.host.split(':')[0] in self.deny_host_headers: return HTTPForbidden(request=req, body='Invalid host header') self.logger.set_statsd_prefix('proxy-server.' + controller.server_type.lower()) # 实例化 controller controller = controller(self, **path_parts) if 'swift.trans_id' not in req.environ: # if this wasn't set by an earlier middleware, set it now trans_id_suffix = self.trans_id_suffix trans_id_extra = req.headers.get('x-trans-id-extra') if trans_id_extra: trans_id_suffix += '-' + trans_id_extra[:32] trans_id = generate_trans_id(trans_id_suffix) req.environ['swift.trans_id'] = trans_id self.logger.txn_id = trans_id req.headers['x-trans-id'] = req.environ['swift.trans_id'] controller.trans_id = req.environ['swift.trans_id'] self.logger.client_ip = get_remote_client(req) if req.method not in controller.allowed_methods: return HTTPMethodNotAllowed( request=req, headers={'Allow': ', '.join(controller.allowed_methods)}) # getattr(object, name) 返回一个对象的属性值 # 根据 req.method 的值返回controller的 HEAD() GET() PUT() 等函数 handler = getattr(controller, req.method) old_authorize = None # swift.authrize 是 swift_auth 提供的句柄 if 'swift.authorize' in req.environ: # We call authorize before the handler, always. If authorized, # we remove the swift.authorize hook so isn't ever called # again. If not authorized, we return the denial unless the # controller's method indicates it'd like to gather more # information and try again later. resp = req.environ['swift.authorize'](req) if not resp: # No resp means authorized, no delayed recheck required. old_authorize = req.environ['swift.authorize'] else: # Response indicates denial, but we might delay the denial # and recheck later. If not delayed, return the error now. if not getattr(handler, 'delay_denial', None): return resp # Save off original request method (GET, POST, etc.) in case it # gets mutated during handling. This way logging can display the # method the client actually sent. req.environ.setdefault('swift.orig_req_method', req.method) try: if old_authorize: req.environ.pop('swift.authorize', None) return handler(req) # call HEAD(),GET(),PUT(),etc... finally: if old_authorize: req.environ['swift.authorize'] = old_authorize except HTTPException as error_response: return error_response except (Exception, Timeout): self.logger.exception(_('ERROR Unhandled exception in request')) return HTTPServerError(request=req)
def handle_request(self, req): """ Entry point for proxy server. Should return a WSGI-style callable (such as swob.Response). :param req: swob.Request object """ try: self.logger.set_statsd_prefix("proxy-server") if req.content_length and req.content_length < 0: self.logger.increment("errors") return HTTPBadRequest(request=req, body="Invalid Content-Length") try: if not check_utf8(req.path_info): self.logger.increment("errors") return HTTPPreconditionFailed(request=req, body="Invalid UTF8 or contains NULL") except UnicodeError: self.logger.increment("errors") return HTTPPreconditionFailed(request=req, body="Invalid UTF8 or contains NULL") try: controller, path_parts = self.get_controller(req) p = req.path_info if isinstance(p, six.text_type): p = p.encode("utf-8") except APIVersionError: self.logger.increment("errors") return HTTPBadRequest(request=req) except ValueError: self.logger.increment("errors") return HTTPNotFound(request=req) if not controller: self.logger.increment("errors") return HTTPPreconditionFailed(request=req, body="Bad URL") if self.deny_host_headers and req.host.split(":")[0] in self.deny_host_headers: return HTTPForbidden(request=req, body="Invalid host header") self.logger.set_statsd_prefix("proxy-server." + controller.server_type.lower()) controller = controller(self, **path_parts) if "swift.trans_id" not in req.environ: # if this wasn't set by an earlier middleware, set it now trans_id_suffix = self.trans_id_suffix trans_id_extra = req.headers.get("x-trans-id-extra") if trans_id_extra: trans_id_suffix += "-" + trans_id_extra[:32] trans_id = generate_trans_id(trans_id_suffix) req.environ["swift.trans_id"] = trans_id self.logger.txn_id = trans_id req.headers["x-trans-id"] = req.environ["swift.trans_id"] controller.trans_id = req.environ["swift.trans_id"] self.logger.client_ip = get_remote_client(req) try: handler = getattr(controller, req.method) getattr(handler, "publicly_accessible") except AttributeError: allowed_methods = getattr(controller, "allowed_methods", set()) return HTTPMethodNotAllowed(request=req, headers={"Allow": ", ".join(allowed_methods)}) old_authorize = None if "swift.authorize" in req.environ: # We call authorize before the handler, always. If authorized, # we remove the swift.authorize hook so isn't ever called # again. If not authorized, we return the denial unless the # controller's method indicates it'd like to gather more # information and try again later. resp = req.environ["swift.authorize"](req) if ( not resp and not req.headers.get("X-Copy-From-Account") and not req.headers.get("Destination-Account") ): # No resp means authorized, no delayed recheck required. old_authorize = req.environ["swift.authorize"] else: # Response indicates denial, but we might delay the denial # and recheck later. If not delayed, return the error now. if not getattr(handler, "delay_denial", None): return resp # Save off original request method (GET, POST, etc.) in case it # gets mutated during handling. This way logging can display the # method the client actually sent. req.environ["swift.orig_req_method"] = req.method try: if old_authorize: req.environ.pop("swift.authorize", None) return handler(req) finally: if old_authorize: req.environ["swift.authorize"] = old_authorize except HTTPException as error_response: return error_response except (Exception, Timeout): self.logger.exception(_("ERROR Unhandled exception in request")) return HTTPServerError(request=req)
def handle_request(self, env, start_response): trans_id_suffix = self.trans_id_suffix trans_id_extra = env.get('HTTP_X_TRANS_ID_EXTRA') if trans_id_extra: trans_id_suffix += '-' + trans_id_extra[:32] trans_id = generate_trans_id(trans_id_suffix) env['swift.trans_id'] = trans_id self.logger.txn_id = trans_id try: # catch any errors in the pipeline resp = self._app_call(env) except: # noqa self.logger.exception(_('Error: An error occurred')) resp = HTTPServerError(request=Request(env), body=b'An error occurred', content_type='text/plain') resp.headers['X-Trans-Id'] = trans_id resp.headers['X-Openstack-Request-Id'] = trans_id return resp(env, start_response) # If the app specified a Content-Length, enforce that it sends that # many bytes. # # If an app gives too few bytes, then the client will wait for the # remainder before sending another HTTP request on the same socket; # since no more bytes are coming, this will result in either an # infinite wait or a timeout. In this case, we want to raise an # exception to signal to the WSGI server that it should close the # TCP connection. # # If an app gives too many bytes, then we can deadlock with the # client; if the client reads its N bytes and then sends a large-ish # request (enough to fill TCP buffers), it'll block until we read # some of the request. However, we won't read the request since # we'll be trying to shove the rest of our oversized response out # the socket. In that case, we truncate the response body at N bytes # and raise an exception to stop any more bytes from being # generated and also to kill the TCP connection. if env['REQUEST_METHOD'] == 'HEAD': resp = enforce_byte_count(resp, 0) elif self._response_headers: content_lengths = [ val for header, val in self._response_headers if header.lower() == "content-length" ] if len(content_lengths) == 1: try: content_length = int(content_lengths[0]) except ValueError: pass else: resp = enforce_byte_count(resp, content_length) # make sure the response has the trans_id if self._response_headers is None: self._response_headers = [] self._response_headers.append(('X-Trans-Id', trans_id)) self._response_headers.append(('X-Openstack-Request-Id', trans_id)) start_response(self._response_status, self._response_headers, self._response_exc_info) return resp
def handle_request(self, env, start_response): trans_id_suffix = self.trans_id_suffix trans_id_extra = env.get('HTTP_X_TRANS_ID_EXTRA') if trans_id_extra: trans_id_suffix += '-' + trans_id_extra[:32] trans_id = generate_trans_id(trans_id_suffix) env['swift.trans_id'] = trans_id self.logger.txn_id = trans_id try: # catch any errors in the pipeline resp = self._app_call(env) except: # noqa self.logger.exception(_('Error: An error occurred')) resp = HTTPServerError(request=Request(env), body=b'An error occurred', content_type='text/plain') resp.headers['X-Trans-Id'] = trans_id resp.headers['X-Openstack-Request-Id'] = trans_id return resp(env, start_response) # If the app specified a Content-Length, enforce that it sends that # many bytes. # # If an app gives too few bytes, then the client will wait for the # remainder before sending another HTTP request on the same socket; # since no more bytes are coming, this will result in either an # infinite wait or a timeout. In this case, we want to raise an # exception to signal to the WSGI server that it should close the # TCP connection. # # If an app gives too many bytes, then we can deadlock with the # client; if the client reads its N bytes and then sends a large-ish # request (enough to fill TCP buffers), it'll block until we read # some of the request. However, we won't read the request since # we'll be trying to shove the rest of our oversized response out # the socket. In that case, we truncate the response body at N bytes # and raise an exception to stop any more bytes from being # generated and also to kill the TCP connection. if env['REQUEST_METHOD'] == 'HEAD': resp = enforce_byte_count(resp, 0) elif self._response_headers: content_lengths = [val for header, val in self._response_headers if header.lower() == "content-length"] if len(content_lengths) == 1: try: content_length = int(content_lengths[0]) except ValueError: pass else: resp = enforce_byte_count(resp, content_length) # make sure the response has the trans_id if self._response_headers is None: self._response_headers = [] self._response_headers.append(('X-Trans-Id', trans_id)) self._response_headers.append(('X-Openstack-Request-Id', trans_id)) start_response(self._response_status, self._response_headers, self._response_exc_info) return resp
def handle_request(self, req): """ Entry point for proxy server. Should return a WSGI-style callable (such as swob.Response). :param req: swob.Request object """ try: self.logger.set_statsd_prefix('proxy-server') if req.content_length and req.content_length < 0: self.logger.increment('errors') return HTTPBadRequest(request=req, body='Invalid Content-Length') try: if not check_utf8(req.path_info): self.logger.increment('errors') return HTTPPreconditionFailed( request=req, body='Invalid UTF8 or contains NULL') except UnicodeError: self.logger.increment('errors') return HTTPPreconditionFailed( request=req, body='Invalid UTF8 or contains NULL') try: # 这里确定controller的类型,根据req的内容分别返回: # account controller,container controller 或者 object controller。 controller, path_parts = self.get_controller(req) p = req.path_info if isinstance(p, unicode): p = p.encode('utf-8') except APIVersionError: self.logger.increment('errors') return HTTPBadRequest(request=req) except ValueError: self.logger.increment('errors') return HTTPNotFound(request=req) if not controller: self.logger.increment('errors') return HTTPPreconditionFailed(request=req, body='Bad URL') if self.deny_host_headers and \ req.host.split(':')[0] in self.deny_host_headers: return HTTPForbidden(request=req, body='Invalid host header') self.logger.set_statsd_prefix('proxy-server.' + controller.server_type.lower()) controller = controller(self, **path_parts) if 'swift.trans_id' not in req.environ: # if this wasn't set by an earlier middleware, set it now trans_id_suffix = self.trans_id_suffix trans_id_extra = req.headers.get('x-trans-id-extra') if trans_id_extra: trans_id_suffix += '-' + trans_id_extra[:32] trans_id = generate_trans_id(trans_id_suffix) req.environ['swift.trans_id'] = trans_id self.logger.txn_id = trans_id req.headers['x-trans-id'] = req.environ['swift.trans_id'] controller.trans_id = req.environ['swift.trans_id'] self.logger.client_ip = get_remote_client(req) try: # 这里的handler是相应controller类中对应于req中方法的方法。 # 这些方法包括:GET,HEAD,POST,PUT,DELETE,COPY handler = getattr(controller, req.method) getattr(handler, 'publicly_accessible') except AttributeError: allowed_methods = getattr(controller, 'allowed_methods', set()) return HTTPMethodNotAllowed( request=req, headers={'Allow': ', '.join(allowed_methods)}) if 'swift.authorize' in req.environ: # We call authorize before the handler, always. If authorized, # we remove the swift.authorize hook so isn't ever called # again. If not authorized, we return the denial unless the # controller's method indicates it'd like to gather more # information and try again later. resp = req.environ['swift.authorize'](req) if not resp and not req.headers.get('X-Copy-From-Account') \ and not req.headers.get('Destination-Account'): # No resp means authorized, no delayed recheck required. del req.environ['swift.authorize'] else: # Response indicates denial, but we might delay the denial # and recheck later. If not delayed, return the error now. if not getattr(handler, 'delay_denial', None): return resp # Save off original request method (GET, POST, etc.) in case it # gets mutated during handling. This way logging can display the # method the client actually sent. req.environ['swift.orig_req_method'] = req.method # 这里返回的是相应于req的controller中具体的处理这个类型的req的方法。 # 经过层层调用之后,handler(req)其实是一个Response类的实例。 # 调用过程为(以get object为例): # swift.proxy.controllers.ObjectControllerRouter 中找到对应的controller # 在 BaseObjectController 中找到 GET 方法,GET 方法使用 GETorHEAD 方法 # GETorHEAD 方法跳到 ReplicatedObjectController 中的 _get_or_head_response 方法 # _get_or_head_response 使用 swift.proxy.controller.Controller(base.py)中的 GETorHEAD_base 方法 # GETorHEAD_base 中调用 GetOrHeadHandler 类中的 get_working_response 方法 # get_working_response 方法构建一个 Response 类的实例,并返回。 # 这个 Response 类的实例就是这里被返回的值。 return handler(req) except HTTPException as error_response: return error_response except (Exception, Timeout): self.logger.exception(_('ERROR Unhandled exception in request')) return HTTPServerError(request=req)