Package wsgitools :: Module applications
[hide private]
[frames] | no frames]

Source Code for Module wsgitools.applications

  1  import os.path 
  2   
  3  __all__ = [] 
  4   
  5  try: 
  6      basestring 
  7  except NameError: 
  8      basestring = str 
  9   
 10  __all__.append("StaticContent") 
11 -class StaticContent(object):
12 """ 13 This wsgi application provides static content on whatever request it 14 receives with method GET or HEAD (content stripped). If not present, a 15 content-length header is computed. 16 """
17 - def __init__(self, status, headers, content, anymethod=False):
18 """ 19 @type status: str 20 @param status: is the HTTP status returned to the browser (ex: "200 OK") 21 @type headers: list 22 @param headers: is a list of C{(header, value)} pairs being delivered as 23 HTTP headers 24 @type content: bytes 25 @param content: contains the data to be delivered to the client. It is 26 either a string or some kind of iterable yielding strings. 27 @type anymethod: boolean 28 @param anymethod: determines whether any request method should be 29 answered with this response instead of a 501 30 """ 31 assert isinstance(status, str) 32 assert isinstance(headers, list) 33 assert isinstance(content, bytes) or hasattr(content, "__iter__") 34 self.status = status 35 self.headers = headers 36 self.anymethod = anymethod 37 length = -1 38 if isinstance(content, bytes): 39 self.content = [content] 40 length = len(content) 41 else: 42 self.content = content 43 if isinstance(self.content, list): 44 length = sum(map(len, self.content)) 45 if length >= 0: 46 if not [v for h, v in headers if h.lower() == "content-length"]: 47 headers.append(("Content-length", str(length)))
48 - def __call__(self, environ, start_response):
49 """wsgi interface""" 50 assert isinstance(environ, dict) 51 if environ["REQUEST_METHOD"].upper() not in ["GET", "HEAD"] and \ 52 not self.anymethod: 53 resp = b"Request method not implemented" 54 start_response("501 Not Implemented", 55 [("Content-length", str(len(resp)))]) 56 return [resp] 57 start_response(self.status, list(self.headers)) 58 if environ["REQUEST_METHOD"].upper() == "HEAD": 59 return [] 60 return self.content
61 62 __all__.append("StaticFile")
63 -class StaticFile(object):
64 """ 65 This wsgi application provides the content of a static file on whatever 66 request it receives with method GET or HEAD (content stripped). If not 67 present, a content-length header is computed. 68 """
69 - def __init__(self, filelike, status="200 OK", headers=list(), 70 blocksize=4096):
71 """ 72 @type status: str 73 @param status: is the HTTP status returned to the browser 74 @type headers: [(str, str)] 75 @param headers: is a list of C{(header, value)} pairs being delivered as 76 HTTP headers 77 @type filelike: str or file-like 78 @param filelike: may either be an path in the local file system or a 79 file-like that must support C{read(size)} and C{seek(0)}. If 80 C{tell()} is present, C{seek(0, 2)} and C{tell()} will be used 81 to compute the content-length. 82 @type blocksize: int 83 @param blocksize: the content is provided in chunks of this size 84 """ 85 self.filelike = filelike 86 self.status = status 87 self.headers = headers 88 self.blocksize = blocksize
89
90 - def _serve_in_chunks(self, stream):
91 """internal method yielding data from the given stream""" 92 while True: 93 data = stream.read(self.blocksize) 94 if not data: 95 break 96 yield data 97 if isinstance(self.filelike, basestring): 98 stream.close()
99
100 - def __call__(self, environ, start_response):
101 """wsgi interface""" 102 assert isinstance(environ, dict) 103 104 if environ["REQUEST_METHOD"].upper() not in ["GET", "HEAD"]: 105 resp = b"Request method not implemented" 106 start_response("501 Not Implemented", 107 [("Content-length", str(len(resp)))]) 108 return [resp] 109 110 stream = None 111 size = -1 112 try: 113 if isinstance(self.filelike, basestring): 114 # raises IOError 115 stream = open(self.filelike, "rb") 116 size = os.path.getsize(self.filelike) 117 else: 118 stream = self.filelike 119 if hasattr(stream, "tell"): 120 stream.seek(0, 2) 121 size = stream.tell() 122 stream.seek(0) 123 except IOError: 124 resp = b"File not found" 125 start_response("404 File not found", 126 [("Content-length", str(len(resp)))]) 127 return [resp] 128 129 headers = list(self.headers) 130 if size >= 0: 131 if not [v for h, v in headers if h.lower() == "content-length"]: 132 headers.append(("Content-length", str(size))) 133 134 start_response(self.status, headers) 135 if environ["REQUEST_METHOD"].upper() == "HEAD": 136 if isinstance(self.filelike, basestring): 137 stream.close() 138 return [] 139 140 if isinstance(self.filelike, basestring) and 'wsgi.file_wrapper' in environ: 141 return environ['wsgi.file_wrapper'](stream, self.blocksize) 142 143 if 0 <= size <= self.blocksize: 144 data = stream.read(size) 145 if isinstance(self.filelike, basestring): 146 stream.close() 147 return [data] 148 return self._serve_in_chunks(stream)
149