Reputation: 458
First time using a web framework, hope to get advice on the correct approach.
My aim is to have a server which can return static files based on a url passed in. I use Flask as my web framework and I intent to use CherryPy as my web server. The web describes many ways of setting up Flask with CherryPy and I am not sure if I am doing it correctly.
Resources I have been using:
A simplified version of my Flask app, test.py:
from flask import Flask
from flask import request
from flask import send_from_directory
import os
FOLDER='contents'
ROOT=os.path.abspath(os.path.join('.', FOLDER))
@app.route("/get")
def route_3():
return flask.send_from_directory(os.path.join(ROOT, 'p01', 'p02'), 'file12.zip', as_attachment=True)
if __name__ == "__main__":
app.config.update(DEBUG=True)
app.run()
My script for to run CherryPy:
import os
import cherrypy
from test import app
from cherrypy import wsgiserver
def option_1():
cherrypy.tree.graft(app, '/')
# If I comment this out, the server works
#cherrypy.tree.mount(None, '/', config={
# '/': {
# 'tools.staticdir.on': True,
# 'tools.staticdir.dir': app.static_folder
# },
# })
cherrypy.config.update({'server.socket_port': 5000})
cherrypy.engine.start()
cherrypy.engine.block()
def option2():
d = wsgiserver.WSGIPathInfoDispatcher({'/': app})
server = wsgiserver.CherryPyWSGIServer(('127.0.0.1', 5000), d)
try:
server.start()
except KeyboardInterrupt:
server.stop()
if __name__ == '__main__':
#option_1()
option_2()
I have two questions:
Upvotes: 2
Views: 3182
Reputation: 3948
If you want to replace the development server provided inside Werkzeug, I use the following in Flask-Script to replace runserver()
. This will however in __main__
def runserver():
"""
Overwriting the Flask Script runserver() default.
CherryPy is much more stable than the built-in Flask dev server
"""
debug_app = DebuggedApplication(app, True)
cherrypy.tree.graft(debug_app, '/')
cherrypy.config.update({
'engine.autoreload_on': True,
'server.socket_port': 5000,
'server.socket_host': '0.0.0.0'
})
try:
cherrypy.engine.start()
cherrypy.engine.block()
except KeyboardInterrupt:
cherrypy.engine.stop()
If you do not have DebuggedApplication wrapper the DEBUG = True
will not work. You may need to adjust this slightly based on your application. It will also provide Ctrl+C
Joe
Upvotes: 1
Reputation: 159875
option_1
actually uses the entirety of the CherryPy web framework (which their documentation refers to as the APPLICATION layer) to mount your WSGI application - plugins, tools, etc. can be utilized fully. To serve static files with CherryPy you would want to change your commented out code to be something like this:
cherrypy.tree.mount(None, '/static', config={
'/': {
'tools.staticdir.on': True,
'tools.staticdir.dir': app.static_folder
},
})
option_2
, on the other hand, simply makes use of CherryPy's WSGI server implementation (the CORE layer) to serve your Flask app - it does not use any of the more framework-like aspects of CherryPy. If you are fine with serving your static files through Flask's routing layer as well, you can even remove the WSGIPathInfoDispatcher
middleware and directly mount app
under the CherryPyWSGIServer
. If you want CherryPy to manage the /static
route serving then you will want to mount an instance of cherrypy.tools.staticdir.handler
under the /static
route, like so:
static_handler = tools.staticdir.handler(section='/', dir=app.static_folder)
d = wsgiserver.WSGIPathInfoDispatcher({'/': app, '/static': static_handler})
Upvotes: 7