|
2 | 2 | # SPDX-License-Identifier: AGPL-3.0-or-later |
3 | 3 |
|
4 | 4 | from contextlib import asynccontextmanager |
5 | | -from functools import partial |
6 | 5 | from starlette.applications import Starlette |
7 | 6 | from starlette.routing import Mount, Route |
8 | 7 | from starlette.staticfiles import StaticFiles |
@@ -61,53 +60,37 @@ def session(self): |
61 | 60 | return self.db.session() |
62 | 61 |
|
63 | 62 |
|
64 | | -# Playback formats for which we know that they sometimes expect their files |
65 | | -# in /{format}/* instead of the default /playback/{format}/* path. |
66 | | -PLAYBACK_FROM_ROOT_FORMATS = ("presentation", "video") |
67 | | - |
68 | | - |
69 | | -async def format_redirect_app(format, scope, receive, send): |
70 | | - assert scope["type"] == "http" |
71 | | - path = scope["path"].lstrip("/") |
72 | | - response = RedirectResponse(url=f"/playback/{format}/{path}") |
73 | | - await response(scope, receive, send) |
74 | | - |
75 | | - |
76 | 63 | def redirect(src, dst): |
77 | 64 | async def handler(request): |
78 | 65 | return RedirectResponse(url=dst) |
79 | 66 |
|
80 | 67 | return Route(src, endpoint=handler) |
81 | 68 |
|
82 | 69 |
|
83 | | -def make_routes(config: BBBLBConfig): |
84 | | - from bbblb.web import bbbapi, bbblbapi |
| 70 | +async def collect_routes(sr: ServiceRegistry): |
| 71 | + from bbblb.web import bbbapi, bbblbapi, playback |
85 | 72 |
|
86 | | - playback_dir = config.PATH_DATA / "recordings" / "public" |
87 | | - playback_dir.mkdir(parents=True, exist_ok=True) |
| 73 | + config = await sr.use(BBBLBConfig) |
88 | 74 | static_dir = config.PATH_DATA / "htdocs" |
89 | 75 | static_dir.mkdir(parents=True, exist_ok=True) |
90 | 76 |
|
91 | 77 | return [ |
92 | 78 | Mount("/bigbluebutton/api", routes=bbbapi.api_routes), |
93 | 79 | Mount("/bbblb/api", routes=bbblbapi.api_routes), |
94 | | - # Serve /playback/* files in case the reverse proxy in front if BBBLB does not. |
| 80 | + Mount( |
| 81 | + "/playback/presentation/2.3/{record_id}", |
| 82 | + app=playback.PlaybackPlayerApp(config), |
| 83 | + name="bbb:playback:player", |
| 84 | + ), |
95 | 85 | Mount( |
96 | 86 | "/playback", |
97 | | - app=StaticFiles( |
98 | | - directory=playback_dir, |
99 | | - check_dir=False, |
100 | | - follow_symlink=True, |
101 | | - ), |
102 | | - name="bbb:playback", |
| 87 | + app=playback.PlaybackMediaApp(config, await sr.use(DBContext)), |
| 88 | + name="bbb:playback:media", |
103 | 89 | ), |
104 | 90 | # Redirect misguided playback file requests to the real path. We send |
105 | 91 | # redirects instead of real files in case a reverse proxy in front if BBBLB |
106 | | - # serves /playback/* for us more efficiently. |
107 | | - *[ |
108 | | - Mount(f"/{format}", app=partial(format_redirect_app, format)) |
109 | | - for format in PLAYBACK_FROM_ROOT_FORMATS |
110 | | - ], |
| 92 | + # serves /playback/* for us. |
| 93 | + *playback.PLAYBACK_FORMAT_REDIRECTS, |
111 | 94 | # Redirect non-slash requests to prefix mounts, because automatic slash handling |
112 | 95 | # breaks if there are other routes matching the non-slash request :/ |
113 | 96 | redirect("/bigbluebutton/api", "/bigbluebutton/api/"), |
@@ -139,8 +122,9 @@ async def lifespan(app: Starlette): |
139 | 122 | async with services: |
140 | 123 | if autostart: |
141 | 124 | await services.start_all() |
142 | | - app.state.config = config |
| 125 | + app.router.routes.extend(await collect_routes(services)) |
143 | 126 | app.state.services = services |
| 127 | + |
144 | 128 | yield |
145 | 129 |
|
146 | | - return Starlette(debug=config.DEBUG, routes=make_routes(config), lifespan=lifespan) |
| 130 | + return Starlette(debug=config.DEBUG, lifespan=lifespan) |
0 commit comments