CherryPy is a python web framework which I really like. It is minimalistic in nature, is very pleasant to work with, and still can accomplish much. Below I will detail a basic web app setup with CherryPy demonstrating basic usage which one can expand further.
# blossoms.py
"""A blossoms server with CherryPy."""
import cherrypy
import os
class CherryBlossom(object):
"""The server route handler methods."""
def __init__(self):
pass
@cherrypy.expose
def index(self):
"""The root url, when not mapped to static response, this action will be invoked."""
return self.about()
@cherrypy.expose
def about(self):
return 'Enjoy cherry blossoms.'
@cherrypy.expose(['greet'])
@cherrypy.tools.json_out()
def get_greeting_message(self, name):
"""Return greetings to the given name in JSON format."""
return {'msg': 'Greetings %s' % name'}
@cherrypy.tools.register('before_finalize', priority=60)
def secureheaders():
"""Update server response headers."""
headers = cherrypy.response.headers
headers['X-Frame-Options'] = 'DENY'
headers['X-XSS-Protection'] = '1; mode=block'
headers['X-Powered-By'] = 'Cherry Blossoms'
headers['Server'] = 'Sakura'
class Blossoms(object):
"""Server configuration and initialisation."""
def __init__(self):
pass
def start(self):
"""Start the service."""
blossom = CherryBlossom()
# routes
dispatcher = cherrypy.dispatch.RoutesDispatcher()
dispatcher.explicit = False
dispatcher.connect('home', '/', blossom.index)
dispatcher.connect('about', '/about/', controller=blossom, action='about', conditions=dict(method=['GET']))
dispatcher.connect('greetings', '/greet/{name}/', controller=blossom, action='greet', conditions=dict(method=['GET']))
# config
root_dir = os.path.dirname(os.path.abspath(__file__))
global_conf = root_dir + '/blossoms.conf'
cherrypy.config.update(global_conf)
conf = {
'/': {
'request.dispatch' : dispatcher,
'tools.staticdir.dir': root_dir
}
}
app = cherrypy.tree.mount(None, '/', global_conf)
app.merge(conf)
if hasattr(cherrypy.engine, "signal_handler"):
cherrypy.engine.signal_handler.subscribe()
if hasattr(cherrypy.engine, "console_control_handler"):
cherrypy.engine.console_control_handler.subscribe()
cherrypy.engine.start()
cherrypy.engine.block()
# pyserver.py
from blossoms import Blossoms
blossom = Blossoms()
blossom.start()
The configuration are present in the blossoms.conf
file.
[global]
server.socket_host: '127.0.0.1'
server.socket_port: 1729
server.thread_pool: 8
[/]
tools.gzip.on: True
tools.staticdir.on: True
tools.staticdir.index: 'index.html'
tools.staticdir.debug: True,
tools.secureheaders.on = True,
tools.response_headers.on: True,
tools.response.stream: True,
tools.sessions.on = True
tools.sessions.secure = True
tools.sessions.httponly = True
log.screen: True
Calling the /
, FQDN alone is configured to serve static content. The GET
endpoints are /greet/{name}
and /about/
. The RoutesDispatcher
uses routes
package to do the dispatch. The requirements.txt
is below.
cherrypy==11.1.0
routes==2.4.1
We load the config and merge it with few updated setting from the code before starting the server. We have a server that handles static content, does REST based routing, custom response headers, JSON, html responses, with configurable settings. Enjoy cherry blossoms.