示例#1
0
    def update_data_record(self, record):
        """
        Perform any mutations to container listing records that are common to
        all serialization formats, and returns it as a dict.

        Converts created time to iso timestamp.
        Replaces size with 'swift_bytes' content type parameter.

        :params record: object entry record
        :returns: modified record
        """
        (name, created, size, content_type, etag) = record
        if content_type is None:
            return {'subdir': name}
        response = {'bytes': size, 'hash': etag, 'name': name}
        last_modified = datetime.utcfromtimestamp(float(created)).isoformat()
        # python isoformat() doesn't include msecs when zero
        if len(last_modified) < len("1970-01-01T00:00:00.000000"):
            last_modified += ".000000"
        response['last_modified'] = last_modified
        content_type, params = parse_content_type(content_type)
        for key, value in params:
            if key == 'swift_bytes':
                try:
                    response['bytes'] = int(value)
                except ValueError:
                    self.logger.exception("Invalid swift_bytes")
            else:
                content_type += ';%s=%s' % (key, value)
        response['content_type'] = content_type
        return response
示例#2
0
文件: server.py 项目: r0mik/swift
    def update_data_record(self, record):
        """
        Perform any mutations to container listing records that are common to
        all serialization formats, and returns it as a dict.

        Converts created time to iso timestamp.
        Replaces size with 'swift_bytes' content type parameter.

        :params record: object entry record
        :returns: modified record
        """
        (name, created, size, content_type, etag) = record
        if content_type is None:
            return {'subdir': name}
        response = {'bytes': size, 'hash': etag, 'name': name}
        last_modified = datetime.utcfromtimestamp(float(created)).isoformat()
        # python isoformat() doesn't include msecs when zero
        if len(last_modified) < len("1970-01-01T00:00:00.000000"):
            last_modified += ".000000"
        response['last_modified'] = last_modified
        content_type, params = parse_content_type(content_type)
        for key, value in params:
            if key == 'swift_bytes':
                try:
                    response['bytes'] = int(value)
                except ValueError:
                    self.logger.exception("Invalid swift_bytes")
            else:
                content_type += ';%s=%s' % (key, value)
        response['content_type'] = content_type
        return response
示例#3
0
def http_response_to_document_iters(response, read_chunk_size=4096):
    """
    Takes a successful object-GET HTTP response and turns it into an
    iterator of (first-byte, last-byte, length, headers, body-file)
    5-tuples.

    The response must either be a 200 or a 206; if you feed in a 204 or
    something similar, this probably won't work.

    :param response: HTTP response, like from bufferedhttp.http_connect(),
        not a swob.Response.
    """
    chunked = is_chunked(dict(response.getheaders()))

    if response.status == 200:
        if chunked:
            # Single "range" that's the whole object with an unknown length
            return iter([(0, None, None, response.getheaders(), response)])

        # Single "range" that's the whole object
        content_length = int(response.getheader("Content-Length"))
        return iter([(0, content_length - 1, content_length, response.getheaders(), response)])

    content_type, params_list = parse_content_type(response.getheader("Content-Type"))
    if content_type != "multipart/byteranges":
        # Single range; no MIME framing, just the bytes. The start and end
        # byte indices are in the Content-Range header.
        start, end, length = parse_content_range(response.getheader("Content-Range"))
        return iter([(start, end, length, response.getheaders(), response)])
    else:
        # Multiple ranges; the response body is a multipart/byteranges MIME
        # document, and we have to parse it using the MIME boundary
        # extracted from the Content-Type header.
        params = dict(params_list)
        return multipart_byteranges_to_document_iters(response, params["boundary"], read_chunk_size)
