Skip to content

Commit

Permalink
Expose CdnHostEnum
Browse files Browse the repository at this point in the history
  • Loading branch information
waketzheng committed Dec 16, 2023
1 parent 7c237bc commit f433091
Show file tree
Hide file tree
Showing 25 changed files with 206 additions and 47 deletions.
4 changes: 2 additions & 2 deletions fastapi_cdn_host/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import importlib.metadata
from pathlib import Path

from .client import monkey_patch_for_docs_ui
from .client import CdnHostEnum, monkey_patch_for_docs_ui

monkey_patch = monkey_patch_for_docs_ui
__version__ = importlib.metadata.version(Path(__file__).parent.name)
__all__ = ("__version__", "monkey_patch", "monkey_patch_for_docs_ui")
__all__ = ("__version__", "CdnHostEnum", "monkey_patch", "monkey_patch_for_docs_ui")
3 changes: 3 additions & 0 deletions scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
set -e
set -x

python tests/prepare_media.py
cd tests/online_cdn && coverage run -m pytest test_*.py
cd ../favicon_online_cdn && coverage run -m pytest test_*.py
cd ../static_auto && coverage run -m pytest test_*.py
Expand All @@ -15,6 +16,8 @@ cd ../root_path_without_static && coverage run -m pytest test_*.py
cd ../static_favicon_without_swagger_ui && coverage run -m pytest test_*.py
cd ../private_cdn && coverage run -m pytest test_*.py
cd ../cdn_with_default_asset_path && coverage run -m pytest test_*.py
cd ../explicit_cdn_host && coverage run -m pytest test_*.py
cd ../simple_asset_path && coverage run -m pytest test_*.py

