def best_response(self, req, statuses, reasons, bodies, server_type, etag=None): """ Given a list of responses from several servers, choose the best to return to the API. :param req: swob.Request object :param statuses: list of statuses returned :param reasons: list of reasons for each status :param bodies: bodies of each response :param server_type: type of server the responses came from :param etag: etag :returns: swob.Response object with the correct status, body, etc. set """ resp = Response(request=req) if len(statuses): for hundred in (HTTP_OK, HTTP_MULTIPLE_CHOICES, HTTP_BAD_REQUEST): hstatuses = \ [s for s in statuses if hundred <= s < hundred + 100] if len(hstatuses) > len(statuses) / 2: status = max(hstatuses) status_index = statuses.index(status) resp.status = '%s %s' % (status, reasons[status_index]) resp.body = bodies[status_index] if etag: resp.headers['etag'] = etag.strip('"') return resp self.app.logger.error(_('%(type)s returning 503 for %(statuses)s'), {'type': server_type, 'statuses': statuses}) resp.status = '503 Internal Server Error' return resp
def best_response(self, req, statuses, reasons, bodies, server_type, etag=None): """ Given a list of responses from several servers, choose the best to return to the API. :param req: swob.Request object :param statuses: list of statuses returned :param reasons: list of reasons for each status :param bodies: bodies of each response :param server_type: type of server the responses came from :param etag: etag :returns: swob.Response object with the correct status, body, etc. set """ resp = Response(request=req) if len(statuses): for hundred in (HTTP_OK, HTTP_MULTIPLE_CHOICES, HTTP_BAD_REQUEST): hstatuses = [s for s in statuses if hundred <= s < hundred + 100] if len(hstatuses) > len(statuses) / 2: status = max(hstatuses) status_index = statuses.index(status) resp.status = "%s %s" % (status, reasons[status_index]) resp.body = bodies[status_index] if etag: resp.headers["etag"] = etag.strip('"') return resp self.app.logger.error(_("%(type)s returning 503 for %(statuses)s"), {"type": server_type, "statuses": statuses}) resp.status = "503 Internal Server Error" return resp
def best_response(self, req, statuses, reasons, bodies, server_type, etag=None, headers=None): """ Given a list of responses from several servers, choose the best to return to the API. :param req: swob.Request object :param statuses: list of statuses returned :param reasons: list of reasons for each status :param bodies: bodies of each response :param server_type: type of server the responses came from :param etag: etag :param headers: headers of each response :returns: swob.Response object with the correct status, body, etc. set """ resp = Response(request=req) if len(statuses): for hundred in (HTTP_OK, HTTP_MULTIPLE_CHOICES, HTTP_BAD_REQUEST): hstatuses = \ [s for s in statuses if hundred <= s < hundred + 100] if len(hstatuses) >= quorum_size(len(statuses)): status = max(hstatuses) status_index = statuses.index(status) resp.status = '%s %s' % (status, reasons[status_index]) resp.body = bodies[status_index] if headers: update_headers(resp, headers[status_index]) if etag: resp.headers['etag'] = etag.strip('"') return resp self.app.logger.error(_('%(type)s returning 503 for %(statuses)s'), {'type': server_type, 'statuses': statuses}) resp.status = '503 Internal Server Error' return resp
def page_obj_list(self, req, storage_url, token, template=None): """ """ if template is None: tmpl = self.tmpl path = urlparse(self.del_prefix(req.url)).path if len(path.split('/')) <= 2: path = urlparse(storage_url).path vrs, acc, cont, obj = split_path(path, 1, 4, True) lang = self.get_lang(req) base = self.add_prefix(urlparse(storage_url).path) status = self.token_bank.get(token, None) msg = status.get('msg', '') if status else '' params = req.params_alt() limit = params.get('limit', self.items_per_page) marker = params.get('marker', '') end_marker = params.get('end_marker', '') prefix = params.get('prefix', '') delete_confirm = quote(params.get('delete_confirm', '')) acl_edit = quote(params.get('acl_edit', '')) meta_edit = quote(params.get('meta_edit', '')) # whole container list try: whole_cont_list = self._get_whole_cont_list(storage_url, token) except ClientException, err: resp = Response(charset='utf8') resp.status = err.http_status return resp
def page_obj_list(self, req, storage_url, token, template=None): """ """ if template is None: tmpl = self.tmpl path = urlparse(self.del_prefix(req.url)).path if len(path.split('/')) <= 2: path = urlparse(storage_url).path vrs, acc, cont, obj = split_path(path, 1, 4, True) lang = self.get_lang(req) base = self.add_prefix(urlparse(storage_url).path) status = self.token_bank.get(token, None) msg = status.get('msg', '') if status else '' params = req.params_alt() limit = params.get('limit', self.items_per_page) marker = params.get('marker', '') end_marker = params.get('end_marker', '') prefix = params.get('prefix', '') delete_confirm = quote(params.get('delete_confirm', '')) acl_edit = quote(params.get('acl_edit', '')) meta_edit = quote(params.get('meta_edit', '')) # whole container list try: whole_cont_list = self._get_whole_cont_list(storage_url, token) except ClientException, err: resp = Response(charset='utf8') resp.status = err.http_status return resp
def PUT(self, env, start_response): """ Handle PUT Bucket request """ if 'HTTP_X_AMZ_ACL' in env: amz_acl = env['HTTP_X_AMZ_ACL'] # Translate the Amazon ACL to something that can be # implemented in Swift, 501 otherwise. Swift uses POST # for ACLs, whereas S3 uses PUT. del env['HTTP_X_AMZ_ACL'] if 'QUERY_STRING' in env: del env['QUERY_STRING'] translated_acl = swift_acl_translate(amz_acl) if translated_acl == 'Unsupported': return get_err_response('Unsupported') elif translated_acl == 'InvalidArgument': return get_err_response('InvalidArgument') for header, acl in translated_acl: env[header] = acl if 'CONTENT_LENGTH' in env: content_length = env['CONTENT_LENGTH'] try: content_length = int(content_length) except (ValueError, TypeError): return get_err_response('InvalidArgument') if content_length < 0: return get_err_response('InvalidArgument') if 'QUERY_STRING' in env: args = dict(urlparse.parse_qsl(env['QUERY_STRING'], 1)) if 'acl' in args: # We very likely have an XML-based ACL request. body = env['wsgi.input'].readline().decode() translated_acl = swift_acl_translate(body, xml=True) if translated_acl == 'Unsupported': return get_err_response('Unsupported') elif translated_acl == 'InvalidArgument': return get_err_response('InvalidArgument') for header, acl in translated_acl: env[header] = acl env['REQUEST_METHOD'] = 'POST' body_iter = self._app_call(env) status = self._get_status_int() if status != HTTP_CREATED and status != HTTP_NO_CONTENT: if status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return get_err_response('AccessDenied') elif status == HTTP_ACCEPTED: return get_err_response('BucketAlreadyExists') else: return get_err_response('InvalidURI') resp = Response() resp.headers['Location'] = self.container_name resp.status = HTTP_OK return resp
def PUT(self, env, start_response): """ Handle PUT Bucket request """ if 'HTTP_X_AMZ_ACL' in env: amz_acl = env['HTTP_X_AMZ_ACL'] # Translate the Amazon ACL to something that can be # implemented in Swift, 501 otherwise. Swift uses POST # for ACLs, whereas S3 uses PUT. del env['HTTP_X_AMZ_ACL'] if 'QUERY_STRING' in env: del env['QUERY_STRING'] translated_acl = swift_acl_translate(amz_acl) if translated_acl == 'Unsupported': return get_err_response('Unsupported') elif translated_acl == 'InvalidArgument': return get_err_response('InvalidArgument') for header, acl in translated_acl: env[header] = acl if 'CONTENT_LENGTH' in env: content_length = env['CONTENT_LENGTH'] try: content_length = int(content_length) except (ValueError, TypeError): return get_err_response('InvalidArgument') if content_length < 0: return get_err_response('InvalidArgument') if 'QUERY_STRING' in env: args = dict(urlparse.parse_qsl(env['QUERY_STRING'], 1)) if 'acl' in args: # We very likely have an XML-based ACL request. body = env['wsgi.input'].readline().decode() translated_acl = swift_acl_translate(body, xml=True) if translated_acl == 'Unsupported': return get_err_response('Unsupported') elif translated_acl == 'InvalidArgument': return get_err_response('InvalidArgument') for header, acl in translated_acl: env[header] = acl env['REQUEST_METHOD'] = 'POST' self._app_call(env) status = self._get_status_int() if status != HTTP_CREATED and status != HTTP_NO_CONTENT: if status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return get_err_response('AccessDenied') elif status == HTTP_ACCEPTED: return get_err_response('BucketAlreadyExists') else: return get_err_response('InvalidURI') resp = Response() resp.headers['Location'] = self.container_name resp.status = HTTP_OK return resp
def OPTIONS(self, req): """ Base handler for OPTIONS requests :param req: swob.Request object :returns: swob.Response object """ # Prepare the default response headers = {'Allow': ', '.join(self.allowed_methods)} resp = Response(status=200, request=req, headers=headers) # If this isn't a CORS pre-flight request then return now req_origin_value = req.headers.get('Origin', None) if not req_origin_value: return resp # This is a CORS preflight request so check it's allowed try: container_info = \ self.container_info(self.account_name, self.container_name, req) except AttributeError: # This should only happen for requests to the Account. A future # change could allow CORS requests to the Account level as well. return resp cors = container_info.get('cors', {}) # If the CORS origin isn't allowed return a 401 if not self.is_origin_allowed(cors, req_origin_value) or ( req.headers.get('Access-Control-Request-Method') not in self.allowed_methods): resp.status = HTTP_UNAUTHORIZED return resp # Allow all headers requested in the request. The CORS # specification does leave the door open for this, as mentioned in # http://www.w3.org/TR/cors/#resource-preflight-requests # Note: Since the list of headers can be unbounded # simply returning headers can be enough. allow_headers = set() if req.headers.get('Access-Control-Request-Headers'): allow_headers.update( list_from_csv(req.headers['Access-Control-Request-Headers'])) # Populate the response with the CORS preflight headers if cors.get('allow_origin', '').strip() == '*': headers['access-control-allow-origin'] = '*' else: headers['access-control-allow-origin'] = req_origin_value if cors.get('max_age') is not None: headers['access-control-max-age'] = cors.get('max_age') headers['access-control-allow-methods'] = \ ', '.join(self.allowed_methods) if allow_headers: headers['access-control-allow-headers'] = ', '.join(allow_headers) resp.headers = headers return resp
def get_err_response(self, msg='Unable to process requested file'): self.logger.error(msg) resp = Response(content_type='text/xml') resp.status = HTTP_BAD_REQUEST resp.body = '<?xml version="1.0" encoding="UTF-8"?>\r\n<Error>\r\n ' \ '<Code>%s</Code>\r\n <Message>%s</Message>\r\n</Error>\r\n' \ % (HTTP_BAD_REQUEST, msg) return resp
def get_err_response(self, msg="Unable to process requested file"): self.logger.error(msg) resp = Response(content_type="text/xml") resp.status = HTTP_BAD_REQUEST resp.body = ( '<?xml version="1.0" encoding="UTF-8"?>\r\n<Error>\r\n ' "<Code>%s</Code>\r\n <Message>%s</Message>\r\n</Error>\r\n" % (HTTP_BAD_REQUEST, msg) ) return resp
def OPTIONS(self, req): """ Base handler for OPTIONS requests :param req: swob.Request object :returns: swob.Response object """ # Prepare the default response headers = {'Allow': ', '.join(self.allowed_methods)} resp = Response(status=200, request=req, headers=headers) # If this isn't a CORS pre-flight request then return now req_origin_value = req.headers.get('Origin', None) if not req_origin_value: return resp # This is a CORS preflight request so check it's allowed try: container_info = \ self.container_info(self.account_name, self.container_name, req) except AttributeError: # This should only happen for requests to the Account. A future # change could allow CORS requests to the Account level as well. return resp cors = container_info.get('cors', {}) # If the CORS origin isn't allowed return a 401 if not self.is_origin_allowed(cors, req_origin_value) or ( req.headers.get('Access-Control-Request-Method') not in self.allowed_methods): resp.status = HTTP_UNAUTHORIZED return resp # Allow all headers requested in the request. The CORS # specification does leave the door open for this, as mentioned in # http://www.w3.org/TR/cors/#resource-preflight-requests # Note: Since the list of headers can be unbounded # simply returning headers can be enough. allow_headers = set() if req.headers.get('Access-Control-Request-Headers'): allow_headers.update( list_from_csv(req.headers['Access-Control-Request-Headers'])) # Populate the response with the CORS preflight headers headers['access-control-allow-origin'] = req_origin_value if cors.get('max_age') is not None: headers['access-control-max-age'] = cors.get('max_age') headers['access-control-allow-methods'] = \ ', '.join(self.allowed_methods) if allow_headers: headers['access-control-allow-headers'] = ', '.join(allow_headers) resp.headers = headers return resp
def OPTIONS(self, req): """ Base handler for OPTIONS requests :param req: swob.Request object :returns: swob.Response object """ # Prepare the default response headers = {'Allow': ', '.join(self.allowed_methods)} resp = Response(status=200, request=req, headers=headers) # If this isn't a CORS pre-flight request then return now req_origin_value = req.headers.get('Origin', None) if not req_origin_value: return resp # This is a CORS preflight request so check it's allowed try: container_info = \ self.container_info(self.account_name, self.container_name) except AttributeError: # This should only happen for requests to the Account. A future # change could allow CORS requests to the Account level as well. return resp cors = container_info.get('cors', {}) # If the CORS origin isn't allowed return a 401 if not self.is_origin_allowed(cors, req_origin_value) or ( req.headers.get('Access-Control-Request-Method') not in self.allowed_methods): resp.status = HTTP_UNAUTHORIZED return resp # Always allow the x-auth-token header. This ensures # clients can always make a request to the resource. allow_headers = set() if cors.get('allow_headers'): allow_headers.update( [a.strip() for a in cors['allow_headers'].split(' ') if a.strip()]) allow_headers.add('x-auth-token') # Populate the response with the CORS preflight headers headers['access-control-allow-origin'] = req_origin_value if cors.get('max_age') is not None: headers['access-control-max-age'] = cors.get('max_age') headers['access-control-allow-methods'] = \ ', '.join(self.allowed_methods) headers['access-control-allow-headers'] = ', '.join(allow_headers) resp.headers = headers return resp
def get_err_response(code): """ Given an HTTP response code, create a properly formatted xml error response :param code: error code :returns: webob.response object """ error_table = { 'AccessDenied': (HTTP_FORBIDDEN, 'Access denied'), 'BucketAlreadyExists': (HTTP_CONFLICT, 'The requested bucket name is not available'), 'BucketNotEmpty': (HTTP_CONFLICT, 'The bucket you tried to delete is not empty'), 'InvalidArgument': (HTTP_BAD_REQUEST, 'Invalid Argument'), 'InvalidBucketName': (HTTP_BAD_REQUEST, 'The specified bucket is not valid'), 'InvalidURI': (HTTP_BAD_REQUEST, 'Could not parse the specified URI'), 'InvalidDigest': (HTTP_BAD_REQUEST, 'The Content-MD5 you specified was invalid'), 'BadDigest': (HTTP_BAD_REQUEST, 'The Content-Length you specified was invalid'), 'NoSuchBucket': (HTTP_NOT_FOUND, 'The specified bucket does not exist'), 'SignatureDoesNotMatch': (HTTP_FORBIDDEN, 'The calculated request signature does not ' 'match your provided one'), 'RequestTimeTooSkewed': (HTTP_FORBIDDEN, 'The difference between the request time and the' ' current time is too large'), 'NoSuchKey': (HTTP_NOT_FOUND, 'The resource you requested does not exist'), 'Unsupported': (HTTP_NOT_IMPLEMENTED, 'The feature you requested is not yet' ' implemented'), 'MissingContentLength': (HTTP_LENGTH_REQUIRED, 'Length Required'), 'ServiceUnavailable': (HTTP_SERVICE_UNAVAILABLE, 'Please reduce your request rate'), 'IllegalVersioningConfigurationException': (HTTP_BAD_REQUEST, 'The specified versioning configuration invalid'), 'MalformedACLError': (HTTP_BAD_REQUEST, 'The XML you provided was not well-formed or did ' 'not validate against our published schema') } resp = Response(content_type='text/xml') resp.status = error_table[code][0] resp.body = '<?xml version="1.0" encoding="UTF-8"?>\r\n<Error>\r\n ' \ '<Code>%s</Code>\r\n <Message>%s</Message>\r\n</Error>\r\n' \ % (code, error_table[code][1]) return resp
def get_err_response(self, code): """ Given an HTTP response code, create a properly formatted xml error response :param code: error code :returns: webob.response object """ error_table = { 'AccessDenied': (HTTP_FORBIDDEN, 'Access denied'), 'BucketAlreadyExists': (HTTP_CONFLICT, 'The requested bucket name is not available'), 'BucketNotEmpty': (HTTP_CONFLICT, 'The bucket you tried to delete is not empty'), 'InvalidArgument': (HTTP_BAD_REQUEST, 'Invalid Argument'), 'InvalidBucketName': (HTTP_BAD_REQUEST, 'The specified bucket is not valid'), 'InvalidURI': (HTTP_BAD_REQUEST, 'Could not parse the specified URI'), 'InvalidDigest': (HTTP_BAD_REQUEST, 'The Content-MD5 you specified was invalid'), 'BadDigest': (HTTP_BAD_REQUEST, 'The Content-Length you specified was invalid'), 'NoSuchBucket': (HTTP_NOT_FOUND, 'The specified bucket does not exist'), 'SignatureDoesNotMatch': (HTTP_FORBIDDEN, 'The calculated request signature does not ' 'match your provided one'), 'RequestTimeTooSkewed': (HTTP_FORBIDDEN, 'The difference between the request time and the' ' current time is too large'), 'NoSuchKey': (HTTP_NOT_FOUND, 'The resource you requested does not exist'), 'NotSuchPolicy': (HTTP_NOT_FOUND, 'The Policy you requested does not exist'), 'NotSuchWebsite': (HTTP_NOT_FOUND, 'The Website you requested does not exist'), 'Unsupported': (HTTP_NOT_IMPLEMENTED, 'The feature you requested is not yet' ' implemented'), 'MissingContentLength': (HTTP_LENGTH_REQUIRED, 'Length Required'), 'ServiceUnavailable': (HTTP_SERVICE_UNAVAILABLE, 'Please reduce your request rate') } resp = Response(content_type='text/xml') resp.status = error_table[code][0] resp.body = '<?xml version="1.0" encoding="UTF-8"?>\r\n<Error>\r\n ' \ '<Code>%s</Code>\r\n <Message>%s</Message>\r\n</Error>\r\n' \ % (code, error_table[code][1]) return resp
def _deny_request(self, code): error_table = { 'AccessDenied': (401, 'Access denied'), 'InvalidURI': (400, 'Could not parse the specified URI'), } resp = Response(content_type='text/xml') resp.status = error_table[code][0] error_msg = ('<?xml version="1.0" encoding="UTF-8"?>\r\n' '<Error>\r\n <Code>%s</Code>\r\n ' '<Message>%s</Message>\r\n</Error>\r\n' % (code, error_table[code][1])) if six.PY3: error_msg = error_msg.encode() resp.body = error_msg return resp
def get_err_response(code): """ Given an HTTP response code, create a properly formatted xml error response :param code: error code :returns: webob.response object """ error_table = { 'AccessDenied': (HTTP_FORBIDDEN, 'Access denied'), 'BucketAlreadyExists': ( HTTP_CONFLICT, 'The requested bucket name is not available'), 'BucketNotEmpty': ( HTTP_CONFLICT, 'The bucket you tried to delete is not empty'), 'InvalidArgument': (HTTP_BAD_REQUEST, 'Invalid Argument'), 'InvalidBucketName': ( HTTP_BAD_REQUEST, 'The specified bucket is not valid'), 'InvalidURI': (HTTP_BAD_REQUEST, 'Could not parse the specified URI'), 'InvalidDigest': ( HTTP_BAD_REQUEST, 'The Content-MD5 you specified was invalid'), 'BadDigest': ( HTTP_BAD_REQUEST, 'The Content-Length you specified was invalid'), 'EntityTooLarge': ( HTTP_BAD_REQUEST, 'Your proposed upload exceeds the maximum ' 'allowed object size.'), 'NoSuchBucket': ( HTTP_NOT_FOUND, 'The specified bucket does not exist'), 'SignatureDoesNotMatch': ( HTTP_FORBIDDEN, 'The calculated request signature does not match ' 'your provided one'), 'RequestTimeTooSkewed': ( HTTP_FORBIDDEN, 'The difference between the request time and the ' 'current time is too large'), 'NoSuchKey': ( HTTP_NOT_FOUND, 'The resource you requested does not exist'), 'Unsupported': ( HTTP_NOT_IMPLEMENTED, 'The feature you requested is not yet ' 'implemented'), 'MissingContentLength': (HTTP_LENGTH_REQUIRED, 'Length Required'), 'ServiceUnavailable': ( HTTP_SERVICE_UNAVAILABLE, 'Please reduce your request rate')} resp = Response(content_type='text/xml') resp.status = error_table[code][0] resp.body = """%s <Error><Code>%s</Code><Message>%s</Message></Error> """ % (XML_HEADER, code, error_table[code][1]) return resp
def DELETE(self, env, start_response): """ Handle DELETE Object request """ body_iter = self._app_call(env) status = self._get_status_int() if status != HTTP_NO_CONTENT: if status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return get_err_response('AccessDenied') elif status == HTTP_NOT_FOUND: return get_err_response('NoSuchKey') else: return get_err_response('InvalidURI') resp = Response() resp.status = HTTP_NO_CONTENT return resp
def OPTIONS_base(self, req): """ Base handler for OPTIONS requests :param req: swob.Request object :returns: swob.Response object """ headers = {'Allow': ', '.join(self.allowed_methods)} resp = Response(status=200, request=req, headers=headers) req_origin_value = req.headers.get('Origin', None) if not req_origin_value: # NOT a CORS request return resp # CORS preflight request try: container_info = \ self.container_info(self.account_name, self.container_name) except AttributeError: container_info = {} cors = container_info.get('cors', {}) allowed_origins = set() if cors.get('allow_origin'): allowed_origins.update(cors['allow_origin'].split(' ')) if self.app.cors_allow_origin: allowed_origins.update(self.app.cors_allow_origin) if (req_origin_value not in allowed_origins and '*' not in allowed_origins) or ( req.headers.get('Access-Control-Request-Method') not in self.allowed_methods): resp.status = HTTP_UNAUTHORIZED return resp # CORS preflight request that isn't valid headers['access-control-allow-origin'] = req_origin_value if cors.get('max_age', None) is not None: headers['access-control-max-age'] = '%d' % cors.get('max_age') headers['access-control-allow-methods'] = ', '.join( self.allowed_methods) if cors.get('allow_headers'): headers['access-control-allow-headers'] = cors.get('allow_headers') resp.headers = headers return resp
def page_main(self, req, storage_url, token): """ main page container list or object list """ path = urlparse(self.del_prefix(req.url)).path if len(path.split('/')) <= 2: path = urlparse(storage_url).path vrs, acc, cont, obj = split_path(path, 1, 4, True) path_type = len([i for i in [vrs, acc, cont, obj] if i]) if path_type == 2: # account return self.page_cont_list(req, storage_url, token) if path_type == 3: # container return self.page_obj_list(req, storage_url, token) if path_type == 4: # object try: (obj_status, objct) = get_object(storage_url, token, cont, obj) except ClientException, e: resp = Response(charset='utf8') resp.status = e.http_status return resp except err: pass
def page_main(self, req, storage_url, token): """ main page container list or object list """ path = urlparse(self.del_prefix(req.url)).path if len(path.split('/')) <= 2: path = urlparse(storage_url).path vrs, acc, cont, obj = split_path(path, 1, 4, True) path_type = len([i for i in [vrs, acc, cont, obj] if i]) if path_type == 2: # account return self.page_cont_list(req, storage_url, token) if path_type == 3: # container return self.page_obj_list(req, storage_url, token) if path_type == 4: # object try: (obj_status, objct) = get_object(storage_url, token, cont, obj) except ClientException, e: resp = Response(charset='utf8') resp.status = e.http_status return resp except err: pass
def get_working_response(self, req): source, node = self._get_source_and_node() res = None if source: res = Response(request=req) if req.method == "GET" and source.status in (HTTP_OK, HTTP_PARTIAL_CONTENT): res.app_iter = self._make_app_iter(node, source) # See NOTE: swift_conn at top of file about this. res.swift_conn = source.swift_conn res.status = source.status update_headers(res, source.getheaders()) if not res.environ: res.environ = {} res.environ["swift_x_timestamp"] = source.getheader("x-timestamp") res.accept_ranges = "bytes" res.content_length = source.getheader("Content-Length") if source.getheader("Content-Type"): res.charset = None res.content_type = source.getheader("Content-Type") return res
def DELETE(self, env, start_response): """ Handle DELETE Bucket request """ body_iter = self._app_call(env) status = self._get_status_int() if status != HTTP_NO_CONTENT: if status == HTTP_UNAUTHORIZED: return get_err_response('AccessDenied') elif status == HTTP_NOT_FOUND: return get_err_response('NoSuchBucket') elif status == HTTP_CONFLICT: return get_err_response('BucketNotEmpty') else: return get_err_response('InvalidURI') resp = Response() resp.status = HTTP_NO_CONTENT return resp
def DELETE(self, env, start_response): """ Handle DELETE Bucket request """ self._app_call(env) status = self._get_status_int() if status != HTTP_NO_CONTENT: if status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return get_err_response('AccessDenied') elif status == HTTP_NOT_FOUND: return get_err_response('NoSuchBucket') elif status == HTTP_CONFLICT: return get_err_response('BucketNotEmpty') else: return get_err_response('InvalidURI') resp = Response() resp.status = HTTP_NO_CONTENT return resp
def OPTIONS_base(self, req): """ Base handler for OPTIONS requests :param req: swob.Request object :returns: swob.Response object """ headers = {'Allow': ', '.join(self.allowed_methods)} resp = Response(status=200, request=req, headers=headers) req_origin_value = req.headers.get('Origin', None) if not req_origin_value: # NOT a CORS request return resp # CORS preflight request try: container_info = \ self.container_info(self.account_name, self.container_name) except AttributeError: container_info = {} cors = container_info.get('cors', {}) allowed_origins = set() if cors.get('allow_origin'): allowed_origins.update(cors['allow_origin'].split(' ')) if self.app.cors_allow_origin: allowed_origins.update(self.app.cors_allow_origin) if (req_origin_value not in allowed_origins and '*' not in allowed_origins) or ( req.headers.get('Access-Control-Request-Method') not in self.allowed_methods): resp.status = HTTP_UNAUTHORIZED return resp # CORS preflight request that isn't valid headers['access-control-allow-origin'] = req_origin_value if cors.get('max_age') is not None: headers['access-control-max-age'] = cors.get('max_age') headers['access-control-allow-methods'] = ', '.join( self.allowed_methods) if cors.get('allow_headers'): headers['access-control-allow-headers'] = cors.get('allow_headers') resp.headers = headers return resp
def get_err_response(code): """ Given an HTTP response code, create a properly formatted xml error response :param code: error code :returns: webob.response object """ error_table = { "AccessDenied": (HTTP_FORBIDDEN, "Access denied"), "BucketAlreadyExists": (HTTP_CONFLICT, "The requested bucket name is not available"), "BucketNotEmpty": (HTTP_CONFLICT, "The bucket you tried to delete is not empty"), "InvalidArgument": (HTTP_BAD_REQUEST, "Invalid Argument"), "InvalidBucketName": (HTTP_BAD_REQUEST, "The specified bucket is not valid"), "InvalidURI": (HTTP_BAD_REQUEST, "Could not parse the specified URI"), "InvalidDigest": (HTTP_BAD_REQUEST, "The Content-MD5 you specified was invalid"), "BadDigest": (HTTP_BAD_REQUEST, "The Content-Length you specified was invalid"), "NoSuchObject": (HTTP_NOT_FOUND, "The specified object does not exist"), "NoSuchBucket": (HTTP_NOT_FOUND, "The specified bucket does not exist"), "NoSuchUpload": (HTTP_NOT_FOUND, "The specified bucket does not exist"), "SignatureDoesNotMatch": ( HTTP_FORBIDDEN, "The calculated request signature does not " "match your provided one", ), "RequestTimeTooSkewed": ( HTTP_FORBIDDEN, "The difference between the request time and the" " current time is too large", ), "NoSuchKey": (HTTP_NOT_FOUND, "The resource you requested does not exist"), "Unsupported": (HTTP_NOT_IMPLEMENTED, "The feature you requested is not yet" " implemented"), "MissingContentLength": (HTTP_LENGTH_REQUIRED, "Length Required"), "ServiceUnavailable": (HTTP_SERVICE_UNAVAILABLE, "Please reduce your request rate"), } resp = Response(content_type="text/xml") resp.status = error_table[code][0] resp.body = ( '<?xml version="1.0" encoding="UTF-8"?>\r\n<Error>\r\n ' "<Code>%s</Code>\r\n <Message>%s</Message>\r\n</Error>\r\n" % (code, error_table[code][1]) ) return resp
def DELETE(self, env, start_response): """ Handle DELETE Object request """ try: self._app_call(env) except: return get_err_response('InvalidURI') status = self._get_status_int() if status != HTTP_NO_CONTENT: if status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return get_err_response('AccessDenied') elif status == HTTP_NOT_FOUND: return get_err_response('NoSuchKey') else: return get_err_response('InvalidURI') resp = Response() resp.status = HTTP_NO_CONTENT return resp
def get_working_response(self, req): source, node = self._get_source_and_node() res = None if source: res = Response(request=req) if req.method == 'GET' and \ source.status in (HTTP_OK, HTTP_PARTIAL_CONTENT): res.app_iter = self._make_app_iter(node, source) # See NOTE: swift_conn at top of file about this. res.swift_conn = source.swift_conn res.status = source.status update_headers(res, source.getheaders()) if not res.environ: res.environ = {} res.environ['swift_x_timestamp'] = \ source.getheader('x-timestamp') res.accept_ranges = 'bytes' res.content_length = source.getheader('Content-Length') if source.getheader('Content-Type'): res.charset = None res.content_type = source.getheader('Content-Type') return res
def GETorHEAD_base(self, req, server_type, partition, nodes, path, attempts): """ Base handler for HTTP GET or HEAD requests. :param req: swob.Request object :param server_type: server type :param partition: partition :param nodes: nodes :param path: path for the request :param attempts: number of attempts to try :returns: swob.Response object """ statuses = [] reasons = [] bodies = [] sources = [] newest = config_true_value(req.headers.get("x-newest", "f")) nodes = iter(nodes) while len(statuses) < attempts: try: node = nodes.next() except StopIteration: break if self.error_limited(node): continue try: with ConnectionTimeout(self.app.conn_timeout): headers = dict(req.headers) headers["Connection"] = "close" conn = http_connect( node["ip"], node["port"], node["device"], partition, req.method, path, headers=headers, query_string=req.query_string, ) with Timeout(self.app.node_timeout): possible_source = conn.getresponse() # See NOTE: swift_conn at top of file about this. possible_source.swift_conn = conn except (Exception, Timeout): self.exception_occurred( node, server_type, _("Trying to %(method)s %(path)s") % {"method": req.method, "path": req.path} ) continue if self.is_good_source(possible_source): # 404 if we know we don't have a synced copy if not float(possible_source.getheader("X-PUT-Timestamp", 1)): statuses.append(HTTP_NOT_FOUND) reasons.append("") bodies.append("") self.close_swift_conn(possible_source) else: statuses.append(possible_source.status) reasons.append(possible_source.reason) bodies.append("") sources.append(possible_source) if not newest: # one good source is enough break else: statuses.append(possible_source.status) reasons.append(possible_source.reason) bodies.append(possible_source.read()) if possible_source.status == HTTP_INSUFFICIENT_STORAGE: self.error_limit(node) elif is_server_error(possible_source.status): self.error_occurred( node, _("ERROR %(status)d %(body)s " "From %(type)s Server") % {"status": possible_source.status, "body": bodies[-1][:1024], "type": server_type}, ) if sources: sources.sort(key=source_key) source = sources.pop() for src in sources: self.close_swift_conn(src) res = Response(request=req, conditional_response=True) if req.method == "GET" and source.status in (HTTP_OK, HTTP_PARTIAL_CONTENT): res.app_iter = self._make_app_iter(node, source) # See NOTE: swift_conn at top of file about this. res.swift_conn = source.swift_conn res.status = source.status update_headers(res, source.getheaders()) if not res.environ: res.environ = {} res.environ["swift_x_timestamp"] = source.getheader("x-timestamp") res.accept_ranges = "bytes" res.content_length = source.getheader("Content-Length") if source.getheader("Content-Type"): res.charset = None res.content_type = source.getheader("Content-Type") return res return self.best_response(req, statuses, reasons, bodies, "%s %s" % (server_type, req.method))
def DELETE(self, env, start_response): """ Handle DELETE Bucket request """ key_args = set(["cors", "lifecycle", "policy", "tagging", "website"]) qs = env.get("QUERY_STRING", "") args = urlparse.parse_qs(qs, 1) if not key_args & set(args): # DELETE a Bucket version = args.get("versionId") if version: vid = version[0] if vid.lower() == "lastest": pass else: env["PATH_INFO"] = "/v1/AUTH_%s/%s/%s" % ( quote(self.account_name), quote(self.version_name(self.container_name)), vid, ) body_iter = self._app_call(env) status = self._get_status_int() if status != HTTP_NO_CONTENT: if status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") elif status == HTTP_NOT_FOUND: return self.get_err_response("NoSuchBucket") elif status == HTTP_CONFLICT: return self.get_err_response("BucketNotEmpty") else: return self.get_err_response("InvalidURI") resp = Response() resp.status = HTTP_NO_CONTENT return resp else: # DELETE specified data action = args.keys().pop() if action == "cors": # delete cors env["HTTP_X_CONTAINER_META_ACCESS_CONTROL_ALLOW_ORIGIN"] = "" env["HTTP_X_CONTAINER_META_ACCESS_CONTROL_MAX_AGE"] = "" env["HTTP_X_CONTAINER_META_ACCESS_CONTROL_EXPOSE_HEADERS"] = "" env["HTTP_X_CONTAINER_META_ACCESS_CONTROL_ALLOW_METHOD"] = "" env["QUERY_STRING"] = "" env["REQUEST_METHOD"] = "POST" body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_NO_CONTENT return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") else: return self.get_err_response("InvalidURI") elif action == "lifecycle": # delete lifecycle env["HTTP_X_CONTAINER_META_TRANS_AT"] = "" env["HTTP_X_CONTAINER_META_TRANS_AFTER"] = "" env["HTTP_X_CONTAINER_META_TRANS_CLASS"] = "" env["HTTP_X_CONTAINER_META_EXPIRATION_AT"] = "" env["HTTP_X_CONTAINER_META_EXPIRATION_AFTER"] = "" env["HTTP_X_CONTAINER_META_EXPIRATION_PREFIX"] = "" env["HTTP_X_CONTAINER_META_EXPIRATION_STATUS"] = "" env["REQUEST_METHOD"] = "POST" env["QUERY_STRING"] = "" body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_NO_CONTENT return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") else: return self.get_err_response("InvalidURI") elif action == "policy": # delete policy env["REQUEST_METHOD"] = "POST" env["QUERY_STRING"] = "" env["HTTP_X_CONTAINER_META_POLICY"] = "" body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_NO_CONTENT return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") else: return self.get_err_response("InvalidURI") elif action == "tagging": # delete tagging env2 = copy(env) container_info = get_container_info(env2, self.app) meta_keys = container_info["meta"].keys() for key in meta_keys: env["HTTP_X_CONTAINER_META_" + key.replace("-", "_").upper()] = "" env["QUERY_STRING"] = "" env["REQUEST_METHOD"] = "POST" body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_NO_CONTENT return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") else: return self.get_err_response("InvalidURI") elif action == "website": # delete website body = env["wsgi.input"].read() env["REQUEST_METHOD"] = "POST" env["QUERY_STRING"] = "" env["HTTP_X_CONTAINER_META_WEBSITE"] = quote(body) body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") else: return self.get_err_response("InvalidURI") else: return self.get_err_response("InvalidURI")
def PUT(self, env, start_response): """ Handle PUT Bucket request """ # checking params available AMZ_ACL = set( [ "HTTP_X_AMZ_GRANT_READ", "HTTP_X_AMZ_GRANT_WRITE", "HTTP_X_AMZ_GRANT_READ_ACP", "HTTP_X_AMZ_GRANT_WRITE_ACP", "HTTP_X_AMZ_GRANT_FULL_CONTROL", ] ) qs = env.get("QUERY_STRING", "") args = urlparse.parse_qs(qs, 1) if not args: if not self.validate_bucket_name(self.container_name): return self.get_err_response("InvalidBucketName") if not self.is_unique(self.container_name): return self.get_err_response("BucketAlreadyExists") # to create a new one if "HTTP_X_AMZ_ACL" in env: amz_acl = env["HTTP_X_AMZ_ACL"] translated_acl = self.swift_acl_translate(canned=amz_acl) for header, value in translated_acl: env[header] = value elif AMZ_ACL & set(env.keys()): acld = dict() if "HTTP_X_AMZ_GRANT_READ" in env.keys(): acld["read"] = self.keyvalue2dict(env["HTTP_X_AMZ_GRANT_READ"]) if "HTTP_X_AMZ_GRANT_WRITE" in env.keys(): acld["write"] = self.keyvalue2dict(env["HTTP_X_AMZ_GRANT_WRITE"]) if "HTTP_X_AMZ_GRANT_FULL_CONTROL" in env.keys(): acld["full"] = self.keyvalue2dict(env["HTTP_X_AMZ_GRANT_FULL_CONTROL"]) translated_acl = self.swift_acl_translate(acl=acld) for header, value in translated_acl: env[header] = value # modify env put to swift body_iter = self._app_call(env) status = self._get_status_int() if status != HTTP_CREATED: if status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") elif status == HTTP_ACCEPTED: return self.get_err_response("BucketAlreadyExists") else: return self.get_err_response("InvalidURI") resp = Response() resp.headers["Location"] = self.container_name resp.status = HTTP_OK return resp if len(args) > 1: return self.get_err_response("InvalidURI") # now args only 1 action = args.keys().pop() if action == "acl": # put acl acl = env["wsgi.input"].read() env["REQUEST_METHOD"] = "POST" env["QUERY_STRING"] = "" env["HTTP_X_CONTAINER_META_ACL"] = quote(acl) body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") else: return self.get_err_response("InvalidURI") elif action == "cors": # put cors bodye = self.xmlbody2elem(env["wsgi.input"].read()) env["HTTP_X_CONTAINER_META_ACCESS_CONTROL_ALLOW_ORIGIN"] = ",".join( [i.text for i in bodye.xpath("/CORSConfiguration/CORSRule/AllowedOrigin")] ) env["HTTP_X_CONTAINER_META_ACCESS_CONTROL_MAX_AGE"] = ",".join( [i.text for i in bodye.xpath("/CORSConfiguration/CORSRule/MaxAgeSeconds")] ) env["HTTP_X_CONTAINER_META_ACCESS_CONTROL_EXPOSE_HEADERS"] = ",".join( [i.text for i in bodye.xpath("/CORSConfiguration/CORSRule/ExposeHeader")] ) env["HTTP_X_CONTAINER_META_ACCESS_CONTROL_ALLOW_METHOD"] = ",".join( i.text for i in bodye.xpath("/CORSConfiguration/CORSRule/AllowedMethod") ) env["QUERY_STRING"] = "" env["REQUEST_METHOD"] = "POST" body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.headers["Location"] = self.container_name resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") else: return self.get_err_response("InvalidURI") elif action == "lifecycle": # put lifecycle container_info = get_container_info(env, self.app) if container_info["versions"]: return self.get_err_response("AccessDenied") bodye = self.xmlbody2elem(env["wsgi.input"].read()) tat = bodye.xpath("/LifecycleConfiguration/Rule/Transition/Date") env["HTTP_X_CONTAINER_META_TRANS_AT"] = tat[0].text if tat else "" tafter = bodye.xpath("/LifecycleConfiguration/Rule/Transition/Days") env["HTTP_X_CONTAINER_META_TRANS_AFTER"] = tafter[0].text if tafter else "" trans = bodye.xpath("/LifecycleConfiguration/Rule/Transition/StorageClass") env["HTTP_X_CONTAINER_META_TRANS_CLASS"] = trans[0].text if trans else "" at = bodye.xpath("/LifecycleConfiguration/Rule/Expiration/Date") env["HTTP_X_CONTAINER_META_EXPIRATION_AT"] = at[0].text if at else "" after = bodye.xpath("/LifecycleConfiguration/Rule/Expiration/Days") env["HTTP_X_CONTAINER_META_EXPIRATION_AFTER"] = after[0].text if after else "" prefix = bodye.xpath("/LifecycleConfiguration/Rule/Prefix") env["HTTP_X_CONTAINER_META_EXPIRATION_PREFIX"] = prefix[0].text if prefix else "" stat = bodye.xpath("/LifecycleConfiguration/Rule/Status") env["HTTP_X_CONTAINER_META_EXPIRATION_STATUS"] = stat[0].text if stat else "" env["REQUEST_METHOD"] = "POST" env["QUERY_STRING"] = "" body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") else: return self.get_err_response("InvalidURI") elif action == "policy": # put policy json = env["wsgi.input"].read() env["REQUEST_METHOD"] = "POST" env["QUERY_STRING"] = "" env["HTTP_X_CONTAINER_META_POLICY"] = quote(json) body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") else: return self.get_err_response("InvalidURI") elif action == "logging": # put logging env["REQUEST_METHOD"] = "POST" env["QUERY_STRING"] = "" bodye = self.xmlbody2elem(env["wsgi.input"].read()) target = bodye.xpath("/BucketLoggingStatus/LoggingEnabled/TargetBucket") if target: env["HTTP_X_CONTAINER_META_LOGGING_TARGET"] = target[0].text prefix = bodye.xpath("/BucketLoggingStatus/LoggingEnabled/TargetPrefix") if prefix: env["HTTP_X_CONTAINER_META_LOGGING_PREFIX"] = prefix[0].text else: env["HTTP_X_CONTAINER_META_LOGGING_TARGET"] = "" env["HTTP_X_CONTAINER_META_LOGGING_PREFIX"] = "" body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") else: return self.get_err_response("InvalidURI") elif action == "notification": # put it bodye = self.xmlbody2elem(env["wsgi.input"].read()) topic = bodye.xpath("/NotificationConfiguration/TopicConfiguration/Topic") event = bodye.xpath("/NotificationConfiguration/TopicConfiguration/Event") if not topic or not event: return self.get_err_response("InvalidArgument") env["REQUEST_METHOD"] = "POST" env["QUERY_STRING"] = "" env["HTTP_CONTAINER_META_NOTI_TOPIC"] = topic[0].text env["HTTP_CONTAINER_META_NOTI_EVENT"] = event[0].text env["HTTP_X_CONTAINER_META_NOTI"] = quote(body) body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") else: return self.get_err_response("InvalidURI") elif action == "tagging": # put tagging bodye = self.xmlbody2elem(env["wsgi.input"].read()) for tag in bodye.xpath("/Tagging/TagSet/Tag"): key = tag.xpath("Key")[0].text value = tag.xpath("Key")[0].text + tag.xpath("Value")[0].text env["HTTP_X_CONTAINER_META_TAG_%s" % key.upper()] = value env["REQUEST_METHOD"] = "POST" env["QUERY_STRING"] = "" body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_NO_CONTENT return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") else: return self.get_err_response("InvalidURI") elif action == "requestPayment": # put it bodye = self.xmlbody2elem(env["wsgi.input"].read()) target = bodye.xpath("/RequestPaymentConfiguration/Payer") if not target or target[0].text not in ("BucketOwner", "Requester"): return self.get_err_response("InvalidArgument") env["REQUEST_METHOD"] = "POST" env["QUERY_STRING"] = "" env["HTTP_X_CONTAINER_META_PAYMENT"] = quote(body) body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") else: return self.get_err_response("InvalidURI") elif action == "versioning": bodye = self.xmlbody2elem(env["wsgi.input"].read()) status = bodye.xpath("/VersioningConfiguration/Status") if status: status = status[0].text env["REQUEST_METHOD"] = "POST" env["HTTP_X_VERSIONS_LOCATION"] = self.version_name(self.container_name) if status == "Enabled" else "" env["QUERY_STRING"] = "" body_iter = self._app_call(env) status = self._get_status_int() path = "/v1/AUTH_%s/%s" % (self.account_name, self.version_name(self.container_name)) env2 = copyenv(env, method="PUT", path=path, query_string="") body_iter2 = self._app_call(env2) status2 = self._get_status_int() if is_success(status) and is_success(status2): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") else: return self.get_err_response("InvalidURI") elif action == "website": # put website body = env["wsgi.input"].read() env["REQUEST_METHOD"] = "POST" env["QUERY_STRING"] = "" env["HTTP_X_CONTAINER_META_WEBSITE"] = quote(body) body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response("AccessDenied") else: return self.get_err_response("InvalidURI") else: return self.get_err_response("InvalidURI")
if path_type == 4: # object try: (obj_status, objct) = get_object(storage_url, token, cont, obj) except ClientException, e: resp = Response(charset='utf8') resp.status = e.http_status return resp except err: pass resp = Response() resp.set_cookie('_token', token, path=self.page_path, max_age=self.cookie_max_age, secure=self.secure) resp.status = HTTP_OK resp.headers = obj_status resp.body = objct self.token_bank[token].update({'msg': ''}) self.memcache_update(token) return resp return HTTPFound(location=self.add_prefix(storage_url)) def page_cont_list(self, req, storage_url, token, template=None): """ """ if template is None: tmpl = self.tmpl path = urlparse(self.del_prefix(req.url)).path if len(path.split('/')) <= 2: path = urlparse(storage_url).path vrs, acc, cont, obj = split_path(path, 1, 4, True)
def PUT(self, env, start_response): """ Handle PUT Bucket request """ # checking params available AMZ_ACL = set([ 'HTTP_X_AMZ_GRANT_READ', 'HTTP_X_AMZ_GRANT_WRITE', 'HTTP_X_AMZ_GRANT_READ_ACP', 'HTTP_X_AMZ_GRANT_WRITE_ACP', 'HTTP_X_AMZ_GRANT_FULL_CONTROL' ]) qs = env.get('QUERY_STRING', '') args = urlparse.parse_qs(qs, 1) if not args: if not self.validate_bucket_name(self.container_name): return self.get_err_response('InvalidBucketName') if not self.is_unique(self.container_name): return self.get_err_response('BucketAlreadyExists') # to create a new one if 'HTTP_X_AMZ_ACL' in env: amz_acl = env['HTTP_X_AMZ_ACL'] translated_acl = self.swift_acl_translate(canned=amz_acl) for header, value in translated_acl: env[header] = value elif AMZ_ACL & set(env.keys()): acld = dict() if 'HTTP_X_AMZ_GRANT_READ' in env.keys(): acld['read'] = self.keyvalue2dict( env['HTTP_X_AMZ_GRANT_READ']) if 'HTTP_X_AMZ_GRANT_WRITE' in env.keys(): acld['write'] = self.keyvalue2dict( env['HTTP_X_AMZ_GRANT_WRITE']) if 'HTTP_X_AMZ_GRANT_FULL_CONTROL' in env.keys(): acld['full'] = self.keyvalue2dict( env['HTTP_X_AMZ_GRANT_FULL_CONTROL']) translated_acl = self.swift_acl_translate(acl=acld) for header, value in translated_acl: env[header] = value # modify env put to swift body_iter = self._app_call(env) status = self._get_status_int() if status != HTTP_CREATED: if status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') elif status == HTTP_ACCEPTED: return self.get_err_response('BucketAlreadyExists') else: return self.get_err_response('InvalidURI') resp = Response() resp.headers['Location'] = self.container_name resp.status = HTTP_OK return resp if len(args) > 1: return self.get_err_response('InvalidURI') # now args only 1 action = args.keys().pop() if action == 'acl': # put acl acl = env['wsgi.input'].read() env['REQUEST_METHOD'] = 'POST' env['QUERY_STRING'] = '' env['HTTP_X_CONTAINER_META_ACL'] = quote(acl) body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') else: return self.get_err_response('InvalidURI') elif action == 'cors': # put cors bodye = self.xmlbody2elem(env['wsgi.input'].read()) env['HTTP_X_CONTAINER_META_ACCESS_CONTROL_ALLOW_ORIGIN'] = ','.join( [ i.text for i in bodye.xpath( '/CORSConfiguration/CORSRule/AllowedOrigin') ]) env['HTTP_X_CONTAINER_META_ACCESS_CONTROL_MAX_AGE'] = ','.join([ i.text for i in bodye.xpath( '/CORSConfiguration/CORSRule/MaxAgeSeconds') ]) env['HTTP_X_CONTAINER_META_ACCESS_CONTROL_EXPOSE_HEADERS'] = ','.join( [ i.text for i in bodye.xpath( '/CORSConfiguration/CORSRule/ExposeHeader') ]) env['HTTP_X_CONTAINER_META_ACCESS_CONTROL_ALLOW_METHOD'] = ','.join( i.text for i in bodye.xpath( '/CORSConfiguration/CORSRule/AllowedMethod')) env['QUERY_STRING'] = '' env['REQUEST_METHOD'] = 'POST' body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.headers['Location'] = self.container_name resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') else: return self.get_err_response('InvalidURI') elif action == 'lifecycle': # put lifecycle container_info = get_container_info(env, self.app) if container_info['versions']: return self.get_err_response('AccessDenied') bodye = self.xmlbody2elem(env['wsgi.input'].read()) tat = bodye.xpath('/LifecycleConfiguration/Rule/Transition/Date') env['HTTP_X_CONTAINER_META_TRANS_AT'] = tat[0].text if tat else '' tafter = bodye.xpath( '/LifecycleConfiguration/Rule/Transition/Days') env['HTTP_X_CONTAINER_META_TRANS_AFTER'] = tafter[ 0].text if tafter else '' trans = bodye.xpath( '/LifecycleConfiguration/Rule/Transition/StorageClass') env['HTTP_X_CONTAINER_META_TRANS_CLASS'] = trans[ 0].text if trans else '' at = bodye.xpath('/LifecycleConfiguration/Rule/Expiration/Date') env['HTTP_X_CONTAINER_META_EXPIRATION_AT'] = at[ 0].text if at else '' after = bodye.xpath('/LifecycleConfiguration/Rule/Expiration/Days') env['HTTP_X_CONTAINER_META_EXPIRATION_AFTER'] = after[ 0].text if after else '' prefix = bodye.xpath('/LifecycleConfiguration/Rule/Prefix') env['HTTP_X_CONTAINER_META_EXPIRATION_PREFIX'] = prefix[ 0].text if prefix else '' stat = bodye.xpath('/LifecycleConfiguration/Rule/Status') env['HTTP_X_CONTAINER_META_EXPIRATION_STATUS'] = stat[ 0].text if stat else '' env['REQUEST_METHOD'] = 'POST' env['QUERY_STRING'] = '' body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') else: return self.get_err_response('InvalidURI') elif action == 'policy': # put policy json = env['wsgi.input'].read() env['REQUEST_METHOD'] = 'POST' env['QUERY_STRING'] = '' env['HTTP_X_CONTAINER_META_POLICY'] = quote(json) body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') else: return self.get_err_response('InvalidURI') elif action == 'logging': # put logging env['REQUEST_METHOD'] = 'POST' env['QUERY_STRING'] = '' bodye = self.xmlbody2elem(env['wsgi.input'].read()) target = bodye.xpath( '/BucketLoggingStatus/LoggingEnabled/TargetBucket') if target: env['HTTP_X_CONTAINER_META_LOGGING_TARGET'] = target[0].text prefix = bodye.xpath( '/BucketLoggingStatus/LoggingEnabled/TargetPrefix') if prefix: env['HTTP_X_CONTAINER_META_LOGGING_PREFIX'] = prefix[ 0].text else: env['HTTP_X_CONTAINER_META_LOGGING_TARGET'] = '' env['HTTP_X_CONTAINER_META_LOGGING_PREFIX'] = '' body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') else: return self.get_err_response('InvalidURI') elif action == 'notification': # put it bodye = self.xmlbody2elem(env['wsgi.input'].read()) topic = bodye.xpath( '/NotificationConfiguration/TopicConfiguration/Topic') event = bodye.xpath( '/NotificationConfiguration/TopicConfiguration/Event') if not topic or not event: return self.get_err_response('InvalidArgument') env['REQUEST_METHOD'] = 'POST' env['QUERY_STRING'] = '' env['HTTP_CONTAINER_META_NOTI_TOPIC'] = topic[0].text env['HTTP_CONTAINER_META_NOTI_EVENT'] = event[0].text env['HTTP_X_CONTAINER_META_NOTI'] = quote(body) body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') else: return self.get_err_response('InvalidURI') elif action == 'tagging': # put tagging bodye = self.xmlbody2elem(env['wsgi.input'].read()) for tag in bodye.xpath('/Tagging/TagSet/Tag'): key = tag.xpath('Key')[0].text value = tag.xpath('Key')[0].text + tag.xpath('Value')[0].text env['HTTP_X_CONTAINER_META_TAG_%s' % key.upper()] = value env['REQUEST_METHOD'] = 'POST' env['QUERY_STRING'] = '' body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_NO_CONTENT return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') else: return self.get_err_response('InvalidURI') elif action == 'requestPayment': # put it bodye = self.xmlbody2elem(env['wsgi.input'].read()) target = bodye.xpath('/RequestPaymentConfiguration/Payer') if not target or target[0].text not in ('BucketOwner', 'Requester'): return self.get_err_response('InvalidArgument') env['REQUEST_METHOD'] = 'POST' env['QUERY_STRING'] = '' env['HTTP_X_CONTAINER_META_PAYMENT'] = quote(body) body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') else: return self.get_err_response('InvalidURI') elif action == 'versioning': bodye = self.xmlbody2elem(env['wsgi.input'].read()) status = bodye.xpath('/VersioningConfiguration/Status') if status: status = status[0].text env['REQUEST_METHOD'] = 'POST' env['HTTP_X_VERSIONS_LOCATION'] = self.version_name( self.container_name) if status == 'Enabled' else '' env['QUERY_STRING'] = '' body_iter = self._app_call(env) status = self._get_status_int() path = '/v1/AUTH_%s/%s' % (self.account_name, self.version_name(self.container_name)) env2 = copyenv(env, method='PUT', path=path, query_string='') body_iter2 = self._app_call(env2) status2 = self._get_status_int() if is_success(status) and is_success(status2): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') else: return self.get_err_response('InvalidURI') elif action == 'website': # put website body = env['wsgi.input'].read() env['REQUEST_METHOD'] = 'POST' env['QUERY_STRING'] = '' env['HTTP_X_CONTAINER_META_WEBSITE'] = quote(body) body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') else: return self.get_err_response('InvalidURI') else: return self.get_err_response('InvalidURI')
def DELETE(self, env, start_response): """ Handle DELETE Bucket request """ key_args = set(['cors', 'lifecycle', 'policy', 'tagging', 'website']) qs = env.get('QUERY_STRING', '') args = urlparse.parse_qs(qs, 1) if not key_args & set(args): # DELETE a Bucket version = args.get('versionId') if version: vid = version[0] if vid.lower() == 'lastest': pass else: env['PATH_INFO'] = '/v1/AUTH_%s/%s/%s' % ( quote(self.account_name), quote(self.version_name(self.container_name)), vid) body_iter = self._app_call(env) status = self._get_status_int() if status != HTTP_NO_CONTENT: if status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') elif status == HTTP_NOT_FOUND: return self.get_err_response('NoSuchBucket') elif status == HTTP_CONFLICT: return self.get_err_response('BucketNotEmpty') else: return self.get_err_response('InvalidURI') resp = Response() resp.status = HTTP_NO_CONTENT return resp else: # DELETE specified data action = args.keys().pop() if action == 'cors': # delete cors env['HTTP_X_CONTAINER_META_ACCESS_CONTROL_ALLOW_ORIGIN'] = '' env['HTTP_X_CONTAINER_META_ACCESS_CONTROL_MAX_AGE'] = '' env['HTTP_X_CONTAINER_META_ACCESS_CONTROL_EXPOSE_HEADERS'] = '' env['HTTP_X_CONTAINER_META_ACCESS_CONTROL_ALLOW_METHOD'] = '' env['QUERY_STRING'] = '' env['REQUEST_METHOD'] = 'POST' body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_NO_CONTENT return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') else: return self.get_err_response('InvalidURI') elif action == 'lifecycle': # delete lifecycle env['HTTP_X_CONTAINER_META_TRANS_AT'] = '' env['HTTP_X_CONTAINER_META_TRANS_AFTER'] = '' env['HTTP_X_CONTAINER_META_TRANS_CLASS'] = '' env['HTTP_X_CONTAINER_META_EXPIRATION_AT'] = '' env['HTTP_X_CONTAINER_META_EXPIRATION_AFTER'] = '' env['HTTP_X_CONTAINER_META_EXPIRATION_PREFIX'] = '' env['HTTP_X_CONTAINER_META_EXPIRATION_STATUS'] = '' env['REQUEST_METHOD'] = 'POST' env['QUERY_STRING'] = '' body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_NO_CONTENT return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') else: return self.get_err_response('InvalidURI') elif action == 'policy': # delete policy env['REQUEST_METHOD'] = 'POST' env['QUERY_STRING'] = '' env['HTTP_X_CONTAINER_META_POLICY'] = '' body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_NO_CONTENT return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') else: return self.get_err_response('InvalidURI') elif action == 'tagging': # delete tagging env2 = copy(env) container_info = get_container_info(env2, self.app) meta_keys = container_info['meta'].keys() for key in meta_keys: env['HTTP_X_CONTAINER_META_' + key.replace('-', '_').upper()] = '' env['QUERY_STRING'] = '' env['REQUEST_METHOD'] = 'POST' body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_NO_CONTENT return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') else: return self.get_err_response('InvalidURI') elif action == 'website': # delete website body = env['wsgi.input'].read() env['REQUEST_METHOD'] = 'POST' env['QUERY_STRING'] = '' env['HTTP_X_CONTAINER_META_WEBSITE'] = quote(body) body_iter = self._app_call(env) status = self._get_status_int() if is_success(status): resp = Response() resp.status = HTTP_OK return resp elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN): return self.get_err_response('AccessDenied') else: return self.get_err_response('InvalidURI') else: return self.get_err_response('InvalidURI')
def GETorHEAD_base(self, req, server_type, ring, partition, path): """ Base handler for HTTP GET or HEAD requests. :param req: swob.Request object :param server_type: server type :param ring: the ring to obtain nodes from :param partition: partition :param path: path for the request :returns: swob.Response object """ statuses = [] reasons = [] bodies = [] source_headers = [] sources = [] newest = config_true_value(req.headers.get('x-newest', 'f')) headers = self.generate_request_headers(req, additional=req.headers) for node in self.iter_nodes(ring, partition): start_node_timing = time.time() try: with ConnectionTimeout(self.app.conn_timeout): conn = http_connect( node['ip'], node['port'], node['device'], partition, req.method, path, headers=headers, query_string=req.query_string) self.app.set_node_timing(node, time.time() - start_node_timing) with Timeout(self.app.node_timeout): possible_source = conn.getresponse() # See NOTE: swift_conn at top of file about this. possible_source.swift_conn = conn except (Exception, Timeout): self.exception_occurred( node, server_type, _('Trying to %(method)s %(path)s') % {'method': req.method, 'path': req.path}) continue if self.is_good_source(possible_source): # 404 if we know we don't have a synced copy if not float(possible_source.getheader('X-PUT-Timestamp', 1)): statuses.append(HTTP_NOT_FOUND) reasons.append('') bodies.append('') source_headers.append('') self.close_swift_conn(possible_source) else: statuses.append(possible_source.status) reasons.append(possible_source.reason) bodies.append('') source_headers.append('') sources.append((possible_source, node)) if not newest: # one good source is enough break else: statuses.append(possible_source.status) reasons.append(possible_source.reason) bodies.append(possible_source.read()) source_headers.append(possible_source.getheaders()) if possible_source.status == HTTP_INSUFFICIENT_STORAGE: self.error_limit(node, _('ERROR Insufficient Storage')) elif is_server_error(possible_source.status): self.error_occurred(node, _('ERROR %(status)d %(body)s ' 'From %(type)s Server') % {'status': possible_source.status, 'body': bodies[-1][:1024], 'type': server_type}) res = None if sources: sources.sort(key=lambda s: source_key(s[0])) source, node = sources.pop() for src, _junk in sources: self.close_swift_conn(src) res = Response(request=req) if req.method == 'GET' and \ source.status in (HTTP_OK, HTTP_PARTIAL_CONTENT): res.app_iter = self._make_app_iter(node, source) # See NOTE: swift_conn at top of file about this. res.swift_conn = source.swift_conn res.status = source.status update_headers(res, source.getheaders()) if not res.environ: res.environ = {} res.environ['swift_x_timestamp'] = \ source.getheader('x-timestamp') res.accept_ranges = 'bytes' res.content_length = source.getheader('Content-Length') if source.getheader('Content-Type'): res.charset = None res.content_type = source.getheader('Content-Type') if not res: res = self.best_response(req, statuses, reasons, bodies, '%s %s' % (server_type, req.method), headers=source_headers) try: (account, container) = split_path(req.path_info, 1, 2) _set_info_cache(self.app, req.environ, account, container, res) except ValueError: pass try: (account, container, obj) = split_path(req.path_info, 3, 3, True) _set_object_info_cache(self.app, req.environ, account, container, obj, res) except ValueError: pass return res
def GETorHEAD_base(self, req, server_type, partition, nodes, path, attempts): """ Base handler for HTTP GET or HEAD requests. :param req: swob.Request object :param server_type: server type :param partition: partition :param nodes: nodes :param path: path for the request :param attempts: number of attempts to try :returns: swob.Response object """ statuses = [] reasons = [] bodies = [] sources = [] newest = config_true_value(req.headers.get('x-newest', 'f')) nodes = iter(nodes) while len(statuses) < attempts: try: node = nodes.next() except StopIteration: break if self.error_limited(node): continue start_node_timing = time.time() try: with ConnectionTimeout(self.app.conn_timeout): headers = dict(req.headers) headers['Connection'] = 'close' conn = http_connect( node['ip'], node['port'], node['device'], partition, req.method, path, headers=headers, query_string=req.query_string) self.app.set_node_timing(node, time.time() - start_node_timing) with Timeout(self.app.node_timeout): possible_source = conn.getresponse() # See NOTE: swift_conn at top of file about this. possible_source.swift_conn = conn except (Exception, Timeout): self.exception_occurred( node, server_type, _('Trying to %(method)s %(path)s') % {'method': req.method, 'path': req.path}) continue if self.is_good_source(possible_source): # 404 if we know we don't have a synced copy if not float(possible_source.getheader('X-PUT-Timestamp', 1)): statuses.append(HTTP_NOT_FOUND) reasons.append('') bodies.append('') self.close_swift_conn(possible_source) else: statuses.append(possible_source.status) reasons.append(possible_source.reason) bodies.append('') sources.append(possible_source) if not newest: # one good source is enough break else: statuses.append(possible_source.status) reasons.append(possible_source.reason) bodies.append(possible_source.read()) if possible_source.status == HTTP_INSUFFICIENT_STORAGE: self.error_limit(node) elif is_server_error(possible_source.status): self.error_occurred(node, _('ERROR %(status)d %(body)s ' 'From %(type)s Server') % {'status': possible_source.status, 'body': bodies[-1][:1024], 'type': server_type}) if sources: sources.sort(key=source_key) source = sources.pop() for src in sources: self.close_swift_conn(src) res = Response(request=req, conditional_response=True) if req.method == 'GET' and \ source.status in (HTTP_OK, HTTP_PARTIAL_CONTENT): res.app_iter = self._make_app_iter(node, source) # See NOTE: swift_conn at top of file about this. res.swift_conn = source.swift_conn res.status = source.status update_headers(res, source.getheaders()) if not res.environ: res.environ = {} res.environ['swift_x_timestamp'] = \ source.getheader('x-timestamp') res.accept_ranges = 'bytes' res.content_length = source.getheader('Content-Length') if source.getheader('Content-Type'): res.charset = None res.content_type = source.getheader('Content-Type') return res return self.best_response(req, statuses, reasons, bodies, '%s %s' % (server_type, req.method))
def GETorHEAD_base(self, req, server_type, ring, partition, path): """ Base handler for HTTP GET or HEAD requests. :param req: swob.Request object :param server_type: server type :param ring: the ring to obtain nodes from :param partition: partition :param path: path for the request :returns: swob.Response object """ statuses = [] reasons = [] bodies = [] sources = [] newest = config_true_value(req.headers.get('x-newest', 'f')) for node in self.iter_nodes(ring, partition): start_node_timing = time.time() try: with ConnectionTimeout(self.app.conn_timeout): headers = dict(req.headers) headers['Connection'] = 'close' conn = http_connect(node['ip'], node['port'], node['device'], partition, req.method, path, headers=headers, query_string=req.query_string) self.app.set_node_timing(node, time.time() - start_node_timing) with Timeout(self.app.node_timeout): possible_source = conn.getresponse() # See NOTE: swift_conn at top of file about this. possible_source.swift_conn = conn except (Exception, Timeout): self.exception_occurred( node, server_type, _('Trying to %(method)s %(path)s') % { 'method': req.method, 'path': req.path }) continue if self.is_good_source(possible_source): # 404 if we know we don't have a synced copy if not float(possible_source.getheader('X-PUT-Timestamp', 1)): statuses.append(HTTP_NOT_FOUND) reasons.append('') bodies.append('') self.close_swift_conn(possible_source) else: statuses.append(possible_source.status) reasons.append(possible_source.reason) bodies.append('') sources.append((possible_source, node)) if not newest: # one good source is enough break else: statuses.append(possible_source.status) reasons.append(possible_source.reason) bodies.append(possible_source.read()) if possible_source.status == HTTP_INSUFFICIENT_STORAGE: self.error_limit(node, _('ERROR Insufficient Storage')) elif is_server_error(possible_source.status): self.error_occurred( node, _('ERROR %(status)d %(body)s ' 'From %(type)s Server') % { 'status': possible_source.status, 'body': bodies[-1][:1024], 'type': server_type }) if sources: sources.sort(key=lambda s: source_key(s[0])) source, node = sources.pop() for src, _junk in sources: self.close_swift_conn(src) res = Response(request=req, conditional_response=True) if req.method == 'GET' and \ source.status in (HTTP_OK, HTTP_PARTIAL_CONTENT): res.app_iter = self._make_app_iter(node, source) # See NOTE: swift_conn at top of file about this. res.swift_conn = source.swift_conn res.status = source.status update_headers(res, source.getheaders()) if not res.environ: res.environ = {} res.environ['swift_x_timestamp'] = \ source.getheader('x-timestamp') res.accept_ranges = 'bytes' res.content_length = source.getheader('Content-Length') if source.getheader('Content-Type'): res.charset = None res.content_type = source.getheader('Content-Type') return res return self.best_response(req, statuses, reasons, bodies, '%s %s' % (server_type, req.method))
if path_type == 3: # container return self.page_obj_list(req, storage_url, token) if path_type == 4: # object try: (obj_status, objct) = get_object(storage_url, token, cont, obj) except ClientException, e: resp = Response(charset='utf8') resp.status = e.http_status return resp except err: pass resp = Response() resp.set_cookie('_token', token, path=self.page_path, max_age=self.cookie_max_age, secure=self.secure) resp.status = HTTP_OK resp.headers = obj_status resp.body = objct self.token_bank[token].update({'msg': ''}) self.memcache_update(token) return resp return HTTPFound(location=self.add_prefix(storage_url)) def page_cont_list(self, req, storage_url, token, template=None): """ """ if template is None: tmpl = self.tmpl path = urlparse(self.del_prefix(req.url)).path if len(path.split('/')) <= 2: path = urlparse(storage_url).path vrs, acc, cont, obj = split_path(path, 1, 4, True)