aster_server/routes/
tunnel.rs1use crate::state::AppState;
2use axum::{
3 extract::State,
4 http::StatusCode,
5 response::{IntoResponse, Response},
6 routing::{get, post},
7 Json, Router,
8};
9use serde::Serialize;
10use std::sync::Arc;
11use utoipa::ToSchema;
12
13#[derive(Debug, Serialize, ToSchema)]
14pub struct ErrorResponse {
15 pub error: String,
16}
17
18#[utoipa::path(
20 post,
21 path = "/tunnel/start",
22 responses(
23 (status = 200, description = "Tunnel started successfully", body = TunnelInfo),
24 (status = 400, description = "Bad request", body = ErrorResponse),
25 (status = 500, description = "Internal server error", body = ErrorResponse)
26 )
27)]
28#[axum::debug_handler]
29pub async fn start_tunnel(State(state): State<Arc<AppState>>) -> Response {
30 match state.tunnel_manager.start().await {
31 Ok(info) => (StatusCode::OK, Json(info)).into_response(),
32 Err(e) => {
33 tracing::error!("Failed to start tunnel: {}", e);
34 (
35 StatusCode::INTERNAL_SERVER_ERROR,
36 Json(ErrorResponse {
37 error: e.to_string(),
38 }),
39 )
40 .into_response()
41 }
42 }
43}
44
45#[utoipa::path(
47 post,
48 path = "/tunnel/stop",
49 responses(
50 (status = 200, description = "Tunnel stopped successfully"),
51 (status = 500, description = "Internal server error", body = ErrorResponse)
52 )
53)]
54pub async fn stop_tunnel(State(state): State<Arc<AppState>>) -> Response {
55 state.tunnel_manager.stop(true).await;
56 StatusCode::OK.into_response()
57}
58
59#[utoipa::path(
61 get,
62 path = "/tunnel/status",
63 responses(
64 (status = 200, description = "Tunnel info", body = TunnelInfo)
65 )
66)]
67pub async fn get_tunnel_status(State(state): State<Arc<AppState>>) -> Response {
68 let info = state.tunnel_manager.get_info().await;
69 (StatusCode::OK, Json(info)).into_response()
70}
71
72pub fn routes(state: Arc<AppState>) -> Router {
73 Router::new()
74 .route("/tunnel/start", post(start_tunnel))
75 .route("/tunnel/stop", post(stop_tunnel))
76 .route("/tunnel/status", get(get_tunnel_status))
77 .with_state(state)
78}