[Checkins] SVN: z3c.extfile/trunk/ see CHANGES.txt
Bernd Dorn
bernd.dorn at lovelysystems.com
Sat Jan 19 07:06:52 EST 2008
Log message for revision 82949:
see CHANGES.txt
Changed:
U z3c.extfile/trunk/CHANGES.txt
U z3c.extfile/trunk/src/z3c/extfile/filter.py
U z3c.extfile/trunk/src/z3c/extfile/filter.txt
U z3c.extfile/trunk/src/z3c/extfile/testing.py
U z3c.extfile/trunk/src/z3c/extfile/testing.txt
-=-
Modified: z3c.extfile/trunk/CHANGES.txt
===================================================================
--- z3c.extfile/trunk/CHANGES.txt 2008-01-18 15:49:30 UTC (rev 82948)
+++ z3c.extfile/trunk/CHANGES.txt 2008-01-19 12:06:51 UTC (rev 82949)
@@ -5,7 +5,7 @@
After
=====
-- TODO: set content-type in wsgi filter if info is present when
+- set content-type and length in wsgi filter if info is present when
delivering files
- tell and abort methods on WriteFile
Modified: z3c.extfile/trunk/src/z3c/extfile/filter.py
===================================================================
--- z3c.extfile/trunk/src/z3c/extfile/filter.py 2008-01-18 15:49:30 UTC (rev 82948)
+++ z3c.extfile/trunk/src/z3c/extfile/filter.py 2008-01-19 12:06:51 UTC (rev 82949)
@@ -21,31 +21,33 @@
self.hd = hashdir.HashDir(self.dir)
def __call__(self, env, start_response):
- if env.get('X-EXTFILE-HANDLE') and env.get('REQUEST_METHOD')=='POST' and \
- env.get('CONTENT_TYPE','').startswith('multipart/form-data;'):
- fp = env['wsgi.input']
- out = StringIO()
- proc = processor.Processor(
- self.hd,
- contentInfo=env.has_key('X-EXTFILE-INFO'),
- allowedTypes=env.get('X-EXTFILE-TYPES'),
- )
- cl = env.get('CONTENT_LENGTH')
- if not cl:
- raise RuntimeError, "No content-length header found"
- cl = int(cl)
- try:
- proc.pushInput(fp, out, cl)
- except interfaces.TypeNotAllowed:
- start_response("400 Bad Request", [
- ('Content-Type', 'text/plain')])
- return []
- env['CONTENT_LENGTH'] = out.tell()
- out.seek(0)
- env['wsgi.input'] = out
- elif env.get('REQUEST_METHOD') in ('GET',):
- resp = FileResponse(self.app, self.hd)
- return resp(env, start_response)
+ method = env.get('REQUEST_METHOD')
+ if env.get('X-EXTFILE-HANDLE'):
+ if method=='POST' and \
+ env.get('CONTENT_TYPE','').startswith('multipart/form-data;'):
+ fp = env['wsgi.input']
+ out = StringIO()
+ proc = processor.Processor(
+ self.hd,
+ contentInfo=env.has_key('X-EXTFILE-INFO'),
+ allowedTypes=env.get('X-EXTFILE-TYPES'),
+ )
+ cl = env.get('CONTENT_LENGTH')
+ if not cl:
+ raise RuntimeError, "No content-length header found"
+ cl = int(cl)
+ try:
+ proc.pushInput(fp, out, cl)
+ except interfaces.TypeNotAllowed:
+ start_response("400 Bad Request", [
+ ('Content-Type', 'text/plain')])
+ return []
+ env['CONTENT_LENGTH'] = out.tell()
+ out.seek(0)
+ env['wsgi.input'] = out
+ elif method == 'GET':
+ resp = FileResponse(self.app, self.hd)
+ return resp(env, start_response)
return self.app(env, start_response)
@@ -58,6 +60,15 @@
def start_response(self, status, headers_out, exc_info=None):
"""Intercept the response start from the filtered app."""
+ self.doHandle = False
+ if '200' in status:
+ for n,v in headers_out:
+ # the length is digest(40) + len(z3c.extfile.digest)
+ # we do not now how long the info is getting but it should
+ # be under 100
+ if n.lower()=='content-length' and len(v)<3:
+ self.doHandle = True
+ break
self.status = status
self.headers_out = headers_out
self.exc_info = exc_info
@@ -66,60 +77,44 @@
"""Facilitate WSGI API by providing a callable hook."""
self.env = env
self.real_start = start_response
- return self.__iter__()
-
- def __iter__(self):
-
- result = self.app(self.env, self.start_response)
- result_iter = result.__iter__()
- doHandle = False
- for n,v in self.headers_out:
- # the length is digest(40) + len(z3c.extfile.digest)
- if n.lower()=='content-length' and v=='59':
- doHandle = True
- break
- if not doHandle:
- # this is not for us
- headers_out = self.headers_out
- iter_out = result_iter
+ self.response = self.app(self.env, self.start_response)
+ if self.doHandle is False:
+ return self._orgStart()
+ body = "".join(self.response)
+ if not body.startswith('z3c.extfile.digest:'):
+ return self._orgStart()
+ parts = body.split(':')
+ contentType = contentLength = None
+ if len(parts)==2:
+ digest = parts[1]
+ elif len(parts)==4:
+ digest, contentType, contentLength = parts[1:]
else:
- headers_out = dict(
- [(k.lower(),v) for k,v in self.headers_out]
- )
+ return self._orgStart()
+ try:
+ f = self.hd.open(digest)
+ except KeyError:
+ # no such digest
+ return self._orgStart()
+ headers_out = dict(
+ [(k.lower(),v) for k,v in self.headers_out]
+ )
+ if contentType:
+ headers_out['content-type'] = contentType
+ if contentLength:
+ headers_out['content-length'] = contentLength
+ else:
+ headers_out['content-length'] = str(len(f))
+ headers_out = headers_out.items()
+ fw = self.env.get('wsgi.file_wrapper')
+ self.real_start(self.status, headers_out, self.exc_info)
+ return f.__iter__()
+# return fw(f, BLOCK_SIZE)
- body = "".join(result_iter)
- if body.startswith('z3c.extfile.digest:'):
- digest = body[19:]
- else:
- digest = None
- # do we have to handle the content. type?
- # zope sniffs if it has no extension, so we get an unknown
- # text content-type for our digest
- filename = self.env['PATH_INFO']
- content_type, content_encoding =mimetypes.guess_type(filename)
- if content_type and not 'unknown' in \
- headers_out.get('content-type','unknown'):
- headers_out['content-type'] = content_type
- if content_encoding and not 'content-encoding' in headers_out:
- headers_out['content-encoding'] = content_encoding
- if digest is not None:
- try:
- size = self.hd.getSize(digest)
- headers_out['content-length'] = size
- f = self.hd.open(digest)
- fw = self.env.get('wsgi.file_wrapper')
- iter_out = fw(f, BLOCK_SIZE)
- except KeyError:
- # no such digest available, just return the body
- iter_out = body.__iter__()
- else:
- # we have no digest so return body
- iter_out = body.__iter__()
- headers_out = headers_out.items()
- self.real_start(self.status, headers_out, exc_info=self.exc_info)
- return iter_out
+ def _orgStart(self):
+ self.real_start(self.status, self.headers_out, self.exc_info)
+ return self.response
-
def filter_factory(global_conf, **local_conf):
if local_conf.has_key('directory'):
local_conf['directory'] = os.path.join(
Modified: z3c.extfile/trunk/src/z3c/extfile/filter.txt
===================================================================
--- z3c.extfile/trunk/src/z3c/extfile/filter.txt 2008-01-18 15:49:30 UTC (rev 82948)
+++ z3c.extfile/trunk/src/z3c/extfile/filter.txt 2008-01-19 12:06:51 UTC (rev 82949)
@@ -132,3 +132,55 @@
z3c...:3641323866cd50dd809a926cee773849cb6c8a85:application/x-gzip:4552
...
+GET Requests
+============
+
+The also replaces the extfile info with the real file. Our test
+application behind the filter returns the path on GET request, so we
+can just set the body we want.
+
+Here is an example.
+
+ >>> app.get('/abc').body
+ 'abc'
+
+So let us request a file that we uploaded previously. If the header is
+not set nothing is done.
+
+
+ >>> info = 'z3c.extfile.digest:9a2e5260cd0001b96b623d25b01194ca7d8008db:text/html:126'
+ >>> app.get('/%s' % info).body == info
+ True
+
+Let us enable the filter by setting the environment.
+
+ >>> env = {'X-EXTFILE-HANDLE':'on'}
+ >>> res = app.get('/%s' % info, extra_environ=env)
+ >>> print res.body
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>Title</title>
+ <BLANKLINE>
+ <body>
+ body
+ </body>
+ </html>
+ <BLANKLINE>
+ >>> res.headers
+ [('content-length', '126'), ('content-type', 'text/html')]
+
+ >>> info='z3c.extfile.digest:4934828cf300711df0af9879b0b479c1c18e5707:video/mp4:1026603'
+
+ >>> res = app.get('/%s' % info, extra_environ=env)
+ >>> res.headers
+ [('content-length', '1026603'), ('content-type', 'video/mp4')]
+ >>> len(res.body)
+ 1026603
+
+If we have no info the content-type is not modified. The length is taken
+from the files size.
+
+ >>> info='z3c.extfile.digest:4934828cf300711df0af9879b0b479c1c18e5707'
+ >>> res = app.get('/%s' % info, extra_environ=env)
+ >>> res.headers
+ [('content-length', '1026603'), ('content-type', 'text/plain')]
Modified: z3c.extfile/trunk/src/z3c/extfile/testing.py
===================================================================
--- z3c.extfile/trunk/src/z3c/extfile/testing.py 2008-01-18 15:49:30 UTC (rev 82948)
+++ z3c.extfile/trunk/src/z3c/extfile/testing.py 2008-01-19 12:06:51 UTC (rev 82949)
@@ -28,10 +28,17 @@
returns the input stream
"""
def __call__(self, environ, start_response):
- #import pdb;pdb.set_trace()
- start_response("200 OK", [('Content-Type', 'text/plain')])
- for l in environ.get('wsgi.input'):
- yield l
+ method = environ.get('REQUEST_METHOD')
+ if method=='POST':
+ start_response("200 OK", [('Content-Type', 'text/plain')])
+ return [l for l in environ.get('wsgi.input')]
+ else:
+ path = environ.get('PATH_INFO')[1:]
+ start_response("200 OK", [('Content-Type', 'text/plain'),
+ ('Content-Length', str(len(path))),
+ ])
+ return [path]
+
def app_factory(global_conf, **local_conf):
return In2OutApplication()
Modified: z3c.extfile/trunk/src/z3c/extfile/testing.txt
===================================================================
--- z3c.extfile/trunk/src/z3c/extfile/testing.txt 2008-01-18 15:49:30 UTC (rev 82948)
+++ z3c.extfile/trunk/src/z3c/extfile/testing.txt 2008-01-19 12:06:51 UTC (rev 82949)
@@ -18,6 +18,6 @@
and we have the environment vaiable set
>>> import os
- >>> os.environ['EXTFILE_STORAGEDIR'] == oldEnv
+ >>> os.environ.get('EXTFILE_STORAGEDIR') == oldEnv
False
More information about the Checkins
mailing list