kgriffs: Routing tree from the test: https://github.com/falconry/falcon/pull/723
jmvrbanac: Interesting. Seems to look good to me.
kgriffs: Sorry, I had the wrong link for the routing tree. Updated.
jmvrbanac: Outside of of @fxfitz's suggestion, :+1: 
diff --git a/falcon/routing/compiled.py b/falcon/routing/compiled.py
index 5f8f951..9177edb 100644
--- a/falcon/routing/compiled.py
+++ b/falcon/routing/compiled.py
@@ -95,7 +95,7 @@ class CompiledRouter(object):
         else:
             return None, None, None
 
-    def _compile_tree(self, nodes, indent=1, level=0):
+    def _compile_tree(self, nodes, indent=1, level=0, fast_return=True):
         """Generates Python code for a routing tree or subtree."""
 
         def line(text, indent_offset=0):
@@ -119,6 +119,18 @@ class CompiledRouter(object):
             nodes, key=lambda node: node.is_var + (node.is_var and
                                                    not node.is_complex))
 
+        # NOTE(kgriffs): Down to this branch in the tree, we can do a
+        # fast 'return None'. See if the nodes at this branch are
+        # all still simple, meaning there is only one possible path.
+        if fast_return:
+            if len(nodes) > 1:
+                # NOTE(kgriffs): There's the possibility of more than
+                # one path.
+                var_nodes = [node for node in nodes if node.is_var]
+                found_var_nodes = bool(var_nodes)
+
+                fast_return = not found_var_nodes
+
         for node in nodes:
             if node.is_var:
                 if node.is_complex:
@@ -162,10 +174,11 @@ class CompiledRouter(object):
                 resource_idx = len(self._return_values)
                 self._return_values.append(node)
 
-            self._compile_tree(node.children, indent, level + 1)
+            self._compile_tree(node.children, indent, level + 1, fast_return)
 
             if node.resource is None:
-                line('return None')
+                if fast_return:
+                    line('return None')
             else:
                 # NOTE(kgriffs): Make sure that we have consumed all of
                 # the segments for the requested route; otherwise we could
@@ -173,11 +186,12 @@ class CompiledRouter(object):
                 line('if path_len == %d:' % (level + 1))
                 line('return return_values[%d]' % resource_idx, 1)
 
-                line('return None')
+                if fast_return:
+                    line('return None')
 
             indent = level_indent
 
-        if not found_simple:
+        if not found_simple and fast_return:
             line('return None')
 
     def _compile(self):

Path segment in one route's URI template masks the field expression in another route
The following test demonstrates the issue. The assertion fails since the resulting status code is 404, rather than 200. "/v2.0/thing" should route to `/{version}/thing` instead of `/v2.0`.

```py
def test_string_vs_var(self):
    self.api.add_route('/v2.0', self.resource)
    self.simulate_request('/v2.0')

    self.api.add_route('/{version}/thing', testing.TestResource())
    self.simulate_request('/v2.0/thing')
    self.assertEqual(self.srmock.status, falcon.HTTP_200)
```

```
/{version}/foo/bar
/v1.0
```
diff --git a/tests/test_default_router.py b/tests/test_default_router.py
index 9dc5ecd..84af78f 100644
--- a/tests/test_default_router.py
+++ b/tests/test_default_router.py
@@ -1,5 +1,6 @@
 import ddt
 
+from falcon.routing import DefaultRouter
 import falcon.testing as testing
 
 
@@ -14,66 +15,115 @@ class ResourceWithId(object):
         resp.body = self.resource_id
 
 
