I'm not sure if this is TurboGears specific...
My problem seems to be that every other request.
cherrypy.lib.cptools.serveFile returns an empty list "[]" instead of a
generator. This produces the following backtrace:
Page handler: <bound method Root.default of
<softproof.controllers.Root object at 0xb72840ec>>
Traceback (most recent call last):
File "/usr/lib/python2.4/site-packages/CherryPy-2.2.1-py2.4.egg/cherrypy/_cphttptools.py",
line 105, in _run
self.main()
File "/usr/lib/python2.4/site-packages/CherryPy-2.2.1-py2.4.egg/cherrypy/_cphttptools.py",
line 254, in main
body = page_handler(*virtual_path, **self.params)
File "<string>", line 3, in default
File "/usr/lib/python2.4/site-packages/TurboGears-0.9a6-py2.4.egg/turbogears/controllers.py",
line 273, in expose
output = database.run_with_transaction(
File "/usr/lib/python2.4/site-packages/TurboGears-0.9a6-py2.4.egg/turbogears/database.py",
line 221, in run_with_transaction
retval = func(*args, **kw)
File "<string>", line 5, in _expose
File "/usr/lib/python2.4/site-packages/TurboGears-0.9a6-py2.4.egg/turbogears/controllers.py",
line 290, in <lambda>
mapping, fragment, *args, **kw)))
File "/usr/lib/python2.4/site-packages/TurboGears-0.9a6-py2.4.egg/turbogears/controllers.py",
line 314, in _execute_func
output = errorhandling.try_call(func, *args, **kw)
File "/usr/lib/python2.4/site-packages/TurboGears-0.9a6-py2.4.egg/turbogears/errorhandling.py",
line 71, in try_call
return func(self, *args, **kw)
File "/home/arnarb/workdir/softproof/webinterface/softproof/softproof/controllers.py",
line 255, in default
return meth( **kwargs )
File "<string>", line 3, in thumbs
File "/usr/lib/python2.4/site-packages/TurboGears-0.9a6-py2.4.egg/turbogears/controllers.py",
line 269, in expose
output = func._expose(func, accept, func._allow_json,
File "<string>", line 5, in _expose
File "/usr/lib/python2.4/site-packages/TurboGears-0.9a6-py2.4.egg/turbogears/controllers.py",
line 290, in <lambda>
mapping, fragment, *args, **kw)))
File "/usr/lib/python2.4/site-packages/TurboGears-0.9a6-py2.4.egg/turbogears/controllers.py",
line 315, in _execute_func
assert isinstance(output, basestring) or isinstance(output, dict) \
AssertionError: Method JobsByKey.thumbs() returned unexpected output.
Output should be of type basestring, dict or generator.
The relevant code is:
from cherrypy.lib.cptools import serveFile
class JobBrowserBase(object):
def _serveThumb(self, job, page):
datadir = turbogears.config.get('softproof.datadir', None)
thumbpath = os.path.join(datadir, job[:5] + '000', job[:6] +
'00', job, '.thumbs', page)
if not os.path.exists(thumbpath):
raise cherrypy.NotFound()
return serveFile(thumbpath, 'image/jpeg')
class JobsByKey(controllers.RootController, JobBrowserBase):
@expose()
@identity.require(identity.not_anonymous())
def thumbs(self, key, page):
job, expires_d = decodekey(key)
if expires_d is not None and expires_d < datetime.datetime.now():
raise Exception("expired key") # TODO real error
return self._serveThumb(job, page)
# x = self._serveThumb(job, page)
# log.debug(repr(x))
# return x
The strange thing that this seems to happen _exactly_ every other
request. Hitting reload again produces the jpeg-file.
These are my versions:
TurboGears 0.9a6
CherryPy 2.2.1
Any ideas?
Arnar
The only place where CherryPy returns a [] in that context is when the
static file has not been modified and CherryPy decides to return a 304 Not
Modified.
The problem comes from the TG controller which asserts on the returned
type I think.
- Sylvain
So the solution would be to make the TG controller return 304 to the
browser? Im not familiar with TG's internals, but I guess
controllers._execute_func is not the appropriate place for that.
Meanwhile, I guess a workaround would be to return fileGenarator
directly instead of going through serveFile (which is mainly about
setting headers and dealing with ranges).
I'll file a TG bug in Trac.
Arnar
Arnar
TG is going fast... too fast for us :)
Actually, 1026 is long past. You've found a legitimate bug. Please
open a ticket and set the milestone to 1.0b1...
Thanks!
Kevin
Yup, I didn't read #686 carefully before posting here :o)
I filed another ticket yesterday, #879 - setting the milestone now.
Until then, if anyone else is having problems with this, a workaround
is to remove the 'If-Modified-Since' header from the request before
calling serveFile:
if 'If-Modified-Since' in cherrypy.request.headers:
del cherrypy.request.headers['If-Modified-Since']
return serveFile(thumbpath, 'image/jpeg')
This makes CherryPy return a generator that reads the file every time.
Arnar
That is really ugly and makes serveFile almost pointless I'm afraid.
The point of the If-Modified-Since header is for the UA to check if the
requested resource has been modified since its last retrieval.
That avoids wasting bandwith and using your server for processing each
time the same resource over and over.
Your workaround is therefore a bad one.
- Sylvain