Esempio n. 1
0
    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
Esempio n. 2
0
    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
Esempio n. 3
0
    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
Esempio n. 4
0
 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
Esempio n. 5
0
 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
Esempio n. 6
0
    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
Esempio n. 7
0
    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
Esempio n. 8
0
    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
Esempio n. 9
0
 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
Esempio n. 11
0
    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
Esempio n. 12
0
    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
Esempio n. 13
0
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
Esempio n. 14
0
    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
Esempio n. 15
0
 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
Esempio n. 16
0
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
Esempio n. 17
0
    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
Esempio n. 18
0
    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
Esempio n. 19
0
 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
Esempio n. 20
0
 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
Esempio n. 21
0
 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
Esempio n. 22
0
    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
Esempio n. 23
0
    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
Esempio n. 24
0
    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
Esempio n. 25
0
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
Esempio n. 26
0
    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
Esempio n. 27
0
 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
Esempio n. 28
0
    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))
Esempio n. 29
0
    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")
Esempio n. 30
0
    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")
Esempio n. 31
0
        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)
Esempio n. 32
0
    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')
Esempio n. 33
0
    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')
Esempio n. 34
0
    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
Esempio n. 35
0
    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))
Esempio n. 36
0
File: base.py Progetto: shenps/swift
    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))
Esempio n. 37
0
        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)