Trailing Slash tool in CherryPy 3.2 not adding a trailing slash
-
02-06-2021 - |
Question
I cannot get the trailing_slash tool to work. I've played around with the options for the trailing_slash tool and nothing seems to have any effect. I am using CherryPy 3.2.2 and Routes 1.13. I would like to have a trailing slash added. There is no errors in the debug output.
If I go to 127.0.0.1:8080/blog/ it works, however if I go to 127.0.0.1:8080/blog it doesn't.
My Configuration is:
conf = {
'/': {
'request.dispatch': setup_routes(),
# This trailing slash stuff has no effect :(
'tools.trailing_slash.on': True,
'tools.trailing_slash.missing': True,
'tools.trailing_slash.status': 301,
},
'/static': {
'tools.staticdir.on': True,
'tools.staticdir.root': os.path.dirname(os.path.abspath(__file__)),
'tools.staticdir.dir': 'static'
}
}
And the example route is:
routes = [["blog_index", "/blog/", {'controller': BlogController(), 'action': 'index','entry_id': 'index'}],]
Can anybody see what I am doing wrong? Is there a bug or lack of essential documentation? Does the trailing_slash tool work with the Routes Dispatcher?
The full src: https://bitbucket.org/ddevine/icdy/src
Solution
The trailing slash Tool doesn't work with the Routes Dispatcher. The trailing slash tool expects that whatever dispatcher is chosen will set cherrypy.request.is_index
to True or False, which it looks like the RoutesDispatcher
class doesn't do at all. Therefore, is_index
is left at None, and the trailing slash Tool does nothing. It might be possible for someone with a good knowledge of Routes to fix that in the CherryPy codebase, or write their own dispatcher which sets is_index, or try to write another Tool which fixes up is_index after the fact.
OTHER TIPS
Long time asked, but here is a way to make it work:
def index(index=True):
cherrypy.request.is_index = index
cherrypy.tools.index = cherrypy.Tool('on_start_resource', index)
config = {
...
'tools.trailing_slash.status': 307,
'tools.index.on': True,
...
}
There's no notion of an "index" in Routes because you can define 2 connections of the same path, one with a trailing slash and one without, and have them connected to 2 completely different controllers and/or actions. You won't do this in real life, but it's possible in Routes, so there's really not a good way to change the trailing_slash tool to deal with this.
IMHO, the trailing_slash tool is a bit lacking and it should probably be elevated to the level of a WSGI middleware that sits in front of the default WSGI middle pipeline, like the InternalRedirect middleware is doing in CherryPy now. For example, if you've mounted a RouteDispatcher under a script_name, you can't put the trailing_slash tool anywhere to have CP put a trailing slash after the script_name because all the routes in Routes must start with a slash, and it will throw a RoutesException if the path_info is an empty string when you try to match.