Revert "gs_archive_server: add content-length header to extract rpc"
This reverts commit 9dce0f9d6cd825597b76eae4bb1dcad2ba697ebb.
Reason for revert: crbug.com/1158258
Original change's description:
> gs_archive_server: add content-length header to extract rpc
>
> BUG=chromium:1143435
> TEST=Tested manually. Details http://gpaste/5452986865156096
>
> Change-Id: I4eb2f858d6498e6fd3aa67ad413553837631f0d6
> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/dev-util/+/2538137
> Tested-by: Sanika Kulkarni <sanikak@chromium.org>
> Reviewed-by: Allen Li <ayatane@chromium.org>
> Reviewed-by: Congbin Guo <guocb@chromium.org>
> Commit-Queue: Sanika Kulkarni <sanikak@chromium.org>
> Auto-Submit: Sanika Kulkarni <sanikak@chromium.org>
Bug: chromium:1143435
Change-Id: Ie1c3865996149ce32ee564e5da30aa43e9cfc624
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/dev-util/+/2589894
Reviewed-by: Gregory Nisbet <gregorynisbet@google.com>
Reviewed-by: Congbin Guo <guocb@chromium.org>
Commit-Queue: Congbin Guo <guocb@chromium.org>
Tested-by: Congbin Guo <guocb@chromium.org>
diff --git a/gs_cache/gs_archive_server.py b/gs_cache/gs_archive_server.py
index 7f207b5..d0326ae 100644
--- a/gs_cache/gs_archive_server.py
+++ b/gs_cache/gs_archive_server.py
@@ -343,57 +343,27 @@
Extracted file content (Binary data).
"""
rsp = self._caching_server.download(archive, headers=headers)
- # --to-command pipes the extracted file contents to the provided command.
- # See https://www.gnu.org/software/tar/manual/html_node/
- # Writing-to-an-External-Program.html
- cmd = ['tar', '-x', target_file, '--to-command',
- "sh -c 'echo $TAR_SIZE; cat'"]
- ef = tempfile.TemporaryFile()
- try:
- proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=ef)
+ cmd = ['tar', '-O', '-x', target_file]
+
+ with tempfile.SpooledTemporaryFile(max_size=_SPOOL_FILE_SIZE_BYTES) as df:
+ proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=df)
for chunk in rsp.iter_content(constants.READ_BUFFER_SIZE_BYTES):
proc.stdin.write(chunk)
proc.stdin.close()
- returncode = proc.wait()
- if returncode:
- raise cherrypy.HTTPError(
- httplib.INTERNAL_SERVER_ERROR,
- 'Tar command to extract the %s from %s finished with exit code: '
- '%d.', target_file, archive, returncode)
-
- # Go to the beginning of the file. The first line will contain the file
- # size. Beyond that will be contents of the extracted file.
- ef.seek(0)
- extracted_content_length = ef.readline().strip()
- _log('Extracted content length is %s bytes.', extracted_content_length)
- cherrypy.response.headers['Content-Length'] = extracted_content_length
+ proc.wait()
# Update the response's content type to support yielding binary data.
cherrypy.response.headers['Content-Type'] = 'application/octet-stream'
- except Exception as e:
- ef.close()
- raise cherrypy.HTTPError(
- httplib.INTERNAL_SERVER_ERROR,
- 'An exception occurred while extracting %s from %s: %s' %
- (target_file, archive, e))
- def extracted_content():
- _log('Begin streaming extracted contents of "%s".', target_file)
- try:
- # Read the TemporaryFile in chunks and yield the data.
- while True:
- data = ef.read(constants.READ_BUFFER_SIZE_BYTES)
- if not data:
- break
- yield data
- _log('Streaming of "%s" done.', target_file)
- except Exception as e:
- raise cherrypy.HTTPError(
- httplib.INTERNAL_SERVER_ERROR,
- 'An exception occurred while reading extracted data: %s' % e)
- finally:
- ef.close()
- return extracted_content()
+ # Go to the beginning of the file.
+ df.seek(0)
+
+ # Read the SpooledFile in chunks and yield the data.
+ while True:
+ data = df.read(constants.READ_BUFFER_SIZE_BYTES)
+ if not data:
+ break
+ yield data
@cherrypy.expose
@cherrypy.config(**{'response.stream': True})
@@ -427,48 +397,37 @@
'.xz': ['xz', '-d', '-c'],
'.bz2': ['bzip2', '-d', '-c'],
}
- decompressed_file = tempfile.TemporaryFile()
- try:
- proc = subprocess.Popen(commands[extname], stdin=subprocess.PIPE,
- stdout=decompressed_file)
- _log('Decompress process id: %s.', proc.pid)
- for chunk in rsp.iter_content(constants.READ_BUFFER_SIZE_BYTES):
- proc.stdin.write(chunk)
- proc.stdin.close()
- _log('Decompression done.')
- proc.wait()
+ decompressed_file = tempfile.SpooledTemporaryFile(
+ max_size=_SPOOL_FILE_SIZE_BYTES)
+ proc = subprocess.Popen(commands[extname], stdin=subprocess.PIPE,
+ stdout=decompressed_file)
+ _log('Decompress process id: %s.', proc.pid)
+ for chunk in rsp.iter_content(constants.READ_BUFFER_SIZE_BYTES):
+ proc.stdin.write(chunk)
+ proc.stdin.close()
+ _log('Decompression done.')
+ proc.wait()
- # The header of Content-Length is necessary for supporting range request.
- # So we have to decompress the file locally to get the size. This may
- # cause connection timeout issue if the decompression take too long time
- # (e.g. 90 seconds). As a reference, it takes about 10 seconds to
- # decompress a 400MB tgz file.
- decompressed_file.seek(0, os.SEEK_END)
- content_length = decompressed_file.tell()
- _log('Decompressed content length is %d bytes.', content_length)
- cherrypy.response.headers['Content-Length'] = str(content_length)
- decompressed_file.seek(0)
- except Exception as e:
- decompressed_file.close()
- raise cherrypy.HTTPError(
- httplib.INTERNAL_SERVER_ERROR,
- 'An exception occurred while decompressing %s: %s' % (zarchive, e))
+ # The header of Content-Length is necessary for supporting range request.
+ # So we have to decompress the file locally to get the size. This may cause
+ # connection timeout issue if the decompression take too long time (e.g. 90
+ # seconds). As a reference, it takes about 10 seconds to decompress a 400MB
+ # tgz file.
+ decompressed_file.seek(0, os.SEEK_END)
+ content_length = decompressed_file.tell()
+ _log('Decompressed content length is %d bytes.', content_length)
+ cherrypy.response.headers['Content-Length'] = str(content_length)
+ decompressed_file.seek(0)
def decompressed_content():
- _log('Begin streaming decompressed content of "%s".', zarchive)
- try:
- while True:
- data = decompressed_file.read(constants.READ_BUFFER_SIZE_BYTES)
- if not data:
- break
- yield data
- _log('Streaming of "%s" done.', zarchive)
- except Exception as e:
- raise cherrypy.HTTPError(
- httplib.INTERNAL_SERVER_ERROR,
- 'An exception occurred while reading decompressed data: %s' % e)
- finally:
- decompressed_file.close()
+ _log('Streaming decompressed content of "%s" begin.', zarchive)
+ while True:
+ data = decompressed_file.read(constants.READ_BUFFER_SIZE_BYTES)
+ if not data:
+ break
+ yield data
+ decompressed_file.close()
+ _log('Streaming of "%s" done.', zarchive)
return decompressed_content()