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))
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))
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)
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)
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)