Call `gzip` in subprocess instead of gzipping in Python in http_server.

Before:

```
$ time wget http://127.0.0.1:59993/spinning_cube.mojo
(...)

real    0m3.987s
user    0m0.001s
sys     0m0.017s
```

After:

```
$ time wget http://127.0.0.1:55035/spinning_cube.mojo
(...)

real    0m1.226s
user    0m0.004s
sys     0m0.014s
```

Fixes domokit/devtools#35.

R=piotrt@google.com

Review URL: https://codereview.chromium.org/1316443002 .

Cr-Mirrored-From: https://github.com/domokit/mojo
Cr-Mirrored-Commit: c1d55465d7c2ce8717b59677d08b430344c31dbd
diff --git a/devtoolslib/http_server.py b/devtoolslib/http_server.py
index d8a2757..fe2be7a 100644
--- a/devtoolslib/http_server.py
+++ b/devtoolslib/http_server.py
@@ -6,15 +6,14 @@
 import datetime
 import email.utils
 import errno
-import gzip
 import hashlib
 import logging
 import math
 import os.path
-import shutil
 import socket
-import threading
+import subprocess
 import tempfile
+import threading
 
 import SimpleHTTPServer
 import SocketServer
@@ -37,6 +36,24 @@
 _UTC = UTC_TZINFO()
 
 
+def _gzip(file_path):
+  """Gzips the given file storing the result in a temporary file.
+
+  Returns:
+    Path to the resulting file.
+  """
+  gzipped_file = tempfile.NamedTemporaryFile(delete=False)
+  try:
+    subprocess.check_call(['gzip', '-c', file_path],
+                          stdout=gzipped_file)
+  except Exception:
+    print ('http_server: call to gzip failed, make sure that '
+           'gzip is installed on the host.')
+    raise
+  gzipped_file.close()
+  return gzipped_file.name
+
+
 class _SilentTCPServer(SocketServer.TCPServer):
   """A TCPServer that won't display any error, unless debugging is enabled. This
   is useful because the client might stop while it is fetching an URL, which
@@ -73,7 +90,7 @@
 
     def __init__(self, *args, **kwargs):
       self.etag = None
-      self.gzipped_file = None
+      self.gzipped_file_name = None
       self.original_file_name = None
       SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, *args, **kwargs)
 
@@ -138,7 +155,7 @@
       return SimpleHTTPServer.SimpleHTTPRequestHandler.end_headers(self)
 
     # pylint: disable=W0221
-    def translate_path(self, path, gzipped=True):
+    def translate_path(self, path, gzip=True):
       # Parent translate_path() will strip away the query string and fragment
       # identifier, but also will prepend the cwd to the path. relpath() gives
       # us the relative path back.
@@ -146,24 +163,22 @@
           SimpleHTTPServer.SimpleHTTPRequestHandler.translate_path(self, path))
 
       for prefix, local_base_path_list in mappings:
-        if normalized_path.startswith(prefix):
-          for local_base_path in local_base_path_list:
-            candidate = os.path.join(local_base_path,
-                                     normalized_path[len(prefix):])
-            if os.path.isfile(candidate):
-              if gzipped:
-                if not self.gzipped_file:
-                  self.gzipped_file = tempfile.NamedTemporaryFile(delete=False)
-                  self.original_file_name = candidate
-                  with open(candidate, 'rb') as source:
-                    with gzip.GzipFile(fileobj=self.gzipped_file) as target:
-                      shutil.copyfileobj(source, target)
-                  self.gzipped_file.close()
-                return self.gzipped_file.name
-              return candidate
-          else:
-            self.send_response(404)
-            return None
+        if not normalized_path.startswith(prefix):
+          continue
+
+        for local_base_path in local_base_path_list:
+          candidate = os.path.join(local_base_path,
+                                   normalized_path[len(prefix):])
+          if os.path.isfile(candidate):
+            if gzip:
+              if not self.gzipped_file_name:
+                self.original_file_name = candidate
+                self.gzipped_file_name = _gzip(candidate)
+              return self.gzipped_file_name
+            return candidate
+        else:
+          self.send_response(404)
+          return None
       self.send_response(404)
       return None
 
@@ -184,8 +199,8 @@
       pass
 
     def __del__(self):
-      if self.gzipped_file:
-        os.remove(self.gzipped_file.name)
+      if self.gzipped_file_name:
+        os.remove(self.gzipped_file_name)
 
   RequestHandler.protocol_version = 'HTTP/1.1'
   return RequestHandler
diff --git a/devtoolslib/shell_arguments.py b/devtoolslib/shell_arguments.py
index f479248..53e467f 100644
--- a/devtoolslib/shell_arguments.py
+++ b/devtoolslib/shell_arguments.py
@@ -159,7 +159,8 @@
   """
   server_url = shell.serve_local_directories(dev_server_config.mappings)
   shell_args.append('--map-origin=%s=%s' % (dev_server_config.host, server_url))
-  print "Configured %s locally to serve:" % (dev_server_config.host)
+  print "Configured %s locally at %s to serve:" % (dev_server_config.host,
+                                                   server_url)
   for mapping_prefix, mapping_path in dev_server_config.mappings:
     print "  /%s -> %s" % (mapping_prefix, mapping_path)
   return shell_args