File size: 1,931 Bytes
a1a6d79
 
bb7c9a3
a1a6d79
 
 
 
bb7c9a3
a1a6d79
bb7c9a3
 
 
a1a6d79
bb7c9a3
 
 
a1a6d79
 
 
bb7c9a3
a1a6d79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
from aiohttp.web import Application, AppRunner, Response, RouteTableDef, TCPSite
from dependency_injector.containers import DeclarativeContainer
from dependency_injector.resources import AsyncResource
from itertools import chain
from loguru import logger
from pydantic import ConfigDict, PrivateAttr
from typing import Self, Sequence

from ctp_slack_bot.controllers.base import ControllerBase, Route
from ctp_slack_bot.core import ApplicationComponentBase, Settings


class HTTPServer(ApplicationComponentBase):
    model_config = ConfigDict(frozen=True)

    settings: Settings
    routes: Sequence[Route]
    _app_runner: AppRunner = PrivateAttr()
    _site: TCPSite = PrivateAttr()

    async def initialize(self: Self) -> None:
        app = Application()
        for route in self.routes:
            app.router.add_route(route.method, route.path, route.handler)
            logger.info("Registered HTTP route: {} {}", route.method, route.path)
        self._app_runner = AppRunner(app)
        await self._app_runner.setup()
        self._site = TCPSite(self._app_runner, self.settings.http_host, self.settings.http_port)

    async def start(self: Self) -> None:
        await self._site.start()

    async def stop(self: Self) -> None:
        await self._app_runner.cleanup()

    @property
    def name(self: Self) -> str:
        return "http_server"


class HTTPServerResource(AsyncResource):
    async def init(self: Self, settings: Settings, controllers: Sequence[ControllerBase]) -> HTTPServer:
        routes = tuple(chain.from_iterable(controller.get_routes()
                                           for controller
                                           in controllers))
        http_server = HTTPServer(settings=settings, routes=routes)
        await http_server.initialize()
        return http_server

    async def shutdown(self: Self, http_server: HTTPServer) -> None:
        await http_server.stop()