Skip to main content

snap_control/api/
http.rs

1// Copyright 2026 Anapaya Systems
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//   http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//! HTTP API endpoint definitions and endpoint handlers.
15
16use std::sync::Arc;
17
18use axum::{Json, routing::get};
19use utoipa::OpenApi;
20use utoipa_axum::router::OpenApiRouter;
21
22use crate::api::http::model::PgWapSessionManager;
23
24mod v1;
25
26#[derive(OpenApi)]
27#[openapi(info(
28    title = "SNAP HTTP API",
29    version = "0.1.0",
30    description = "Anapaya SNAP HTTP API"
31))]
32struct SnapApi;
33
34/// HTTP API models.
35pub mod model {
36    use std::net::IpAddr;
37
38    /// Information about an authenticated IP address.
39    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
40    pub struct Session {
41        /// The authenticated IP address.
42        pub ip: IpAddr,
43        /// The AP ID to use for sessions authenticated with this IP address.
44        pub ap_id: String,
45        /// The port to use for data plane sessions.
46        pub data_plane_port: u16,
47        /// The time until which the authentication is valid. After this time, the client needs to
48        /// reauthenticate.
49        pub valid_until: chrono::DateTime<chrono::Utc>,
50        /// The target domains a client is allowed to connect to.
51        pub target_domains: Vec<String>,
52    }
53
54    /// PathGuard WAP session manager.
55    pub trait PgWapSessionManager: Send + Sync {
56        /// Create a new session for the given client IP address.
57        fn new_session(
58            &self,
59            client_ip: IpAddr,
60            target_domains: &[&str],
61        ) -> Result<Session, anyhow::Error>;
62    }
63}
64
65/// Nests the SNAP HTTP API routes into the provided `base_router`.
66pub fn nest_http_api(
67    router: axum::Router,
68    pg_wap_session_manager: Arc<dyn PgWapSessionManager>,
69) -> axum::Router {
70    let mut doc = SnapApi::openapi();
71
72    let (api_router, api_spec) = OpenApiRouter::new()
73        .nest(v1::PG_WAP_API_V1, v1::pg_wap_router(pg_wap_session_manager))
74        .split_for_parts();
75
76    doc.merge(api_spec);
77
78    router
79        .merge(api_router)
80        .route("/.well-known/openapi.json", get(|| async { Json(doc) }))
81}