See
https://groups.google.com/d/topic/web2py/guc_tkj6b7s/discussion. It looks like routes_onerror can enter an infinite loop when there are URL rewrites involved. Here's the current code from try_rewrite_on_error() in rewrite.py:
else:
path_info = '/' + path_info.lstrip('/') # add leading '/' if missing
if path_info != environ['PATH_INFO']:
# rewrite request, call wsgibase recursively, avoid loop
environ['PATH_INFO'] = path_info
environ['QUERY_STRING'] = query_string
return None, environ
In the above, path_info is the error handler path given in routes_onerror in routes.py. To avoid an infinite loop, the code checks to make sure path_info is not the same as environ['PATH_INFO'] (i.e., the URL that raised the error). If not, it then sets environ['PATH_INFO'] to the error handler path, and when the function is returned in wsgibase, wsgibase gets called recursively with the new path. The problem is, early in the recursive call to wsgibase, the new environ['PATH_INFO'] gets rewritten according to the routes_in rules. As a result, when the above 'if' clause is reached again, path_info does not match environ['PATH_INFO'], even though they do represent the same URL, so you get a loop.
The code below attempts a fix by first rewriting path_info before comparing it to environ['PATH_INFO']. The fix works in the case referenced in the above linked discussion, but I'm not sure this is the best approach, or whether it breaks something else. Massimo, Jonathan, perhaps you could have a look and see if there is a better alternative.
else:
error_raising_path = environ['PATH_INFO']
# Rewrite routes_onerror path.
path_info = '/' + path_info.lstrip('/') # add leading '/' if missing
environ['PATH_INFO'] = path_info
error_handling_path = url_in(request, environ)[1]['PATH_INFO']
# Avoid infinite loop.
if error_handling_path != error_raising_path:
# wsgibase will be called recursively with the routes_onerror path.
environ['QUERY_STRING'] = query_string
return None, environ
Patch file is attached.
Anthony