-def setup_routes(router_interface):
-    router_interface.add_route(
-        '/repos', {}, ResourceWithId(1))
-    router_interface.add_route(
-        '/repos/{org}', {}, ResourceWithId(2))
-    router_interface.add_route(
-        '/repos/{org}/{repo}', {}, ResourceWithId(3))
-    router_interface.add_route(
-        '/repos/{org}/{repo}/commits', {}, ResourceWithId(4))
-    router_interface.add_route(
-        '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}',
-        {}, ResourceWithId(5))
-    router_interface.add_route(
-        '/teams/{id}', {}, ResourceWithId(6))
-    router_interface.add_route(
-        '/teams/{id}/members', {}, ResourceWithId(7))
-    router_interface.add_route(
-        '/user/memberships', {}, ResourceWithId(8))
-    router_interface.add_route(
-        '/emojis', {}, ResourceWithId(9))
-    router_interface.add_route(
-        '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}/full',
-        {}, ResourceWithId(10))
-    router_interface.add_route(
-        '/repos/{org}/{repo}/compare/all', {}, ResourceWithId(11))
-
-    # NOTE(kgriffs): The ordering of these calls is significant; we
-    # need to test that the {id} field does not match the other routes,
-    # regardless of the order they are added.
-    router_interface.add_route(
-        '/emojis/signs/0', {}, ResourceWithId(12))
-    router_interface.add_route(
-        '/emojis/signs/{id}', {}, ResourceWithId(13))
-    router_interface.add_route(
-        '/emojis/signs/42', {}, ResourceWithId(14))
-    router_interface.add_route(
-        '/emojis/signs/42/small', {}, ResourceWithId(14.1))
-    router_interface.add_route(
-        '/emojis/signs/78/small', {}, ResourceWithId(14.1))
-
-    router_interface.add_route(
-        '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}/part',
-        {}, ResourceWithId(15))
-    router_interface.add_route(
-        '/repos/{org}/{repo}/compare/{usr0}:{branch0}',
-        {}, ResourceWithId(16))
-    router_interface.add_route(
-        '/repos/{org}/{repo}/compare/{usr0}:{branch0}/full',
-        {}, ResourceWithId(17))
-
-    router_interface.add_route(
-        '/gists/{id}/raw', {}, ResourceWithId(18))
+class TestRegressionCases(testing.TestBase):
+    """Test specific repros reported by users of the framework."""
+
+    def before(self):
+        self.router = DefaultRouter()
+
+    def test_versioned_url(self):
+        self.router.add_route('/{version}/messages', {}, ResourceWithId(2))
+
+        resource, method_map, params = self.router.find('/v2/messages')
+        self.assertEqual(resource.resource_id, 2)
+
+        self.router.add_route('/v2', {}, ResourceWithId(1))
+
+        resource, method_map, params = self.router.find('/v2')
+        self.assertEqual(resource.resource_id, 1)
+
+        resource, method_map, params = self.router.find('/v2/messages')
+        self.assertEqual(resource.resource_id, 2)
+
+        resource, method_map, params = self.router.find('/v1/messages')
+        self.assertEqual(resource.resource_id, 2)
+
+        resource, method_map, params = self.router.find('/v1')
+        self.assertIs(resource, None)
+
+    def test_recipes(self):
+        self.router.add_route(
+            '/recipes/{activity}/{type_id}', {}, ResourceWithId(1))
+        self.router.add_route(
+            '/recipes/baking', {}, ResourceWithId(2))
+
+        resource, method_map, params = self.router.find('/recipes/baking/4242')
+        self.assertEqual(resource.resource_id, 1)
+
+        resource, method_map, params = self.router.find('/recipes/baking')
+        self.assertEqual(resource.resource_id, 2)
+
+        resource, method_map, params = self.router.find('/recipes/grilling')
+        self.assertIs(resource, None)
 
 
 @ddt.ddt
-class TestStandaloneRouter(testing.TestBase):
+class TestComplexRouting(testing.TestBase):
     def before(self):
-        from falcon.routing import DefaultRouter
         self.router = DefaultRouter()
