def create(self, env, vrs, account, container, versions=None):
        """
        Perform a container PUT request

        :param env: WSGI environment for original request
        :param vrs: API version, e.g. "v1"
        :param account: account in which to create the container
        :param container: container name
        :param versions: value for X-Versions-Location header
            (for container versioning)

        :returns: None
        :raises: HTTPException on failure (non-2xx response)
        """
        env = env.copy()
        env['REQUEST_METHOD'] = 'PUT'
        env["PATH_INFO"] = "/%s/%s/%s" % (vrs, account, container)
        if versions:
            env['HTTP_X_VERSIONS_LOCATION'] = versions

        resp_iter = self._app_call(env)
        # The body of a PUT response is either empty or very short (e.g. error
        # message), so we can get away with slurping the whole thing.
        body = ''.join(resp_iter)
        close_if_possible(resp_iter)

        status_int = int(self._response_status.split(' ', 1)[0])
        if not http.is_success(status_int):
            raise swob.HTTPException(
                status=self._response_status,
                headers=self._response_headers,
                body=friendly_error(body))
Beispiel #2
0
    def create(self, env, vrs, account, container, versions=None):
        """
        Perform a container PUT request

        :param env: WSGI environment for original request
        :param vrs: API version, e.g. "v1"
        :param account: account in which to create the container
        :param container: container name
        :param versions: value for X-Versions-Location header
            (for container versioning)

        :returns: None
        :raises: HTTPException on failure (non-2xx response)
        """
        env = env.copy()
        env['REQUEST_METHOD'] = 'PUT'
        env["PATH_INFO"] = "/%s/%s/%s" % (vrs, account, container)
        if versions:
            env['HTTP_X_VERSIONS_LOCATION'] = versions

        resp_iter = self._app_call(env)
        # The body of a PUT response is either empty or very short (e.g. error
        # message), so we can get away with slurping the whole thing.
        body = ''.join(resp_iter)
        close_if_possible(resp_iter)

        status_int = int(self._response_status.split(' ', 1)[0])
        if not http.is_success(status_int):
            raise swob.HTTPException(status=self._response_status,
                                     headers=self._response_headers,
                                     body=friendly_error(body))
Beispiel #3
0
    def handle_slo_get_or_head(self, req, start_response):
        """
        Takes a request and a start_response callable and does the normal WSGI
        thing with them. Returns an iterator suitable for sending up the WSGI
        chain.

        :param req: swob.Request object; is a GET or HEAD request aimed at
                    what may be a static large object manifest (or may not).
        :param start_response: WSGI start_response callable
        """
        resp_iter = self._app_call(req.environ)

        # make sure this response is for a static large object manifest
        for header, value in self._response_headers:
            if (header.lower() == 'x-static-large-object' and
                    config_true_value(value)):
                break
        else:
            # Not a static large object manifest. Just pass it through.
            start_response(self._response_status,
                           self._response_headers,
                           self._response_exc_info)
            return resp_iter

        # Handle pass-through request for the manifest itself
        if req.params.get('multipart-manifest') == 'get':
            new_headers = []
            for header, value in self._response_headers:
                if header.lower() == 'content-type':
                    new_headers.append(('Content-Type',
                                        'application/json; charset=utf-8'))
                else:
                    new_headers.append((header, value))
            self._response_headers = new_headers
            start_response(self._response_status,
                           self._response_headers,
                           self._response_exc_info)
            return resp_iter

        if self._need_to_refetch_manifest(req):
            req.environ['swift.non_client_disconnect'] = True
            close_if_possible(resp_iter)
            del req.environ['swift.non_client_disconnect']

            get_req = make_request(
                req.environ, method='GET',
                headers={'x-auth-token': req.headers.get('x-auth-token')},
                agent=('%(orig)s ' + 'SLO MultipartGET'), swift_source='SLO')
            resp_iter = self._app_call(get_req.environ)

        # Any Content-Range from a manifest is almost certainly wrong for the
        # full large object.
        resp_headers = [(h, v) for h, v in self._response_headers
                        if not h.lower() == 'content-range']

        response = self.get_or_head_response(
            req, resp_headers, resp_iter)
        return response(req.environ, start_response)
