thirdparty/google_appengine/google/appengine/ext/zipserve/__init__.py
author Sverre Rabbelier <srabbelier@gmail.com>
Sat, 06 Dec 2008 16:52:21 +0000
changeset 686 df109be0567c
parent 149 f2e327a7c5de
permissions -rwxr-xr-x
Load ../../google_appengine_1.1.7/ into trunk/thirdparty/google_appengine.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
149
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     1
#!/usr/bin/env python
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     2
#
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     3
# Copyright 2007 Google Inc.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     4
#
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     5
# Licensed under the Apache License, Version 2.0 (the "License");
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     6
# you may not use this file except in compliance with the License.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     7
# You may obtain a copy of the License at
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     8
#
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
     9
#     http://www.apache.org/licenses/LICENSE-2.0
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    10
#
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    11
# Unless required by applicable law or agreed to in writing, software
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    12
# distributed under the License is distributed on an "AS IS" BASIS,
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    13
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    14
# See the License for the specific language governing permissions and
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    15
# limitations under the License.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    16
#
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    17
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    18
"""Serve static files from a zipfile.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    19
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    20
This is a solution for apps that want to serve 1000s of small static
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    21
files while staying withing the 1000 file limit.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    22
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    23
The simplest use case is driven purely from the handlers section in
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    24
app.yaml, e.g.:
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    25
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    26
  - url: /images/.*
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    27
    script: $PYTHON_LIB/google/appengine/ext/zipserve
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    28
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    29
This would invoke a main() within zipserve/__init__.py.  This code
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    30
would then take the URL path, and look for a .zip file under the first
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    31
component of the path, in this case "images.zip" in the app's working
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    32
directory.  If found, it will then serve any matching paths below that
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    33
from the zip file.  In other words, /images/foo/icon.gif would map to
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    34
foo/icon.gif in the zip file images.zip.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    35
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    36
You can also customize the behavior by adding a custom line to your
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    37
WSGIApplication() invocation:
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    38
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    39
  def main():
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    40
    app = webapp.WSGIApplication(
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    41
            [('/', MainPage),
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    42
             ('/static/(.*)', zipserve.make_zip_handler('staticfiles.zip')),
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    43
            ])
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    44
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    45
You can pass max_age=N to the make_zip_handler() call to override the
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    46
expiration time in seconds, which defaults to 600.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    47
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    48
To customize the behavior even more, you can subclass ZipHandler and
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    49
override the get() method, or override it and call ServeFromZipFile()
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    50
directly.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    51
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    52
Note that by default, a Cache-control is added that makes these pages
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    53
cacheable even if they require authentication.  If this is not what
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    54
you want, override ZipHandler.SetCachingHeaders().
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    55
"""
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    56
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    57
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    58
import email.Utils
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    59
import logging
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    60
import mimetypes
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    61
import time
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    62
import zipfile
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    63
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    64
from google.appengine.ext import webapp
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    65
from google.appengine.ext.webapp import util
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    66
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    67
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    68
def make_zip_handler(zipfilename, max_age=None, public=None):
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    69
  """Factory function to construct a custom ZipHandler instance.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    70
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    71
  Args:
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    72
    zipfilename: The filename of a zipfile.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    73
    max_age: Optional expiration time; defaults to ZipHandler.MAX_AGE.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    74
    public: Optional public flag; defaults to ZipHandler.PUBLIC.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    75
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    76
  Returns:
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    77
    A ZipHandler subclass.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    78
  """
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    79
  class CustomZipHandler(ZipHandler):
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    80
    def get(self, name):
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    81
      self.ServeFromZipFile(self.ZIPFILENAME, name)
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    82
    ZIPFILENAME = zipfilename
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    83
    if max_age is not None:
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    84
      MAX_AGE = max_age
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    85
    if public is not None:
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    86
      PUBLIC = public
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    87
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    88
  return CustomZipHandler
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    89
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    90
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    91
class ZipHandler(webapp.RequestHandler):
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    92
  """Request handler serving static files from zipfiles."""
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    93
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    94
  zipfile_cache = {}
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    95
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    96
  def get(self, prefix, name):
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    97
    """GET request handler.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    98
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
    99
    Typically the arguments are passed from the matching groups in the
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   100
    URL pattern passed to WSGIApplication().
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   101
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   102
    Args:
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   103
      prefix: The zipfilename without the .zip suffix.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   104
      name: The name within the zipfile.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   105
    """
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   106
    self.ServeFromZipFile(prefix + '.zip', name)
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   107
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   108
  def ServeFromZipFile(self, zipfilename, name):
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   109
    """Helper for the GET request handler.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   110
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   111
    This serves the contents of file 'name' from zipfile
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   112
    'zipfilename', logging a message and returning a 404 response if
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   113
    either the zipfile cannot be opened or the named file cannot be
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   114
    read from it.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   115
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   116
    Args:
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   117
      zipfilename: The name of the zipfile.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   118
      name: The name within the zipfile.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   119
    """
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   120
    zipfile_object = self.zipfile_cache.get(zipfilename)
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   121
    if zipfile_object is None:
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   122
      try:
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   123
        zipfile_object = zipfile.ZipFile(zipfilename)
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   124
      except (IOError, RuntimeError), err:
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   125
        logging.error('Can\'t open zipfile %s: %s', zipfilename, err)
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   126
        zipfile_object = ''
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   127
      self.zipfile_cache[zipfilename] = zipfile_object
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   128
    if zipfile_object == '':
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   129
      self.error(404)
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   130
      self.response.out.write('Not found')
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   131
      return
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   132
    try:
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   133
      data = zipfile_object.read(name)
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   134
    except (KeyError, RuntimeError), err:
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   135
      self.error(404)
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   136
      self.response.out.write('Not found')
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   137
      return
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   138
    content_type, encoding = mimetypes.guess_type(name)
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   139
    if content_type:
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   140
      self.response.headers['Content-Type'] = content_type
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   141
    self.SetCachingHeaders()
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   142
    self.response.out.write(data)
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   143
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   144
  MAX_AGE = 600
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   145
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   146
  PUBLIC = True
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   147
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   148
  def SetCachingHeaders(self):
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   149
    """Helper to set the caching headers.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   150
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   151
    Override this to customize the headers beyond setting MAX_AGE.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   152
    """
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   153
    max_age = self.MAX_AGE
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   154
    self.response.headers['Expires'] = email.Utils.formatdate(
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   155
        time.time() + max_age, usegmt=True)
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   156
    cache_control = []
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   157
    if self.PUBLIC:
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   158
      cache_control.append('public')
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   159
    cache_control.append('max-age=%d' % max_age)
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   160
    self.response.headers['Cache-Control'] = ', '.join(cache_control)
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   161
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   162
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   163
def main():
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   164
  """Main program.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   165
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   166
  This is invoked when this package is referenced from app.yaml.
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   167
  """
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   168
  application = webapp.WSGIApplication([('/([^/]+)/(.*)', ZipHandler)])
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   169
  util.run_wsgi_app(application)
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   170
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   171
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   172
if __name__ == '__main__':
f2e327a7c5de Load ../google_appengine into trunk/thirdparty/google_appengine.
Todd Larsen <tlarsen@google.com>
parents:
diff changeset
   173
  main()