-        setup_routes(self.router)
+
+        self.router.add_route(
+            '/repos', {}, ResourceWithId(1))
+        self.router.add_route(
+            '/repos/{org}', {}, ResourceWithId(2))
+        self.router.add_route(
+            '/repos/{org}/{repo}', {}, ResourceWithId(3))
+        self.router.add_route(
+            '/repos/{org}/{repo}/commits', {}, ResourceWithId(4))
+        self.router.add_route(
+            '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}',
+            {}, ResourceWithId(5))
+
+        self.router.add_route(
+            '/teams/{id}', {}, ResourceWithId(6))
+        self.router.add_route(
+            '/teams/{id}/members', {}, ResourceWithId(7))
+
+        self.router.add_route(
+            '/teams/default', {}, ResourceWithId(19))
+        self.router.add_route(
+            '/teams/default/members/thing', {}, ResourceWithId(19))
+
+        self.router.add_route(
+            '/user/memberships', {}, ResourceWithId(8))
+        self.router.add_route(
+            '/emojis', {}, ResourceWithId(9))
+        self.router.add_route(
+            '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}/full',
+            {}, ResourceWithId(10))
+        self.router.add_route(
+            '/repos/{org}/{repo}/compare/all', {}, ResourceWithId(11))
+
+        # NOTE(kgriffs): The ordering of these calls is significant; we
+        # need to test that the {id} field does not match the other routes,
+        # regardless of the order they are added.
+        self.router.add_route(
+            '/emojis/signs/0', {}, ResourceWithId(12))
+        self.router.add_route(
+            '/emojis/signs/{id}', {}, ResourceWithId(13))
+        self.router.add_route(
+            '/emojis/signs/42', {}, ResourceWithId(14))
+        self.router.add_route(
+            '/emojis/signs/42/small', {}, ResourceWithId(14.1))
+        self.router.add_route(
+            '/emojis/signs/78/small', {}, ResourceWithId(22))
+
+        self.router.add_route(
+            '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}/part',
+            {}, ResourceWithId(15))
+        self.router.add_route(
+            '/repos/{org}/{repo}/compare/{usr0}:{branch0}',
+            {}, ResourceWithId(16))
+        self.router.add_route(
+            '/repos/{org}/{repo}/compare/{usr0}:{branch0}/full',
+            {}, ResourceWithId(17))
+
+        self.router.add_route(
+            '/gists/{id}/{representation}', {}, ResourceWithId(21))
+        self.router.add_route(
+            '/gists/{id}/raw', {}, ResourceWithId(18))
+        self.router.add_route(
+            '/gists/first', {}, ResourceWithId(20))
 
     @ddt.data(
         '/teams/{collision}',  # simple vs simple
@@ -103,20 +153,6 @@ class TestStandaloneRouter(testing.TestBase):
         resource, method_map, params = self.router.find('/emojis/signs/0')
         self.assertEqual(resource.resource_id, -1)
 
-    def test_missing(self):
-        resource, method_map, params = self.router.find('/this/does/not/exist')
-        self.assertIs(resource, None)
-
-        resource, method_map, params = self.router.find('/user/bogus')
-        self.assertIs(resource, None)
-
-        resource, method_map, params = self.router.find('/teams/1234/bogus')
-        self.assertIs(resource, None)
-
-        resource, method_map, params = self.router.find(
-            '/repos/racker/falcon/compare/johndoe:master...janedoe:dev/bogus')
-        self.assertIs(resource, None)
-
     def test_literal_segment(self):
         resource, method_map, params = self.router.find('/emojis/signs/0')
         self.assertEqual(resource.resource_id, 12)
@@ -167,6 +203,54 @@ class TestStandaloneRouter(testing.TestBase):
         resource, method_map, params = self.router.find('/gists/42/raw')
         self.assertEqual(params, {'id': '42'})
 
+    @ddt.data(
+        ('/teams/default', 19),
+        ('/teams/default/members', 7),
+        ('/teams/foo', 6),
+        ('/teams/foo/members', 7),
+        ('/gists/first', 20),
+        ('/gists/first/raw', 18),
+        ('/gists/first/pdf', 21),
+        ('/gists/1776/pdf', 21),
+        ('/emojis/signs/78', 13),
+        ('/emojis/signs/78/small', 22),
+    )
+    @ddt.unpack
+    def test_literal_vs_variable(self, path, expected_id):
+        resource, method_map, params = self.router.find(path)
+        self.assertEqual(resource.resource_id, expected_id)
+
+    @ddt.data(
+        # Misc.
+        '/this/does/not/exist',
+        '/user/bogus',
+        '/repos/racker/falcon/compare/johndoe:master...janedoe:dev/bogus',
+
+        # Literal vs variable (teams)
+        '/teams',
+        '/teams/42/members/undefined',
+        '/teams/42/undefined',
+        '/teams/42/undefined/segments',
+        '/teams/default/members/undefined',
+        '/teams/default/members/thing/undefined',
+        '/teams/default/members/thing/undefined/segments',
+        '/teams/default/undefined',
+        '/teams/default/undefined/segments',
+
+        # Literal vs variable (emojis)
+        '/emojis/signs',
+        '/emojis/signs/0/small',
+        '/emojis/signs/0/undefined',
+        '/emojis/signs/0/undefined/segments',
+        '/emojis/signs/20/small',
+        '/emojis/signs/20/undefined',
+        '/emojis/signs/42/undefined',
+        '/emojis/signs/78/undefined',
+    )
+    def test_not_found(self, path):
+        resource, method_map, params = self.router.find(path)
+        self.assertIs(resource, None)
+
     def test_subsegment_not_found(self):
         resource, method_map, params = self.router.find('/emojis/signs/0/x')
         self.assertIs(resource, None)
@@ -195,7 +279,7 @@ class TestStandaloneRouter(testing.TestBase):
             'usr0': 'johndoe',
             'branch0': 'master',
             'usr1': 'janedoe',
-            'branch1': 'dev'
+            'branch1': 'dev',
         })
 
     @ddt.data(('', 16), ('/full', 17))

