def RefreshResumableUploadState(self):
        """Talk to the server and refresh the state of this resumable upload.

    Returns:
      Response if the upload is complete.
    """
        if self.strategy != RESUMABLE_UPLOAD:
            return
        self.EnsureInitialized()
        refresh_request = http_wrapper.Request(
            url=self.url,
            http_method='PUT',
            headers={'Content-Range': 'bytes */*'})
        refresh_response = http_wrapper.MakeRequest(self.http,
                                                    refresh_request,
                                                    redirections=0,
                                                    retries=self.num_retries)
        range_header = self._GetRangeHeaderFromResponse(refresh_response)
        if refresh_response.status_code in (httplib.OK, httplib.CREATED):
            self.__complete = True
            self.__progress = self.total_size
            self.stream.seek(self.progress)
            # If we're finished, the refresh response will contain the metadata
            # originally requested. Cache it so it can be returned in StreamInChunks.
            self.__final_response = refresh_response
        elif refresh_response.status_code == http_wrapper.RESUME_INCOMPLETE:
            if range_header is None:
                self.__progress = 0
            else:
                self.__progress = self.__GetLastByte(range_header) + 1
            self.stream.seek(self.progress)
        else:
            raise exceptions.HttpError.FromResponse(refresh_response)
Пример #2
0
    def PrepareHttpRequest(self,
                           method_config,
                           request,
                           global_params=None,
                           upload=None,
                           upload_config=None,
                           download=None):
        """Prepares an HTTP request to be sent."""
        request_type = _LoadClass(method_config.request_type_name,
                                  self.__client.MESSAGES_MODULE)
        util.Typecheck(request, request_type)
        request = self.__client.ProcessRequest(method_config, request)

        http_request = http_wrapper.Request(
            http_method=method_config.http_method)
        self.__SetBaseHeaders(http_request, self.__client)
        self.__SetBody(http_request, method_config, request, upload)

        url_builder = _UrlBuilder(self.__client.url,
                                  relative_path=method_config.relative_path)
        url_builder.query_params = self.__ConstructQueryParams(
            method_config.query_params, request, global_params)

        # It's important that upload and download go before we fill in the
        # relative path, so that they can replace it.
        if upload is not None:
            upload.ConfigureRequest(upload_config, http_request, url_builder)
        if download is not None:
            download.ConfigureRequest(http_request, url_builder)

        url_builder.relative_path = self.__ConstructRelativePath(
            method_config, request, relative_path=url_builder.relative_path)
        self.__FinalizeRequest(http_request, url_builder)

        return self.__client.ProcessHttpRequest(http_request)
Пример #3
0
    def __SendChunk(self, start, additional_headers=None):
        """Send the specified chunk."""
        self.EnsureInitialized()
        if self.total_size is None:
            # For the streaming resumable case, we need to detect when we're at the
            # end of the stream.
            body_stream = buffered_stream.BufferedStream(
                self.stream, start, self.chunksize)
            end = body_stream.stream_end_position
            if body_stream.stream_exhausted:
                self.__total_size = end
        else:
            end = min(start + self.chunksize, self.total_size)
            body_stream = stream_slice.StreamSlice(self.stream, end - start)
        # TODO: Think about clearer errors on "no data in stream".

        request = http_wrapper.Request(url=self.url,
                                       http_method='PUT',
                                       body=body_stream)
        request.headers['Content-Type'] = self.mime_type
        if self.total_size is None:
            # Streaming resumable upload case, unknown total size.
            range_string = 'bytes %s-%s/*' % (start, end - 1)
        elif end == start:
            # End of an upload with 0 bytes left to send; just finalize.
            range_string = 'bytes */%s' % self.total_size
        else:
            # Normal resumable upload case with known sizes.
            range_string = 'bytes %s-%s/%s' % (start, end - 1, self.total_size)

        request.headers['Content-Range'] = range_string
        if additional_headers:
            request.headers.update(additional_headers)

        return self.__SendMediaRequest(request, end)