示例#4
0
文件: decrypter.py 项目: mahak/swift
    def handle(self, req, start_response):
        app_resp = self._app_call(req.environ)

        try:
            put_crypto_meta = self._read_crypto_meta(
                'X-Object-Sysmeta-Crypto-Body-Meta', True)
            put_keys = self.get_decryption_keys(req, put_crypto_meta)
            post_crypto_meta = self._read_crypto_meta(
                'X-Object-Transient-Sysmeta-Crypto-Meta', False)
            post_keys = self.get_decryption_keys(req, post_crypto_meta)
        except EncryptionException as err:
            self.logger.error(
                "Error decrypting object: %s",
                err)
            raise HTTPInternalServerError(
                body='Error decrypting object',
                content_type='text/plain')

        if put_keys is None and post_keys is None:
            # skip decryption
            start_response(self._response_status, self._response_headers,
                           self._response_exc_info)
            return app_resp

        mod_resp_headers = self.decrypt_resp_headers(put_keys, post_keys)

        if put_crypto_meta and req.method == 'GET' and \
                is_success(self._get_status_int()):
            # 2xx response and encrypted body
            body_key = self.get_unwrapped_key(
                put_crypto_meta, put_keys['object'])
            content_type, content_type_attrs = parse_content_type(
                self._response_header_value('Content-Type'))

            if (self._get_status_int() == 206 and
                    content_type == 'multipart/byteranges'):
                boundary = wsgi_to_bytes(dict(content_type_attrs)["boundary"])
                resp_iter = self.multipart_response_iter(
                    app_resp, boundary, body_key, put_crypto_meta)
            else:
                offset = 0
                content_range = self._response_header_value('Content-Range')
                if content_range:
                    # Determine offset within the whole object if ranged GET
                    offset, end, total = parse_content_range(content_range)
                resp_iter = self.response_iter(
                    app_resp, body_key, put_crypto_meta, offset)
        else:
            # don't decrypt body of unencrypted or non-2xx responses
            resp_iter = app_resp

        mod_resp_headers = purge_crypto_sysmeta_headers(mod_resp_headers)
        start_response(self._response_status, mod_resp_headers,
                       self._response_exc_info)

        return resp_iter
示例#5
0
    def handle(self, req, start_response):
        app_resp = self._app_call(req.environ)

        try:
            put_crypto_meta = self._read_crypto_meta(
                'X-Object-Sysmeta-Crypto-Body-Meta', True)
            put_keys = self.get_decryption_keys(req, put_crypto_meta)
            post_crypto_meta = self._read_crypto_meta(
                'X-Object-Transient-Sysmeta-Crypto-Meta', False)
            post_keys = self.get_decryption_keys(req, post_crypto_meta)
        except EncryptionException as err:
            self.logger.error(
                "Error decrypting object: %s",
                err)
            raise HTTPInternalServerError(
                body='Error decrypting object',
                content_type='text/plain')

        if put_keys is None and post_keys is None:
            # skip decryption
            start_response(self._response_status, self._response_headers,
                           self._response_exc_info)
            return app_resp

        mod_resp_headers = self.decrypt_resp_headers(put_keys, post_keys)

        if put_crypto_meta and req.method == 'GET' and \
                is_success(self._get_status_int()):
            # 2xx response and encrypted body
            body_key = self.get_unwrapped_key(
                put_crypto_meta, put_keys['object'])
            content_type, content_type_attrs = parse_content_type(
                self._response_header_value('Content-Type'))

            if (self._get_status_int() == 206 and
                    content_type == 'multipart/byteranges'):
                boundary = wsgi_to_bytes(dict(content_type_attrs)["boundary"])
                resp_iter = self.multipart_response_iter(
                    app_resp, boundary, body_key, put_crypto_meta)
            else:
                offset = 0
                content_range = self._response_header_value('Content-Range')
                if content_range:
                    # Determine offset within the whole object if ranged GET
                    offset, end, total = parse_content_range(content_range)
                resp_iter = self.response_iter(
                    app_resp, body_key, put_crypto_meta, offset)
        else:
            # don't decrypt body of unencrypted or non-2xx responses
            resp_iter = app_resp

        mod_resp_headers = purge_crypto_sysmeta_headers(mod_resp_headers)
        start_response(self._response_status, mod_resp_headers,
                       self._response_exc_info)

        return resp_iter