pip install -e .[dev]
parse_log_pytest
requirements.txt
nose tox coveralls pytest
apt-get update apt-get install -y gcc
3.5
tools/test-requires
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
certifi==2021.5.30
charset-normalizer==2.0.12
coverage==6.2
coveralls==3.3.1
ddt==1.7.2
distlib==0.3.9
docopt==0.6.2
-e git+https://github.com/falconry/falcon.git@ac03888ad750598175fa1591ef11ec8ae31b0dc0#egg=falcon
filelock==3.4.1
fixtures==4.0.1
idna==3.10
importlib-metadata==4.8.3
importlib-resources==5.4.0
iniconfig==1.1.1
nose==1.3.7
packaging==21.3
pbr==6.1.1
platformdirs==2.4.0
pluggy==1.0.0
py==1.11.0
pyparsing==3.1.4
pytest==7.0.1
python-mimeparse==1.6.0
PyYAML==6.0.1
requests==2.27.1
six==1.17.0
testtools==2.6.0
toml==0.10.2
tomli==1.2.3
tox==3.28.0
typing_extensions==4.1.1
urllib3==1.26.20
virtualenv==20.17.1
zipp==3.6.0

name: falcon
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - charset-normalizer==2.0.12
      - coverage==6.2
      - coveralls==3.3.1
      - ddt==1.7.2
      - distlib==0.3.9
      - docopt==0.6.2
      - filelock==3.4.1
      - fixtures==4.0.1
      - idna==3.10
      - importlib-metadata==4.8.3
      - importlib-resources==5.4.0
      - iniconfig==1.1.1
      - nose==1.3.7
      - packaging==21.3
      - pbr==6.1.1
      - platformdirs==2.4.0
      - pluggy==1.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-mimeparse==1.6.0
      - pyyaml==6.0.1
      - requests==2.27.1
      - six==1.17.0
      - testtools==2.6.0
      - toml==0.10.2
      - tomli==1.2.3
      - tox==3.28.0
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - virtualenv==20.17.1
      - zipp==3.6.0
prefix: /opt/conda/envs/falcon

