def __call__(self, env, start_response): req = Request(env) if env['REQUEST_METHOD'] == 'GET' or env['REQUEST_METHOD'] == 'HEAD': if self.status == 200: if 'HTTP_RANGE' in env: resp = Response(request=req, body=self.object_body, conditional_response=True) return resp(env, start_response) start_response(Response(request=req).status, self.response_headers.items()) if env['REQUEST_METHOD'] == 'GET': return self.object_body elif self.status == 401: start_response(HTTPUnauthorized(request=req).status, []) elif self.status == 403: start_response(HTTPForbidden(request=req).status, []) elif self.status == 404: start_response(HTTPNotFound(request=req).status, []) else: start_response(HTTPBadRequest(request=req).status, []) elif env['REQUEST_METHOD'] == 'PUT': if self.status == 201: start_response(HTTPCreated(request=req).status, [('etag', self.response_headers['etag'])]) elif self.status == 401: start_response(HTTPUnauthorized(request=req).status, []) elif self.status == 403: start_response(HTTPForbidden(request=req).status, []) elif self.status == 404: start_response(HTTPNotFound(request=req).status, []) elif self.status == 413: start_response(HTTPRequestEntityTooLarge(request=req).status, []) else: start_response(HTTPBadRequest(request=req).status, []) elif env['REQUEST_METHOD'] == 'DELETE': if self.status == 204: start_response(HTTPNoContent(request=req).status, []) elif self.status == 401: start_response(HTTPUnauthorized(request=req).status, []) elif self.status == 403: start_response(HTTPForbidden(request=req).status, []) elif self.status == 404: start_response(HTTPNotFound(request=req).status, []) else: start_response(HTTPBadRequest(request=req).status, []) return []
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) 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') if req.method not in self.allowed_methods: raise AttributeError('Not allowed method.') except AttributeError: res = HTTPMethodNotAllowed() else: res = method(req) except DiskFileCollision: res = HTTPForbidden(request=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 = 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 == 'REPLICATE': 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): if not self.storage_domain: return self.app(env, start_response) if 'HTTP_HOST' in env: given_domain = env['HTTP_HOST'] else: given_domain = env['SERVER_NAME'] port = '' if ':' in given_domain: given_domain, port = given_domain.rsplit(':', 1) if given_domain.endswith(self.storage_domain): parts_to_parse = given_domain[:-len(self.storage_domain)] parts_to_parse = parts_to_parse.strip('.').split('.') len_parts_to_parse = len(parts_to_parse) if len_parts_to_parse == 2: container, account = parts_to_parse elif len_parts_to_parse == 1: container, account = None, parts_to_parse[0] else: resp = HTTPBadRequest(request=Request(env), body='Bad domain in host header', content_type='text/plain') return resp(env, start_response) if '_' not in account and '-' in account: account = account.replace('-', '_', 1) account_reseller_prefix = account.split('_', 1)[0].lower() if account_reseller_prefix not in self.reseller_prefixes_lower: # account prefix is not in config list. bail. return self.app(env, start_response) prefix_index = self.reseller_prefixes_lower.index( account_reseller_prefix) real_prefix = self.reseller_prefixes[prefix_index] if not account.startswith(real_prefix): account_suffix = account[len(real_prefix):] account = real_prefix + account_suffix path = env['PATH_INFO'].strip('/') new_path_parts = ['', self.path_root, account] if container: new_path_parts.append(container) if path.startswith(self.path_root): path = path[len(self.path_root):].lstrip('/') if path: new_path_parts.append(path) new_path = '/'.join(new_path_parts) env['PATH_INFO'] = new_path return self.app(env, start_response)
def __call__(self, env, start_response): req = Request(env) removed = remove_items(req.headers, self.inbound_condition) if removed: self.logger.debug('removed request headers: %s' % removed) if 'X-Timestamp' in req.headers and self.shunt_x_timestamp: ts = req.headers.pop('X-Timestamp') req.headers['X-Backend-Inbound-X-Timestamp'] = ts # log in a similar format as the removed headers self.logger.debug('shunted request headers: %s' % [('X-Timestamp', ts)]) def gatekeeper_response(status, response_headers, exc_info=None): def fixed_response_headers(): def relative_path(value): parsed = urlsplit(value) new_path = parsed.path if parsed.query: new_path += ('?%s' % parsed.query) if parsed.fragment: new_path += ('#%s' % parsed.fragment) return new_path if not env.get('swift.leave_relative_location'): return response_headers else: return [ (k, v) if k.lower() != 'location' else (k, relative_path(v)) for (k, v) in response_headers ] response_headers = fixed_response_headers() removed = filter( lambda h: self.outbound_condition(h[0]), response_headers) if removed: self.logger.debug('removed response headers: %s' % removed) new_headers = filter( lambda h: not self.outbound_condition(h[0]), response_headers) return start_response(status, new_headers, exc_info) return start_response(status, response_headers, exc_info) return self.app(env, gatekeeper_response)
def __call__(self, env, start_response): req = Request(env) removed = remove_items(req.headers, self.inbound_condition) if removed: self.logger.debug('removed request headers: %s' % removed) def gatekeeper_response(status, response_headers, exc_info=None): removed = filter( lambda h: self.outbound_condition(h[0]), response_headers) if removed: self.logger.debug('removed response headers: %s' % removed) new_headers = filter( lambda h: not self.outbound_condition(h[0]), response_headers) return start_response(status, new_headers, exc_info) return start_response(status, response_headers, exc_info) return self.app(env, gatekeeper_response)
def __call__(self, env, start_response): req = Request(env) try: parts = req.split_path(2, 4, True) except ValueError: return self.app(env, start_response) if req.method in ('PUT', 'POST', 'GET', 'HEAD'): # handle only those request methods that may require keys km_context = KeyMasterContext(self, *parts[1:]) try: return km_context.handle_request(req, start_response) except HTTPException as err_resp: return err_resp(env, start_response) # anything else return self.app(env, start_response)
def __call__(self, env, start_response): req = Request(env) try: parts = req.split_path(2, 4, True) except ValueError: return self.app(env, start_response) if hasattr(KeyMasterContext, req.method): # handle only those request methods that may require keys km_context = KeyMasterContext(self, *parts[1:]) try: return getattr(km_context, req.method)(req, start_response) except HTTPException as err_resp: return err_resp(env, start_response) # anything else return self.app(env, start_response)
def iter_response(iterable): iterator = iter(iterable) try: chunk = iterator.next() while not chunk: chunk = iterator.next() except StopIteration: chunk = '' for h, v in start_response_args[0][1]: if h.lower() in ('content-length', 'transfer-encoding'): break else: if not chunk: start_response_args[0][1].append(('content-length', '0')) elif isinstance(iterable, list): start_response_args[0][1].append( ('content-length', str(sum(len(i) for i in iterable)))) start_response(*start_response_args[0]) req = Request(env) # Log timing information for time-to-first-byte (GET requests only) method = self.method_from_req(req) if method == 'GET' and not self.req_already_logged(req): status_int = status_int_for_logging() metric_name = self.statsd_metric_name(req, status_int, method) if metric_name: self.access_logger.timing_since( metric_name + '.first-byte.timing', start_time) bytes_sent = 0 client_disconnect = False try: while chunk: bytes_sent += len(chunk) yield chunk chunk = iterator.next() except GeneratorExit: # generator was closed before we finished client_disconnect = True raise finally: status_int = status_int_for_logging(client_disconnect) self.log_request(req, status_int, input_proxy.bytes_received, bytes_sent, time.time() - start_time)
def __call__(self, environ, start_response): request = Request(environ) path_entry = request.path_info.split('/') # hijack favicon request sent by browser so that it doesn't # invoke profiling hook and contaminate the data. if path_entry[1] == 'favicon.ico': start_response('200 OK', []) return '' elif path_entry[1] == self.path: try: self.dump_checkpoint() query_dict = self._combine_body_qs(request) content, headers = self.viewer.render(request.url, request.method, path_entry, query_dict, self.renew_profile) start_response('200 OK', headers) return [bytes_(content)] except MethodNotAllowed as mx: start_response('405 Method Not Allowed', []) return '%s' % mx except NotFoundException as nx: start_response('404 Not Found', []) return '%s' % nx except ProfileException as pf: start_response('500 Internal Server Error', []) return '%s' % pf except Exception as ex: start_response('500 Internal Server Error', []) return _('Error on render profiling results: %s') % ex else: try: _locals = locals() code = self.unwind and PROFILE_EXEC_EAGER or\ PROFILE_EXEC_LAZY self.profiler.runctx(code, globals(), _locals) app_iter = _locals['app_iter_'] self.dump_checkpoint() return app_iter except: self.logger.exception(_('Error profiling code')) finally: pass
def __call__(self, env, start_response): if env['REQUEST_METHOD'] != 'GET': return self.app(env, start_response) req = Request(env) version, account, container, obj = req.split_path(1, 4, True) if None in [version, account, container, obj]: return self.app(env, start_response) if random.randint(1, self.max_range) > self.count_threshold: return self.app(env, start_response) return_status = [None, None] start_t = time.time() def start_response_wc(status, headers): return_status[0] = status content_len = 0 for item in headers: if item[0] == "Content-Length": content_len = long(item[1]) headers.append(('objslo_start_time', start_t)) headers.append(('objslo_end_time', time.time())) return_status[1] = content_len return start_response(status, headers) if env['REQUEST_METHOD'] == 'GET': server_ip = env['SERVER_NAME'] server_port = str(env['SERVER_PORT']) device = ":".join([server_ip, server_port]) self.redis_client.hincrby(self.incomingreqkey, device, 1 * self.sample_ratio) data = self.app(env, start_response_wc) duration = time.time() - start_t if self.durationswitch: self.redis_client.lpush("%s_duration" % (device), duration) if duration > self.slolatency: self.redis_client.hincrby(self.sloviolatecounter, device, 1 * self.sample_ratio) else: self.redis_client.hincrby(self.slomeetcounter, device, 1 * self.sample_ratio) content_len = return_status[1] self.redis_client.hincrby(self.returnreqkey, device, 1 * self.sample_ratio) self.redis_client.hincrby(self.returnreqsizekey, device, content_len * self.sample_ratio) self.redis_client.hincrby(self.returnreqlatencykey, device, int(duration*1000) * self.sample_ratio) self.redis_client.hincrby(self.readcountskey, device, (int(content_len/self.blocksize) + 1) * self.sample_ratio) return data
def __call__(self, env, start_response): """ Get Request object from variable env, then get account name. Further generate or get associated key_id from key_manage_base and add this information in Headears of request. :param env: WSGI environment dictionary :param start_response: WSGI callable :return self.app: standart next WSGI app in the pipeline """ req = Request(env) if req.method in ('PUT', 'POST'): _, account, container, obj = split_path(req.path, 1, 4, True) if account and container and obj: key_id = self.get_key_id(account) req.headers['X-Object-Meta-Key-Id'] = key_id env = req.environ return self.app(env, start_response)
def __call__(self, env, start_response): if 'swift.authorize' in env: aresp = env['swift.authorize'](Request(env)) if aresp: return aresp(env, start_response) if env['REQUEST_METHOD'] == "HEAD" and \ env['PATH_INFO'] == '/v1/a/c2/o2': env_key = get_object_env_key('a', 'c2', 'o2') env[env_key] = headers_to_object_info(self.headers, 200) start_response('200 OK', self.headers) elif env['REQUEST_METHOD'] == "HEAD" and \ env['PATH_INFO'] == '/v1/a/c2/o3': start_response('404 Not Found', []) else: # Cache the account_info (same as a real application) cache_key, env_key = _get_cache_key('a', None) env[env_key] = headers_to_account_info(self.headers, 200) start_response('200 OK', self.headers) return []
def __call__(self, env, start_response): def _start_response(status, headers, exc_info=None): """start_response wrapper to add request status to env""" env['informant.status'] = int(status.split(' ', 1)[0]) env['informant.start_response_time'] = time() start_response(status, headers, exc_info) req = Request(env) try: if 'eventlet.posthooks' in env: env['informant.start_time'] = time() env['eventlet.posthooks'].append( (self.statsd_event, (req, ), {})) return self.app(env, _start_response) except Exception: self.logger.exception('WSGI EXCEPTION:') _start_response('500 Internal Server Error', [('Content-Length', '0')]) return []
def __call__(self, env, start_response): """ WSGI entry point """ req = Request(env) try: vrs, account, container, obj = req.split_path(4, 4, True) except ValueError: return self.app(env, start_response) if ((req.method == 'GET' or req.method == 'HEAD') and req.params.get('multipart-manifest') != 'get'): return GetContext(self, self.logger).\ handle_request(req, start_response) elif req.method == 'PUT': error_response = self._validate_x_object_manifest_header(req) if error_response: return error_response(env, start_response) return self.app(env, start_response)
def __call__(self, env, start_response): req = Request(env) try: version, acc, cont, obj = req.split_path(3, 4, True) except ValueError: return self.app(env, start_response) try: if obj: # object context context = SymlinkObjectContext(self.app, self.logger, self.symloop_max) return context.handle_object(req, start_response) else: # container context context = SymlinkContainerContext(self.app, self.logger) return context.handle_container(req, start_response) except HTTPException as err_resp: return err_resp(env, start_response)
def __call__(self, env, start_response): """ WSGI entry point. Wraps env in swob.Request object and passes it down. :param env: WSGI environment dictionary :param start_response: WSGI callable """ try: req = self.update_request(Request(env)) return self.handle_request(req)(env, start_response) except UnicodeError: err = HTTPPreconditionFailed(request=req, body='Invalid UTF8 or contains NULL') return err(env, start_response) except (Exception, Timeout): start_response('500 Server Error', [('Content-Type', 'text/plain')]) return [b'Internal server error.\n']
def __call__(self, env, start_response): req = Request(env) try: parts = req.split_path(3, 4, True) except ValueError: return self.app(env, start_response) if parts[3] and req.method in ('GET', 'HEAD'): handler = DecrypterObjContext(self, self.logger).handle elif parts[2] and req.method == 'GET': handler = DecrypterContContext(self, self.logger).handle else: # url and/or request verb is not handled by decrypter return self.app(env, start_response) try: return handler(req, start_response) except HTTPException as err_resp: return err_resp(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 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 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): """ Accepts a standard WSGI application call. There are 2 types of requests that this middleware will affect. 1. Requests to CDN 'database' that will enable, list, etc. containers for the CDN. 2. Requests (GETs, HEADs) from CDN provider to publicly available containers. The types of requests can be determined by looking at the hostname of the incoming call. Wraps env in swob.Request object and passes it down. :param env: WSGI environment dictionary :param start_response: WSGI callable """ env['sos.start_time'] = time() host = env.get('HTTP_HOST', '').split(':')[0] try: handler = None request_type = 'SOS_LOG' if host in self.origin_db_hosts: handler = OriginDbHandler(self.app, self.conf, self.logger) request_type = 'SOS_DB' for cdn_host_suffix in self.origin_cdn_host_suffixes: if host.endswith(cdn_host_suffix) and \ host not in self.ignore_hosts: handler = CdnHandler(self.app, self.conf, self.logger) request_type = 'SOS_ORIGIN' break if env['PATH_INFO'].startswith(self.origin_prefix): handler = AdminHandler(self.app, self.conf, self.logger) request_type = 'SOS_ADMIN' if handler: req = Request(env) resp = handler.handle_request(env, req) if request_type != 'SOS_ORIGIN': self._log_request(env, resp, request_type) return resp(env, start_response) except InvalidConfiguration, e: self.logger.exception(e) return HTTPInternalServerError(body=str(e))(env, start_response)
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 handle_container(self, env, start_response): """ Handles a possible static web request for a container. :param env: The original WSGI environment dict. :param start_response: The original WSGI start_response hook. """ container_info = self._get_container_info(env) req = Request(env) req.acl = container_info['read_acl'] # we checked earlier that swift.authorize is set in env aresp = env['swift.authorize'](req) if aresp: resp = aresp(env, self._start_response) return self._error_response(resp, env, start_response) if not self._listings and not self._index: if config_true_value(env.get('HTTP_X_WEB_MODE', 'f')): return HTTPNotFound()(env, start_response) return self.app(env, start_response) if not env['PATH_INFO'].endswith('/'): resp = HTTPMovedPermanently( location=(env['PATH_INFO'] + '/')) return resp(env, start_response) if not self._index: return self._listing(env, start_response) tmp_env = dict(env) tmp_env['HTTP_USER_AGENT'] = \ '%s StaticWeb' % env.get('HTTP_USER_AGENT') tmp_env['swift.source'] = 'SW' tmp_env['PATH_INFO'] += self._index resp = self._app_call(tmp_env) status_int = self._get_status_int() if status_int == HTTP_NOT_FOUND: return self._listing(env, start_response) elif not is_success(self._get_status_int()) and \ not is_redirection(self._get_status_int()): return self._error_response(resp, env, start_response) start_response(self._response_status, self._response_headers, self._response_exc_info) return resp
def __call__(self, env, start_response): # making a duplicate, because if this is a COPY request, we will # modify the PATH_INFO to find out if the 'Destination' is in a # versioned container req = Request(env.copy()) try: (version, account, container, obj) = req.split_path(3, 4, True) except ValueError: return self.app(env, start_response) # In case allow_versioned_writes is set in the filter configuration, # the middleware becomes the authority on whether object # versioning is enabled or not. In case it is not set, then # the option in the container configuration is still checked # for backwards compatibility # For a container request, first just check if option is set, # can be either true or false. # If set, check if enabled when actually trying to set container # header. If not set, let request be handled by container server # for backwards compatibility. # For an object request, also check if option is set (either T or F). # If set, check if enabled when checking versions container in # sysmeta property. If it is not set check 'versions' property in # container_info allow_versioned_writes = self.conf.get('allow_versioned_writes') if allow_versioned_writes and container and not obj: try: return self.container_request(req, start_response, allow_versioned_writes) except HTTPException as error_response: return error_response(env, start_response) elif obj and req.method in ('PUT', 'COPY', 'DELETE'): try: return self.object_request(req, version, account, container, obj, allow_versioned_writes)( env, start_response) except HTTPException as error_response: return error_response(env, start_response) else: return self.app(env, start_response)
def __call__(self, env, start_response): req = Request(env) new_service = env.get('liteauth.new_service', None) if new_service: account_id = env.get('REMOTE_USER', '') if not account_id: return HTTPInternalServerError() if not self.activate_service(account_id, new_service, req.environ): return HTTPInternalServerError() if req.method in ['PUT', 'POST' ] and not 'x-zerovm-execute' in req.headers: account_info = get_account_info(req.environ, self.app, swift_source='litequota') service_plan = assemble_from_partial(self.metadata_key, account_info['meta']) if service_plan: try: service_plan = json.loads(service_plan) path_parts = req.split_path(2, 4, rest_with_last=True) except ValueError: return self.app(env, start_response) if len(path_parts) == 3: quota = service_plan['storage']['containers'] new_size = int(account_info['container_count']) if 0 <= quota < new_size: return HTTPRequestEntityTooLarge( body='Over quota: containers')(env, start_response) else: new_size = int(account_info['bytes']) + (req.content_length or 0) quota = service_plan['storage']['bytes'] if 0 <= quota < new_size: return HTTPRequestEntityTooLarge( body='Over quota: bytes')(env, start_response) quota = service_plan['storage']['objects'] new_size = int(account_info['total_object_count']) if 0 <= quota < new_size: return HTTPRequestEntityTooLarge( body='Over quota: objects')(env, start_response) return self.app(env, start_response)
def __call__(self, env, start_response): request = Request(env) if request.method == 'PUT': try: version, account, container, obj = \ request.split_path(1, 4, True) except ValueError: return self.app(env, start_response) # check container creation request if account and container and not obj: policy_name = request.headers.get('X-Storage-Policy', '') default_policy = POLICIES.default.name if (policy_name in self.policies) or \ (policy_name == '' and default_policy in self.policies): container = unquote(container) if len(container) > constraints. \ SOF_MAX_CONTAINER_NAME_LENGTH: resp = HTTPBadRequest(request=request) resp.body = \ 'Container name length of %d longer than %d' % \ (len(container), constraints.SOF_MAX_CONTAINER_NAME_LENGTH) return resp(env, start_response) elif account and container and obj: # check object creation request obj = unquote(obj) container_info = get_container_info(env, self.app) policy = POLICIES.get_by_index( container_info['storage_policy']) if policy.name in self.policies: error_response = sof_check_object_creation(request, obj) if error_response: self.logger.warn("returning error: %s", error_response) return error_response(env, start_response) return self.app(env, start_response)
def __call__(self, env, start_response): req = Request(env) try: (api_version, account, container, obj) = req.split_path(3, 4, True) except ValueError: return self.app(env, start_response) # In case allow_versioned_writes is set in the filter configuration, # the middleware becomes the authority on whether object # versioning is enabled or not. In case it is not set, then # the option in the container configuration is still checked # for backwards compatibility # For a container request, first just check if option is set, # can be either true or false. # If set, check if enabled when actually trying to set container # header. If not set, let request be handled by container server # for backwards compatibility. # For an object request, also check if option is set (either T or F). # If set, check if enabled when checking versions container in # sysmeta property. If it is not set check 'versions' property in # container_info allow_versioned_writes = self.conf.get('allow_versioned_writes') if allow_versioned_writes and container and not obj: try: return self.container_request(req, start_response, allow_versioned_writes) except HTTPException as error_response: return error_response(env, start_response) elif (obj and (req.method in ('PUT', 'DELETE') and not req.environ.get('swift.post_as_copy') or req.method in ('HEAD', 'GET'))): try: return self.object_request( req, api_version, account, container, obj, allow_versioned_writes)(env, start_response) except HTTPException as error_response: return error_response(env, start_response) else: return self.app(env, start_response)
def __call__(self, env, start_response): """ If used, this should be the first middleware in pipeline. """ trans_id = 'tx' + uuid.uuid4().hex env['swift.trans_id'] = trans_id self.logger.txn_id = trans_id try: def my_start_response(status, response_headers, exc_info=None): trans_header = ('x-trans-id', trans_id) response_headers.append(trans_header) return start_response(status, response_headers, exc_info) return self.app(env, my_start_response) 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 __call__(self, env, start_response): req = Request(env) if self.check_character(req): return HTTPBadRequest( request=req, body=("Object/Container name contains forbidden chars from %s" % self.forbidden_chars))(env, start_response) elif self.check_length(req): return HTTPBadRequest( request=req, body=("Object/Container name longer than the allowed maximum " "%s" % self.maximum_length))(env, start_response) elif self.check_regexp(req): return HTTPBadRequest( request=req, body=("Object/Container name contains a forbidden substring " "from regular expression %s" % self.forbidden_regexp))(env, start_response) else: # Pass on to downstream WSGI component return self.app(env, start_response)