Beispiel #4
0
    def handle_slo_get_or_head(self, req, start_response):
        """
        Takes a request and a start_response callable and does the normal WSGI
        thing with them. Returns an iterator suitable for sending up the WSGI
        chain.

        :param req: swob.Request object; is a GET or HEAD request aimed at
                    what may be a static large object manifest (or may not).
        :param start_response: WSGI start_response callable
        """
        resp_iter = self._app_call(req.environ)

        # make sure this response is for a static large object manifest
        for header, value in self._response_headers:
            if (header.lower() == 'x-static-large-object'
                    and config_true_value(value)):
                break
        else:
            # Not a static large object manifest. Just pass it through.
            start_response(self._response_status, self._response_headers,
                           self._response_exc_info)
            return resp_iter

        # Handle pass-through request for the manifest itself
        if req.params.get('multipart-manifest') == 'get':
            new_headers = []
            for header, value in self._response_headers:
                if header.lower() == 'content-type':
                    new_headers.append(
                        ('Content-Type', 'application/json; charset=utf-8'))
                else:
                    new_headers.append((header, value))
            self._response_headers = new_headers
            start_response(self._response_status, self._response_headers,
                           self._response_exc_info)
            return resp_iter

        if self._need_to_refetch_manifest(req):
            req.environ['swift.non_client_disconnect'] = True
            close_if_possible(resp_iter)
            del req.environ['swift.non_client_disconnect']

            get_req = make_subrequest(
                req.environ,
                method='GET',
                headers={'x-auth-token': req.headers.get('x-auth-token')},
                agent=('%(orig)s ' + 'SLO MultipartGET'),
                swift_source='SLO')
            resp_iter = self._app_call(get_req.environ)

        # Any Content-Range from a manifest is almost certainly wrong for the
        # full large object.
        resp_headers = [(h, v) for h, v in self._response_headers
                        if not h.lower() == 'content-range']

        response = self.get_or_head_response(req, resp_headers, resp_iter)
        return response(req.environ, start_response)
Beispiel #5
0
    def copy(self,
             env,
             destination_container,
             destination_object,
             delete_after=None):
        """
        Perform a COPY from source to destination.

        :param env: WSGI environment for a request aimed at the source
            object.
        :param destination_container: container to copy into.
            Note: this must not contain any slashes or the request is
            guaranteed to fail.
        :param destination_object: destination object name
        :param delete_after: value of X-Delete-After; object will be deleted
                             after that many seconds have elapsed. Set to 0 or
                             None to keep the object forever.

        :returns: 3-tuple (HTTP status code, response headers,
                           full response body)
        """
        env = env.copy()
        env['REQUEST_METHOD'] = 'COPY'
        env['HTTP_DESTINATION'] = '/'.join(
            (destination_container, destination_object))
        qs = env.get('QUERY_STRING', '')
        if qs:
            qs += '&multipart-manifest=get'
        else:
            qs = 'multipart-manifest=get'
        env['QUERY_STRING'] = qs
        if delete_after:
            env['HTTP_X_DELETE_AFTER'] = str(delete_after)
        resp_iter = self._app_call(env)
        # The body of a COPY response is either empty or very short (e.g.
        # error message), so we can get away with slurping the whole thing.
        body = ''.join(resp_iter)
        close_if_possible(resp_iter)

        status_int = int(self._response_status.split(' ', 1)[0])
        return (status_int, self._response_headers, body)
    def copy(self, env, destination_container, destination_object,
             delete_after=None):
        """
        Perform a COPY from source to destination.

        :param env: WSGI environment for a request aimed at the source
            object.
        :param destination_container: container to copy into.
            Note: this must not contain any slashes or the request is
            guaranteed to fail.
        :param destination_object: destination object name
        :param delete_after: value of X-Delete-After; object will be deleted
                             after that many seconds have elapsed. Set to 0 or
                             None to keep the object forever.

        :returns: 3-tuple (HTTP status code, response headers,
                           full response body)
        """
        env = env.copy()
        env['REQUEST_METHOD'] = 'COPY'
        env['HTTP_DESTINATION'] = '/'.join(
            (destination_container, destination_object))
        qs = env.get('QUERY_STRING', '')
        if qs:
            qs += '&multipart-manifest=get'
        else:
            qs = 'multipart-manifest=get'
        env['QUERY_STRING'] = qs
        if delete_after:
            env['HTTP_X_DELETE_AFTER'] = str(delete_after)
        resp_iter = self._app_call(env)
        # The body of a COPY response is either empty or very short (e.g.
        # error message), so we can get away with slurping the whole thing.
        body = ''.join(resp_iter)
        close_if_possible(resp_iter)

        status_int = int(self._response_status.split(' ', 1)[0])
        return (status_int, self._response_headers, body)