Пример #4
0
    def __SendMediaBody(self, start, additional_headers=None):
        """Send the entire media stream in a single request."""
        self.EnsureInitialized()
        if self.total_size is None:
            raise exceptions.TransferInvalidError(
                'Total size must be known for SendMediaBody')
        body_stream = stream_slice.StreamSlice(self.stream,
                                               self.total_size - start)

        request = http_wrapper.Request(url=self.url,
                                       http_method='PUT',
                                       body=body_stream)
        request.headers['Content-Type'] = self.mime_type
        if start == self.total_size:
            # End of an upload with 0 bytes left to send; just finalize.
            range_string = 'bytes */%s' % self.total_size
        else:
            range_string = 'bytes %s-%s/%s' % (start, self.total_size - 1,
                                               self.total_size)

        request.headers['Content-Range'] = range_string
        if additional_headers:
            request.headers.update(additional_headers)

        return self.__SendMediaRequest(request, self.total_size)
Пример #5
0
    def __SendChunk(self, start, additional_headers=None):
        """Send the specified chunk."""
        self.EnsureInitialized()
        end = min(start + self.chunksize, self.total_size)
        body_stream = stream_slice.StreamSlice(self.stream, end - start)
        # TODO: Think about clearer errors on "no data in stream".

        request = http_wrapper.Request(url=self.url,
                                       http_method='PUT',
                                       body=body_stream)
        request.headers['Content-Type'] = self.mime_type
        request.headers['Content-Range'] = 'bytes %s-%s/%s' % (start, end - 1,
                                                               self.total_size)
        if additional_headers:
            request.headers.update(additional_headers)

        response = http_wrapper.MakeRequest(self.bytes_http,
                                            request,
                                            retry_func=self.retry_func)
        if response.status_code not in (httplib.OK, httplib.CREATED,
                                        http_wrapper.RESUME_INCOMPLETE):
            # We want to reset our state to wherever the server left us
            # before this failed request, and then raise.
            self.RefreshResumableUploadState()
            raise exceptions.HttpError.FromResponse(response)
        if response.status_code == http_wrapper.RESUME_INCOMPLETE:
            last_byte = self.__GetLastByte(
                self._GetRangeHeaderFromResponse(response))
            if last_byte + 1 != end:
                self.stream.seek(last_byte)
        return response
Пример #6
0
 def __GetChunk(self, start, end=None, additional_headers=None):
     """Retrieve a chunk, and return the full response."""
     self.EnsureInitialized()
     end_byte = end
     if self.total_size and end:
         end_byte = min(end, self.total_size)
     request = http_wrapper.Request(url=self.url)
     self.__SetRangeHeader(request, start, end=end_byte)
     if additional_headers is not None:
         request.headers.update(additional_headers)
     return http_wrapper.MakeRequest(self.bytes_http,
                                     request,
                                     retry_func=self.retry_func)
    def __SendChunk(self, start, additional_headers=None):
        """Send the specified chunk."""
        self.EnsureInitialized()
        if self.total_size is None:
            # For the streaming resumable case, we need to detect when we're at the
            # end of the stream.
            body_stream = buffered_stream.BufferedStream(
                self.stream, start, self.chunksize)
            end = body_stream.stream_end_position
            if body_stream.stream_exhausted:
                self.__total_size = end
        else:
            end = min(start + self.chunksize, self.total_size)
            body_stream = stream_slice.StreamSlice(self.stream, end - start)
        # TODO: Think about clearer errors on "no data in stream".

        request = http_wrapper.Request(url=self.url,
                                       http_method='PUT',
                                       body=body_stream)
        request.headers['Content-Type'] = self.mime_type
        if self.total_size is None:
            # Streaming resumable upload case, unknown total size.
            range_string = 'bytes %s-%s/*' % (start, end - 1)
        elif end == start:
            # End of an upload with 0 bytes left to send; just finalize.
            range_string = 'bytes */%s' % self.total_size
        else:
            # Normal resumable upload case with known sizes.
            range_string = 'bytes %s-%s/%s' % (start, end - 1, self.total_size)

        request.headers['Content-Range'] = range_string
        if additional_headers:
            request.headers.update(additional_headers)

        response = http_wrapper.MakeRequest(self.bytes_http,
                                            request,
                                            retry_func=self.retry_func,
                                            retries=self.num_retries)
        if response.status_code not in (httplib.OK, httplib.CREATED,
                                        http_wrapper.RESUME_INCOMPLETE):
            # We want to reset our state to wherever the server left us
            # before this failed request, and then raise.
            self.RefreshResumableUploadState()
            raise exceptions.HttpError.FromResponse(response)
        if response.status_code == http_wrapper.RESUME_INCOMPLETE:
            last_byte = self.__GetLastByte(
                self._GetRangeHeaderFromResponse(response))
            if last_byte + 1 != end:
                self.stream.seek(last_byte)
        return response