示例#6
0
文件: decrypter.py 项目: goulon/swift
    def handle_get(self, req, start_response):
        app_resp = self._app_call(req.environ)

        keys = self.get_decryption_keys(req)
        if keys is None:
            # skip decryption
            start_response(self._response_status, self._response_headers,
                           self._response_exc_info)
            return app_resp

        mod_resp_headers = self.decrypt_resp_headers(keys)

        crypto_meta = None
        if is_success(self._get_status_int()):
            try:
                crypto_meta = self.get_crypto_meta(
                    'X-Object-Sysmeta-Crypto-Body-Meta')
            except EncryptionException as err:
                msg = 'Error decrypting object'
                self.logger.error(
                    _('%(msg)s: %(err)s') % {
                        'msg': msg,
                        'err': err
                    })
                raise HTTPInternalServerError(body=msg,
                                              content_type='text/plain')

        if crypto_meta:
            # 2xx response and encrypted body
            body_key = self.get_unwrapped_key(crypto_meta, keys['object'])
            content_type, content_type_attrs = parse_content_type(
                self._response_header_value('Content-Type'))

            if (self._get_status_int() == 206
                    and content_type == 'multipart/byteranges'):
                boundary = dict(content_type_attrs)["boundary"]
                resp_iter = self.multipart_response_iter(
                    app_resp, boundary, body_key, crypto_meta)
            else:
                offset = 0
                content_range = self._response_header_value('Content-Range')
                if content_range:
                    # Determine offset within the whole object if ranged GET
                    offset, end, total = parse_content_range(content_range)
                resp_iter = self.response_iter(app_resp, body_key, crypto_meta,
                                               offset)
        else:
            # don't decrypt body of unencrypted or non-2xx responses
            resp_iter = app_resp

        mod_resp_headers = purge_crypto_sysmeta_headers(mod_resp_headers)
        start_response(self._response_status, mod_resp_headers,
                       self._response_exc_info)

        return resp_iter
示例#7
0
    def handle_get(self, req, start_response):
        app_resp = self._app_call(req.environ)

        keys = self.get_decryption_keys(req)
        if keys is None:
            # skip decryption
            start_response(self._response_status, self._response_headers,
                           self._response_exc_info)
            return app_resp

        mod_resp_headers = self.decrypt_resp_headers(keys)

        crypto_meta = None
        if is_success(self._get_status_int()):
            try:
                crypto_meta = self.get_crypto_meta(
                    'X-Object-Sysmeta-Crypto-Body-Meta')
            except EncryptionException as err:
                msg = 'Error decrypting object'
                self.logger.error(_('%(msg)s: %(err)s') %
                                  {'msg': msg, 'err': err})
                raise HTTPInternalServerError(
                    body=msg, content_type='text/plain')

        if crypto_meta:
            # 2xx response and encrypted body
            body_key = self.get_unwrapped_key(crypto_meta, keys['object'])
            content_type, content_type_attrs = parse_content_type(
                self._response_header_value('Content-Type'))

            if (self._get_status_int() == 206 and
                    content_type == 'multipart/byteranges'):
                boundary = dict(content_type_attrs)["boundary"]
                resp_iter = self.multipart_response_iter(
                    app_resp, boundary, body_key, crypto_meta)
            else:
                offset = 0
                content_range = self._response_header_value('Content-Range')
                if content_range:
                    # Determine offset within the whole object if ranged GET
                    offset, end, total = parse_content_range(content_range)
                resp_iter = self.response_iter(
                    app_resp, body_key, crypto_meta, offset)
        else:
            # don't decrypt body of unencrypted or non-2xx responses
            resp_iter = app_resp

        mod_resp_headers = purge_crypto_sysmeta_headers(mod_resp_headers)
        start_response(self._response_status, mod_resp_headers,
                       self._response_exc_info)

        return resp_iter
