Added special handling for mapped paths with trailing slashes
parent
b11438b69c
commit
92ba7c9387
|
@ -11,12 +11,6 @@
|
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
from milla.dispatch import UnresolvedPath
|
||||
import functools
|
||||
import re
|
||||
import sys
|
||||
import urllib
|
||||
import urlparse
|
||||
'''URL router
|
||||
|
||||
:Created: Mar 13, 2011
|
||||
|
@ -25,6 +19,13 @@ import urlparse
|
|||
:Updater: $Author$
|
||||
'''
|
||||
|
||||
from milla.dispatch import UnresolvedPath
|
||||
import functools
|
||||
import milla
|
||||
import re
|
||||
import sys
|
||||
import urllib
|
||||
import urlparse
|
||||
|
||||
class Router(object):
|
||||
'''A dispatcher that maps arbitrary paths to controller callables
|
||||
|
@ -34,14 +35,43 @@ class Router(object):
|
|||
router = Router()
|
||||
router.add_route('/foo/{bar}/{baz:\d+}', some_func)
|
||||
app = milla.Application(dispatcher=router)
|
||||
|
||||
In many cases, paths with trailing slashes need special handling.
|
||||
The ``Router`` has two ways of dealing with requests that should
|
||||
have a trailing slash but do not. The default is to send the client
|
||||
an HTTP 301 Moved Permanently response, and the other is to
|
||||
simply treat the request as if it had the necessary trailing slash.
|
||||
A third option is to disable special handling entirely and simply
|
||||
return HTTP 404 Not Found for requests with missing trailing
|
||||
slashes. To change the behavior, pass a different value to the
|
||||
constructor's ``trailing_slash`` keyword.
|
||||
|
||||
Redirect the client to the proper path (the default)::
|
||||
|
||||
router = Router(trailing_slash=Router.REDIRECT)
|
||||
router.add_route('/my_collection/', some_func)
|
||||
|
||||
Pretend the request had a trailing slash, even if it didn't::
|
||||
|
||||
router = Router(trailing_slash=Router.SILENT)
|
||||
router.add_route('/my_collection/', some_func)
|
||||
|
||||
Do nothing, let the client get a 404 error::
|
||||
|
||||
router = Router(trailing_slash=None)
|
||||
router.add_route('/my_collection/', some_func)
|
||||
'''
|
||||
|
||||
class REDIRECT(object): pass
|
||||
class SILENT(object): pass
|
||||
|
||||
#: Compiled regular expression for variable segments
|
||||
template_re = re.compile(r'\{(\w+)(?::([^}]+))?\}')
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, trailing_slash=REDIRECT):
|
||||
self.routes = []
|
||||
self._cache = {}
|
||||
self.trailing_slash=trailing_slash
|
||||
|
||||
def resolve(self, path_info):
|
||||
'''Find a controller for a given path
|
||||
|
@ -56,9 +86,8 @@ class Router(object):
|
|||
matches the given path. Variable segments are added as keywords
|
||||
to the controller function.
|
||||
'''
|
||||
try:
|
||||
return self._cache[path_info]
|
||||
except KeyError:
|
||||
|
||||
def lookup(path_info):
|
||||
for regex, controller, vars in self.routes:
|
||||
match = regex.match(path_info)
|
||||
if match:
|
||||
|
@ -71,6 +100,27 @@ class Router(object):
|
|||
func.__doc__ = controller.__doc__
|
||||
self._cache[path_info] = func
|
||||
return func
|
||||
|
||||
try:
|
||||
return self._cache[path_info]
|
||||
except KeyError:
|
||||
func = lookup(path_info)
|
||||
if func:
|
||||
return func
|
||||
elif self.trailing_slash and not path_info.endswith('/'):
|
||||
# Try to resolve the path with a trailing slash
|
||||
new_path_info = path_info + '/'
|
||||
func = lookup(new_path_info)
|
||||
if func and self.trailing_slash is Router.REDIRECT:
|
||||
# Return a dummy function that just raises
|
||||
# HTTPMovedPermanently to redirect the client to
|
||||
# the canonical URL
|
||||
def redir(*args, **kwargs):
|
||||
raise milla.HTTPMovedPermanently(location=new_path_info)
|
||||
return redir
|
||||
elif func and self.trailing_slash is Router.SILENT:
|
||||
# Return the function found at the alternate path
|
||||
return func
|
||||
raise UnresolvedPath
|
||||
|
||||
def _compile_template(self, template):
|
||||
|
|
Loading…
Reference in New Issue