Found this solution when I was looking for the same thing for my project
def add_auto_route(config,name, pattern, **kw): config.add_route(name, pattern, **kw) if not pattern.endswith('/'): config.add_route(name + '_auto', pattern + '/') def redirector(request): return HTTPMovedPermanently(request.route_url(name)) config.add_view(redirector, route_name=name + '_auto')
And then during route setup
add_auto_route(config,'events','/events')
Instead of doing config.add_route('events','/events')
This is basically a hybrid of your methods. A new route has been defined with a name ending in _auto , and its representation is redirected to the original route.
EDIT
The solution does not take into account dynamic URL components and GET parameters. For a URL such as /abc/{def}?m=aasa , using add_auto_route() will cause a key error because the redirector function does not take request.matchdict into account. Below is the code. It also uses _query=request.GET to access the GET parameters.
def add_auto_route(config,name, pattern, **kw): config.add_route(name, pattern, **kw) if not pattern.endswith('/'): config.add_route(name + '_auto', pattern + '/') def redirector(request): return HTTPMovedPermanently(request.route_url(name,_query=request.GET,**request.matchdict)) config.add_view(redirector, route_name=name + '_auto')