Skip to content

Commit 3d16116

Browse files
mmerickelzupo
authored andcommitted
allow the app to be hosted at a prefix in script_name but still validate against allowed servers
1 parent 92797d9 commit 3d16116

File tree

3 files changed

+106
-2
lines changed

3 files changed

+106
-2
lines changed

Diff for: pyramid_openapi3/tests/test_validation.py

+104
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,110 @@ def test_request_validation_disabled_response_validation_enabled(self) -> None:
363363
self.assertEqual(start_response.status, "500 Internal Server Error")
364364

365365

366+
class TestServerRequestValidation(RequestValidationBase): # noqa: D101
367+
368+
openapi_spec = (
369+
b"openapi: '3.1.0'\n"
370+
b"info:\n"
371+
b" version: '1.0.0'\n"
372+
b" title: Foo API\n"
373+
b"servers:\n"
374+
b" - url: /prefix/v1\n"
375+
b" - url: http://example.com/prefix\n"
376+
b"paths:\n"
377+
b" /foo:\n"
378+
b" get:\n"
379+
b" responses:\n"
380+
b" 200:\n"
381+
b" description: A foo\n"
382+
b" content:\n"
383+
b" application/json:\n"
384+
b" schema:\n"
385+
b" type: object\n"
386+
b" properties:\n"
387+
b" test:\n"
388+
b" type: string\n"
389+
b" 400:\n"
390+
b" description: Bad Request\n"
391+
)
392+
393+
def test_server_validation_works_with_script_name(self) -> None:
394+
"""Expect to find a match for http://localhost:8080/prefix/v1/foo."""
395+
self._add_view(lambda *arg: {"test": "correct"})
396+
# run request through router
397+
router = Router(self.config.registry)
398+
environ = {
399+
"wsgi.url_scheme": "http",
400+
"SERVER_NAME": "localhost",
401+
"SERVER_PORT": "8080",
402+
"REQUEST_METHOD": "GET",
403+
"SCRIPT_NAME": "/prefix/v1",
404+
"PATH_INFO": "/foo",
405+
"HTTP_ACCEPT": "application/json",
406+
}
407+
start_response = DummyStartResponse()
408+
response = router(environ, start_response)
409+
410+
self.assertEqual(start_response.status, "200 OK")
411+
self.assertEqual(json.loads(response[0]), {"test": "correct"})
412+
413+
def test_server_validation_works_with_script_name_and_hostname(self) -> None:
414+
"""Expect to find a match for http://example.com/prefix/foo."""
415+
self._add_view(lambda *arg: {"test": "correct"})
416+
# run request through router
417+
router = Router(self.config.registry)
418+
environ = {
419+
"wsgi.url_scheme": "http",
420+
"SERVER_NAME": "localhost",
421+
"SERVER_PORT": "8080",
422+
"REQUEST_METHOD": "GET",
423+
"SCRIPT_NAME": "/prefix",
424+
"PATH_INFO": "/foo",
425+
"HTTP_HOST": "example.com",
426+
"HTTP_ACCEPT": "application/json",
427+
}
428+
start_response = DummyStartResponse()
429+
response = router(environ, start_response)
430+
431+
self.assertEqual(start_response.status, "200 OK")
432+
self.assertEqual(json.loads(response[0]), {"test": "correct"})
433+
434+
def test_server_validation_fails_with_bad_hostname(self) -> None:
435+
"""Expect to fail for /prefix/v2/foo."""
436+
self._add_view()
437+
# run request through router
438+
router = Router(self.config.registry)
439+
environ = {
440+
"wsgi.url_scheme": "http",
441+
"SERVER_NAME": "localhost",
442+
"SERVER_PORT": "8080",
443+
"REQUEST_METHOD": "GET",
444+
"SCRIPT_NAME": "/prefix/v2",
445+
"PATH_INFO": "/foo",
446+
"HTTP_HOST": "example.com",
447+
"HTTP_ACCEPT": "application/json",
448+
}
449+
start_response = DummyStartResponse()
450+
with self.assertLogs(level="ERROR") as cm:
451+
response = router(environ, start_response)
452+
self.assertEqual(start_response.status, "500 Internal Server Error")
453+
self.assertEqual(
454+
json.loads(response[0]),
455+
[
456+
{
457+
"exception": "ServerNotFound",
458+
"message": "Server not found for http://example.com/prefix/v2/foo",
459+
}
460+
],
461+
)
462+
self.assertEqual(
463+
cm.output,
464+
[
465+
"ERROR:pyramid_openapi3:Server not found for http://example.com/prefix/v2/foo"
466+
],
467+
)
468+
469+
366470
class TestImproperAPISpecValidation(RequestValidationBase): # noqa: D101
367471

368472
openapi_spec = (

Diff for: pyramid_openapi3/tests/test_wrappers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def test_relative_app_request() -> None:
6969
)
7070
assert openapi_request.host_url == "http://example.com"
7171
assert openapi_request.path == "/subpath/foo"
72-
assert openapi_request.path_pattern == "/foo"
72+
assert openapi_request.path_pattern == "/subpath/foo"
7373
assert openapi_request.method == "get"
7474
assert openapi_request.body == b""
7575
assert openapi_request.mimetype == "text/html"

Diff for: pyramid_openapi3/wrappers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def path_pattern(self) -> str:
4141
if self.request.matched_route
4242
else self.request.path_info
4343
)
44-
return path_pattern
44+
return self.request.script_name + path_pattern
4545

4646
@property
4747
def method(self) -> str:

0 commit comments

Comments
 (0)