Bladeren bron

Merge pull request #1196 from DaelonSuzuka/endpoint_documentation

Hide endpoints from OpenAPI schema by default
Falko Schindler 1 jaar geleden
bovenliggende
commit
649d6f82da
5 gewijzigde bestanden met toevoegingen van 55 en 0 verwijderingen
  1. 1 0
      nicegui/globals.py
  2. 3 0
      nicegui/page.py
  3. 9 0
      nicegui/run.py
  4. 1 0
      tests/conftest.py
  5. 41 0
      tests/test_endpoint_docs.py

+ 1 - 0
nicegui/globals.py

@@ -45,6 +45,7 @@ binding_refresh_interval: float
 tailwind: bool
 air: Optional['Air'] = None
 socket_io_js_extra_headers: Dict = {}
+endpoint_documentation: Literal['none', 'internal', 'page', 'all'] = 'none'
 socket_io_js_transports: List[Literal['websocket', 'polling']] = ['websocket', 'polling']
 
 _socket_id: Optional[str] = None

+ 3 - 0
nicegui/page.py

@@ -107,6 +107,9 @@ class page:
             parameters.insert(0, request)
         decorated.__signature__ = inspect.Signature(parameters)
 
+        if 'include_in_schema' not in self.kwargs:
+            self.kwargs['include_in_schema'] = globals.endpoint_documentation in {'page', 'all'}
+
         self.api_router.get(self._path, **self.kwargs)(decorated)
         globals.page_routes[func] = self.path
         return func

+ 9 - 0
nicegui/run.py

@@ -53,6 +53,7 @@ def run(*,
         uvicorn_reload_includes: str = '*.py',
         uvicorn_reload_excludes: str = '.*, .py[cod], .sw.*, ~*',
         tailwind: bool = True,
+        endpoint_documentation: Literal['none', 'internal', 'page', 'all'] = 'none',
         storage_secret: Optional[str] = None,
         **kwargs: Any,
         ) -> None:
@@ -79,6 +80,7 @@ def run(*,
     :param uvicorn_reload_includes: string with comma-separated list of glob-patterns which trigger reload on modification (default: `'.py'`)
     :param uvicorn_reload_excludes: string with comma-separated list of glob-patterns which should be ignored for reload (default: `'.*, .py[cod], .sw.*, ~*'`)
     :param tailwind: whether to use Tailwind (experimental, default: `True`)
+    :param endpoint_documentation: control what endpoints appear in the autogenerated OpenAPI docs (default: 'none', options: 'none', 'internal', 'page', 'all')
     :param storage_secret: secret key for browser based storage (default: `None`, a value is required to enable ui.storage.individual and ui.storage.browser)
     :param kwargs: additional keyword arguments are passed to `uvicorn.run`    
     '''
@@ -91,6 +93,13 @@ def run(*,
     globals.language = language
     globals.binding_refresh_interval = binding_refresh_interval
     globals.tailwind = tailwind
+    globals.endpoint_documentation = endpoint_documentation
+
+    for route in globals.app.routes:
+        if route.path.startswith('/_nicegui') and hasattr(route, 'methods'):
+            route.include_in_schema = endpoint_documentation in {'internal', 'all'}
+        if route.path == '/' or route.path in globals.page_routes.values():
+            route.include_in_schema = endpoint_documentation in {'page', 'all'}
 
     if on_air:
         globals.air = Air('' if on_air is True else on_air)

+ 1 - 0
tests/conftest.py

@@ -35,6 +35,7 @@ def reset_globals() -> Generator[None, None, None]:
     print('!!! resetting globals !!!')
     for path in {'/'}.union(globals.page_routes.values()):
         globals.app.remove_route(path)
+    globals.app.openapi_schema = None
     globals.app.middleware_stack = None
     globals.app.user_middleware.clear()
     # NOTE favicon routes must be removed separately because they are not "pages"

+ 41 - 0
tests/test_endpoint_docs.py

@@ -0,0 +1,41 @@
+from typing import Set
+
+import requests
+
+from nicegui import __version__
+
+from .screen import Screen
+
+
+def get_openapi_paths() -> Set[str]:
+    return set(requests.get(f'http://localhost:{Screen.PORT}/openapi.json').json()['paths'])
+
+
+def test_endpoint_documentation_default(screen: Screen):
+    screen.open('/')
+    assert get_openapi_paths() == set()
+
+
+def test_endpoint_documentation_page_only(screen: Screen):
+    screen.ui_run_kwargs['endpoint_documentation'] = 'page'
+    screen.open('/')
+    assert get_openapi_paths() == {'/'}
+
+
+def test_endpoint_documentation_internal_only(screen: Screen):
+    screen.ui_run_kwargs['endpoint_documentation'] = 'internal'
+    screen.open('/')
+    assert get_openapi_paths() == {
+        f'/_nicegui/{__version__}/libraries/{{key}}',
+        f'/_nicegui/{__version__}/components/{{key}}',
+    }
+
+
+def test_endpoint_documentation_all(screen: Screen):
+    screen.ui_run_kwargs['endpoint_documentation'] = 'all'
+    screen.open('/')
+    assert get_openapi_paths() == {
+        '/',
+        f'/_nicegui/{__version__}/libraries/{{key}}',
+        f'/_nicegui/{__version__}/components/{{key}}',
+    }