I have an application that serves files. The methods HTTP GET/POST/PUT/DELETE should do different stuff (obviously). Therefore I wrote an object representing a file that provides the GET/POST/... methods. This file is returned by the _cp_dispatch
method of a dispatcher application. See my source code.
However Cherrypy raises an exception stating that
TypeError: 'DispatchedFile1' object is not callable
TypeError: unsupported callable
TypeError: <__main__.DispatchedFile1 object at 0x7f209b4e7d30> is not a callable object
If I use the "normal" way of creating a web app by using an @expose
d index
method this sample works fine.
import cherrypy, os
@cherrypy.expose
class DispatchedFile1(object):
def __init__(self, path):
self._path = path
def GET(self, start = 0, chunk_size = 0):
if(start and chunk_size):
return "{} ; OFFSET: {}, CHUNK_SIZE: {}".format(self._path,
start, chunk_size).encode("UTF-8")
return self._path.encode("UTF-8")
class DispatchedFile2(object):
def __init__(self, path):
self._path = path
@cherrypy.expose
def index(self, start = 0, chunk_size = 0):
if(start and chunk_size):
return "{} ; OFFSET: {}, CHUNK_SIZE: {}".format(self._path,
start, chunk_size).encode("UTF-8")
return self._path.encode("UTF-8")
class FileDispatcherApp1(object):
def _cp_dispatch(self, vpath):
print(vpath)
res = DispatchedFile1("/".join(vpath))
vpath.clear()
print(vpath)
return res
class FileDispatcherApp2(object):
def _cp_dispatch(self, vpath):
print(vpath)
res = DispatchedFile2("/".join(vpath))
vpath.clear()
print(vpath)
return res
class DummyApp(object):
@cherrypy.expose
def index(self):
return "index"
cherrypy.tree.mount(FileDispatcherApp1(), "/files1")
cherrypy.tree.mount(FileDispatcherApp2(), "/files2")
cherrypy.quickstart(DummyApp(), "/")
The second version works fine but it does not fulfil my needs. Am I missing something here? How can I fix my first version?
PS.: I know that I can manually lookup the method using cherrypy.request
.
Well, turns out I forgot to add the correct request dispatcher.
The correct source code is:
import cherrypy, os
@cherrypy.expose
class DispatchedFile1(object):
def __init__(self, path):
self._path = path
def GET(self, start = 0, chunk_size = 0):
if(start and chunk_size):
return "{} ; OFFSET: {}, CHUNK_SIZE: {}".format(self._path,
start, chunk_size).encode("UTF-8")
return self._path.encode("UTF-8")
class DispatchedFile2(object):
def __init__(self, path):
self._path = path
@cherrypy.expose
def index(self, start = 0, chunk_size = 0):
if(start and chunk_size):
return "{} ; OFFSET: {}, CHUNK_SIZE: {}".format(self._path,
start, chunk_size).encode("UTF-8")
return self._path.encode("UTF-8")
class FileDispatcherApp1(object):
def _cp_dispatch(self, vpath):
print(vpath)
res = DispatchedFile1("/".join(vpath))
vpath.clear()
print(vpath)
return res
class FileDispatcherApp2(object):
def _cp_dispatch(self, vpath):
print(vpath)
res = DispatchedFile2("/".join(vpath))
vpath.clear()
print(vpath)
return res
class DummyApp(object):
@cherrypy.expose
def index(self):
return "index"
cherrypy.tree.mount(FileDispatcherApp1(), "/files1", {"/": {'request.dispatch': cherrypy.dispatch.MethodDispatcher()}})
cherrypy.tree.mount(FileDispatcherApp2(), "/files2")
cherrypy.quickstart(DummyApp(), "/")
Note the {'request.dispatch': cherrypy.dispatch.MethodDispatcher()}
when mounting the application.