示例#8
0
文件: utils.py 项目: logorn/swift3
def extract_s3_etag(content_type):
    """
    Parse a content-type and return a tuple containing:
       - the content_type string minus any swift_bytes param,
       - the s3_etag value or None if the param was not found

    :param content_type: a content-type string
    :return: a tuple of (content-type, s3_etag or None)
    """
    content_type, params = parse_content_type(content_type)
    s3_etag = None
    for key, value in params:
        if key == 's3_etag':
            s3_etag = value
        else:
            content_type += ';%s=%s' % (key, value)
    return content_type, s3_etag
示例#9
0
    def handle_get(self, req, start_response):
        app_resp = self._app_call(req.environ)

        put_crypto_meta = self._read_crypto_meta(
            'X-Object-Sysmeta-Crypto-Body-Meta', True)
        put_keys = self.get_decryption_keys(req, put_crypto_meta)
        post_crypto_meta = self._read_crypto_meta(
            'X-Object-Transient-Sysmeta-Crypto-Meta', False)
        post_keys = self.get_decryption_keys(req, post_crypto_meta)
        if put_keys is None and post_keys is None:
            # skip decryption
            start_response(self._response_status, self._response_headers,
                           self._response_exc_info)
            return app_resp

        mod_resp_headers = self.decrypt_resp_headers(put_keys, post_keys)

        if put_crypto_meta and is_success(self._get_status_int()):
            # 2xx response and encrypted body
            body_key = self.get_unwrapped_key(put_crypto_meta,
                                              put_keys['object'])
            content_type, content_type_attrs = parse_content_type(
                self._response_header_value('Content-Type'))

            if (self._get_status_int() == 206
                    and content_type == 'multipart/byteranges'):
                boundary = dict(content_type_attrs)["boundary"]
                resp_iter = self.multipart_response_iter(
                    app_resp, boundary, body_key, put_crypto_meta)
            else:
                offset = 0
                content_range = self._response_header_value('Content-Range')
                if content_range:
                    # Determine offset within the whole object if ranged GET
                    offset, end, total = parse_content_range(content_range)
                resp_iter = self.response_iter(app_resp, body_key,
                                               put_crypto_meta, offset)
        else:
            # don't decrypt body of unencrypted or non-2xx responses
            resp_iter = app_resp

        mod_resp_headers = purge_crypto_sysmeta_headers(mod_resp_headers)
        start_response(self._response_status, mod_resp_headers,
                       self._response_exc_info)

        return resp_iter
def http_response_to_document_iters(response, read_chunk_size=4096):
    """
    Takes a successful object-GET HTTP response and turns it into an
    iterator of (first-byte, last-byte, length, headers, body-file)
    5-tuples.

    The response must either be a 200 or a 206; if you feed in a 204 or
    something similar, this probably won't work.

    :param response: HTTP response, like from bufferedhttp.http_connect(),
        not a swob.Response.
    """
    chunked = is_chunked(dict(response.getheaders()))

    if response.status == 200:
        if chunked:
            # Single "range" that's the whole object with an unknown length
            return iter([(0, None, None, response.getheaders(), response)])

        # Single "range" that's the whole object
        print 'Content-Length : ' + response.getheader('Content-Length')
        content_length = int(response.getheader('Content-Length'))
        return iter([(0, content_length - 1, content_length,
                      response.getheaders(), response)])

    content_type, params_list = parse_content_type(
        response.getheader('Content-Type'))
    if content_type != 'multipart/byteranges':
        # Single range; no MIME framing, just the bytes. The start and end
        # byte indices are in the Content-Range header.
        start, end, length = parse_content_range(
            response.getheader('Content-Range'))
        return iter([(start, end, length, response.getheaders(), response)])
    else:
        # Multiple ranges; the response body is a multipart/byteranges MIME
        # document, and we have to parse it using the MIME boundary
        # extracted from the Content-Type header.
        params = dict(params_list)
        return multipart_byteranges_to_document_iters(response,
                                                      params['boundary'],
                                                      read_chunk_size)