def handle_request(self): if hasattr(self, self.request.method): try: handler = getattr(self, self.request.method) getattr(handler, 'publicly_accessible') except AttributeError: # TODO(kota_): add allowed_method list to Allow header return HTTPMethodNotAllowed(request=self.request) return handler() else: raise HTTPMethodNotAllowed(request=self.request)
def DELETE(self, req): """HTTP DELETE request handler.""" # Extra safety in case someone typos a query string for an # account-level DELETE request that was really meant to be caught by # some middleware. if req.query_string: return HTTPBadRequest(request=req) if not self.app.allow_account_management: return HTTPMethodNotAllowed( request=req, headers={'Allow': ', '.join(self.allowed_methods)}) account_partition, accounts = \ self.app.account_ring.get_nodes(self.account_name) headers = { 'X-Timestamp': normalize_timestamp(time.time()), 'X-Trans-Id': self.trans_id, 'Connection': 'close' } if self.app.memcache: self.app.memcache.delete( get_account_memcache_key(self.account_name)) resp = self.make_requests(req, self.app.account_ring, account_partition, 'DELETE', req.path_info, [headers] * len(accounts)) return resp
def handle_request(self, env, req): if req.method not in ('GET', 'HEAD'): headers = self._getCacheHeaders(CACHE_BAD_URL) return HTTPMethodNotAllowed(request=req, headers=headers) if self.allowed_origin_remote_ips and \ req.remote_addr not in self.allowed_origin_remote_ips: raise OriginRequestNotAllowed( 'SOS Origin: Remote IP %s not allowed' % req.remote_addr) # allow earlier middleware to override hash and obj_name hsh = env.get('swift.cdn_hash') object_name = env.get('swift.cdn_object_name') if hsh is None or object_name is None: for regex in self.cdn_regexes: match_obj = regex.match(req.url) if match_obj: match_dict = match_obj.groupdict() if not hsh: hsh = match_dict.get('hash') if not object_name: object_name = match_dict.get('object_name') break if not hsh: self.logger.debug('Hash %s not found in %s' % (hsh, req.url)) headers = self._getCacheHeaders(CACHE_BAD_URL) return HTTPNotFound(request=req, headers=headers) if hsh.find('-') >= 0: hsh = hsh.split('-', 1)[1] try: cdn_obj_path = self.get_hsh_obj_path(hsh) except ValueError, e: self.logger.debug('get_hsh_obj_path error: %s' % e) headers = self._getCacheHeaders(CACHE_BAD_URL) return HTTPBadRequest(request=req, headers=headers)
def __call__(self, env, start_response): start_time = time.time() req = Request(env) self.logger.txn_id = req.headers.get('x-trans-id', None) if not check_utf8(req.path_info): res = HTTPPreconditionFailed(body='Invalid UTF8 or contains NULL') else: try: # disallow methods which have not been marked 'public' try: method = getattr(self, req.method) getattr(method, 'publicly_accessible') replication_method = getattr(method, 'replication', False) if (self.replication_server is not None and self.replication_server != replication_method): raise AttributeError('Not allowed method.') except AttributeError: res = HTTPMethodNotAllowed() else: res = method(req) except HTTPException as error_response: res = error_response except (Exception, Timeout): self.logger.exception(_( 'ERROR __call__ error with %(method)s %(path)s '), {'method': req.method, 'path': req.path}) res = HTTPInternalServerError(body=traceback.format_exc()) if self.log_requests: trans_time = time.time() - start_time log_message = get_log_line(req, res, trans_time, '') if req.method.upper() == 'REPLICATE': self.logger.debug(log_message) else: self.logger.info(log_message) return res(env, start_response)
def __call__(self, env, start_response): start_time = time.time() req = Request(env) self.logger.txn_id = req.headers.get('x-trans-id', None) if not check_utf8(req.path_info): res = HTTPPreconditionFailed(body='Invalid UTF8') else: try: # disallow methods which have not been marked 'public' try: method = getattr(self, req.method) getattr(method, 'publicly_accessible') except AttributeError: res = HTTPMethodNotAllowed() else: res = method(req) except (Exception, Timeout): self.logger.exception( _('ERROR __call__ error with %(method)s %(path)s '), { 'method': req.method, 'path': req.path }) res = HTTPInternalServerError(body=traceback.format_exc()) trans_time = '%.4f' % (time.time() - start_time) log_message = '%s - - [%s] "%s %s" %s %s "%s" "%s" "%s" %s' % ( req.remote_addr, time.strftime('%d/%b/%Y:%H:%M:%S +0000', time.gmtime()), req.method, req.path, res.status.split()[0], res.content_length or '-', req.headers.get('x-trans-id', '-'), req.referer or '-', req.user_agent or '-', trans_time) if req.method.upper() == 'REPLICATE': self.logger.debug(log_message) else: self.logger.info(log_message) return res(env, start_response)
def __call__(self, env, start_response): start_time = time.time() req = Request(env) self.logger.txn_id = req.headers.get('x-trans-id', None) if not check_utf8(req.path_info): res = HTTPPreconditionFailed(body='Invalid UTF8 or contains NULL') else: try: # disallow methods which are not publicly accessible if req.method not in self.allowed_methods: res = HTTPMethodNotAllowed() else: res = getattr(self, req.method)(req) except HTTPException as error_response: res = error_response except (Exception, Timeout): self.logger.exception( _('ERROR __call__ error with %(method)s' ' %(path)s '), { 'method': req.method, 'path': req.path }) res = HTTPInternalServerError(body=traceback.format_exc()) if self.log_requests: trans_time = time.time() - start_time additional_info = '' if res.headers.get('x-container-timestamp') is not None: additional_info += 'x-container-timestamp: %s' % \ res.headers['x-container-timestamp'] log_msg = get_log_line(req, res, trans_time, additional_info) if req.method.upper() == 'REPLICATE': self.logger.debug(log_msg) else: self.logger.info(log_msg) return res(env, start_response)
def __call__(self, env, start_response): request = Request(env) if not request.path.startswith(self.endpoints_path): return self.app(env, start_response) if request.method != 'GET': return HTTPMethodNotAllowed(req=request, headers={"Allow": "GET"})(env, start_response) try: version, account, container, obj = self._parse_path(request) except ValueError as err: return HTTPBadRequest(str(err))(env, start_response) if account is not None: account = unquote(account) if container is not None: container = unquote(container) if obj is not None: obj = unquote(obj) storage_policy_index = None if obj is not None: container_info = get_container_info( {'PATH_INFO': '/v1/%s/%s' % (account, container)}, self.app, swift_source='LE') storage_policy_index = container_info['storage_policy'] obj_ring = self.get_object_ring(storage_policy_index) partition, nodes = obj_ring.get_nodes(account, container, obj) endpoint_template = 'http://{ip}:{port}/{device}/{partition}/' + \ '{account}/{container}/{obj}' elif container is not None: partition, nodes = self.container_ring.get_nodes( account, container) endpoint_template = 'http://{ip}:{port}/{device}/{partition}/' + \ '{account}/{container}' else: partition, nodes = self.account_ring.get_nodes(account) endpoint_template = 'http://{ip}:{port}/{device}/{partition}/' + \ '{account}' endpoints = [] for node in nodes: endpoint = endpoint_template.format(ip=node['ip'], port=node['port'], device=node['device'], partition=partition, account=quote(account), container=quote(container or ''), obj=quote(obj or '')) endpoints.append(endpoint) resp = self.response_map[version]( request, endpoints=endpoints, storage_policy_index=storage_policy_index) return resp(env, start_response)
def PUT(self, req): """HTTP PUT request handler.""" if not self.app.allow_account_management: return HTTPMethodNotAllowed( request=req, headers={'Allow': ', '.join(self.allowed_methods)}) error_response = check_metadata(req, 'account') if error_response: return error_response if len(self.account_name) > MAX_ACCOUNT_NAME_LENGTH: resp = HTTPBadRequest(request=req) resp.body = 'Account name length of %d longer than %d' % \ (len(self.account_name), MAX_ACCOUNT_NAME_LENGTH) return resp account_partition, accounts = \ self.app.account_ring.get_nodes(self.account_name) headers = { 'X-Timestamp': normalize_timestamp(time.time()), 'x-trans-id': self.trans_id, 'Connection': 'close' } self.transfer_headers(req.headers, headers) if self.app.memcache: self.app.memcache.delete( get_account_memcache_key(self.account_name)) resp = self.make_requests(req, self.app.account_ring, account_partition, 'PUT', req.path_info, [headers] * len(accounts)) return resp
def handle_request(self, req): """ Entry point for auth requests (ones that match the self.auth_prefix). Should return a WSGI-style callable (such as swob.Response). :param req: swob.Request object """ req.start_time = time() handler = None if req.method != 'GET': req.response = HTTPMethodNotAllowed(request=req) return req.response try: version, account, user, _junk = split_path(req.path_info, 1, 4, True) except ValueError: self.logger.increment('errors') return HTTPNotFound(request=req) if version in ('v1', 'v1.0', 'auth'): if req.method == 'GET': handler = self.handle_get_token if not handler: self.logger.increment('errors') req.response = HTTPBadRequest(request=req) else: req.response = handler(req) return req.response
def __call__(self, env, start_response): start_time = time.time() req = Request(env) self.logger.txn_id = req.headers.get('x-trans-id', None) if not check_utf8(wsgi_to_str(req.path_info), internal=True): res = HTTPPreconditionFailed(body='Invalid UTF8 or contains NULL') else: try: # disallow methods which have not been marked 'public' if req.method not in self.allowed_methods: res = HTTPMethodNotAllowed() else: res = getattr(self, req.method)(req) except HTTPException as error_response: res = error_response except (Exception, Timeout): self.logger.exception( _('ERROR __call__ error with %(method)s %(path)s '), { 'method': req.method, 'path': req.path }) res = HTTPInternalServerError(body=traceback.format_exc()) if self.log_requests: trans_time = time.time() - start_time log_message = get_log_line(req, res, trans_time, '', self.log_format, self.anonymization_method, self.anonymization_salt) if req.method.upper() == 'REPLICATE': self.logger.debug(log_message) else: self.logger.info(log_message) return res(env, start_response)
def PUT(self, req): """HTTP PUT request handler.""" if not self.app.allow_account_management: return HTTPMethodNotAllowed( request=req, headers={'Allow': ', '.join(self.allowed_methods)}) error_response = check_metadata(req, 'account') if error_response: return error_response if len(self.account_name) > constraints.MAX_ACCOUNT_NAME_LENGTH: resp = HTTPBadRequest(request=req) resp.body = 'Account name length of %d longer than %d' % \ (len(self.account_name), constraints.MAX_ACCOUNT_NAME_LENGTH) return resp account_partition, accounts = \ self.app.account_ring.get_nodes(self.account_name) headers = self.generate_request_headers(req, transfer=True) clear_info_cache(self.app, req.environ, self.account_name) resp = self.make_requests(req, self.app.account_ring, account_partition, 'PUT', req.swift_entity_path, [headers] * len(accounts)) self.add_acls_from_sys_metadata(resp) return resp
def origin_db_delete(self, env, req): """ Handles DELETEs in the Origin database. This is not really a delete- it will remove the object from the container listing and set cdn_enabled=false and a deleted flag in the .hash_* obj that says that the obj is deleted. This way the container won't show up in the listings, HEAD to the object will return 404s but behind the scenes lookups to the object will be able to determine the account and container from a container_hash. """ try: vsn, account, container = split_path(req.path, 3, 3) except ValueError: return HTTPBadRequest( 'Invalid request. ' 'URI format: /<api version>/<account>/<container>') if self.extra_header_for_deletes and not req.headers.get( self.extra_header_for_deletes, 'f').lower() in TRUE_VALUES: # only do delete if header is set (assuming you want the header) return HTTPMethodNotAllowed(request=req) hsh = self.hash_path(account, container) cdn_obj_path = self.get_hsh_obj_path(hsh) # Remove memcache entry memcache_client = utils.cache_from_env(env) if memcache_client: memcache_key = self.cdn_data_memcache_key(cdn_obj_path) memcache_client.delete(memcache_key) ref_hash_data = HashData(account, container, self.default_ttl, False, False, deleted=True) self._set_hash_data(env, cdn_obj_path, ref_hash_data, update_listings=False) cdn_list_path = quote('/v1/%s/%s/%s' % (self.origin_account, account, container)) list_resp = make_pre_authed_request(env, 'DELETE', cdn_list_path, agent='SwiftOrigin', swift_source='SOS').get_response( self.app) if list_resp.status_int // 100 != 2 and list_resp.status_int != 404: raise OriginDbFailure('Could not DELETE listing path in origin ' 'db: %s %s' % (cdn_list_path, list_resp.status_int)) # Return 404 if container didn't exist if list_resp.status_int == 404: return HTTPNotFound(request=req) return HTTPNoContent(request=req)
def handle_request(self): if hasattr(self, self.request.method) and self.is_valid_request: try: handler = getattr(self, self.request.method) getattr(handler, 'publicly_accessible') except AttributeError: return HTTPMethodNotAllowed(request=self.request) return handler() else: return self.request.get_response(self.app)
def get_handler(self, controller, 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)}) else: return handler(req)
def _not_allowed_wrapper(self, req, *args, **kwargs): try: return fnc(self, req, *args, **kwargs) except MethodNotAllowed as exc: headers = dict() if 'worm' in exc.message.lower(): headers['Allow'] = 'GET, HEAD, PUT' else: # TODO(FVE): load Allow header from exception attributes pass return HTTPMethodNotAllowed(request=req, headers=headers)
def __call__(self, env, start_response): request = Request(env) if not request.path.startswith(self.endpoints_path): return self.app(env, start_response) if request.method != 'GET': return HTTPMethodNotAllowed(req=request, headers={"Allow": "GET"})(env, start_response) try: clean_path = request.path[len(self.endpoints_path) - 1:] account, container, obj = \ split_path(clean_path, 1, 3, True) except ValueError: return HTTPBadRequest('No account specified')(env, start_response) if account is not None: account = unquote(account) if container is not None: container = unquote(container) if obj is not None: obj = unquote(obj) if obj is not None: partition, nodes = self.object_ring.get_nodes( account, container, obj) endpoint_template = 'http://{ip}:{port}/{device}/{partition}/' + \ '{account}/{container}/{obj}' elif container is not None: partition, nodes = self.container_ring.get_nodes( account, container) endpoint_template = 'http://{ip}:{port}/{device}/{partition}/' + \ '{account}/{container}' else: partition, nodes = self.account_ring.get_nodes(account) endpoint_template = 'http://{ip}:{port}/{device}/{partition}/' + \ '{account}' endpoints = [] for node in nodes: endpoint = endpoint_template.format(ip=node['ip'], port=node['port'], device=node['device'], partition=partition, account=quote(account), container=quote(container or ''), obj=quote(obj or '')) endpoints.append(endpoint) return Response(json.dumps(endpoints), content_type='application/json')(env, start_response)
def handle_request(self): if self.is_crystal_valid_request and hasattr(self, self.request.method): try: handler = getattr(self, self.request.method) getattr(handler, 'publicly_accessible') except AttributeError: return HTTPMethodNotAllowed(request=self.request) return handler() else: self.logger.info('Request disabled for Crystal') return self.request.get_response(self.app)
def DELETE(self, req): """HTTP DELETE request handler.""" if req.query_string: return HTTPBadRequest(request=req) if not self.app.allow_account_management: return HTTPMethodNotAllowed( request=req, headers={'Allow': ', '.join(self.allowed_methods)}) headers = self.generate_request_headers(req) clear_info_cache(self.app, req.environ, self.account_name) resp = self.get_account_delete_resp(req, headers) return resp
def __call__(self, env, start_response): """WSGI Application entry point for the Swift Object Server.""" start_time = time.time() req = Request(env) self.logger.txn_id = req.headers.get('x-trans-id', None) if not check_utf8(req.path_info): res = HTTPPreconditionFailed(body='Invalid UTF8 or contains NULL') else: try: # disallow methods which have not been marked 'public' try: method = getattr(self, req.method) getattr(method, 'publicly_accessible') replication_method = getattr(method, 'replication', False) if (self.replication_server is not None and self.replication_server != replication_method): raise AttributeError('Not allowed method.') except AttributeError: res = HTTPMethodNotAllowed() else: res = method(req) except DiskFileCollision: res = HTTPForbidden(request=req) except HTTPException as error_response: res = error_response except (Exception, Timeout): self.logger.exception(_( 'ERROR __call__ error with %(method)s' ' %(path)s '), {'method': req.method, 'path': req.path}) res = HTTPInternalServerError(body=traceback.format_exc()) trans_time = time.time() - start_time if self.log_requests: log_line = '%s - - [%s] "%s %s" %s %s "%s" "%s" "%s" %.4f' % ( req.remote_addr, time.strftime('%d/%b/%Y:%H:%M:%S +0000', time.gmtime()), req.method, req.path, res.status.split()[0], res.content_length or '-', req.referer or '-', req.headers.get('x-trans-id', '-'), req.user_agent or '-', trans_time) if req.method in ('REPLICATE', 'REPLICATION') or \ 'X-Backend-Replication' in req.headers: self.logger.debug(log_line) else: self.logger.info(log_line) if req.method in ('PUT', 'DELETE'): slow = self.slow - trans_time if slow > 0: sleep(slow) return res(env, start_response)
def __call__(self, env, start_response): """ Boilerplate code for how the server's code gets called upon receiving a request. Taken directly from other servers. """ # start_time = time.time() req = Request(env) self.logger.txn_id = req.headers.get('x-trans-id', None) if not check_utf8(req.path_info): res = HTTPPreconditionFailed(body='Invalid UTF8 or contains NULL') else: try: # disallow methods which have not been marked 'public' try: method = getattr(self, req.method) getattr(method, 'publicly_accessible') replication_method = getattr(method, 'replication', False) if (self.replication_server is not None and self.replication_server != replication_method): raise AttributeError('Not allowed method.') except AttributeError: res = HTTPMethodNotAllowed() else: res = method(req) except HTTPException as error_response: res = error_response except (Exception, Timeout): self.logger.exception( _('ERROR __call__ error with %(method)s %(path)s '), { 'method': req.method, 'path': req.path }) res = HTTPInternalServerError(body=traceback.format_exc()) # trans_time = '%.4f' % (time.time() - start_time) # if self.log_requests: # log_message = '%s - - [%s] "%s %s" %s %s "%s" "%s" "%s" %s' % ( # req.remote_addr, # time.strftime('%d/%b/%Y:%H:%M:%S +0000', # time.gmtime()), # req.method, req.path, # res.status.split()[0], res.content_length or '-', # req.headers.get('x-trans-id', '-'), # req.referer or '-', req.user_agent or '-', # trans_time) # if req.method.upper() == 'REPLICATE': # self.logger.debug(log_message) # else: # self.logger.info(log_message) return res(env, start_response)
def origin_db_delete(self, env, req): """ Handles DELETEs in the Origin database """ if not self.delete_enabled: return HTTPMethodNotAllowed(request=req) try: vsn, account, container = split_path(req.path, 3, 3) except ValueError: return HTTPBadRequest( 'Invalid request. ' 'URI format: /<api version>/<account>/<container>') hsh = self.hash_path(account, container) cdn_obj_path = self.get_hsh_obj_path(hsh) # Remove memcache entry memcache_client = utils.cache_from_env(env) if memcache_client: memcache_key = self.cdn_data_memcache_key(cdn_obj_path) memcache_client.delete(memcache_key) resp = make_pre_authed_request(env, 'DELETE', cdn_obj_path, agent='SwiftOrigin', swift_source='SOS').get_response( self.app) # A 404 means it's already deleted, which is okay if resp.status_int // 100 != 2 and resp.status_int != 404: raise OriginDbFailure('Could not DELETE .hash obj in origin ' 'db: %s %s' % (cdn_obj_path, resp.status_int)) cdn_list_path = quote('/v1/%s/%s/%s' % (self.origin_account, account, container)) list_resp = make_pre_authed_request(env, 'DELETE', cdn_list_path, agent='SwiftOrigin', swift_source='SOS').get_response( self.app) if list_resp.status_int // 100 != 2 and list_resp.status_int != 404: raise OriginDbFailure('Could not DELETE listing path in origin ' 'db: %s %s' % (cdn_list_path, list_resp.status_int)) # Return 404 if container didn't exist if resp.status_int == 404 and list_resp.status_int == 404: return HTTPNotFound(request=req) return HTTPNoContent(request=req)
def create_error_response(error, message): if error == 400: response = HTTPBadRequest(body=message) elif error == 401: response = HTTPUnauthorized(body=message) elif error == 403: response = HTTPForbidden(body=message) elif error == 404: response = HTTPNotFound(body=message) elif error == 405: response = HTTPMethodNotAllowed(body=message) else: response = HTTPServerError(body=message) return response
def DELETE(self, req): """HTTP DELETE request handler.""" if not self.app.allow_account_management: return HTTPMethodNotAllowed(request=req) account_partition, accounts = \ self.app.account_ring.get_nodes(self.account_name) headers = {'X-Timestamp': normalize_timestamp(time.time()), 'X-Trans-Id': self.trans_id, 'Connection': 'close'} if self.app.memcache: self.app.memcache.delete('account%s' % req.path_info.rstrip('/')) resp = self.make_requests(req, self.app.account_ring, account_partition, 'DELETE', req.path_info, [headers] * len(accounts)) return resp
def __call__(self, env, start_response): print "account server __call__" start_time = time.time() req = Request(env) self.logger.txn_id = req.headers.get('x-trans-id', None) if not check_utf8(req.path_info): res = HTTPPreconditionFailed(body='Invalid UTF8 or contains NULL') else: try: # disallow methods which are not publicly accessible try: method = getattr(self, req.method) getattr(method, 'publicly_accessible') replication_method = getattr(method, 'replication', False) if (self.replication_server is not None and self.replication_server != replication_method): raise AttributeError('Not allowed method.') except AttributeError: res = HTTPMethodNotAllowed() else: res = method(req) except HTTPException as error_response: res = error_response except (Exception, Timeout): self.logger.exception( _('ERROR __call__ error with %(method)s' ' %(path)s '), { 'method': req.method, 'path': req.path }) res = HTTPInternalServerError(body=traceback.format_exc()) trans_time = '%.4f' % (time.time() - start_time) additional_info = '' if res.headers.get('x-container-timestamp') is not None: additional_info += 'x-container-timestamp: %s' % \ res.headers['x-container-timestamp'] log_message = '%s - - [%s] "%s %s" %s %s "%s" "%s" "%s" %s "%s"' % ( req.remote_addr, time.strftime('%d/%b/%Y:%H:%M:%S +0000', time.gmtime()), req.method, req.path, res.status.split()[0], res.content_length or '-', req.headers.get('x-trans-id', '-'), req.referer or '-', req.user_agent or '-', trans_time, additional_info) if req.method.upper() == 'REPLICATE': self.logger.debug(log_message) else: self.logger.info(log_message) return res(env, start_response)
def __call__(self, env, start_response): """WSGI Application entry point for the Swift Object Server.""" start_time = time.time() req = Request(env) self.logger.txn_id = req.headers.get('x-trans-id', None) if not check_utf8(req.path_info): res = HTTPPreconditionFailed(body='Invalid UTF8 or contains NULL') else: try: # disallow methods which have not been marked 'public' try: method = getattr(self, req.method) getattr(method, 'publicly_accessible') replication_method = getattr(method, 'replication', False) if (self.replication_server is not None and self.replication_server != replication_method): raise AttributeError('Not allowed method.') except AttributeError: res = HTTPMethodNotAllowed() else: res = method(req) except DiskFileCollision: res = HTTPForbidden(request=req) except HTTPException as error_response: res = error_response except (Exception, Timeout): self.logger.exception(_( 'ERROR __call__ error with %(method)s' ' %(path)s '), {'method': req.method, 'path': req.path}) res = HTTPInternalServerError(body=traceback.format_exc()) trans_time = time.time() - start_time if self.log_requests: log_line = get_log_line(req, res, trans_time, '') if req.method in ('REPLICATE', 'REPLICATION') or \ 'X-Backend-Replication' in req.headers: self.logger.debug(log_line) else: self.logger.info(log_line) if req.method in ('PUT', 'DELETE'): slow = self.slow - trans_time if slow > 0: sleep(slow) my_debug('returning from __call__ or objserver', res) my_debug('returnign from __call__ of objserver', start_response) return res(env, start_response)
def DELETE(self, req): """HTTP DELETE request handler.""" # Extra safety in case someone typos a query string for an # account-level DELETE request that was really meant to be caught by # some middleware. if req.query_string: return HTTPBadRequest(request=req) if not self.app.allow_account_management: return HTTPMethodNotAllowed( request=req, headers={'Allow': ', '.join(self.allowed_methods)}) account_partition, accounts = \ self.app.account_ring.get_nodes(self.account_name) headers = self.generate_request_headers(req) clear_info_cache(self.app, req.environ, self.account_name) resp = self.make_requests(req, self.app.account_ring, account_partition, 'DELETE', req.path_info, [headers] * len(accounts)) return resp
def __call__(self, env, start_response): req = Request(env) if req.method not in self.write_methods: return self.app(env, start_response) try: version, account, container, obj = req.split_path(1, 4, True) except ValueError: return self.app(env, start_response) if req.method == 'COPY' and 'Destination-Account' in req.headers: dest_account = req.headers.get('Destination-Account') account = check_account_format(req, dest_account) if self.account_read_only(req, account): msg = 'Writes are disabled for this account.' return HTTPMethodNotAllowed(body=msg)(env, start_response) return self.app(env, start_response)
def PUT(self, req): """HTTP PUT request handler.""" if not self.app.allow_account_management: return HTTPMethodNotAllowed( request=req, headers={'Allow': ', '.join(self.allowed_methods)}) error_response = check_metadata(req, 'account') if error_response: return error_response if len(self.account_name) > constraints.MAX_ACCOUNT_NAME_LENGTH: resp = HTTPBadRequest(request=req) resp.body = ('Account name length of %d longer than %d' % (len(self.account_name), constraints.MAX_ACCOUNT_NAME_LENGTH)).encode('utf-8') return resp headers = self.generate_request_headers(req, transfer=True) clear_info_cache(self.app, req.environ, self.account_name) resp = self.get_account_put_resp(req, headers) self.add_acls_from_sys_metadata(resp) return resp
def PUT(self, req): """HTTP PUT request handler.""" if not self.app.allow_account_management: return HTTPMethodNotAllowed( request=req, headers={'Allow': ', '.join(self.allowed_methods)}) error_response = check_metadata(req, 'account') if error_response: return error_response if len(self.account_name) > MAX_ACCOUNT_NAME_LENGTH: resp = HTTPBadRequest(request=req) resp.body = 'Account name length of %d longer than %d' % \ (len(self.account_name), MAX_ACCOUNT_NAME_LENGTH) return resp account_partition, accounts = \ self.app.account_ring.get_nodes(self.account_name) headers = self.generate_request_headers(req, transfer=True) if self.app.memcache: self.app.memcache.delete( get_account_memcache_key(self.account_name)) resp = self.make_requests(req, self.app.account_ring, account_partition, 'PUT', req.path_info, [headers] * len(accounts)) 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) 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)