Skip to main content

greentic_runner_host/runner/
mod.rs

1pub mod adapt_messaging;
2pub mod adapt_slack;
3pub mod adapt_teams;
4pub mod adapt_timer;
5pub mod adapt_webchat;
6pub mod adapt_webex;
7pub mod adapt_webhook;
8pub mod adapt_whatsapp;
9pub mod contract_cache;
10pub mod contract_introspection;
11pub mod engine;
12pub mod flow_adapter;
13pub mod i18n;
14pub mod ingress_util;
15pub mod invocation;
16pub mod mocks;
17pub mod operator;
18pub mod schema_validator;
19pub mod templating;
20
21use std::net::SocketAddr;
22use std::sync::Arc;
23
24use anyhow::Result;
25use axum::routing::{any, get, post};
26use axum::{Router, serve};
27use tokio::net::TcpListener;
28
29use crate::http::{self, admin, auth::AdminAuth, health::HealthState};
30use crate::routing::TenantRouting;
31use crate::runtime::ActivePacks;
32use crate::watcher::PackReloadHandle;
33
34pub struct HostServer {
35    addr: SocketAddr,
36    router: Router,
37    _state: ServerState,
38}
39
40impl HostServer {
41    pub fn new(
42        port: u16,
43        active: Arc<ActivePacks>,
44        routing: TenantRouting,
45        health: Arc<HealthState>,
46        reload: Option<PackReloadHandle>,
47        admin: AdminAuth,
48    ) -> Result<Self> {
49        let addr = SocketAddr::from(([0, 0, 0, 0], port));
50        let state = ServerState {
51            active,
52            routing,
53            health,
54            reload,
55            admin,
56        };
57        let router = Router::new()
58            .route(
59                "/messaging/telegram/webhook",
60                post(adapt_messaging::telegram_webhook),
61            )
62            .route("/webchat/activities", post(adapt_webchat::activities))
63            .route("/teams/activities", post(adapt_teams::activities))
64            .route("/slack/events", post(adapt_slack::events))
65            .route("/slack/interactive", post(adapt_slack::interactive))
66            .route("/webex/webhook", post(adapt_webex::webhook))
67            .route(
68                "/whatsapp/webhook",
69                get(adapt_whatsapp::verify).post(adapt_whatsapp::webhook),
70            )
71            .route("/webhook/{flow_id}", any(adapt_webhook::dispatch))
72            .route("/operator/op/invoke", post(operator::invoke))
73            .route("/healthz", get(http::health::handler))
74            .route("/admin/packs/status", get(admin::status))
75            .route("/admin/packs/reload", post(admin::reload))
76            .with_state(state.clone());
77        Ok(Self {
78            addr,
79            router,
80            _state: state,
81        })
82    }
83
84    pub async fn serve(self) -> Result<()> {
85        tracing::info!(addr = %self.addr, "starting host server");
86        let listener = TcpListener::bind(self.addr).await?;
87        serve(
88            listener,
89            self.router
90                .into_make_service_with_connect_info::<SocketAddr>(),
91        )
92        .await?;
93        Ok(())
94    }
95}
96
97#[derive(Clone)]
98pub struct ServerState {
99    pub active: Arc<ActivePacks>,
100    pub routing: TenantRouting,
101    pub health: Arc<HealthState>,
102    pub reload: Option<PackReloadHandle>,
103    pub admin: AdminAuth,
104}