|
93 | 93 | description: A bar |
94 | 94 | """ |
95 | 95 |
|
| 96 | +# A test for when a `server.url` prefix is a string-prefix, but not a |
| 97 | +# path-segment-prefix, of a route's pattern (see GH #146): neither `/v` nor |
| 98 | +# `/api` should be treated as a prefix of `/version`/`/apidocs` respectively |
| 99 | +# (the two literal cases from the issue). `/foo` and `/` are genuinely under |
| 100 | +# the `/v` prefix (registered as routes `/v/foo` and `/v` respectively) and |
| 101 | +# must still be recognized as such. |
| 102 | +PREFIX_BOUNDARY_DOCUMENT = b""" |
| 103 | + openapi: "3.1.0" |
| 104 | + info: |
| 105 | + version: "1.0.0" |
| 106 | + title: Foo API |
| 107 | + servers: |
| 108 | + - url: /v |
| 109 | + - url: /api |
| 110 | + paths: |
| 111 | + /version: |
| 112 | + get: |
| 113 | + responses: |
| 114 | + 200: |
| 115 | + description: Not under the /v prefix, just shares a string prefix |
| 116 | + /apidocs: |
| 117 | + get: |
| 118 | + responses: |
| 119 | + 200: |
| 120 | + description: Not under the /api prefix, just shares a string prefix |
| 121 | + /foo: |
| 122 | + get: |
| 123 | + responses: |
| 124 | + 200: |
| 125 | + description: A foo, genuinely under the /v prefix |
| 126 | + /: |
| 127 | + get: |
| 128 | + responses: |
| 129 | + 200: |
| 130 | + description: Root, registered at a route matching the prefix exactly |
| 131 | +""" |
| 132 | + |
96 | 133 |
|
97 | 134 | def foo_view(request: Request) -> str: |
98 | 135 | """Return a dummy string.""" |
@@ -138,6 +175,16 @@ def root_server_document() -> t.Generator[t.IO, None, None]: |
138 | 175 | yield document |
139 | 176 |
|
140 | 177 |
|
| 178 | +@pytest.fixture |
| 179 | +def prefix_boundary_document() -> t.Generator[t.IO, None, None]: |
| 180 | + """Load the PREFIX_BOUNDARY_DOCUMENT into a temp file.""" |
| 181 | + with tempfile.NamedTemporaryFile() as document: |
| 182 | + document.write(PREFIX_BOUNDARY_DOCUMENT) |
| 183 | + document.seek(0) |
| 184 | + |
| 185 | + yield document |
| 186 | + |
| 187 | + |
141 | 188 | @pytest.fixture |
142 | 189 | def simple_config() -> t.Generator[Configurator, None, None]: |
143 | 190 | """Config fixture.""" |
@@ -178,6 +225,17 @@ def root_server_app_config( |
178 | 225 | return simple_config |
179 | 226 |
|
180 | 227 |
|
| 228 | +@pytest.fixture |
| 229 | +def prefix_boundary_app_config( |
| 230 | + simple_config: Configurator, prefix_boundary_document: t.IO |
| 231 | +) -> Configurator: |
| 232 | + """Incremented fixture loading the PREFIX_BOUNDARY_DOCUMENT above into the config.""" |
| 233 | + simple_config.pyramid_openapi3_spec( |
| 234 | + prefix_boundary_document.name, route="/foo.yaml", route_name="foo_api_spec" |
| 235 | + ) |
| 236 | + return simple_config |
| 237 | + |
| 238 | + |
181 | 239 | app_config = pytest.mark.parametrize( |
182 | 240 | "app_config", |
183 | 241 | [ |
@@ -325,3 +383,32 @@ def test_root_server_routes(root_server_app_config: Configurator) -> None: |
325 | 383 | ) |
326 | 384 |
|
327 | 385 | root_server_app_config.make_wsgi_app() |
| 386 | + |
| 387 | + |
| 388 | +def test_prefix_boundary_routes(prefix_boundary_app_config: Configurator) -> None: |
| 389 | + """Test case for GH #146. |
| 390 | +
|
| 391 | + A server prefix that is a string-prefix, but not a path-segment-prefix, |
| 392 | + of a route pattern must not be stripped from it -- for both literal cases |
| 393 | + from the issue (`/v`+`/version`, `/api`+`/apidocs`). Also covers routes |
| 394 | + that are genuinely under a prefix (`/v/foo`), and a route that matches a |
| 395 | + prefix exactly (`/v`). |
| 396 | + """ |
| 397 | + prefix_boundary_app_config.add_route(name="version", pattern="/version") |
| 398 | + prefix_boundary_app_config.add_route(name="apidocs", pattern="/apidocs") |
| 399 | + prefix_boundary_app_config.add_route(name="foo", pattern="/v/foo") |
| 400 | + prefix_boundary_app_config.add_route(name="root", pattern="/v") |
| 401 | + prefix_boundary_app_config.add_view( |
| 402 | + foo_view, route_name="version", renderer="string", request_method="GET" |
| 403 | + ) |
| 404 | + prefix_boundary_app_config.add_view( |
| 405 | + foo_view, route_name="apidocs", renderer="string", request_method="GET" |
| 406 | + ) |
| 407 | + prefix_boundary_app_config.add_view( |
| 408 | + foo_view, route_name="foo", renderer="string", request_method="GET" |
| 409 | + ) |
| 410 | + prefix_boundary_app_config.add_view( |
| 411 | + foo_view, route_name="root", renderer="string", request_method="GET" |
| 412 | + ) |
| 413 | + |
| 414 | + prefix_boundary_app_config.make_wsgi_app() |
0 commit comments