def origin_db_get(self, env, req): ''' Handles GETs to the Origin database The only part of the path this pays attention to is the account. ''' #TODO: this does not return transfer-encoding: chunked try: account = req.path.split('/')[2] except IndexError: return HTTPBadRequest('Invalid request. ' 'URI format: /<api version>/<account>') #TODO: make sure to test with unicode container names marker = get_param(req, 'marker', default='') list_format = get_param(req, 'format') enabled_only = get_param(req, 'enabled', default='false') in TRUE_VALUES limit = get_param(req, 'limit') if limit: try: limit = int(limit) except ValueError: return HTTPBadRequest('Invalid limit, must be an integer') listing_path = '/v1/%s/%s?format=json&marker=%s' % \ (self.origin_account, account, marker) # no limit in request because may have to filter on cdn_enabled resp = make_pre_authed_request(env, 'GET', listing_path, agent='SwiftOrigin').get_response(self.app) resp_headers = {} # {'Transfer-Encoding': 'chunked'} #TODO is this right? was chunked in old one if resp.status_int // 100 == 2: cont_listing = json.loads(resp.body) # TODO: is it ok to load the whole thing? do i have a choice? listing_formatted = [] for listing_dict in cont_listing: if limit is None or len(listing_formatted) < limit: try: formatted_data = self._parse_container_listing( account, listing_dict, list_format, only_cdn_enabled=enabled_only) if formatted_data: listing_formatted.append(formatted_data) except InvalidContentType, e: self.logger.exception(e) continue else: break if list_format == 'xml': resp_headers['Content-Type'] = 'application/xml' response_body = ('<?xml version="1.0" encoding="UTF-8"?>\n' '<account name="%s">\n%s\n</account>') % (account, '\n'.join(listing_formatted)) elif list_format == 'json': resp_headers['Content-Type'] = 'application/json' response_body = json.dumps(listing_formatted) else: resp_headers['Content-Type'] = 'text/plain; charset=UTF-8' response_body = '\n'.join(listing_formatted) return Response(body=response_body, headers=resp_headers)
def account_listing_content_type(req): """ Figure out the content type of an account-listing response. Returns a 2-tuple: (content_type, error). Only one of them will be set; the other will be None. """ try: query_format = get_param(req, 'format') except UnicodeDecodeError: return (None, HTTPBadRequest(body='parameters not utf8', content_type='text/plain', request=req)) if query_format: req.accept = FORMAT2CONTENT_TYPE.get(query_format.lower(), FORMAT2CONTENT_TYPE['plain']) content_type = req.accept.best_match( ['text/plain', 'application/json', 'application/xml', 'text/xml']) if not content_type: return (None, HTTPNotAcceptable(request=req)) else: return (content_type, None)
if broker.is_deleted(): return HTTPNotFound(request=req) info = broker.get_info() resp_headers = { 'X-Account-Container-Count': info['container_count'], 'X-Account-Object-Count': info['object_count'], 'X-Account-Bytes-Used': info['bytes_used'], 'X-Timestamp': info['created_at'], 'X-PUT-Timestamp': info['put_timestamp'] } resp_headers.update( (key, value) for key, (value, timestamp) in broker.metadata.iteritems() if value != '') try: prefix = get_param(req, 'prefix') delimiter = get_param(req, 'delimiter') if delimiter and (len(delimiter) > 1 or ord(delimiter) > 254): # delimiters can be made more flexible later return HTTPPreconditionFailed(body='Bad delimiter') limit = ACCOUNT_LISTING_LIMIT given_limit = get_param(req, 'limit') if given_limit and given_limit.isdigit(): limit = int(given_limit) if limit > ACCOUNT_LISTING_LIMIT: return HTTPPreconditionFailed(request=req, body='Maximum limit is %d' % ACCOUNT_LISTING_LIMIT) marker = get_param(req, 'marker', '') end_marker = get_param(req, 'end_marker') query_format = get_param(req, 'format')
'X-Account-Container-Count': info['container_count'], 'X-Account-Object-Count': info['object_count'], 'X-Account-Bytes-Used': info['bytes_used'], 'X-Timestamp': info['created_at'], 'X-PUT-Timestamp': info['put_timestamp']} if not self.fs_object: resp_headers.update((key, value) for key, (value, timestamp) in broker.metadata.iteritems() if value != '') else: resp_headers.update((key, value) for key, value in broker.metadata.iteritems() if value != '') try: prefix = get_param(req, 'prefix') delimiter = get_param(req, 'delimiter') if delimiter and (len(delimiter) > 1 or ord(delimiter) > 254): # delimiters can be made more flexible later return HTTPPreconditionFailed(body='Bad delimiter') limit = ACCOUNT_LISTING_LIMIT given_limit = get_param(req, 'limit') if given_limit and given_limit.isdigit(): limit = int(given_limit) if limit > ACCOUNT_LISTING_LIMIT: return HTTPPreconditionFailed(request=req, body='Maximum limit is %d' % ACCOUNT_LISTING_LIMIT) marker = get_param(req, 'marker', '') end_marker = get_param(req, 'end_marker') query_format = get_param(req, 'format') except UnicodeDecodeError, err:
if broker.is_deleted(): return HTTPNotFound(request=req) info = broker.get_info() resp_headers = { "X-Container-Object-Count": info["object_count"], "X-Container-Bytes-Used": info["bytes_used"], "X-Timestamp": info["created_at"], "X-PUT-Timestamp": info["put_timestamp"], } resp_headers.update( (key, value) for key, (value, timestamp) in broker.metadata.iteritems() if value != "" and (key.lower() in self.save_headers or key.lower().startswith("x-container-meta-")) ) try: path = get_param(req, "path") prefix = get_param(req, "prefix") delimiter = get_param(req, "delimiter") if delimiter and (len(delimiter) > 1 or ord(delimiter) > 254): # delimiters can be made more flexible later return HTTPPreconditionFailed(body="Bad delimiter") marker = get_param(req, "marker", "") end_marker = get_param(req, "end_marker") limit = CONTAINER_LISTING_LIMIT given_limit = get_param(req, "limit") if given_limit and given_limit.isdigit(): limit = int(given_limit) if limit > CONTAINER_LISTING_LIMIT: return HTTPPreconditionFailed(request=req, body="Maximum limit is %d" % CONTAINER_LISTING_LIMIT) query_format = get_param(req, "format") except UnicodeDecodeError, err:
broker.stale_reads_ok = True if broker.is_deleted(): return HTTPNotFound(request=req) info = broker.get_info() headers = { "X-Container-Object-Count": info["object_count"], "X-Container-Bytes-Used": info["bytes_used"], "X-Timestamp": info["created_at"], "X-PUT-Timestamp": info["put_timestamp"], } headers.update( (key, value) for key, (value, timestamp) in broker.metadata.iteritems() if value != "" and (key.lower() in self.save_headers or key.lower().startswith("x-container-meta-")) ) if get_param(req, "format"): req.accept = FORMAT2CONTENT_TYPE.get(get_param(req, "format").lower(), FORMAT2CONTENT_TYPE["plain"]) try: headers["Content-Type"] = req.accept.best_match( ["text/plain", "application/json", "application/xml", "text/xml"], default_match="text/plain" ) except AssertionError, err: return HTTPBadRequest(body="bad accept header: %s" % req.accept, content_type="text/plain", request=req) return HTTPNoContent(request=req, headers=headers, charset="utf-8") @public @timing_stats def GET(self, req): """Handle HTTP GET request.""" try: drive, part, account, container, obj = split_path(unquote(req.path), 4, 5, True)
broker.stale_reads_ok = True if broker.is_deleted(): return HTTPNotFound(request=req) info = broker.get_info() headers = { 'X-Container-Object-Count': info['object_count'], 'X-Container-Bytes-Used': info['bytes_used'], 'X-Timestamp': info['created_at'], 'X-PUT-Timestamp': info['put_timestamp'], } headers.update( (key, value) for key, (value, timestamp) in broker.metadata.iteritems() if value != '' and (key.lower() in self.save_headers or key.lower().startswith('x-container-meta-'))) if get_param(req, 'format'): req.accept = FORMAT2CONTENT_TYPE.get( get_param(req, 'format').lower(), FORMAT2CONTENT_TYPE['plain']) headers['Content-Type'] = req.accept.best_match( ['text/plain', 'application/json', 'application/xml', 'text/xml']) if not headers['Content-Type']: return HTTPNotAcceptable(request=req) return HTTPNoContent(request=req, headers=headers, charset='utf-8') @public @timing_stats def GET(self, req): """Handle HTTP GET request.""" try: drive, part, account, container, obj = split_path( unquote(req.path), 4, 5, True)
broker.stale_reads_ok = True if broker.is_deleted(): return HTTPNotFound(request=req) info = broker.get_info() headers = { 'X-Container-Object-Count': info['object_count'], 'X-Container-Bytes-Used': info['bytes_used'], 'X-Timestamp': info['created_at'], 'X-PUT-Timestamp': info['put_timestamp'], } headers.update( (key, value) for key, (value, timestamp) in broker.metadata.iteritems() if value != '' and (key.lower() in self.save_headers or key.lower().startswith('x-container-meta-'))) if get_param(req, 'format'): req.accept = FORMAT2CONTENT_TYPE.get( get_param(req, 'format').lower(), FORMAT2CONTENT_TYPE['plain']) try: headers['Content-Type'] = req.accept.best_match( [ 'text/plain', 'application/json', 'application/xml', 'text/xml' ], default_match='text/plain') except AssertionError, err: return HTTPBadRequest(body='bad accept header: %s' % req.accept, content_type='text/plain', request=req) return HTTPNoContent(request=req, headers=headers, charset='utf-8')
def origin_db_get(self, env, req): """ Handles GETs to the Origin database The only part of the path this pays attention to is the account. """ try: vsn, account, junk = split_path(req.path, 2, 3, rest_with_last=True) except ValueError: self.logger.debug("Invalid request: %s" % req.path) return HTTPBadRequest('Invalid request. ' 'URL format: /<api version>/<account>') if not account: return HTTPBadRequest('Invalid request. ' 'URL format: /<api version>/<account>') marker = get_param(req, 'marker', default='') list_format = get_param(req, 'format') if list_format: list_format = list_format.lower() enabled_only = None if get_param(req, 'enabled'): enabled_only = get_param(req, 'enabled').lower() in TRUE_VALUES limit = get_param(req, 'limit') if limit: try: limit = int(limit) except ValueError: self.logger.debug("Invalid limit: %s" % get_param(req, 'limit')) return HTTPBadRequest('Invalid limit, must be an integer') def get_listings(marker): listing_path = quote('/v1/%s/%s' % (self.origin_account, account)) listing_path += '?format=json&marker=' + quote(marker) # no limit in request because may have to filter on cdn_enabled resp = make_pre_authed_request(env, 'GET', listing_path, agent='SwiftOrigin').get_response(self.app) resp_headers = {} listing_formatted = [] if resp.status_int // 100 == 2: cont_listing = json.loads(resp.body) for listing_dict in cont_listing: if limit is None or len(listing_formatted) < limit: try: formatted_data = self._parse_container_listing( account, listing_dict, list_format, only_cdn_enabled=enabled_only) if formatted_data: listing_formatted.append(formatted_data) except InvalidContentType, e: self.logger.exception(e) continue else: break if cont_listing and not listing_formatted: # there were rows returned but none matched enabled_only- # requery with new marker new_marker = cont_listing[-1]['name'] if isinstance(new_marker, unicode): new_marker = new_marker.encode('utf-8') return get_listings(new_marker) elif resp.status_int == 404: raise OriginDbNotFound()
try: drive, part, account, container, obj = split_path( unquote(req.path), 4, 5, True) validate_device_partition(drive, part) except ValueError, err: return jresponse('-1', 'bad request', req,400) if self.mount_check and not check_mount(self.root, drive): return jresponse('-1', 'insufficient storage', req,507) broker = self._get_container_broker(drive, part, account, container) if broker.is_deleted(): return jresponse('-1', 'not found', req,404) try: path = get_param(req, 'path') prefix = get_param(req, 'prefix') delimiter = get_param(req, 'delimiter') if delimiter and (len(delimiter) > 1 or ord(delimiter) > 254): # delimiters can be made more flexible later return jresponse('-1', 'bad delimiter', req,412) marker = get_param(req, 'marker', '') end_marker = get_param(req, 'end_marker') limit = CONTAINER_LISTING_LIMIT given_limit = get_param(req, 'limit') if given_limit and given_limit.isdigit(): limit = int(given_limit) if limit > CONTAINER_LISTING_LIMIT: bodyresp='Maximum limit is %d' % CONTAINER_LISTING_LIMIT return jresponse('-1', bodyresp, req,412)