cd ../.. && coverage combine tests/*/.coverage
coverage report -m
1 change: 0 additions & 1 deletion tests/cdn_with_default_asset_path/main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python
from config import MY_CDN
from fastapi import FastAPI, Request
from fastapi.responses import RedirectResponse
Expand Down
18 changes: 0 additions & 18 deletions tests/cdn_with_default_asset_path/media_server.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
import shutil
from pathlib import Path

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles


def prepare_assets() -> None:
parent = Path(__file__).parent
asset_dir = parent.parent / "static_with_favicon/static"
ui_dir = parent / "cdn/[email protected]"
if not ui_dir.exists():
ui_dir.mkdir(parents=True)
for src in asset_dir.glob("swagger-ui*"):
shutil.copyfile(src, ui_dir / src.name)
redoc = ui_dir.parent / "redoc@next/bundles/redoc.standalone.js"
if not redoc.exists():
redoc.parent.mkdir(parents=True)
shutil.copyfile(asset_dir / redoc.name, redoc)


app = FastAPI()
STATIC_ROOT = Path(__file__).parent / "cdn"
if not STATIC_ROOT.exists():
prepare_assets()
app.mount("/cdn", StaticFiles(directory=STATIC_ROOT), name="cdn")
1 change: 1 addition & 0 deletions tests/explicit_cdn_host/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cdn/
2 changes: 2 additions & 0 deletions tests/explicit_cdn_host/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PORT = 8618
MY_CDN = f"http://127.0.0.1:{PORT}/cdn"
19 changes: 19 additions & 0 deletions tests/explicit_cdn_host/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from fastapi import FastAPI, Request
from fastapi.responses import RedirectResponse

from fastapi_cdn_host import CdnHostEnum, monkey_patch_for_docs_ui

app = FastAPI(title="FastAPI CDN host test")


@app.get("/", include_in_schema=False)
async def to_docs():
return RedirectResponse("/docs")


@app.get("/app")
async def get_app(request: Request) -> dict:
return {"routes": str(request.app.routes)}


monkey_patch_for_docs_ui(app, CdnHostEnum.unpkg)
8 changes: 8 additions & 0 deletions tests/explicit_cdn_host/media_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from pathlib import Path

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

app = FastAPI()
STATIC_ROOT = Path(__file__).parent / "cdn"
app.mount("/cdn", StaticFiles(directory=STATIC_ROOT), name="cdn")
39 changes: 39 additions & 0 deletions tests/explicit_cdn_host/test_explicit_cdn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# mypy: no-disallow-untyped-decorators

import pytest
from httpx import AsyncClient
from main import app

from fastapi_cdn_host import CdnHostEnum


@pytest.fixture(scope="module")
def anyio_backend():
return "asyncio"


@pytest.fixture(scope="module")
async def client():
async with AsyncClient(app=app, base_url="http://test") as c:
yield c


@pytest.mark.anyio
async def test_docs(client: AsyncClient): # nosec
host = str(CdnHostEnum.unpkg.value)
css_url = host + "/[email protected]/swagger-ui.css"
js_url = host + "/[email protected]/swagger-ui-bundle.js"
redoc_url = host + "/redoc@next/bundles/redoc.standalone.js"
favicon_url = host + "/favicon.ico"
response = await client.get("/docs")
text = response.text
assert response.status_code == 200, text
assert f'"{favicon_url}"' not in text
assert f'"{css_url}"' in text
assert f'"{js_url}"' in text
response = await client.get("/redoc")
text = response.text
assert response.status_code == 200, text
assert f'"{redoc_url}"' in text
response = await client.get("/app")
assert response.status_code == 200
File renamed without changes.
40 changes: 40 additions & 0 deletions tests/prepare_media.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env python
import shutil
from pathlib import Path


def copy_file(
folder: Path, *ps: Path, force=False, base_dir=Path(__file__).parent.parent
) -> None:
if folder.exists():
if not force:
return
else:
folder.mkdir(parents=True)
for p in ps:
dst = folder / p.name
shutil.copyfile(p, dst)
print(f"File copied: {p.relative_to(base_dir)} --> {dst.relative_to(base_dir)}")


def main():
root = Path(__file__).parent
src = root / "static_with_favicon/static"
swagger_ui_files = list(src.glob("swagger-ui*"))
redoc_file = src / "redoc.standalone.js"
favicon_file = src / "favicon.ico"
copy_file(root / "static_auto" / "static", *swagger_ui_files)
copy_file(root / "static_favicon_without_swagger_ui/static", favicon_file)
pri_cdn = root / "private_cdn/cdn"
copy_file(pri_cdn / "swagger-ui@latest", *swagger_ui_files)
copy_file(pri_cdn / "redoc/next", redoc_file)
pri_cdn2 = root / "cdn_with_default_asset_path/cdn"
copy_file(pri_cdn2 / "[email protected]", *swagger_ui_files)
copy_file(pri_cdn2 / "redoc@next/bundles", redoc_file)
copy_file(
root / "simple_asset_path/cdn", redoc_file, favicon_file, *swagger_ui_files
)


if __name__ == "__main__":
main()
18 changes: 0 additions & 18 deletions tests/private_cdn/media_server.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
import shutil
from pathlib import Path

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles


def prepare_assets() -> None:
parent = Path(__file__).parent
asset_dir = parent.parent / "static_with_favicon/static"
ui_dir = parent / "cdn/swagger-ui@latest"
if not ui_dir.exists():
ui_dir.mkdir(parents=True)
for src in asset_dir.glob("swagger-ui*"):
shutil.copyfile(src, ui_dir / src.name)
redoc = ui_dir.parent / "redoc/next/redoc.standalone.js"
if not redoc.exists():
redoc.parent.mkdir(parents=True)
shutil.copyfile(asset_dir / redoc.name, redoc)


app = FastAPI()
STATIC_ROOT = Path(__file__).parent / "cdn"
if not STATIC_ROOT.exists():
prepare_assets()
app.mount("/cdn", StaticFiles(directory=STATIC_ROOT), name="cdn")
1 change: 1 addition & 0 deletions tests/simple_asset_path/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cdn/
2 changes: 2 additions & 0 deletions tests/simple_asset_path/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PORT = 8619
MY_CDN = f"http://127.0.0.1:{PORT}/cdn"
32 changes: 32 additions & 0 deletions tests/simple_asset_path/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env python
from pathlib import Path

import uvicorn
from config import MY_CDN
from fastapi import FastAPI, Request
from fastapi.responses import RedirectResponse

from fastapi_cdn_host import monkey_patch_for_docs_ui

app = FastAPI(title="FastAPI CDN host test")


@app.get("/", include_in_schema=False)
async def to_docs():
return RedirectResponse("/docs")


@app.get("/app")
async def get_app(request: Request) -> dict:
return {"routes": str(request.app.routes)}


monkey_patch_for_docs_ui(
app,
docs_cdn_host=(MY_CDN, "/"),
favicon_url=MY_CDN + "/favicon.ico",
)


if __name__ == "__main__":
uvicorn.run(f"{Path(__file__).stem}:app", reload=True)
8 changes: 8 additions & 0 deletions tests/simple_asset_path/media_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from pathlib import Path

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

app = FastAPI()
STATIC_ROOT = Path(__file__).parent / "cdn"
app.mount("/cdn", StaticFiles(directory=STATIC_ROOT), name="cdn")
47 changes: 47 additions & 0 deletions tests/simple_asset_path/test_simple_asset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# mypy: no-disallow-untyped-decorators
import sys
from pathlib import Path

import pytest
from config import MY_CDN, PORT
from httpx import AsyncClient
from main import app

try:
from tests.http_race.utils import UvicornServer
except ImportError:
_path = Path(__file__).parent.parent / "http_race"
sys.path.append(_path.as_posix())
from utils import UvicornServer # type: ignore[no-redef]


@pytest.fixture(scope="module")
def anyio_backend():
return "asyncio"


@pytest.fixture(scope="module")
async def client():
async with AsyncClient(app=app, base_url="http://test") as c:
yield c


@pytest.mark.anyio
async def test_docs(client: AsyncClient): # nosec
css_url = MY_CDN + "/swagger-ui.css"
js_url = MY_CDN + "/swagger-ui-bundle.js"
redoc_url = MY_CDN + "/redoc.standalone.js"
favicon_url = MY_CDN + "/favicon.ico"
with UvicornServer("media_server:app", port=PORT).run_in_thread():
response = await client.get("/docs")
text = response.text
assert response.status_code == 200, text
assert f'"{favicon_url}"' in text
assert f'"{css_url}"' in text
assert f'"{js_url}"' in text
response = await client.get("/redoc")
text = response.text
assert response.status_code == 200, text
assert f'"{redoc_url}"' in text
response = await client.get("/app")
assert response.status_code == 200
1 change: 1 addition & 0 deletions tests/static_auto/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
static
3 changes: 0 additions & 3 deletions tests/static_auto/static/swagger-ui-bundle.js

This file was deleted.

1 change: 0 additions & 1 deletion tests/static_auto/static/swagger-ui-bundle.js.map

This file was deleted.

3 changes: 0 additions & 3 deletions tests/static_auto/static/swagger-ui.css

This file was deleted.

1 change: 0 additions & 1 deletion tests/static_auto/static/swagger-ui.css.map

This file was deleted.

1 change: 1 addition & 0 deletions tests/static_favicon_without_swagger_ui/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
static
Binary file not shown.

0 comments on commit f433091

Please sign in to comment.