cherrypy's serveFile fails every-other request

15 views
Skip to first unread message

Arnar Birgisson

unread,
May 15, 2006, 10:47:49 AM5/15/06
to turbo...@googlegroups.com
Hi there,

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

Sylvain Hellegouarch

unread,
May 15, 2006, 10:51:49 AM5/15/06
to turbo...@googlegroups.com
AFAIK,

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

Arnar Birgisson

unread,
May 15, 2006, 11:11:29 AM5/15/06
to turbo...@googlegroups.com
Thanks Sylvain, I verified this by looking at CP's source.

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 Birgisson

unread,
May 15, 2006, 11:13:35 AM5/15/06
to turbo...@googlegroups.com
Answering myself: there's already a bug-report (#686) which is marked
fixed in [1026]

Arnar

Sylvain Hellegouarch

unread,
May 15, 2006, 11:42:11 AM5/15/06
to turbo...@googlegroups.com
Cool.

TG is going fast... too fast for us :)

Kevin Dangoor

unread,
May 16, 2006, 7:20:04 AM5/16/06
to turbo...@googlegroups.com
On 5/15/06, Arnar Birgisson <arn...@gmail.com> wrote:
>
> Answering myself: there's already a bug-report (#686) which is marked
> fixed in [1026]

Actually, 1026 is long past. You've found a legitimate bug. Please
open a ticket and set the milestone to 1.0b1...

http://trac.turbogears.org/

Thanks!

Kevin

Arnar Birgisson

unread,
May 16, 2006, 10:42:15 AM5/16/06
to turbo...@googlegroups.com
On 5/16/06, Kevin Dangoor <dan...@gmail.com> wrote:
> Actually, 1026 is long past. You've found a legitimate bug. Please
> open a ticket and set the milestone to 1.0b1...

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

Sylvain Hellegouarch

unread,
May 16, 2006, 10:51:04 AM5/16/06
to turbo...@googlegroups.com

> 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.
>

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

Reply all
Reply to author
Forward
0 new messages