mirror of
https://github.com/maubot/maubot.git
synced 2024-10-01 01:06:10 -04:00
Make maubot http server serve frontend for production
This commit is contained in:
parent
0264f7b794
commit
e0306d29b5
@ -24,6 +24,11 @@ server:
|
||||
port: 29316
|
||||
# The base management API path.
|
||||
base_path: /_matrix/maubot/v1
|
||||
# The base path for the UI.
|
||||
ui_base_path: /_matrix/maubot
|
||||
# Override path from where to load UI resources.
|
||||
# Set to false to using pkg_resources to find the path.
|
||||
override_resource_path: false
|
||||
# The base appservice API path. Use / for legacy appservice API and /_matrix/app/v1 for v1.
|
||||
appservice_base_path: /_matrix/app/v1
|
||||
# The shared secret to sign API access tokens.
|
||||
|
@ -26,7 +26,7 @@ from .server import MaubotServer
|
||||
from .client import Client, init as init_client_class
|
||||
from .loader.zip import init as init_zip_loader
|
||||
from .instance import init as init_plugin_instance_class
|
||||
from .management.api import init as init_management
|
||||
from .management.api import init as init_management_api
|
||||
from .__meta__ import __version__
|
||||
|
||||
parser = argparse.ArgumentParser(description="A plugin-based Matrix bot system.",
|
||||
@ -52,8 +52,9 @@ init_zip_loader(config)
|
||||
db_session = init_db(config)
|
||||
clients = init_client_class(db_session, loop)
|
||||
plugins = init_plugin_instance_class(db_session, config, loop)
|
||||
management_api = init_management(config, loop)
|
||||
server = MaubotServer(config, management_api, loop)
|
||||
management_api = init_management_api(config, loop)
|
||||
server = MaubotServer(config, loop)
|
||||
server.app.add_subapp(config["server.base_path"], management_api)
|
||||
|
||||
for plugin in plugins:
|
||||
plugin.load()
|
||||
|
@ -38,6 +38,9 @@ class Config(BaseFileConfig):
|
||||
copy("server.hostname")
|
||||
copy("server.port")
|
||||
copy("server.listen")
|
||||
copy("server.base_path")
|
||||
copy("server.ui_base_path")
|
||||
copy("server.override_resource_path")
|
||||
copy("server.appservice_base_path")
|
||||
shared_secret = self["server.unshared_secret"]
|
||||
if shared_secret is None or shared_secret == "generate":
|
||||
|
@ -15,6 +15,7 @@
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
from aiohttp import web
|
||||
|
||||
from ...__meta__ import __version__
|
||||
from ...config import Config
|
||||
|
||||
routes: web.RouteTableDef = web.RouteTableDef()
|
||||
@ -28,3 +29,10 @@ def set_config(config: Config) -> None:
|
||||
|
||||
def get_config() -> Config:
|
||||
return _config
|
||||
|
||||
|
||||
@routes.get("/version")
|
||||
async def version(_: web.Request) -> web.Response:
|
||||
return web.json_response({
|
||||
"version": __version__
|
||||
})
|
||||
|
@ -26,6 +26,7 @@
|
||||
"last 2 ios_saf versions"
|
||||
],
|
||||
"proxy": "http://localhost:29316",
|
||||
"homepage": ".",
|
||||
"devDependencies": {
|
||||
"sass-lint": "^1.12.1",
|
||||
"sass-lint-auto-fix": "^0.15.0"
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
import React, { Component } from "react"
|
||||
import { BrowserRouter as Router, Switch } from "react-router-dom"
|
||||
import { HashRouter as Router, Switch } from "react-router-dom"
|
||||
import PrivateRoute from "../components/PrivateRoute"
|
||||
import Spinner from "../components/Spinner"
|
||||
import api from "../api"
|
||||
|
@ -18,6 +18,7 @@ import asyncio
|
||||
|
||||
from aiohttp import web
|
||||
from aiohttp.abc import AbstractAccessLogger
|
||||
import pkg_resources
|
||||
|
||||
from mautrix.api import PathBuilder, Method
|
||||
|
||||
@ -35,21 +36,56 @@ class AccessLogger(AbstractAccessLogger):
|
||||
class MaubotServer:
|
||||
log: logging.Logger = logging.getLogger("maubot.server")
|
||||
|
||||
def __init__(self, config: Config, management: web.Application,
|
||||
loop: asyncio.AbstractEventLoop) -> None:
|
||||
def __init__(self, config: Config, loop: asyncio.AbstractEventLoop) -> None:
|
||||
self.loop = loop or asyncio.get_event_loop()
|
||||
self.app = web.Application(loop=self.loop)
|
||||
self.config = config
|
||||
|
||||
path = PathBuilder(config["server.base_path"])
|
||||
self.add_route(Method.GET, path.version, self.version)
|
||||
self.app.add_subapp(config["server.base_path"], management)
|
||||
|
||||
as_path = PathBuilder(config["server.appservice_base_path"])
|
||||
self.add_route(Method.PUT, as_path.transactions, self.handle_transaction)
|
||||
|
||||
self.setup_management_ui()
|
||||
|
||||
self.runner = web.AppRunner(self.app, access_log_class=AccessLogger)
|
||||
|
||||
def setup_management_ui(self) -> None:
|
||||
ui_base = self.config["server.ui_base_path"]
|
||||
if ui_base == "/":
|
||||
ui_base = ""
|
||||
directory = (self.config["server.override_resource_path"]
|
||||
or pkg_resources.resource_filename("maubot", "management/frontend/build"))
|
||||
self.app.router.add_static(f"{ui_base}/static", f"{directory}/static")
|
||||
self.setup_static_root_files(directory, ui_base)
|
||||
|
||||
with open(f"{directory}/index.html", "r") as file:
|
||||
index_html = file.read()
|
||||
|
||||
@web.middleware
|
||||
async def frontend_404_middleware(request, handler):
|
||||
if hasattr(handler, "__self__") and isinstance(handler.__self__, web.StaticResource):
|
||||
try:
|
||||
return await handler(request)
|
||||
except web.HTTPNotFound:
|
||||
return web.Response(body=index_html, content_type="text/html")
|
||||
return await handler(request)
|
||||
|
||||
self.app.middlewares.append(frontend_404_middleware)
|
||||
self.app.router.add_get(f"{ui_base}/", lambda _: web.Response(body=index_html,
|
||||
content_type="text/html"))
|
||||
self.app.router.add_get(ui_base, lambda _: web.HTTPFound(f"{ui_base}/"))
|
||||
|
||||
def setup_static_root_files(self, directory: str, ui_base: str) -> None:
|
||||
files = {
|
||||
"asset-manifest.json": "application/json",
|
||||
"manifest.json": "application/json",
|
||||
"favicon.png": "image/png",
|
||||
}
|
||||
for file, mime in files.items():
|
||||
with open(f"{directory}/{file}", "rb") as stream:
|
||||
data = stream.read()
|
||||
self.app.router.add_get(f"{ui_base}/{file}", lambda _: web.Response(body=data,
|
||||
content_type=mime))
|
||||
|
||||
def add_route(self, method: Method, path: PathBuilder, handler) -> None:
|
||||
self.app.router.add_route(method.value, str(path), handler)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user