From ba370731a583bf3d1b0dd42ced0cef7198aad757 Mon Sep 17 00:00:00 2001 From: Min RK Date: Mon, 10 Nov 2014 12:12:13 -0800 Subject: [PATCH] fix and test path regexes - require leading `/` - match empty string - disallow consecutive `//` This means that path_regex should be included as `/api/whatever%s`, not `/api/whatever/%s` --- IPython/html/base/handlers.py | 5 +-- IPython/html/tests/test_paths.py | 61 ++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 IPython/html/tests/test_paths.py diff --git a/IPython/html/base/handlers.py b/IPython/html/base/handlers.py index a08c4c774..2643c2cda 100644 --- a/IPython/html/base/handlers.py +++ b/IPython/html/base/handlers.py @@ -463,8 +463,9 @@ class FilesRedirectHandler(IPythonHandler): # URL pattern fragments for re-use #----------------------------------------------------------------------------- -path_regex = r"(?P.*)" -notebook_path_regex = r"(?P.+\.ipynb)" +# path matches any number of `/foo[/bar...]` or just `/` or '' +path_regex = r"(?P(?:(?:/[^/]+)+|/?))" +notebook_path_regex = r"(?P(?:/[^/]+)+\.ipynb)" #----------------------------------------------------------------------------- # URL to handler mappings diff --git a/IPython/html/tests/test_paths.py b/IPython/html/tests/test_paths.py new file mode 100644 index 000000000..18dc4ad7a --- /dev/null +++ b/IPython/html/tests/test_paths.py @@ -0,0 +1,61 @@ + +import re +import nose.tools as nt + +from IPython.html.base.handlers import path_regex, notebook_path_regex + +try: # py3 + assert_regex = nt.assert_regex + assert_not_regex = nt.assert_not_regex +except AttributeError: # py2 + assert_regex = nt.assert_regexp_matches + assert_not_regex = nt.assert_not_regexp_matches + + +# build regexps that tornado uses: +path_pat = re.compile('^' + '/x%s' % path_regex + '$') +nb_path_pat = re.compile('^' + '/y%s' % notebook_path_regex + '$') + +def test_path_regex(): + for path in ( + '/x', + '/x/', + '/x/foo', + '/x/foo.ipynb', + '/x/foo/bar', + '/x/foo/bar.txt', + ): + assert_regex(path, path_pat) + +def test_path_regex_bad(): + for path in ( + '/xfoo', + '/xfoo/', + '/xfoo/bar', + '/xfoo/bar/', + '/x/foo/bar/', + '/x//foo', + '/y', + '/y/x/foo', + ): + assert_not_regex(path, path_pat) + +def test_notebook_path_regex(): + for path in ( + '/y/asdf.ipynb', + '/y/foo/bar.ipynb', + '/y/a/b/c/d/e.ipynb', + ): + assert_regex(path, nb_path_pat) + +def test_notebook_path_regex_bad(): + for path in ( + '/y', + '/y/', + '/y/.ipynb', + '/y/foo/.ipynb', + '/y/foo/bar', + '/yfoo.ipynb', + '/yfoo/bar.ipynb', + ): + assert_not_regex(path, nb_path_pat)