tests/test_default_router.py::TestRegressionCases::test_recipes tests/test_default_router.py::TestRegressionCases::test_versioned_url tests/test_default_router.py::TestComplexRouting::test_literal_vs_variable_02____teams_default_members___7_ tests/test_default_router.py::TestComplexRouting::test_literal_vs_variable_06____gists_first_raw___18_ tests/test_default_router.py::TestComplexRouting::test_literal_vs_variable_07____gists_first_pdf___21_ tests/test_default_router.py::TestComplexRouting::test_literal_vs_variable_09____emojis_signs_78___13_
tests/test_default_router.py::TestComplexRouting::test_collision_1__teams__collision_ tests/test_default_router.py::TestComplexRouting::test_collision_2__emojis_signs__id_too_ tests/test_default_router.py::TestComplexRouting::test_collision_3__repos__org___repo__compare__complex___vs_____complex2___collision_ tests/test_default_router.py::TestComplexRouting::test_complex_1______5_ tests/test_default_router.py::TestComplexRouting::test_complex_2____full___10_ tests/test_default_router.py::TestComplexRouting::test_complex_3____part___15_ tests/test_default_router.py::TestComplexRouting::test_complex_alt_1______16_ tests/test_default_router.py::TestComplexRouting::test_complex_alt_2____full___17_ tests/test_default_router.py::TestComplexRouting::test_dead_segment_1__teams tests/test_default_router.py::TestComplexRouting::test_dead_segment_2__emojis_signs tests/test_default_router.py::TestComplexRouting::test_dead_segment_3__gists tests/test_default_router.py::TestComplexRouting::test_dead_segment_4__gists_42 tests/test_default_router.py::TestComplexRouting::test_dump tests/test_default_router.py::TestComplexRouting::test_literal tests/test_default_router.py::TestComplexRouting::test_literal_segment tests/test_default_router.py::TestComplexRouting::test_literal_vs_variable_01____teams_default___19_ tests/test_default_router.py::TestComplexRouting::test_literal_vs_variable_03____teams_foo___6_ tests/test_default_router.py::TestComplexRouting::test_literal_vs_variable_04____teams_foo_members___7_ tests/test_default_router.py::TestComplexRouting::test_literal_vs_variable_05____gists_first___20_ tests/test_default_router.py::TestComplexRouting::test_literal_vs_variable_08____gists_1776_pdf___21_ tests/test_default_router.py::TestComplexRouting::test_literal_vs_variable_10____emojis_signs_78_small___22_ tests/test_default_router.py::TestComplexRouting::test_malformed_pattern tests/test_default_router.py::TestComplexRouting::test_multivar tests/test_default_router.py::TestComplexRouting::test_non_collision_1__repos__org___repo__compare__simple_vs_complex_ tests/test_default_router.py::TestComplexRouting::test_non_collision_2__repos__complex___vs___simple_ tests/test_default_router.py::TestComplexRouting::test_non_collision_3__repos__org___repo__compare__complex___vs_____complex2__full tests/test_default_router.py::TestComplexRouting::test_not_found_01__this_does_not_exist tests/test_default_router.py::TestComplexRouting::test_not_found_02__user_bogus tests/test_default_router.py::TestComplexRouting::test_not_found_03__repos_racker_falcon_compare_johndoe_master___janedoe_dev_bogus tests/test_default_router.py::TestComplexRouting::test_not_found_04__teams tests/test_default_router.py::TestComplexRouting::test_not_found_05__teams_42_members_undefined tests/test_default_router.py::TestComplexRouting::test_not_found_06__teams_42_undefined tests/test_default_router.py::TestComplexRouting::test_not_found_07__teams_42_undefined_segments tests/test_default_router.py::TestComplexRouting::test_not_found_08__teams_default_members_undefined tests/test_default_router.py::TestComplexRouting::test_not_found_09__teams_default_members_thing_undefined tests/test_default_router.py::TestComplexRouting::test_not_found_10__teams_default_members_thing_undefined_segments tests/test_default_router.py::TestComplexRouting::test_not_found_11__teams_default_undefined tests/test_default_router.py::TestComplexRouting::test_not_found_12__teams_default_undefined_segments tests/test_default_router.py::TestComplexRouting::test_not_found_13__emojis_signs tests/test_default_router.py::TestComplexRouting::test_not_found_14__emojis_signs_0_small tests/test_default_router.py::TestComplexRouting::test_not_found_15__emojis_signs_0_undefined tests/test_default_router.py::TestComplexRouting::test_not_found_16__emojis_signs_0_undefined_segments tests/test_default_router.py::TestComplexRouting::test_not_found_17__emojis_signs_20_small tests/test_default_router.py::TestComplexRouting::test_not_found_18__emojis_signs_20_undefined tests/test_default_router.py::TestComplexRouting::test_not_found_19__emojis_signs_42_undefined tests/test_default_router.py::TestComplexRouting::test_not_found_20__emojis_signs_78_undefined tests/test_default_router.py::TestComplexRouting::test_override tests/test_default_router.py::TestComplexRouting::test_subsegment_not_found tests/test_default_router.py::TestComplexRouting::test_variable
falcon/routing/compiled.py
falcon/routing/compiled.py