feat(api): add API routes with full state wiring and integration test fixtures
- Add /api routes for agents and proxy resources - Wire all services into ApiState in service/mod.rs - Update route tests with all mock services
This commit is contained in:
41
apps/nxmesh-master/src/routes/api/agents/add_agent.rs
Normal file
41
apps/nxmesh-master/src/routes/api/agents/add_agent.rs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{Json, extract::State, http::StatusCode, response::IntoResponse};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
routes::api::{agents::dto::AgentInfo, error::AppError},
|
||||||
|
service::agent::{AgentService, CreateAgentRecord},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct CreateAgentRequest {
|
||||||
|
pub name: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub ip_address: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn add_agent_handler(
|
||||||
|
State(agent_service): State<Arc<dyn AgentService>>,
|
||||||
|
Json(body): Json<CreateAgentRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
if body.name.trim().is_empty() {
|
||||||
|
return Err(AppError::BadRequest("name is required".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let rec = CreateAgentRecord {
|
||||||
|
name: body.name,
|
||||||
|
ip_address: body.ip_address,
|
||||||
|
};
|
||||||
|
|
||||||
|
let agent = agent_service.create(&rec).await.map_err(|err| {
|
||||||
|
error!("Failed to create agent: {}", err);
|
||||||
|
AppError::InternalServerError
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
StatusCode::CREATED,
|
||||||
|
Json(serde_json::json!({"agent": AgentInfo::from(agent)})),
|
||||||
|
))
|
||||||
|
}
|
||||||
27
apps/nxmesh-master/src/routes/api/agents/delete_agent.rs
Normal file
27
apps/nxmesh-master/src/routes/api/agents/delete_agent.rs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use tracing::{error, info};
|
||||||
|
|
||||||
|
use crate::{routes::api::error::AppError, service::agent::AgentService};
|
||||||
|
|
||||||
|
pub async fn delete_agent_handler(
|
||||||
|
State(agent_service): State<Arc<dyn AgentService>>,
|
||||||
|
Path(id): Path<uuid::Uuid>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let deleted = agent_service.delete(id).await.map_err(|err| {
|
||||||
|
error!("Failed to delete agent: {}", err);
|
||||||
|
AppError::InternalServerError
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if deleted {
|
||||||
|
info!("Agent {} deleted", id);
|
||||||
|
Ok((StatusCode::NO_CONTENT,))
|
||||||
|
} else {
|
||||||
|
Err(AppError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
39
apps/nxmesh-master/src/routes/api/agents/dto.rs
Normal file
39
apps/nxmesh-master/src/routes/api/agents/dto.rs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::service::agent::{AgentRecord, State};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct AgentInfo {
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub state: State,
|
||||||
|
//
|
||||||
|
pub deployment_mode: Option<String>,
|
||||||
|
pub ip_address: Option<String>,
|
||||||
|
pub last_seen_at: Option<String>,
|
||||||
|
pub labels: Option<serde_json::Value>,
|
||||||
|
//
|
||||||
|
pub number_of_routes: usize,
|
||||||
|
//
|
||||||
|
pub created_at: String,
|
||||||
|
pub updated_at: String,
|
||||||
|
pub is_disabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AgentRecord> for AgentInfo {
|
||||||
|
fn from(record: AgentRecord) -> Self {
|
||||||
|
AgentInfo {
|
||||||
|
id: record.id.to_string(),
|
||||||
|
name: record.name,
|
||||||
|
ip_address: record.ip_address,
|
||||||
|
state: record.state,
|
||||||
|
deployment_mode: record.deployment_mode,
|
||||||
|
last_seen_at: record.last_seen_at,
|
||||||
|
labels: record.labels,
|
||||||
|
number_of_routes: 0, // This will be populated later
|
||||||
|
created_at: record.created_at,
|
||||||
|
updated_at: record.updated_at,
|
||||||
|
is_disabled: matches!(record.state, State::Disabled),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
52
apps/nxmesh-master/src/routes/api/agents/get_agent.rs
Normal file
52
apps/nxmesh-master/src/routes/api/agents/get_agent.rs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
};
|
||||||
|
use serde::Serialize;
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
routes::api::{agents::dto::AgentInfo, error::AppError},
|
||||||
|
service::agent::AgentService,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct GetAgentsResponse {
|
||||||
|
agents: Vec<AgentInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct GetAgentResponse {
|
||||||
|
agent: AgentInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_agents_handler(
|
||||||
|
State(agent_service): State<Arc<dyn AgentService>>,
|
||||||
|
) -> Result<Json<GetAgentsResponse>, AppError> {
|
||||||
|
let agents = agent_service.list().await.map_err(|err| {
|
||||||
|
error!("Failed to get agents: {}", err);
|
||||||
|
AppError::InternalServerError
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(Json(GetAgentsResponse {
|
||||||
|
agents: agents.into_iter().map(AgentInfo::from).collect(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_agent_handler(
|
||||||
|
State(agent_service): State<Arc<dyn AgentService>>,
|
||||||
|
Path(id): Path<uuid::Uuid>,
|
||||||
|
) -> Result<Json<GetAgentResponse>, AppError> {
|
||||||
|
let agent = agent_service.get(id).await.map_err(|err| {
|
||||||
|
error!("Failed to get agent: {}", err);
|
||||||
|
AppError::InternalServerError
|
||||||
|
})?;
|
||||||
|
match agent {
|
||||||
|
Some(agent) => Ok(Json(GetAgentResponse {
|
||||||
|
agent: AgentInfo::from(agent),
|
||||||
|
})),
|
||||||
|
None => Err(AppError::NotFound),
|
||||||
|
}
|
||||||
|
}
|
||||||
223
apps/nxmesh-master/src/routes/api/agents/mod.rs
Normal file
223
apps/nxmesh-master/src/routes/api/agents/mod.rs
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
use crate::routes::api::{
|
||||||
|
ApiRouter,
|
||||||
|
agents::{
|
||||||
|
add_agent::add_agent_handler,
|
||||||
|
delete_agent::delete_agent_handler,
|
||||||
|
get_agent::{get_agent_handler, get_agents_handler},
|
||||||
|
update_agent::update_agent_handler,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mod add_agent;
|
||||||
|
mod delete_agent;
|
||||||
|
mod dto;
|
||||||
|
mod get_agent;
|
||||||
|
mod update_agent;
|
||||||
|
|
||||||
|
pub async fn get_router() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.route(
|
||||||
|
"/agents",
|
||||||
|
axum::routing::get(get_agents_handler).post(add_agent_handler),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/agents/{id}",
|
||||||
|
axum::routing::get(get_agent_handler)
|
||||||
|
.put(update_agent_handler)
|
||||||
|
.delete(delete_agent_handler),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
mod tests {
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::service::agent::{AgentRecord, MockAgentService, State};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use axum_test::TestServer;
|
||||||
|
|
||||||
|
async fn make_state(mock: MockAgentService) -> axum::Router {
|
||||||
|
use crate::service::proxy::*;
|
||||||
|
let state = crate::routes::api::LocalApiState::from(crate::routes::api::ApiState {
|
||||||
|
agent_service: Arc::new(mock),
|
||||||
|
proxy_service: Arc::new(MockProxyServiceTrait::new()),
|
||||||
|
server_block_service: Arc::new(server_block::MockServerBlockService::new()),
|
||||||
|
upstream_service: Arc::new(upstream::MockUpstreamService::new()),
|
||||||
|
location_block_service: Arc::new(location_block::MockLocationBlockService::new()),
|
||||||
|
access_rule_service: Arc::new(access_rule::MockAccessRuleService::new()),
|
||||||
|
cache_zone_service: Arc::new(cache_zone::MockCacheZoneService::new()),
|
||||||
|
limit_rule_service: Arc::new(limit_rule::MockLimitRuleService::new()),
|
||||||
|
limit_zone_service: Arc::new(limit_zone::MockLimitZoneService::new()),
|
||||||
|
log_setting_service: Arc::new(log_setting::MockLogSettingService::new()),
|
||||||
|
proxy_setting_service: Arc::new(proxy_setting::MockProxySettingService::new()),
|
||||||
|
rewrite_rule_service: Arc::new(rewrite_rule::MockRewriteRuleService::new()),
|
||||||
|
ssl_certificate_service: Arc::new(ssl_certificate::MockSslCertificateService::new()),
|
||||||
|
config_inheritance_service: Arc::new(config_inheritance::MockConfigInheritanceService::new()),
|
||||||
|
});
|
||||||
|
get_router().await.with_state(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_record(id: uuid::Uuid) -> AgentRecord {
|
||||||
|
AgentRecord {
|
||||||
|
id,
|
||||||
|
name: "agent1".to_string(),
|
||||||
|
ip_address: Some("127.0.0.1".to_string()),
|
||||||
|
state: State::Active,
|
||||||
|
deployment_mode: None,
|
||||||
|
last_seen_at: None,
|
||||||
|
labels: None,
|
||||||
|
created_at: "created".to_string(),
|
||||||
|
updated_at: "updated".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_agents() {
|
||||||
|
let mut agent_service_mock = MockAgentService::new();
|
||||||
|
agent_service_mock.expect_list().returning(|| Ok(vec![]));
|
||||||
|
let server = TestServer::new(make_state(agent_service_mock).await);
|
||||||
|
let response = server.get("/agents").await;
|
||||||
|
assert_eq!(response.status_code(), 200);
|
||||||
|
assert_eq!(response.text(), r#"{"agents":[]}"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_agent_not_found() {
|
||||||
|
let mut agent_service_mock = MockAgentService::new();
|
||||||
|
agent_service_mock.expect_get().returning(|_| Ok(None));
|
||||||
|
let server = TestServer::new(make_state(agent_service_mock).await);
|
||||||
|
let id = uuid::Uuid::new_v4();
|
||||||
|
let response = server.get(&format!("/agents/{}", id)).await;
|
||||||
|
assert_eq!(response.status_code(), 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_agent_found() {
|
||||||
|
let id = uuid::Uuid::new_v4();
|
||||||
|
let mut agent_service_mock = MockAgentService::new();
|
||||||
|
agent_service_mock
|
||||||
|
.expect_get()
|
||||||
|
.returning(move |_| Ok(Some(make_record(id))));
|
||||||
|
let server = TestServer::new(make_state(agent_service_mock).await);
|
||||||
|
let expected = format!(
|
||||||
|
r#"{{"agent":{{"id":"{}","name":"agent1","state":"Active","deployment_mode":null,"ip_address":"127.0.0.1","last_seen_at":null,"labels":null,"number_of_routes":0,"created_at":"created","updated_at":"updated","is_disabled":false}}}}"#,
|
||||||
|
id
|
||||||
|
);
|
||||||
|
let response = server.get(&format!("/agents/{}", id)).await;
|
||||||
|
assert_eq!(response.status_code(), 200);
|
||||||
|
assert_eq!(response.text(), expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_create_agent() {
|
||||||
|
let id = uuid::Uuid::new_v4();
|
||||||
|
let mut agent_service_mock = MockAgentService::new();
|
||||||
|
agent_service_mock.expect_create().returning(move |rec| {
|
||||||
|
Ok(AgentRecord {
|
||||||
|
id,
|
||||||
|
name: rec.name.clone(),
|
||||||
|
ip_address: rec.ip_address.clone(),
|
||||||
|
state: State::Active,
|
||||||
|
deployment_mode: None,
|
||||||
|
last_seen_at: None,
|
||||||
|
labels: None,
|
||||||
|
created_at: "created".to_string(),
|
||||||
|
updated_at: "updated".to_string(),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
let server = TestServer::new(make_state(agent_service_mock).await);
|
||||||
|
let response = server
|
||||||
|
.post("/agents")
|
||||||
|
.json(&serde_json::json!({"name": "new-agent", "ip_address": "10.0.0.1"}))
|
||||||
|
.await;
|
||||||
|
assert_eq!(response.status_code(), 201);
|
||||||
|
let body: serde_json::Value = serde_json::from_str(&response.text()).unwrap();
|
||||||
|
assert_eq!(body["agent"]["name"], "new-agent");
|
||||||
|
assert_eq!(body["agent"]["ip_address"], "10.0.0.1");
|
||||||
|
assert_eq!(body["agent"]["id"], id.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_create_agent_empty_name() {
|
||||||
|
let agent_service_mock = MockAgentService::new();
|
||||||
|
let server = TestServer::new(make_state(agent_service_mock).await);
|
||||||
|
let response = server
|
||||||
|
.post("/agents")
|
||||||
|
.json(&serde_json::json!({"name": ""}))
|
||||||
|
.await;
|
||||||
|
assert_eq!(response.status_code(), 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_create_agent_missing_name() {
|
||||||
|
let agent_service_mock = MockAgentService::new();
|
||||||
|
let server = TestServer::new(make_state(agent_service_mock).await);
|
||||||
|
let response = server.post("/agents").json(&serde_json::json!({})).await;
|
||||||
|
assert_eq!(response.status_code(), 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_update_agent() {
|
||||||
|
let id = uuid::Uuid::new_v4();
|
||||||
|
let mut agent_service_mock = MockAgentService::new();
|
||||||
|
agent_service_mock.expect_update().returning(move |_, _| {
|
||||||
|
Ok(Some(AgentRecord {
|
||||||
|
id,
|
||||||
|
name: "updated-agent".to_string(),
|
||||||
|
ip_address: Some("10.0.0.2".to_string()),
|
||||||
|
state: State::Inactive,
|
||||||
|
deployment_mode: None,
|
||||||
|
last_seen_at: None,
|
||||||
|
labels: None,
|
||||||
|
created_at: "created".to_string(),
|
||||||
|
updated_at: "updated".to_string(),
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
let server = TestServer::new(make_state(agent_service_mock).await);
|
||||||
|
let response = server
|
||||||
|
.put(&format!("/agents/{}", id))
|
||||||
|
.json(&serde_json::json!({"name": "updated-agent", "state": "Inactive"}))
|
||||||
|
.await;
|
||||||
|
assert_eq!(response.status_code(), 200);
|
||||||
|
let body: serde_json::Value = serde_json::from_str(&response.text()).unwrap();
|
||||||
|
assert_eq!(body["agent"]["name"], "updated-agent");
|
||||||
|
assert_eq!(body["agent"]["state"], "Inactive");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_update_agent_not_found() {
|
||||||
|
let mut agent_service_mock = MockAgentService::new();
|
||||||
|
agent_service_mock
|
||||||
|
.expect_update()
|
||||||
|
.returning(|_, _| Ok(None));
|
||||||
|
let server = TestServer::new(make_state(agent_service_mock).await);
|
||||||
|
let id = uuid::Uuid::new_v4();
|
||||||
|
let response = server
|
||||||
|
.put(&format!("/agents/{}", id))
|
||||||
|
.json(&serde_json::json!({"name": "updated-agent"}))
|
||||||
|
.await;
|
||||||
|
assert_eq!(response.status_code(), 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_delete_agent() {
|
||||||
|
let mut agent_service_mock = MockAgentService::new();
|
||||||
|
agent_service_mock.expect_delete().returning(|_| Ok(true));
|
||||||
|
let server = TestServer::new(make_state(agent_service_mock).await);
|
||||||
|
let id = uuid::Uuid::new_v4();
|
||||||
|
let response = server.delete(&format!("/agents/{}", id)).await;
|
||||||
|
assert_eq!(response.status_code(), 204);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_delete_agent_not_found() {
|
||||||
|
let mut agent_service_mock = MockAgentService::new();
|
||||||
|
agent_service_mock.expect_delete().returning(|_| Ok(false));
|
||||||
|
let server = TestServer::new(make_state(agent_service_mock).await);
|
||||||
|
let id = uuid::Uuid::new_v4();
|
||||||
|
let response = server.delete(&format!("/agents/{}", id)).await;
|
||||||
|
assert_eq!(response.status_code(), 404);
|
||||||
|
}
|
||||||
|
}
|
||||||
62
apps/nxmesh-master/src/routes/api/agents/update_agent.rs
Normal file
62
apps/nxmesh-master/src/routes/api/agents/update_agent.rs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
routes::api::{agents::dto::AgentInfo, error::AppError},
|
||||||
|
service::agent::{AgentService, State as AgentState, UpdateAgentRecord},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct UpdateAgentRequest {
|
||||||
|
#[serde(default)]
|
||||||
|
pub name: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub ip_address: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub state: Option<AgentState>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub deployment_mode: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub labels: Option<serde_json::Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn update_agent_handler(
|
||||||
|
State(agent_service): State<Arc<dyn AgentService>>,
|
||||||
|
Path(id): Path<uuid::Uuid>,
|
||||||
|
Json(body): Json<UpdateAgentRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
if let Some(ref name) = body.name {
|
||||||
|
if name.trim().is_empty() {
|
||||||
|
return Err(AppError::BadRequest("name must not be empty".to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let rec = UpdateAgentRecord {
|
||||||
|
name: body.name,
|
||||||
|
ip_address: body.ip_address,
|
||||||
|
state: body.state,
|
||||||
|
deployment_mode: body.deployment_mode,
|
||||||
|
labels: body.labels,
|
||||||
|
};
|
||||||
|
|
||||||
|
let agent = agent_service.update(id, &rec).await.map_err(|err| {
|
||||||
|
error!("Failed to update agent: {}", err);
|
||||||
|
AppError::InternalServerError
|
||||||
|
})?;
|
||||||
|
|
||||||
|
match agent {
|
||||||
|
Some(agent) => Ok((
|
||||||
|
StatusCode::OK,
|
||||||
|
Json(serde_json::json!({"agent": AgentInfo::from(agent)})),
|
||||||
|
)),
|
||||||
|
None => Err(AppError::NotFound),
|
||||||
|
}
|
||||||
|
}
|
||||||
55
apps/nxmesh-master/src/routes/api/error.rs
Normal file
55
apps/nxmesh-master/src/routes/api/error.rs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
use axum::{
|
||||||
|
http::StatusCode,
|
||||||
|
response::{IntoResponse, Response},
|
||||||
|
};
|
||||||
|
use serde_json::json;
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
|
use crate::service::proxy::types::ProxyServiceError;
|
||||||
|
|
||||||
|
impl From<ProxyServiceError> for AppError {
|
||||||
|
fn from(e: ProxyServiceError) -> Self {
|
||||||
|
match e {
|
||||||
|
ProxyServiceError::ConfigNotFound => AppError::NotFound,
|
||||||
|
ProxyServiceError::InvalidConfig(msg) => AppError::BadRequest(msg),
|
||||||
|
ProxyServiceError::RendererNotFound => AppError::InternalServerError,
|
||||||
|
ProxyServiceError::DatabaseError(_) => AppError::InternalServerError,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum AppError {
|
||||||
|
NotFound,
|
||||||
|
InternalServerError,
|
||||||
|
BadRequest(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_error_response(status: StatusCode, code: &str, msg: &str) -> Response {
|
||||||
|
let body = json!({"code": code, "message": msg});
|
||||||
|
Response::builder()
|
||||||
|
.status(status)
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.body(serde_json::to_string(&body).unwrap_or_default().into())
|
||||||
|
.unwrap_or_else(|err| {
|
||||||
|
error!("Failed to build error response: {}", err);
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR.into_response()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoResponse for AppError {
|
||||||
|
fn into_response(self) -> Response {
|
||||||
|
match self {
|
||||||
|
AppError::BadRequest(msg) => {
|
||||||
|
make_error_response(StatusCode::BAD_REQUEST, "BAD_REQUEST", &msg)
|
||||||
|
}
|
||||||
|
AppError::NotFound => {
|
||||||
|
make_error_response(StatusCode::NOT_FOUND, "NOT_FOUND", "Not Found")
|
||||||
|
}
|
||||||
|
AppError::InternalServerError => make_error_response(
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
"INTERNAL_ERROR",
|
||||||
|
"Internal Server Error",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
148
apps/nxmesh-master/src/routes/api/mod.rs
Normal file
148
apps/nxmesh-master/src/routes/api/mod.rs
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{Router, extract::FromRef};
|
||||||
|
|
||||||
|
use crate::service::agent::AgentService;
|
||||||
|
use crate::service::proxy::ProxyServiceTrait;
|
||||||
|
use crate::service::proxy::access_rule::AccessRuleService;
|
||||||
|
use crate::service::proxy::cache_zone::CacheZoneService;
|
||||||
|
use crate::service::proxy::config_inheritance::ConfigInheritanceService;
|
||||||
|
use crate::service::proxy::limit_rule::LimitRuleService;
|
||||||
|
use crate::service::proxy::limit_zone::LimitZoneService;
|
||||||
|
use crate::service::proxy::location_block::LocationBlockService;
|
||||||
|
use crate::service::proxy::log_setting::LogSettingService;
|
||||||
|
use crate::service::proxy::proxy_setting::ProxySettingService;
|
||||||
|
use crate::service::proxy::rewrite_rule::RewriteRuleService;
|
||||||
|
use crate::service::proxy::server_block::ServerBlockService;
|
||||||
|
use crate::service::proxy::ssl_certificate::SslCertificateService;
|
||||||
|
use crate::service::proxy::upstream::UpstreamService;
|
||||||
|
|
||||||
|
mod agents;
|
||||||
|
pub mod error;
|
||||||
|
pub use error::AppError;
|
||||||
|
pub(crate) mod proxy;
|
||||||
|
|
||||||
|
pub struct ApiState {
|
||||||
|
pub agent_service: Arc<dyn AgentService>,
|
||||||
|
pub proxy_service: Arc<dyn ProxyServiceTrait>,
|
||||||
|
pub server_block_service: Arc<dyn ServerBlockService>,
|
||||||
|
pub upstream_service: Arc<dyn UpstreamService>,
|
||||||
|
pub location_block_service: Arc<dyn LocationBlockService>,
|
||||||
|
pub access_rule_service: Arc<dyn AccessRuleService>,
|
||||||
|
pub cache_zone_service: Arc<dyn CacheZoneService>,
|
||||||
|
pub limit_rule_service: Arc<dyn LimitRuleService>,
|
||||||
|
pub limit_zone_service: Arc<dyn LimitZoneService>,
|
||||||
|
pub log_setting_service: Arc<dyn LogSettingService>,
|
||||||
|
pub proxy_setting_service: Arc<dyn ProxySettingService>,
|
||||||
|
pub rewrite_rule_service: Arc<dyn RewriteRuleService>,
|
||||||
|
pub ssl_certificate_service: Arc<dyn SslCertificateService>,
|
||||||
|
pub config_inheritance_service: Arc<dyn ConfigInheritanceService>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct LocalApiState(pub Arc<ApiState>);
|
||||||
|
|
||||||
|
impl From<ApiState> for LocalApiState {
|
||||||
|
fn from(api_state: ApiState) -> Self {
|
||||||
|
LocalApiState(Arc::new(api_state))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Arc<ApiState>> for LocalApiState {
|
||||||
|
fn from(api_state: Arc<ApiState>) -> Self {
|
||||||
|
LocalApiState(api_state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type ApiRouter = Router<LocalApiState>;
|
||||||
|
|
||||||
|
impl FromRef<LocalApiState> for Arc<dyn AgentService> {
|
||||||
|
fn from_ref(api_state: &LocalApiState) -> Arc<dyn AgentService> {
|
||||||
|
api_state.0.agent_service.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRef<LocalApiState> for Arc<dyn ProxyServiceTrait> {
|
||||||
|
fn from_ref(api_state: &LocalApiState) -> Arc<dyn ProxyServiceTrait> {
|
||||||
|
api_state.0.proxy_service.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRef<LocalApiState> for Arc<dyn ServerBlockService> {
|
||||||
|
fn from_ref(api_state: &LocalApiState) -> Arc<dyn ServerBlockService> {
|
||||||
|
api_state.0.server_block_service.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRef<LocalApiState> for Arc<dyn UpstreamService> {
|
||||||
|
fn from_ref(api_state: &LocalApiState) -> Arc<dyn UpstreamService> {
|
||||||
|
api_state.0.upstream_service.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRef<LocalApiState> for Arc<dyn LocationBlockService> {
|
||||||
|
fn from_ref(api_state: &LocalApiState) -> Arc<dyn LocationBlockService> {
|
||||||
|
api_state.0.location_block_service.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRef<LocalApiState> for Arc<dyn AccessRuleService> {
|
||||||
|
fn from_ref(api_state: &LocalApiState) -> Arc<dyn AccessRuleService> {
|
||||||
|
api_state.0.access_rule_service.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRef<LocalApiState> for Arc<dyn CacheZoneService> {
|
||||||
|
fn from_ref(api_state: &LocalApiState) -> Arc<dyn CacheZoneService> {
|
||||||
|
api_state.0.cache_zone_service.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRef<LocalApiState> for Arc<dyn LimitRuleService> {
|
||||||
|
fn from_ref(api_state: &LocalApiState) -> Arc<dyn LimitRuleService> {
|
||||||
|
api_state.0.limit_rule_service.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRef<LocalApiState> for Arc<dyn LimitZoneService> {
|
||||||
|
fn from_ref(api_state: &LocalApiState) -> Arc<dyn LimitZoneService> {
|
||||||
|
api_state.0.limit_zone_service.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRef<LocalApiState> for Arc<dyn LogSettingService> {
|
||||||
|
fn from_ref(api_state: &LocalApiState) -> Arc<dyn LogSettingService> {
|
||||||
|
api_state.0.log_setting_service.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRef<LocalApiState> for Arc<dyn ProxySettingService> {
|
||||||
|
fn from_ref(api_state: &LocalApiState) -> Arc<dyn ProxySettingService> {
|
||||||
|
api_state.0.proxy_setting_service.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRef<LocalApiState> for Arc<dyn RewriteRuleService> {
|
||||||
|
fn from_ref(api_state: &LocalApiState) -> Arc<dyn RewriteRuleService> {
|
||||||
|
api_state.0.rewrite_rule_service.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRef<LocalApiState> for Arc<dyn SslCertificateService> {
|
||||||
|
fn from_ref(api_state: &LocalApiState) -> Arc<dyn SslCertificateService> {
|
||||||
|
api_state.0.ssl_certificate_service.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRef<LocalApiState> for Arc<dyn ConfigInheritanceService> {
|
||||||
|
fn from_ref(api_state: &LocalApiState) -> Arc<dyn ConfigInheritanceService> {
|
||||||
|
api_state.0.config_inheritance_service.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_router(state: impl Into<LocalApiState>) -> Router {
|
||||||
|
ApiRouter::new()
|
||||||
|
.nest("/agents", agents::get_router().await)
|
||||||
|
.nest("/proxy", proxy::get_router().await)
|
||||||
|
.with_state(state.into())
|
||||||
|
}
|
||||||
164
apps/nxmesh-master/src/routes/api/proxy/access_rules.rs
Normal file
164
apps/nxmesh-master/src/routes/api/proxy/access_rules.rs
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::routes::api::{AppError, ApiRouter};
|
||||||
|
use crate::service::proxy::access_rule::{
|
||||||
|
AccessRuleService, CreateAccessRuleParams, UpdateAccessRuleParams,
|
||||||
|
};
|
||||||
|
use crate::service::proxy::types::AccessRuleConfig;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct AccessRuleResponse {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub r#type: String,
|
||||||
|
pub ip_cidr: String,
|
||||||
|
pub description: Option<String>,
|
||||||
|
pub priority: i32,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AccessRuleConfig> for AccessRuleResponse {
|
||||||
|
fn from(c: AccessRuleConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
id: c.id,
|
||||||
|
r#type: c.r#type,
|
||||||
|
ip_cidr: c.ip_cidr,
|
||||||
|
description: c.description,
|
||||||
|
priority: c.priority,
|
||||||
|
override_of_id: c.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct CreateAccessRuleRequest {
|
||||||
|
pub server_id: Option<Uuid>,
|
||||||
|
pub location_id: Option<Uuid>,
|
||||||
|
pub r#type: String,
|
||||||
|
pub ip_cidr: String,
|
||||||
|
pub description: Option<String>,
|
||||||
|
pub priority: i32,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CreateAccessRuleRequest> for CreateAccessRuleParams {
|
||||||
|
fn from(r: CreateAccessRuleRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
server_id: r.server_id,
|
||||||
|
location_id: r.location_id,
|
||||||
|
r#type: r.r#type,
|
||||||
|
ip_cidr: r.ip_cidr,
|
||||||
|
description: r.description,
|
||||||
|
priority: r.priority,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct UpdateAccessRuleRequest {
|
||||||
|
pub server_id: Option<Option<Uuid>>,
|
||||||
|
pub location_id: Option<Option<Uuid>>,
|
||||||
|
pub r#type: Option<String>,
|
||||||
|
pub ip_cidr: Option<String>,
|
||||||
|
pub description: Option<Option<String>>,
|
||||||
|
pub priority: Option<i32>,
|
||||||
|
pub override_of_id: Option<Option<Uuid>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UpdateAccessRuleRequest> for UpdateAccessRuleParams {
|
||||||
|
fn from(r: UpdateAccessRuleRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
server_id: r.server_id,
|
||||||
|
location_id: r.location_id,
|
||||||
|
r#type: r.r#type,
|
||||||
|
ip_cidr: r.ip_cidr,
|
||||||
|
description: r.description,
|
||||||
|
priority: r.priority,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_access_rules_by_server(
|
||||||
|
State(svc): State<Arc<dyn AccessRuleService>>,
|
||||||
|
Path(server_id): Path<Uuid>,
|
||||||
|
) -> Result<Json<Vec<AccessRuleResponse>>, AppError> {
|
||||||
|
let rules = svc.list_by_server(server_id).await?;
|
||||||
|
Ok(Json(rules.into_iter().map(Into::into).collect()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_access_rules_by_location(
|
||||||
|
State(svc): State<Arc<dyn AccessRuleService>>,
|
||||||
|
Path(location_id): Path<Uuid>,
|
||||||
|
) -> Result<Json<Vec<AccessRuleResponse>>, AppError> {
|
||||||
|
let rules = svc.list_by_location(location_id).await?;
|
||||||
|
Ok(Json(rules.into_iter().map(Into::into).collect()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_access_rule(
|
||||||
|
State(svc): State<Arc<dyn AccessRuleService>>,
|
||||||
|
Json(body): Json<CreateAccessRuleRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let rule = svc.create(body.into()).await?;
|
||||||
|
Ok((StatusCode::CREATED, Json(AccessRuleResponse::from(rule))))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_access_rule(
|
||||||
|
State(svc): State<Arc<dyn AccessRuleService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<Json<AccessRuleResponse>, AppError> {
|
||||||
|
let rule = svc.get(id).await?;
|
||||||
|
Ok(Json(rule.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_access_rule(
|
||||||
|
State(svc): State<Arc<dyn AccessRuleService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
Json(body): Json<UpdateAccessRuleRequest>,
|
||||||
|
) -> Result<Json<AccessRuleResponse>, AppError> {
|
||||||
|
let rule = svc.update(id, body.into()).await?;
|
||||||
|
Ok(Json(rule.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_access_rule(
|
||||||
|
State(svc): State<Arc<dyn AccessRuleService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let deleted = svc.delete(id).await?;
|
||||||
|
if deleted {
|
||||||
|
Ok((StatusCode::NO_CONTENT,))
|
||||||
|
} else {
|
||||||
|
Err(AppError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn routes() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.route(
|
||||||
|
"/server-blocks/{server_id}/access-rules",
|
||||||
|
axum::routing::get(list_access_rules_by_server),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/locations/{location_id}/access-rules",
|
||||||
|
axum::routing::get(list_access_rules_by_location),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/access-rules",
|
||||||
|
axum::routing::post(create_access_rule),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/access-rules/{id}",
|
||||||
|
axum::routing::get(get_access_rule)
|
||||||
|
.put(update_access_rule)
|
||||||
|
.delete(delete_access_rule),
|
||||||
|
)
|
||||||
|
}
|
||||||
82
apps/nxmesh-master/src/routes/api/proxy/agents.rs
Normal file
82
apps/nxmesh-master/src/routes/api/proxy/agents.rs
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::routes::api::{AppError, ApiRouter};
|
||||||
|
use crate::service::proxy::{ProxyServiceTrait, types::AgentConfigBinding};
|
||||||
|
|
||||||
|
use super::configs::ProxyConfigResponse;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct AgentConfigResponse {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub agent_id: Option<Uuid>,
|
||||||
|
pub group_id: Option<Uuid>,
|
||||||
|
pub config_id: Uuid,
|
||||||
|
pub is_active: bool,
|
||||||
|
pub applied_at: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AgentConfigBinding> for AgentConfigResponse {
|
||||||
|
fn from(b: AgentConfigBinding) -> Self {
|
||||||
|
Self {
|
||||||
|
id: b.id,
|
||||||
|
agent_id: b.agent_id,
|
||||||
|
group_id: b.group_id,
|
||||||
|
config_id: b.config_id,
|
||||||
|
is_active: b.is_active,
|
||||||
|
applied_at: b.applied_at.to_rfc3339(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct BindAgentRequest {
|
||||||
|
pub config_id: Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_active_agent_config(
|
||||||
|
State(svc): State<Arc<dyn ProxyServiceTrait>>,
|
||||||
|
Path(agent_id): Path<Uuid>,
|
||||||
|
) -> Result<Json<Option<ProxyConfigResponse>>, AppError> {
|
||||||
|
let config = svc.get_active_agent_config(agent_id).await?;
|
||||||
|
Ok(Json(config.map(Into::into)))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn bind_agent(
|
||||||
|
State(svc): State<Arc<dyn ProxyServiceTrait>>,
|
||||||
|
Path(agent_id): Path<Uuid>,
|
||||||
|
Json(body): Json<BindAgentRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let binding = svc.bind_agent(agent_id, body.config_id).await?;
|
||||||
|
Ok((StatusCode::CREATED, Json(AgentConfigResponse::from(binding))))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn unbind_agent(
|
||||||
|
State(svc): State<Arc<dyn ProxyServiceTrait>>,
|
||||||
|
Path(agent_id): Path<Uuid>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let deleted = svc.unbind_agent(agent_id).await?;
|
||||||
|
if deleted {
|
||||||
|
Ok((StatusCode::NO_CONTENT,))
|
||||||
|
} else {
|
||||||
|
Err(AppError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn routes() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.route(
|
||||||
|
"/agents/{agent_id}/config",
|
||||||
|
axum::routing::get(get_active_agent_config)
|
||||||
|
.post(bind_agent)
|
||||||
|
.delete(unbind_agent),
|
||||||
|
)
|
||||||
|
}
|
||||||
133
apps/nxmesh-master/src/routes/api/proxy/cache_zones.rs
Normal file
133
apps/nxmesh-master/src/routes/api/proxy/cache_zones.rs
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::routes::api::{AppError, ApiRouter};
|
||||||
|
use crate::service::proxy::cache_zone::{
|
||||||
|
CacheZoneService, CreateCacheZoneParams, UpdateCacheZoneParams,
|
||||||
|
};
|
||||||
|
use crate::service::proxy::types::CacheZoneConfig;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct CacheZoneResponse {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
pub path: String,
|
||||||
|
pub size: String,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CacheZoneConfig> for CacheZoneResponse {
|
||||||
|
fn from(c: CacheZoneConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
id: c.id,
|
||||||
|
name: c.name,
|
||||||
|
path: c.path,
|
||||||
|
size: c.size,
|
||||||
|
override_of_id: c.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct CreateCacheZoneRequest {
|
||||||
|
pub name: String,
|
||||||
|
pub path: String,
|
||||||
|
pub size_limit: String,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CreateCacheZoneRequest> for CreateCacheZoneParams {
|
||||||
|
fn from(r: CreateCacheZoneRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
name: r.name,
|
||||||
|
path: r.path,
|
||||||
|
size_limit: r.size_limit,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct UpdateCacheZoneRequest {
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub path: Option<String>,
|
||||||
|
pub size_limit: Option<String>,
|
||||||
|
pub override_of_id: Option<Option<Uuid>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UpdateCacheZoneRequest> for UpdateCacheZoneParams {
|
||||||
|
fn from(r: UpdateCacheZoneRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
name: r.name,
|
||||||
|
path: r.path,
|
||||||
|
size_limit: r.size_limit,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_cache_zones(
|
||||||
|
State(svc): State<Arc<dyn CacheZoneService>>,
|
||||||
|
) -> Result<Json<Vec<CacheZoneResponse>>, AppError> {
|
||||||
|
let zones = svc.list().await?;
|
||||||
|
Ok(Json(zones.into_iter().map(Into::into).collect()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_cache_zone(
|
||||||
|
State(svc): State<Arc<dyn CacheZoneService>>,
|
||||||
|
Json(body): Json<CreateCacheZoneRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let zone = svc.create(body.into()).await?;
|
||||||
|
Ok((StatusCode::CREATED, Json(CacheZoneResponse::from(zone))))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_cache_zone(
|
||||||
|
State(svc): State<Arc<dyn CacheZoneService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<Json<CacheZoneResponse>, AppError> {
|
||||||
|
let zone = svc.get(id).await?;
|
||||||
|
Ok(Json(zone.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_cache_zone(
|
||||||
|
State(svc): State<Arc<dyn CacheZoneService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
Json(body): Json<UpdateCacheZoneRequest>,
|
||||||
|
) -> Result<Json<CacheZoneResponse>, AppError> {
|
||||||
|
let zone = svc.update(id, body.into()).await?;
|
||||||
|
Ok(Json(zone.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_cache_zone(
|
||||||
|
State(svc): State<Arc<dyn CacheZoneService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let deleted = svc.delete(id).await?;
|
||||||
|
if deleted {
|
||||||
|
Ok((StatusCode::NO_CONTENT,))
|
||||||
|
} else {
|
||||||
|
Err(AppError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn routes() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.route(
|
||||||
|
"/cache-zones",
|
||||||
|
axum::routing::get(list_cache_zones).post(create_cache_zone),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/cache-zones/{id}",
|
||||||
|
axum::routing::get(get_cache_zone)
|
||||||
|
.put(update_cache_zone)
|
||||||
|
.delete(delete_cache_zone),
|
||||||
|
)
|
||||||
|
}
|
||||||
107
apps/nxmesh-master/src/routes/api/proxy/config_inheritance.rs
Normal file
107
apps/nxmesh-master/src/routes/api/proxy/config_inheritance.rs
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::routes::api::{AppError, ApiRouter};
|
||||||
|
use crate::service::proxy::config_inheritance::{
|
||||||
|
AddInheritanceParams, ConfigInheritanceRecord, ConfigInheritanceService,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct AddParentRequest {
|
||||||
|
pub parent_config_id: Uuid,
|
||||||
|
#[serde(default)]
|
||||||
|
pub priority: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct InheritanceRecordResponse {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub child_config_id: Uuid,
|
||||||
|
pub parent_config_id: Uuid,
|
||||||
|
pub priority: Option<i32>,
|
||||||
|
pub applied_at: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ConfigInheritanceRecord> for InheritanceRecordResponse {
|
||||||
|
fn from(r: ConfigInheritanceRecord) -> Self {
|
||||||
|
Self {
|
||||||
|
id: r.id,
|
||||||
|
child_config_id: r.child_config_id,
|
||||||
|
parent_config_id: r.parent_config_id,
|
||||||
|
priority: r.priority,
|
||||||
|
applied_at: r.applied_at.and_utc().to_rfc3339(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_parents(
|
||||||
|
State(svc): State<Arc<dyn ConfigInheritanceService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<Json<serde_json::Value>, AppError> {
|
||||||
|
let records = svc.list_parents(id).await?;
|
||||||
|
let response: Vec<InheritanceRecordResponse> = records.into_iter().map(Into::into).collect();
|
||||||
|
Ok(Json(serde_json::json!(response)))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn add_parent(
|
||||||
|
State(svc): State<Arc<dyn ConfigInheritanceService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
Json(body): Json<AddParentRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let record = svc
|
||||||
|
.add(AddInheritanceParams {
|
||||||
|
child_config_id: id,
|
||||||
|
parent_config_id: body.parent_config_id,
|
||||||
|
priority: body.priority,
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
Ok((
|
||||||
|
StatusCode::CREATED,
|
||||||
|
Json(InheritanceRecordResponse::from(record)),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn remove_parent(
|
||||||
|
State(svc): State<Arc<dyn ConfigInheritanceService>>,
|
||||||
|
Path((id, parent_id)): Path<(Uuid, Uuid)>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let deleted = svc.remove(id, parent_id).await?;
|
||||||
|
if deleted {
|
||||||
|
Ok((StatusCode::NO_CONTENT,))
|
||||||
|
} else {
|
||||||
|
Err(AppError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_children(
|
||||||
|
State(svc): State<Arc<dyn ConfigInheritanceService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<Json<serde_json::Value>, AppError> {
|
||||||
|
let records = svc.list_children(id).await?;
|
||||||
|
let response: Vec<InheritanceRecordResponse> = records.into_iter().map(Into::into).collect();
|
||||||
|
Ok(Json(serde_json::json!(response)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn routes() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.route(
|
||||||
|
"/configs/{id}/parents",
|
||||||
|
axum::routing::get(list_parents).post(add_parent),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/configs/{id}/parents/{parent_id}",
|
||||||
|
axum::routing::delete(remove_parent),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/configs/{id}/children",
|
||||||
|
axum::routing::get(list_children),
|
||||||
|
)
|
||||||
|
}
|
||||||
147
apps/nxmesh-master/src/routes/api/proxy/configs.rs
Normal file
147
apps/nxmesh-master/src/routes/api/proxy/configs.rs
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::routes::api::{AppError, ApiRouter};
|
||||||
|
use crate::service::proxy::{
|
||||||
|
ProxyServiceTrait,
|
||||||
|
types::{CreateProxyConfigParams, ProxyConfigSummary, UpdateProxyConfigParams},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct ProxyConfigResponse {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
pub description: Option<String>,
|
||||||
|
pub is_template: bool,
|
||||||
|
pub created_at: String,
|
||||||
|
pub updated_at: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ProxyConfigSummary> for ProxyConfigResponse {
|
||||||
|
fn from(s: ProxyConfigSummary) -> Self {
|
||||||
|
Self {
|
||||||
|
id: s.id,
|
||||||
|
name: s.name,
|
||||||
|
description: s.description,
|
||||||
|
is_template: s.is_template,
|
||||||
|
created_at: s.created_at.to_rfc3339(),
|
||||||
|
updated_at: s.updated_at.to_rfc3339(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct CreateConfigRequest {
|
||||||
|
pub name: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub description: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub is_template: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct UpdateConfigRequest {
|
||||||
|
#[serde(default)]
|
||||||
|
pub name: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub description: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub is_template: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct ListConfigsResponse {
|
||||||
|
pub configs: Vec<ProxyConfigResponse>,
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_configs(
|
||||||
|
State(svc): State<Arc<dyn ProxyServiceTrait>>,
|
||||||
|
) -> Result<Json<ListConfigsResponse>, AppError> {
|
||||||
|
let configs = svc.list_configs().await?;
|
||||||
|
Ok(Json(ListConfigsResponse {
|
||||||
|
configs: configs.into_iter().map(Into::into).collect(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_config(
|
||||||
|
State(svc): State<Arc<dyn ProxyServiceTrait>>,
|
||||||
|
Json(body): Json<CreateConfigRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
if body.name.trim().is_empty() {
|
||||||
|
return Err(AppError::BadRequest("name is required".to_string()));
|
||||||
|
}
|
||||||
|
let config = svc
|
||||||
|
.create_config(CreateProxyConfigParams {
|
||||||
|
name: body.name,
|
||||||
|
description: body.description,
|
||||||
|
is_template: body.is_template,
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
Ok((StatusCode::CREATED, Json(ProxyConfigResponse::from(config))))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_config(
|
||||||
|
State(svc): State<Arc<dyn ProxyServiceTrait>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<Json<serde_json::Value>, AppError> {
|
||||||
|
let config = svc.get_proxy_config(id).await?;
|
||||||
|
Ok(Json(serde_json::to_value(&config.id).unwrap_or_default()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_config(
|
||||||
|
State(svc): State<Arc<dyn ProxyServiceTrait>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
Json(body): Json<UpdateConfigRequest>,
|
||||||
|
) -> Result<Json<ProxyConfigResponse>, AppError> {
|
||||||
|
let config = svc
|
||||||
|
.update_config(
|
||||||
|
id,
|
||||||
|
UpdateProxyConfigParams {
|
||||||
|
name: body.name,
|
||||||
|
description: body.description,
|
||||||
|
is_template: body.is_template,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(Json(config.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_config(
|
||||||
|
State(svc): State<Arc<dyn ProxyServiceTrait>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let deleted = svc.delete_config(id).await?;
|
||||||
|
if deleted {
|
||||||
|
Ok((StatusCode::NO_CONTENT,))
|
||||||
|
} else {
|
||||||
|
Err(AppError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn render_config(
|
||||||
|
State(svc): State<Arc<dyn ProxyServiceTrait>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<String, AppError> {
|
||||||
|
let output = svc.render_config(id).await?;
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn routes() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.route("/configs", axum::routing::get(list_configs).post(create_config))
|
||||||
|
.route(
|
||||||
|
"/configs/{id}",
|
||||||
|
axum::routing::get(get_config)
|
||||||
|
.put(update_config)
|
||||||
|
.delete(delete_config),
|
||||||
|
)
|
||||||
|
.route("/configs/{id}/render", axum::routing::get(render_config))
|
||||||
|
}
|
||||||
144
apps/nxmesh-master/src/routes/api/proxy/limit_rules.rs
Normal file
144
apps/nxmesh-master/src/routes/api/proxy/limit_rules.rs
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::routes::api::{AppError, ApiRouter};
|
||||||
|
use crate::service::proxy::limit_rule::{
|
||||||
|
CreateLimitRuleParams, LimitRuleService, UpdateLimitRuleParams,
|
||||||
|
};
|
||||||
|
use crate::service::proxy::types::LimitRuleConfig;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct LimitRuleResponse {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub location_id: Uuid,
|
||||||
|
pub zone_id: Uuid,
|
||||||
|
pub burst: Option<i32>,
|
||||||
|
pub nodelay: Option<bool>,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LimitRuleConfig> for LimitRuleResponse {
|
||||||
|
fn from(c: LimitRuleConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
id: c.id,
|
||||||
|
location_id: c.location_id,
|
||||||
|
zone_id: c.zone_id,
|
||||||
|
burst: c.burst,
|
||||||
|
nodelay: c.nodelay,
|
||||||
|
override_of_id: c.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct CreateLimitRuleRequest {
|
||||||
|
pub location_id: Uuid,
|
||||||
|
pub zone_id: Uuid,
|
||||||
|
pub burst: Option<i32>,
|
||||||
|
pub nodelay: Option<bool>,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CreateLimitRuleRequest> for CreateLimitRuleParams {
|
||||||
|
fn from(r: CreateLimitRuleRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
location_id: r.location_id,
|
||||||
|
zone_id: r.zone_id,
|
||||||
|
burst: r.burst,
|
||||||
|
nodelay: r.nodelay,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct UpdateLimitRuleRequest {
|
||||||
|
pub location_id: Option<Uuid>,
|
||||||
|
pub zone_id: Option<Uuid>,
|
||||||
|
pub burst: Option<Option<i32>>,
|
||||||
|
pub nodelay: Option<Option<bool>>,
|
||||||
|
pub override_of_id: Option<Option<Uuid>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UpdateLimitRuleRequest> for UpdateLimitRuleParams {
|
||||||
|
fn from(r: UpdateLimitRuleRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
location_id: r.location_id,
|
||||||
|
zone_id: r.zone_id,
|
||||||
|
burst: r.burst,
|
||||||
|
nodelay: r.nodelay,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_limit_rules_by_location(
|
||||||
|
State(svc): State<Arc<dyn LimitRuleService>>,
|
||||||
|
Path(location_id): Path<Uuid>,
|
||||||
|
) -> Result<Json<Vec<LimitRuleResponse>>, AppError> {
|
||||||
|
let rules = svc.list_by_location(location_id).await?;
|
||||||
|
Ok(Json(rules.into_iter().map(Into::into).collect()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_limit_rule(
|
||||||
|
State(svc): State<Arc<dyn LimitRuleService>>,
|
||||||
|
Json(body): Json<CreateLimitRuleRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let rule = svc.create(body.into()).await?;
|
||||||
|
Ok((StatusCode::CREATED, Json(LimitRuleResponse::from(rule))))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_limit_rule(
|
||||||
|
State(svc): State<Arc<dyn LimitRuleService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<Json<LimitRuleResponse>, AppError> {
|
||||||
|
let rule = svc.get(id).await?;
|
||||||
|
Ok(Json(rule.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_limit_rule(
|
||||||
|
State(svc): State<Arc<dyn LimitRuleService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
Json(body): Json<UpdateLimitRuleRequest>,
|
||||||
|
) -> Result<Json<LimitRuleResponse>, AppError> {
|
||||||
|
let rule = svc.update(id, body.into()).await?;
|
||||||
|
Ok(Json(rule.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_limit_rule(
|
||||||
|
State(svc): State<Arc<dyn LimitRuleService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let deleted = svc.delete(id).await?;
|
||||||
|
if deleted {
|
||||||
|
Ok((StatusCode::NO_CONTENT,))
|
||||||
|
} else {
|
||||||
|
Err(AppError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn routes() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.route(
|
||||||
|
"/locations/{location_id}/limit-rules",
|
||||||
|
axum::routing::get(list_limit_rules_by_location),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/limit-rules",
|
||||||
|
axum::routing::post(create_limit_rule),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/limit-rules/{id}",
|
||||||
|
axum::routing::get(get_limit_rule)
|
||||||
|
.put(update_limit_rule)
|
||||||
|
.delete(delete_limit_rule),
|
||||||
|
)
|
||||||
|
}
|
||||||
133
apps/nxmesh-master/src/routes/api/proxy/limit_zones.rs
Normal file
133
apps/nxmesh-master/src/routes/api/proxy/limit_zones.rs
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::routes::api::{AppError, ApiRouter};
|
||||||
|
use crate::service::proxy::limit_zone::{
|
||||||
|
CreateLimitZoneParams, LimitZoneService, UpdateLimitZoneParams,
|
||||||
|
};
|
||||||
|
use crate::service::proxy::types::LimitZoneConfig;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct LimitZoneResponse {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
pub key: String,
|
||||||
|
pub rate: String,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LimitZoneConfig> for LimitZoneResponse {
|
||||||
|
fn from(c: LimitZoneConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
id: c.id,
|
||||||
|
name: c.name,
|
||||||
|
key: c.key,
|
||||||
|
rate: c.rate,
|
||||||
|
override_of_id: c.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct CreateLimitZoneRequest {
|
||||||
|
pub name: String,
|
||||||
|
pub key: String,
|
||||||
|
pub rate: String,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CreateLimitZoneRequest> for CreateLimitZoneParams {
|
||||||
|
fn from(r: CreateLimitZoneRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
name: r.name,
|
||||||
|
key: r.key,
|
||||||
|
rate: r.rate,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct UpdateLimitZoneRequest {
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub key: Option<String>,
|
||||||
|
pub rate: Option<String>,
|
||||||
|
pub override_of_id: Option<Option<Uuid>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UpdateLimitZoneRequest> for UpdateLimitZoneParams {
|
||||||
|
fn from(r: UpdateLimitZoneRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
name: r.name,
|
||||||
|
key: r.key,
|
||||||
|
rate: r.rate,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_limit_zones(
|
||||||
|
State(svc): State<Arc<dyn LimitZoneService>>,
|
||||||
|
) -> Result<Json<Vec<LimitZoneResponse>>, AppError> {
|
||||||
|
let zones = svc.list().await?;
|
||||||
|
Ok(Json(zones.into_iter().map(Into::into).collect()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_limit_zone(
|
||||||
|
State(svc): State<Arc<dyn LimitZoneService>>,
|
||||||
|
Json(body): Json<CreateLimitZoneRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let zone = svc.create(body.into()).await?;
|
||||||
|
Ok((StatusCode::CREATED, Json(LimitZoneResponse::from(zone))))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_limit_zone(
|
||||||
|
State(svc): State<Arc<dyn LimitZoneService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<Json<LimitZoneResponse>, AppError> {
|
||||||
|
let zone = svc.get(id).await?;
|
||||||
|
Ok(Json(zone.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_limit_zone(
|
||||||
|
State(svc): State<Arc<dyn LimitZoneService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
Json(body): Json<UpdateLimitZoneRequest>,
|
||||||
|
) -> Result<Json<LimitZoneResponse>, AppError> {
|
||||||
|
let zone = svc.update(id, body.into()).await?;
|
||||||
|
Ok(Json(zone.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_limit_zone(
|
||||||
|
State(svc): State<Arc<dyn LimitZoneService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let deleted = svc.delete(id).await?;
|
||||||
|
if deleted {
|
||||||
|
Ok((StatusCode::NO_CONTENT,))
|
||||||
|
} else {
|
||||||
|
Err(AppError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn routes() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.route(
|
||||||
|
"/limit-zones",
|
||||||
|
axum::routing::get(list_limit_zones).post(create_limit_zone),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/limit-zones/{id}",
|
||||||
|
axum::routing::get(get_limit_zone)
|
||||||
|
.put(update_limit_zone)
|
||||||
|
.delete(delete_limit_zone),
|
||||||
|
)
|
||||||
|
}
|
||||||
142
apps/nxmesh-master/src/routes/api/proxy/locations.rs
Normal file
142
apps/nxmesh-master/src/routes/api/proxy/locations.rs
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::routes::api::{AppError, ApiRouter};
|
||||||
|
use crate::service::proxy::location_block::{
|
||||||
|
CreateLocationBlockParams, LocationBlockService, UpdateLocationBlockParams,
|
||||||
|
};
|
||||||
|
use crate::service::proxy::types::LocationBlockConfig;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct LocationBlockResponse {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub server_id: Uuid,
|
||||||
|
pub path_pattern: String,
|
||||||
|
pub proxy_pass_upstream_id: Option<Uuid>,
|
||||||
|
pub metadata: Option<serde_json::Value>,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LocationBlockConfig> for LocationBlockResponse {
|
||||||
|
fn from(c: LocationBlockConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
id: c.id,
|
||||||
|
server_id: c.server_id,
|
||||||
|
path_pattern: c.path_pattern,
|
||||||
|
proxy_pass_upstream_id: c.proxy_pass_upstream_id,
|
||||||
|
metadata: c.metadata,
|
||||||
|
override_of_id: c.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct CreateLocationBlockRequest {
|
||||||
|
pub path_pattern: String,
|
||||||
|
pub proxy_pass_upstream_id: Option<Uuid>,
|
||||||
|
pub metadata: Option<serde_json::Value>,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CreateLocationBlockRequest> for CreateLocationBlockParams {
|
||||||
|
fn from(r: CreateLocationBlockRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
server_id: Uuid::nil(),
|
||||||
|
path_pattern: r.path_pattern,
|
||||||
|
proxy_pass_upstream_id: r.proxy_pass_upstream_id,
|
||||||
|
metadata: r.metadata,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct UpdateLocationBlockRequest {
|
||||||
|
pub server_id: Option<Uuid>,
|
||||||
|
pub path_pattern: Option<String>,
|
||||||
|
pub proxy_pass_upstream_id: Option<Option<Uuid>>,
|
||||||
|
pub metadata: Option<Option<serde_json::Value>>,
|
||||||
|
pub override_of_id: Option<Option<Uuid>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UpdateLocationBlockRequest> for UpdateLocationBlockParams {
|
||||||
|
fn from(r: UpdateLocationBlockRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
server_id: r.server_id,
|
||||||
|
path_pattern: r.path_pattern,
|
||||||
|
proxy_pass_upstream_id: r.proxy_pass_upstream_id,
|
||||||
|
metadata: r.metadata,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_locations(
|
||||||
|
State(svc): State<Arc<dyn LocationBlockService>>,
|
||||||
|
Path(server_id): Path<Uuid>,
|
||||||
|
) -> Result<Json<Vec<LocationBlockResponse>>, AppError> {
|
||||||
|
let locations = svc.list_by_server(server_id).await?;
|
||||||
|
Ok(Json(locations.into_iter().map(Into::into).collect()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_location(
|
||||||
|
State(svc): State<Arc<dyn LocationBlockService>>,
|
||||||
|
Path(server_id): Path<Uuid>,
|
||||||
|
Json(body): Json<CreateLocationBlockRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let mut params = CreateLocationBlockParams::from(body);
|
||||||
|
params.server_id = server_id;
|
||||||
|
let location = svc.create(params).await?;
|
||||||
|
Ok((StatusCode::CREATED, Json(LocationBlockResponse::from(location))))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_location(
|
||||||
|
State(svc): State<Arc<dyn LocationBlockService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<Json<LocationBlockResponse>, AppError> {
|
||||||
|
let location = svc.get(id).await?;
|
||||||
|
Ok(Json(location.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_location(
|
||||||
|
State(svc): State<Arc<dyn LocationBlockService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
Json(body): Json<UpdateLocationBlockRequest>,
|
||||||
|
) -> Result<Json<LocationBlockResponse>, AppError> {
|
||||||
|
let location = svc.update(id, body.into()).await?;
|
||||||
|
Ok(Json(location.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_location(
|
||||||
|
State(svc): State<Arc<dyn LocationBlockService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let deleted = svc.delete(id).await?;
|
||||||
|
if deleted {
|
||||||
|
Ok((StatusCode::NO_CONTENT,))
|
||||||
|
} else {
|
||||||
|
Err(AppError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn routes() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.route(
|
||||||
|
"/server-blocks/{server_id}/locations",
|
||||||
|
axum::routing::get(list_locations).post(create_location),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/locations/{id}",
|
||||||
|
axum::routing::get(get_location)
|
||||||
|
.put(update_location)
|
||||||
|
.delete(delete_location),
|
||||||
|
)
|
||||||
|
}
|
||||||
140
apps/nxmesh-master/src/routes/api/proxy/log_settings.rs
Normal file
140
apps/nxmesh-master/src/routes/api/proxy/log_settings.rs
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::routes::api::{AppError, ApiRouter};
|
||||||
|
use crate::service::proxy::log_setting::{
|
||||||
|
CreateLogSettingParams, LogSettingService, UpdateLogSettingParams,
|
||||||
|
};
|
||||||
|
use crate::service::proxy::types::LogSettingConfig;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct LogSettingResponse {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub access_log_path: Option<String>,
|
||||||
|
pub error_log_path: Option<String>,
|
||||||
|
pub log_level: Option<String>,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LogSettingConfig> for LogSettingResponse {
|
||||||
|
fn from(c: LogSettingConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
id: c.id,
|
||||||
|
access_log_path: c.access_log_path,
|
||||||
|
error_log_path: c.error_log_path,
|
||||||
|
log_level: c.log_level,
|
||||||
|
override_of_id: c.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct CreateLogSettingRequest {
|
||||||
|
pub access_log_path: Option<String>,
|
||||||
|
pub error_log_path: Option<String>,
|
||||||
|
pub log_level: Option<String>,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CreateLogSettingRequest> for CreateLogSettingParams {
|
||||||
|
fn from(r: CreateLogSettingRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
server_id: Uuid::nil(),
|
||||||
|
access_log_path: r.access_log_path,
|
||||||
|
error_log_path: r.error_log_path,
|
||||||
|
log_level: r.log_level,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct UpdateLogSettingRequest {
|
||||||
|
pub server_id: Option<Uuid>,
|
||||||
|
pub access_log_path: Option<Option<String>>,
|
||||||
|
pub error_log_path: Option<Option<String>>,
|
||||||
|
pub log_level: Option<Option<String>>,
|
||||||
|
pub override_of_id: Option<Option<Uuid>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UpdateLogSettingRequest> for UpdateLogSettingParams {
|
||||||
|
fn from(r: UpdateLogSettingRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
server_id: r.server_id,
|
||||||
|
access_log_path: r.access_log_path,
|
||||||
|
error_log_path: r.error_log_path,
|
||||||
|
log_level: r.log_level,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_log_settings(
|
||||||
|
State(svc): State<Arc<dyn LogSettingService>>,
|
||||||
|
Path(server_id): Path<Uuid>,
|
||||||
|
) -> Result<Json<Vec<LogSettingResponse>>, AppError> {
|
||||||
|
let settings = svc.list_by_server(server_id).await?;
|
||||||
|
Ok(Json(settings.into_iter().map(Into::into).collect()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_log_setting(
|
||||||
|
State(svc): State<Arc<dyn LogSettingService>>,
|
||||||
|
Path(server_id): Path<Uuid>,
|
||||||
|
Json(body): Json<CreateLogSettingRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let mut params = CreateLogSettingParams::from(body);
|
||||||
|
params.server_id = server_id;
|
||||||
|
let setting = svc.create(params).await?;
|
||||||
|
Ok((StatusCode::CREATED, Json(LogSettingResponse::from(setting))))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_log_setting(
|
||||||
|
State(svc): State<Arc<dyn LogSettingService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<Json<LogSettingResponse>, AppError> {
|
||||||
|
let setting = svc.get(id).await?;
|
||||||
|
Ok(Json(setting.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_log_setting(
|
||||||
|
State(svc): State<Arc<dyn LogSettingService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
Json(body): Json<UpdateLogSettingRequest>,
|
||||||
|
) -> Result<Json<LogSettingResponse>, AppError> {
|
||||||
|
let setting = svc.update(id, body.into()).await?;
|
||||||
|
Ok(Json(setting.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_log_setting(
|
||||||
|
State(svc): State<Arc<dyn LogSettingService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let deleted = svc.delete(id).await?;
|
||||||
|
if deleted {
|
||||||
|
Ok((StatusCode::NO_CONTENT,))
|
||||||
|
} else {
|
||||||
|
Err(AppError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn routes() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.route(
|
||||||
|
"/server-blocks/{server_id}/log-settings",
|
||||||
|
axum::routing::get(list_log_settings).post(create_log_setting),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/log-settings/{id}",
|
||||||
|
axum::routing::get(get_log_setting)
|
||||||
|
.put(update_log_setting)
|
||||||
|
.delete(delete_log_setting),
|
||||||
|
)
|
||||||
|
}
|
||||||
37
apps/nxmesh-master/src/routes/api/proxy/mod.rs
Normal file
37
apps/nxmesh-master/src/routes/api/proxy/mod.rs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
use crate::routes::api::ApiRouter;
|
||||||
|
|
||||||
|
pub(crate) mod access_rules;
|
||||||
|
pub(crate) mod agents;
|
||||||
|
pub(crate) mod cache_zones;
|
||||||
|
pub(crate) mod config_inheritance;
|
||||||
|
pub(crate) mod configs;
|
||||||
|
pub(crate) mod limit_rules;
|
||||||
|
pub(crate) mod limit_zones;
|
||||||
|
pub(crate) mod locations;
|
||||||
|
pub(crate) mod log_settings;
|
||||||
|
pub(crate) mod proxy_settings;
|
||||||
|
pub(crate) mod rewrite_rules;
|
||||||
|
pub(crate) mod server_blocks;
|
||||||
|
pub(crate) mod ssl_certificates;
|
||||||
|
pub(crate) mod upstreams;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) mod test_builder;
|
||||||
|
|
||||||
|
pub async fn get_router() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.merge(configs::routes())
|
||||||
|
.merge(agents::routes())
|
||||||
|
.merge(config_inheritance::routes())
|
||||||
|
.merge(server_blocks::routes())
|
||||||
|
.merge(upstreams::routes())
|
||||||
|
.merge(locations::routes())
|
||||||
|
.merge(access_rules::routes())
|
||||||
|
.merge(cache_zones::routes())
|
||||||
|
.merge(limit_rules::routes())
|
||||||
|
.merge(limit_zones::routes())
|
||||||
|
.merge(log_settings::routes())
|
||||||
|
.merge(proxy_settings::routes())
|
||||||
|
.merge(rewrite_rules::routes())
|
||||||
|
.merge(ssl_certificates::routes())
|
||||||
|
}
|
||||||
154
apps/nxmesh-master/src/routes/api/proxy/proxy_settings.rs
Normal file
154
apps/nxmesh-master/src/routes/api/proxy/proxy_settings.rs
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::routes::api::{AppError, ApiRouter};
|
||||||
|
use crate::service::proxy::proxy_setting::{
|
||||||
|
CreateProxySettingParams, ProxySettingService, UpdateProxySettingParams,
|
||||||
|
};
|
||||||
|
use crate::service::proxy::types::ProxySettingConfig;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct ProxySettingResponse {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub location_id: Uuid,
|
||||||
|
pub read_timeout: Option<i32>,
|
||||||
|
pub connect_timeout: Option<i32>,
|
||||||
|
pub buffer_size: Option<i32>,
|
||||||
|
pub cache_enabled: Option<bool>,
|
||||||
|
pub cache_zone: Option<Uuid>,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ProxySettingConfig> for ProxySettingResponse {
|
||||||
|
fn from(c: ProxySettingConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
id: c.id,
|
||||||
|
location_id: c.location_id,
|
||||||
|
read_timeout: c.read_timeout,
|
||||||
|
connect_timeout: c.connect_timeout,
|
||||||
|
buffer_size: c.buffer_size,
|
||||||
|
cache_enabled: c.cache_enabled,
|
||||||
|
cache_zone: c.cache_zone,
|
||||||
|
override_of_id: c.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct CreateProxySettingRequest {
|
||||||
|
pub read_timeout: Option<i32>,
|
||||||
|
pub connect_timeout: Option<i32>,
|
||||||
|
pub buffer_size: Option<i32>,
|
||||||
|
pub cache_enabled: Option<bool>,
|
||||||
|
pub cache_zone: Option<Uuid>,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CreateProxySettingRequest> for CreateProxySettingParams {
|
||||||
|
fn from(r: CreateProxySettingRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
location_id: Uuid::nil(),
|
||||||
|
read_timeout: r.read_timeout,
|
||||||
|
connect_timeout: r.connect_timeout,
|
||||||
|
buffer_size: r.buffer_size,
|
||||||
|
cache_enabled: r.cache_enabled,
|
||||||
|
cache_zone: r.cache_zone,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct UpdateProxySettingRequest {
|
||||||
|
pub location_id: Option<Uuid>,
|
||||||
|
pub read_timeout: Option<Option<i32>>,
|
||||||
|
pub connect_timeout: Option<Option<i32>>,
|
||||||
|
pub buffer_size: Option<Option<i32>>,
|
||||||
|
pub cache_enabled: Option<Option<bool>>,
|
||||||
|
pub cache_zone: Option<Option<Uuid>>,
|
||||||
|
pub override_of_id: Option<Option<Uuid>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UpdateProxySettingRequest> for UpdateProxySettingParams {
|
||||||
|
fn from(r: UpdateProxySettingRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
location_id: r.location_id,
|
||||||
|
read_timeout: r.read_timeout,
|
||||||
|
connect_timeout: r.connect_timeout,
|
||||||
|
buffer_size: r.buffer_size,
|
||||||
|
cache_enabled: r.cache_enabled,
|
||||||
|
cache_zone: r.cache_zone,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_proxy_settings(
|
||||||
|
State(svc): State<Arc<dyn ProxySettingService>>,
|
||||||
|
Path(location_id): Path<Uuid>,
|
||||||
|
) -> Result<Json<Vec<ProxySettingResponse>>, AppError> {
|
||||||
|
let settings = svc.list_by_location(location_id).await?;
|
||||||
|
Ok(Json(settings.into_iter().map(Into::into).collect()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_proxy_setting(
|
||||||
|
State(svc): State<Arc<dyn ProxySettingService>>,
|
||||||
|
Path(location_id): Path<Uuid>,
|
||||||
|
Json(body): Json<CreateProxySettingRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let mut params = CreateProxySettingParams::from(body);
|
||||||
|
params.location_id = location_id;
|
||||||
|
let setting = svc.create(params).await?;
|
||||||
|
Ok((StatusCode::CREATED, Json(ProxySettingResponse::from(setting))))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_proxy_setting(
|
||||||
|
State(svc): State<Arc<dyn ProxySettingService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<Json<ProxySettingResponse>, AppError> {
|
||||||
|
let setting = svc.get(id).await?;
|
||||||
|
Ok(Json(setting.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_proxy_setting(
|
||||||
|
State(svc): State<Arc<dyn ProxySettingService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
Json(body): Json<UpdateProxySettingRequest>,
|
||||||
|
) -> Result<Json<ProxySettingResponse>, AppError> {
|
||||||
|
let setting = svc.update(id, body.into()).await?;
|
||||||
|
Ok(Json(setting.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_proxy_setting(
|
||||||
|
State(svc): State<Arc<dyn ProxySettingService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let deleted = svc.delete(id).await?;
|
||||||
|
if deleted {
|
||||||
|
Ok((StatusCode::NO_CONTENT,))
|
||||||
|
} else {
|
||||||
|
Err(AppError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn routes() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.route(
|
||||||
|
"/locations/{location_id}/proxy-settings",
|
||||||
|
axum::routing::get(list_proxy_settings).post(create_proxy_setting),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/proxy-settings/{id}",
|
||||||
|
axum::routing::get(get_proxy_setting)
|
||||||
|
.put(update_proxy_setting)
|
||||||
|
.delete(delete_proxy_setting),
|
||||||
|
)
|
||||||
|
}
|
||||||
148
apps/nxmesh-master/src/routes/api/proxy/rewrite_rules.rs
Normal file
148
apps/nxmesh-master/src/routes/api/proxy/rewrite_rules.rs
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::routes::api::{AppError, ApiRouter};
|
||||||
|
use crate::service::proxy::rewrite_rule::{
|
||||||
|
CreateRewriteRuleParams, RewriteRuleService, UpdateRewriteRuleParams,
|
||||||
|
};
|
||||||
|
use crate::service::proxy::types::RewriteRuleConfig;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct RewriteRuleResponse {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub location_id: Uuid,
|
||||||
|
pub pattern: String,
|
||||||
|
pub replacement: String,
|
||||||
|
pub flag: Option<String>,
|
||||||
|
pub priority: i32,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RewriteRuleConfig> for RewriteRuleResponse {
|
||||||
|
fn from(c: RewriteRuleConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
id: c.id,
|
||||||
|
location_id: c.location_id,
|
||||||
|
pattern: c.pattern,
|
||||||
|
replacement: c.replacement,
|
||||||
|
flag: c.flag,
|
||||||
|
priority: c.priority,
|
||||||
|
override_of_id: c.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct CreateRewriteRuleRequest {
|
||||||
|
pub pattern: String,
|
||||||
|
pub replacement: String,
|
||||||
|
pub flag: Option<String>,
|
||||||
|
pub priority: i32,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CreateRewriteRuleRequest> for CreateRewriteRuleParams {
|
||||||
|
fn from(r: CreateRewriteRuleRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
location_id: Uuid::nil(),
|
||||||
|
pattern: r.pattern,
|
||||||
|
replacement: r.replacement,
|
||||||
|
flag: r.flag,
|
||||||
|
priority: r.priority,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct UpdateRewriteRuleRequest {
|
||||||
|
pub location_id: Option<Uuid>,
|
||||||
|
pub pattern: Option<String>,
|
||||||
|
pub replacement: Option<String>,
|
||||||
|
pub flag: Option<Option<String>>,
|
||||||
|
pub priority: Option<i32>,
|
||||||
|
pub override_of_id: Option<Option<Uuid>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UpdateRewriteRuleRequest> for UpdateRewriteRuleParams {
|
||||||
|
fn from(r: UpdateRewriteRuleRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
location_id: r.location_id,
|
||||||
|
pattern: r.pattern,
|
||||||
|
replacement: r.replacement,
|
||||||
|
flag: r.flag,
|
||||||
|
priority: r.priority,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_rewrite_rules(
|
||||||
|
State(svc): State<Arc<dyn RewriteRuleService>>,
|
||||||
|
Path(location_id): Path<Uuid>,
|
||||||
|
) -> Result<Json<Vec<RewriteRuleResponse>>, AppError> {
|
||||||
|
let rules = svc.list_by_location(location_id).await?;
|
||||||
|
Ok(Json(rules.into_iter().map(Into::into).collect()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_rewrite_rule(
|
||||||
|
State(svc): State<Arc<dyn RewriteRuleService>>,
|
||||||
|
Path(location_id): Path<Uuid>,
|
||||||
|
Json(body): Json<CreateRewriteRuleRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let mut params = CreateRewriteRuleParams::from(body);
|
||||||
|
params.location_id = location_id;
|
||||||
|
let rule = svc.create(params).await?;
|
||||||
|
Ok((StatusCode::CREATED, Json(RewriteRuleResponse::from(rule))))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_rewrite_rule(
|
||||||
|
State(svc): State<Arc<dyn RewriteRuleService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<Json<RewriteRuleResponse>, AppError> {
|
||||||
|
let rule = svc.get(id).await?;
|
||||||
|
Ok(Json(rule.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_rewrite_rule(
|
||||||
|
State(svc): State<Arc<dyn RewriteRuleService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
Json(body): Json<UpdateRewriteRuleRequest>,
|
||||||
|
) -> Result<Json<RewriteRuleResponse>, AppError> {
|
||||||
|
let rule = svc.update(id, body.into()).await?;
|
||||||
|
Ok(Json(rule.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_rewrite_rule(
|
||||||
|
State(svc): State<Arc<dyn RewriteRuleService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let deleted = svc.delete(id).await?;
|
||||||
|
if deleted {
|
||||||
|
Ok((StatusCode::NO_CONTENT,))
|
||||||
|
} else {
|
||||||
|
Err(AppError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn routes() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.route(
|
||||||
|
"/locations/{location_id}/rewrite-rules",
|
||||||
|
axum::routing::get(list_rewrite_rules).post(create_rewrite_rule),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/rewrite-rules/{id}",
|
||||||
|
axum::routing::get(get_rewrite_rule)
|
||||||
|
.put(update_rewrite_rule)
|
||||||
|
.delete(delete_rewrite_rule),
|
||||||
|
)
|
||||||
|
}
|
||||||
142
apps/nxmesh-master/src/routes/api/proxy/server_blocks.rs
Normal file
142
apps/nxmesh-master/src/routes/api/proxy/server_blocks.rs
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::routes::api::{AppError, ApiRouter};
|
||||||
|
use crate::service::proxy::server_block::{
|
||||||
|
CreateServerBlockParams, ServerBlockService, UpdateServerBlockParams,
|
||||||
|
};
|
||||||
|
use crate::service::proxy::types::ServerBlockConfig;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct ServerBlockResponse {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub server_name: Option<Vec<String>>,
|
||||||
|
pub listen_port: i32,
|
||||||
|
pub ssl_enabled: Option<bool>,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ServerBlockConfig> for ServerBlockResponse {
|
||||||
|
fn from(c: ServerBlockConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
id: c.id,
|
||||||
|
server_name: c.server_name,
|
||||||
|
listen_port: c.listen_port,
|
||||||
|
ssl_enabled: c.ssl_enabled,
|
||||||
|
override_of_id: c.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct CreateServerBlockRequest {
|
||||||
|
pub server_name: Option<Vec<String>>,
|
||||||
|
pub listen_port: i32,
|
||||||
|
pub ssl_enabled: Option<bool>,
|
||||||
|
pub ssl_cert_id: Option<Uuid>,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CreateServerBlockRequest> for CreateServerBlockParams {
|
||||||
|
fn from(r: CreateServerBlockRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
config_id: Uuid::nil(),
|
||||||
|
server_name: r.server_name,
|
||||||
|
listen_port: r.listen_port,
|
||||||
|
ssl_enabled: r.ssl_enabled,
|
||||||
|
ssl_cert_id: r.ssl_cert_id,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct UpdateServerBlockRequest {
|
||||||
|
pub server_name: Option<Option<Vec<String>>>,
|
||||||
|
pub listen_port: Option<i32>,
|
||||||
|
pub ssl_enabled: Option<Option<bool>>,
|
||||||
|
pub ssl_cert_id: Option<Option<Uuid>>,
|
||||||
|
pub override_of_id: Option<Option<Uuid>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UpdateServerBlockRequest> for UpdateServerBlockParams {
|
||||||
|
fn from(r: UpdateServerBlockRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
server_name: r.server_name,
|
||||||
|
listen_port: r.listen_port,
|
||||||
|
ssl_enabled: r.ssl_enabled,
|
||||||
|
ssl_cert_id: r.ssl_cert_id,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_server_blocks(
|
||||||
|
State(svc): State<Arc<dyn ServerBlockService>>,
|
||||||
|
Path(config_id): Path<Uuid>,
|
||||||
|
) -> Result<Json<Vec<ServerBlockResponse>>, AppError> {
|
||||||
|
let blocks = svc.list_by_config(config_id).await?;
|
||||||
|
Ok(Json(blocks.into_iter().map(Into::into).collect()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_server_block(
|
||||||
|
State(svc): State<Arc<dyn ServerBlockService>>,
|
||||||
|
Path(config_id): Path<Uuid>,
|
||||||
|
Json(body): Json<CreateServerBlockRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let mut params = CreateServerBlockParams::from(body);
|
||||||
|
params.config_id = config_id;
|
||||||
|
let block = svc.create(params).await?;
|
||||||
|
Ok((StatusCode::CREATED, Json(ServerBlockResponse::from(block))))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_server_block(
|
||||||
|
State(svc): State<Arc<dyn ServerBlockService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<Json<ServerBlockResponse>, AppError> {
|
||||||
|
let block = svc.get(id).await?;
|
||||||
|
Ok(Json(block.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_server_block(
|
||||||
|
State(svc): State<Arc<dyn ServerBlockService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
Json(body): Json<UpdateServerBlockRequest>,
|
||||||
|
) -> Result<Json<ServerBlockResponse>, AppError> {
|
||||||
|
let block = svc.update(id, body.into()).await?;
|
||||||
|
Ok(Json(block.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_server_block(
|
||||||
|
State(svc): State<Arc<dyn ServerBlockService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let deleted = svc.delete(id).await?;
|
||||||
|
if deleted {
|
||||||
|
Ok((StatusCode::NO_CONTENT,))
|
||||||
|
} else {
|
||||||
|
Err(AppError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn routes() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.route(
|
||||||
|
"/configs/{config_id}/server-blocks",
|
||||||
|
axum::routing::get(list_server_blocks).post(create_server_block),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/server-blocks/{id}",
|
||||||
|
axum::routing::get(get_server_block)
|
||||||
|
.put(update_server_block)
|
||||||
|
.delete(delete_server_block),
|
||||||
|
)
|
||||||
|
}
|
||||||
133
apps/nxmesh-master/src/routes/api/proxy/ssl_certificates.rs
Normal file
133
apps/nxmesh-master/src/routes/api/proxy/ssl_certificates.rs
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::routes::api::{AppError, ApiRouter};
|
||||||
|
use crate::service::proxy::ssl_certificate::{
|
||||||
|
CreateSslCertificateParams, SslCertificateService, UpdateSslCertificateParams,
|
||||||
|
};
|
||||||
|
use crate::service::proxy::types::SslCertificateConfig;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct SslCertificateResponse {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
pub cert_path: String,
|
||||||
|
pub key_path: String,
|
||||||
|
pub expiry_date: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SslCertificateConfig> for SslCertificateResponse {
|
||||||
|
fn from(c: SslCertificateConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
id: c.id,
|
||||||
|
name: c.name,
|
||||||
|
cert_path: c.cert_path,
|
||||||
|
key_path: c.key_path,
|
||||||
|
expiry_date: c.expiry_date.to_rfc3339(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct CreateSslCertificateRequest {
|
||||||
|
pub name: String,
|
||||||
|
pub cert_path: String,
|
||||||
|
pub key_path: String,
|
||||||
|
pub expiry_date: chrono::DateTime<chrono::Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CreateSslCertificateRequest> for CreateSslCertificateParams {
|
||||||
|
fn from(r: CreateSslCertificateRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
name: r.name,
|
||||||
|
cert_path: r.cert_path,
|
||||||
|
key_path: r.key_path,
|
||||||
|
expiry_date: r.expiry_date,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct UpdateSslCertificateRequest {
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub cert_path: Option<String>,
|
||||||
|
pub key_path: Option<String>,
|
||||||
|
pub expiry_date: Option<chrono::DateTime<chrono::Utc>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UpdateSslCertificateRequest> for UpdateSslCertificateParams {
|
||||||
|
fn from(r: UpdateSslCertificateRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
name: r.name,
|
||||||
|
cert_path: r.cert_path,
|
||||||
|
key_path: r.key_path,
|
||||||
|
expiry_date: r.expiry_date,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_ssl_certificates(
|
||||||
|
State(svc): State<Arc<dyn SslCertificateService>>,
|
||||||
|
) -> Result<Json<Vec<SslCertificateResponse>>, AppError> {
|
||||||
|
let certs = svc.list().await?;
|
||||||
|
Ok(Json(certs.into_iter().map(Into::into).collect()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_ssl_certificate(
|
||||||
|
State(svc): State<Arc<dyn SslCertificateService>>,
|
||||||
|
Json(body): Json<CreateSslCertificateRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let cert = svc.create(body.into()).await?;
|
||||||
|
Ok((StatusCode::CREATED, Json(SslCertificateResponse::from(cert))))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_ssl_certificate(
|
||||||
|
State(svc): State<Arc<dyn SslCertificateService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<Json<SslCertificateResponse>, AppError> {
|
||||||
|
let cert = svc.get(id).await?;
|
||||||
|
Ok(Json(cert.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_ssl_certificate(
|
||||||
|
State(svc): State<Arc<dyn SslCertificateService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
Json(body): Json<UpdateSslCertificateRequest>,
|
||||||
|
) -> Result<Json<SslCertificateResponse>, AppError> {
|
||||||
|
let cert = svc.update(id, body.into()).await?;
|
||||||
|
Ok(Json(cert.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_ssl_certificate(
|
||||||
|
State(svc): State<Arc<dyn SslCertificateService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let deleted = svc.delete(id).await?;
|
||||||
|
if deleted {
|
||||||
|
Ok((StatusCode::NO_CONTENT,))
|
||||||
|
} else {
|
||||||
|
Err(AppError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn routes() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.route(
|
||||||
|
"/ssl-certificates",
|
||||||
|
axum::routing::get(list_ssl_certificates).post(create_ssl_certificate),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/ssl-certificates/{id}",
|
||||||
|
axum::routing::get(get_ssl_certificate)
|
||||||
|
.put(update_ssl_certificate)
|
||||||
|
.delete(delete_ssl_certificate),
|
||||||
|
)
|
||||||
|
}
|
||||||
174
apps/nxmesh-master/src/routes/api/proxy/test_builder.rs
Normal file
174
apps/nxmesh-master/src/routes/api/proxy/test_builder.rs
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum_test::TestServer;
|
||||||
|
|
||||||
|
use crate::routes::api::{ApiState, LocalApiState};
|
||||||
|
use crate::service::proxy::*;
|
||||||
|
use crate::service::proxy::{
|
||||||
|
access_rule::MockAccessRuleService,
|
||||||
|
cache_zone::MockCacheZoneService,
|
||||||
|
config_inheritance::MockConfigInheritanceService,
|
||||||
|
limit_rule::MockLimitRuleService,
|
||||||
|
limit_zone::MockLimitZoneService,
|
||||||
|
location_block::MockLocationBlockService,
|
||||||
|
log_setting::MockLogSettingService,
|
||||||
|
proxy_setting::MockProxySettingService,
|
||||||
|
rewrite_rule::MockRewriteRuleService,
|
||||||
|
server_block::MockServerBlockService,
|
||||||
|
ssl_certificate::MockSslCertificateService,
|
||||||
|
upstream::MockUpstreamService,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub(crate) struct TestProxyApiBuilder {
|
||||||
|
proxy_service: Option<MockProxyServiceTrait>,
|
||||||
|
server_block_service: Option<MockServerBlockService>,
|
||||||
|
upstream_service: Option<MockUpstreamService>,
|
||||||
|
location_block_service: Option<MockLocationBlockService>,
|
||||||
|
access_rule_service: Option<MockAccessRuleService>,
|
||||||
|
cache_zone_service: Option<MockCacheZoneService>,
|
||||||
|
limit_rule_service: Option<MockLimitRuleService>,
|
||||||
|
limit_zone_service: Option<MockLimitZoneService>,
|
||||||
|
log_setting_service: Option<MockLogSettingService>,
|
||||||
|
proxy_setting_service: Option<MockProxySettingService>,
|
||||||
|
rewrite_rule_service: Option<MockRewriteRuleService>,
|
||||||
|
ssl_certificate_service: Option<MockSslCertificateService>,
|
||||||
|
config_inheritance_service: Option<MockConfigInheritanceService>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestProxyApiBuilder {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
proxy_service: None,
|
||||||
|
server_block_service: None,
|
||||||
|
upstream_service: None,
|
||||||
|
location_block_service: None,
|
||||||
|
access_rule_service: None,
|
||||||
|
cache_zone_service: None,
|
||||||
|
limit_rule_service: None,
|
||||||
|
limit_zone_service: None,
|
||||||
|
log_setting_service: None,
|
||||||
|
proxy_setting_service: None,
|
||||||
|
rewrite_rule_service: None,
|
||||||
|
ssl_certificate_service: None,
|
||||||
|
config_inheritance_service: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_proxy(mut self, mock: MockProxyServiceTrait) -> Self {
|
||||||
|
self.proxy_service = Some(mock);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_server_block(mut self, mock: MockServerBlockService) -> Self {
|
||||||
|
self.server_block_service = Some(mock);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_upstream(mut self, mock: MockUpstreamService) -> Self {
|
||||||
|
self.upstream_service = Some(mock);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_location_block(mut self, mock: MockLocationBlockService) -> Self {
|
||||||
|
self.location_block_service = Some(mock);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_access_rule(mut self, mock: MockAccessRuleService) -> Self {
|
||||||
|
self.access_rule_service = Some(mock);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_cache_zone(mut self, mock: MockCacheZoneService) -> Self {
|
||||||
|
self.cache_zone_service = Some(mock);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_limit_rule(mut self, mock: MockLimitRuleService) -> Self {
|
||||||
|
self.limit_rule_service = Some(mock);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_limit_zone(mut self, mock: MockLimitZoneService) -> Self {
|
||||||
|
self.limit_zone_service = Some(mock);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_log_setting(mut self, mock: MockLogSettingService) -> Self {
|
||||||
|
self.log_setting_service = Some(mock);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_proxy_setting(mut self, mock: MockProxySettingService) -> Self {
|
||||||
|
self.proxy_setting_service = Some(mock);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_rewrite_rule(mut self, mock: MockRewriteRuleService) -> Self {
|
||||||
|
self.rewrite_rule_service = Some(mock);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_ssl_certificate(mut self, mock: MockSslCertificateService) -> Self {
|
||||||
|
self.ssl_certificate_service = Some(mock);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_config_inheritance(mut self, mock: MockConfigInheritanceService) -> Self {
|
||||||
|
self.config_inheritance_service = Some(mock);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn build(self) -> TestServer {
|
||||||
|
let state = ApiState {
|
||||||
|
proxy_service: Arc::new(self.proxy_service.unwrap_or_else(MockProxyServiceTrait::new)),
|
||||||
|
server_block_service: Arc::new(
|
||||||
|
self.server_block_service.unwrap_or_else(MockServerBlockService::new),
|
||||||
|
),
|
||||||
|
upstream_service: Arc::new(
|
||||||
|
self.upstream_service.unwrap_or_else(MockUpstreamService::new),
|
||||||
|
),
|
||||||
|
location_block_service: Arc::new(
|
||||||
|
self.location_block_service
|
||||||
|
.unwrap_or_else(MockLocationBlockService::new),
|
||||||
|
),
|
||||||
|
access_rule_service: Arc::new(
|
||||||
|
self.access_rule_service.unwrap_or_else(MockAccessRuleService::new),
|
||||||
|
),
|
||||||
|
cache_zone_service: Arc::new(
|
||||||
|
self.cache_zone_service.unwrap_or_else(MockCacheZoneService::new),
|
||||||
|
),
|
||||||
|
limit_rule_service: Arc::new(
|
||||||
|
self.limit_rule_service.unwrap_or_else(MockLimitRuleService::new),
|
||||||
|
),
|
||||||
|
limit_zone_service: Arc::new(
|
||||||
|
self.limit_zone_service.unwrap_or_else(MockLimitZoneService::new),
|
||||||
|
),
|
||||||
|
log_setting_service: Arc::new(
|
||||||
|
self.log_setting_service.unwrap_or_else(MockLogSettingService::new),
|
||||||
|
),
|
||||||
|
proxy_setting_service: Arc::new(
|
||||||
|
self.proxy_setting_service
|
||||||
|
.unwrap_or_else(MockProxySettingService::new),
|
||||||
|
),
|
||||||
|
rewrite_rule_service: Arc::new(
|
||||||
|
self.rewrite_rule_service
|
||||||
|
.unwrap_or_else(MockRewriteRuleService::new),
|
||||||
|
),
|
||||||
|
ssl_certificate_service: Arc::new(
|
||||||
|
self.ssl_certificate_service
|
||||||
|
.unwrap_or_else(MockSslCertificateService::new),
|
||||||
|
),
|
||||||
|
config_inheritance_service: Arc::new(
|
||||||
|
self.config_inheritance_service
|
||||||
|
.unwrap_or_else(MockConfigInheritanceService::new),
|
||||||
|
),
|
||||||
|
// Keep agent_service for ApiState completeness; not used by proxy routes
|
||||||
|
agent_service: Arc::new(crate::service::agent::MockAgentService::new()),
|
||||||
|
};
|
||||||
|
let app = super::get_router()
|
||||||
|
.await
|
||||||
|
.with_state(LocalApiState(Arc::new(state)));
|
||||||
|
TestServer::new(app)
|
||||||
|
}
|
||||||
|
}
|
||||||
144
apps/nxmesh-master/src/routes/api/proxy/upstreams.rs
Normal file
144
apps/nxmesh-master/src/routes/api/proxy/upstreams.rs
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::routes::api::{AppError, ApiRouter};
|
||||||
|
use crate::service::proxy::types::UpstreamConfig;
|
||||||
|
use crate::service::proxy::upstream::{
|
||||||
|
CreateUpstreamParams, UpstreamService, UpdateUpstreamParams,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub(crate) struct UpstreamResponse {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
pub target_host: String,
|
||||||
|
pub target_port: i32,
|
||||||
|
pub metadata: Option<serde_json::Value>,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UpstreamConfig> for UpstreamResponse {
|
||||||
|
fn from(c: UpstreamConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
id: c.id,
|
||||||
|
name: c.name,
|
||||||
|
target_host: c.target_host,
|
||||||
|
target_port: c.target_port,
|
||||||
|
metadata: c.metadata,
|
||||||
|
override_of_id: c.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct CreateUpstreamRequest {
|
||||||
|
pub name: String,
|
||||||
|
pub target_host: String,
|
||||||
|
pub target_port: i32,
|
||||||
|
pub metadata: Option<serde_json::Value>,
|
||||||
|
pub override_of_id: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CreateUpstreamRequest> for CreateUpstreamParams {
|
||||||
|
fn from(r: CreateUpstreamRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
config_id: Uuid::nil(),
|
||||||
|
name: r.name,
|
||||||
|
target_host: r.target_host,
|
||||||
|
target_port: r.target_port,
|
||||||
|
metadata: r.metadata,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct UpdateUpstreamRequest {
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub target_host: Option<String>,
|
||||||
|
pub target_port: Option<i32>,
|
||||||
|
pub metadata: Option<Option<serde_json::Value>>,
|
||||||
|
pub override_of_id: Option<Option<Uuid>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<UpdateUpstreamRequest> for UpdateUpstreamParams {
|
||||||
|
fn from(r: UpdateUpstreamRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
name: r.name,
|
||||||
|
target_host: r.target_host,
|
||||||
|
target_port: r.target_port,
|
||||||
|
metadata: r.metadata,
|
||||||
|
override_of_id: r.override_of_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_upstreams(
|
||||||
|
State(svc): State<Arc<dyn UpstreamService>>,
|
||||||
|
Path(config_id): Path<Uuid>,
|
||||||
|
) -> Result<Json<Vec<UpstreamResponse>>, AppError> {
|
||||||
|
let upstreams = svc.list_by_config(config_id).await?;
|
||||||
|
Ok(Json(upstreams.into_iter().map(Into::into).collect()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_upstream(
|
||||||
|
State(svc): State<Arc<dyn UpstreamService>>,
|
||||||
|
Path(config_id): Path<Uuid>,
|
||||||
|
Json(body): Json<CreateUpstreamRequest>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let mut params = CreateUpstreamParams::from(body);
|
||||||
|
params.config_id = config_id;
|
||||||
|
let upstream = svc.create(params).await?;
|
||||||
|
Ok((StatusCode::CREATED, Json(UpstreamResponse::from(upstream))))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_upstream(
|
||||||
|
State(svc): State<Arc<dyn UpstreamService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<Json<UpstreamResponse>, AppError> {
|
||||||
|
let upstream = svc.get(id).await?;
|
||||||
|
Ok(Json(upstream.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_upstream(
|
||||||
|
State(svc): State<Arc<dyn UpstreamService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
Json(body): Json<UpdateUpstreamRequest>,
|
||||||
|
) -> Result<Json<UpstreamResponse>, AppError> {
|
||||||
|
let upstream = svc.update(id, body.into()).await?;
|
||||||
|
Ok(Json(upstream.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_upstream(
|
||||||
|
State(svc): State<Arc<dyn UpstreamService>>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<impl IntoResponse, AppError> {
|
||||||
|
let deleted = svc.delete(id).await?;
|
||||||
|
if deleted {
|
||||||
|
Ok((StatusCode::NO_CONTENT,))
|
||||||
|
} else {
|
||||||
|
Err(AppError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn routes() -> ApiRouter {
|
||||||
|
ApiRouter::new()
|
||||||
|
.route(
|
||||||
|
"/configs/{config_id}/upstreams",
|
||||||
|
axum::routing::get(list_upstreams).post(create_upstream),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/upstreams/{id}",
|
||||||
|
axum::routing::get(get_upstream)
|
||||||
|
.put(update_upstream)
|
||||||
|
.delete(delete_upstream),
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,21 +1,44 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use axum::Router;
|
use axum::Router;
|
||||||
|
|
||||||
|
pub mod api;
|
||||||
mod frontend;
|
mod frontend;
|
||||||
|
|
||||||
pub async fn get_root_router() -> Router {
|
pub async fn get_root_router(api_state: impl Into<Arc<api::ApiState>>) -> Router {
|
||||||
Router::new()
|
Router::new()
|
||||||
.merge(frontend::get_router().await)
|
.merge(frontend::get_router().await)
|
||||||
|
.nest("/api", api::get_router(api_state.into()).await)
|
||||||
.fallback(frontend::get_fallback_handler().await)
|
.fallback(frontend::get_fallback_handler().await)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::service::agent::MockAgentService;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use axum_test::TestServer;
|
use axum_test::TestServer;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_should_return_index_html_for_root_path() {
|
async fn test_should_return_index_html_for_root_path() {
|
||||||
let router = get_root_router().await;
|
use crate::service::proxy::*;
|
||||||
|
let state = Arc::new(api::ApiState {
|
||||||
|
agent_service: Arc::new(MockAgentService::new()),
|
||||||
|
proxy_service: Arc::new(MockProxyServiceTrait::new()),
|
||||||
|
server_block_service: Arc::new(server_block::MockServerBlockService::new()),
|
||||||
|
upstream_service: Arc::new(upstream::MockUpstreamService::new()),
|
||||||
|
location_block_service: Arc::new(location_block::MockLocationBlockService::new()),
|
||||||
|
access_rule_service: Arc::new(access_rule::MockAccessRuleService::new()),
|
||||||
|
cache_zone_service: Arc::new(cache_zone::MockCacheZoneService::new()),
|
||||||
|
limit_rule_service: Arc::new(limit_rule::MockLimitRuleService::new()),
|
||||||
|
limit_zone_service: Arc::new(limit_zone::MockLimitZoneService::new()),
|
||||||
|
log_setting_service: Arc::new(log_setting::MockLogSettingService::new()),
|
||||||
|
proxy_setting_service: Arc::new(proxy_setting::MockProxySettingService::new()),
|
||||||
|
rewrite_rule_service: Arc::new(rewrite_rule::MockRewriteRuleService::new()),
|
||||||
|
ssl_certificate_service: Arc::new(ssl_certificate::MockSslCertificateService::new()),
|
||||||
|
config_inheritance_service: Arc::new(config_inheritance::MockConfigInheritanceService::new()),
|
||||||
|
});
|
||||||
|
let router = get_root_router(state).await;
|
||||||
let server = TestServer::new(router);
|
let server = TestServer::new(router);
|
||||||
let response = server.get("/").await;
|
let response = server.get("/").await;
|
||||||
assert_eq!(response.status_code(), 200);
|
assert_eq!(response.status_code(), 200);
|
||||||
@@ -23,7 +46,24 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_should_return_index_html_for_nonexistent_path() {
|
async fn test_should_return_index_html_for_nonexistent_path() {
|
||||||
let router = get_root_router().await;
|
use crate::service::proxy::*;
|
||||||
|
let state = Arc::new(api::ApiState {
|
||||||
|
agent_service: Arc::new(MockAgentService::new()),
|
||||||
|
proxy_service: Arc::new(MockProxyServiceTrait::new()),
|
||||||
|
server_block_service: Arc::new(server_block::MockServerBlockService::new()),
|
||||||
|
upstream_service: Arc::new(upstream::MockUpstreamService::new()),
|
||||||
|
location_block_service: Arc::new(location_block::MockLocationBlockService::new()),
|
||||||
|
access_rule_service: Arc::new(access_rule::MockAccessRuleService::new()),
|
||||||
|
cache_zone_service: Arc::new(cache_zone::MockCacheZoneService::new()),
|
||||||
|
limit_rule_service: Arc::new(limit_rule::MockLimitRuleService::new()),
|
||||||
|
limit_zone_service: Arc::new(limit_zone::MockLimitZoneService::new()),
|
||||||
|
log_setting_service: Arc::new(log_setting::MockLogSettingService::new()),
|
||||||
|
proxy_setting_service: Arc::new(proxy_setting::MockProxySettingService::new()),
|
||||||
|
rewrite_rule_service: Arc::new(rewrite_rule::MockRewriteRuleService::new()),
|
||||||
|
ssl_certificate_service: Arc::new(ssl_certificate::MockSslCertificateService::new()),
|
||||||
|
config_inheritance_service: Arc::new(config_inheritance::MockConfigInheritanceService::new()),
|
||||||
|
});
|
||||||
|
let router = get_root_router(state).await;
|
||||||
let server = TestServer::new(router);
|
let server = TestServer::new(router);
|
||||||
let fallback_response = server.get("/nonexistent").await;
|
let fallback_response = server.get("/nonexistent").await;
|
||||||
assert_eq!(fallback_response.status_code(), 200);
|
assert_eq!(fallback_response.status_code(), 200);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::{connector::agent::AgentConnectorTrait, service::certificate::Certifi
|
|||||||
|
|
||||||
pub mod agent;
|
pub mod agent;
|
||||||
pub mod certificate;
|
pub mod certificate;
|
||||||
|
pub mod error;
|
||||||
pub mod proxy;
|
pub mod proxy;
|
||||||
|
|
||||||
pub async fn start_master_server(
|
pub async fn start_master_server(
|
||||||
@@ -51,7 +52,68 @@ pub async fn start_master_server(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let axum_router = crate::routes::get_root_router().await;
|
let api_state = crate::routes::api::ApiState {
|
||||||
|
agent_service: Arc::new(crate::service::agent::AgentServiceImpl::new(
|
||||||
|
db_connection.clone(),
|
||||||
|
)),
|
||||||
|
proxy_service: Arc::new(crate::service::proxy::service::ProxyServiceImpl::new(
|
||||||
|
db_connection.clone(),
|
||||||
|
)),
|
||||||
|
server_block_service: Arc::new(
|
||||||
|
crate::service::proxy::server_block::ServerBlockServiceImpl::new(
|
||||||
|
db_connection.clone(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
upstream_service: Arc::new(
|
||||||
|
crate::service::proxy::upstream::UpstreamServiceImpl::new(db_connection.clone()),
|
||||||
|
),
|
||||||
|
location_block_service: Arc::new(
|
||||||
|
crate::service::proxy::location_block::LocationBlockServiceImpl::new(
|
||||||
|
db_connection.clone(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
access_rule_service: Arc::new(
|
||||||
|
crate::service::proxy::access_rule::AccessRuleServiceImpl::new(
|
||||||
|
db_connection.clone(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
cache_zone_service: Arc::new(
|
||||||
|
crate::service::proxy::cache_zone::CacheZoneServiceImpl::new(db_connection.clone()),
|
||||||
|
),
|
||||||
|
limit_rule_service: Arc::new(
|
||||||
|
crate::service::proxy::limit_rule::LimitRuleServiceImpl::new(db_connection.clone()),
|
||||||
|
),
|
||||||
|
limit_zone_service: Arc::new(
|
||||||
|
crate::service::proxy::limit_zone::LimitZoneServiceImpl::new(db_connection.clone()),
|
||||||
|
),
|
||||||
|
log_setting_service: Arc::new(
|
||||||
|
crate::service::proxy::log_setting::LogSettingServiceImpl::new(
|
||||||
|
db_connection.clone(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
proxy_setting_service: Arc::new(
|
||||||
|
crate::service::proxy::proxy_setting::ProxySettingServiceImpl::new(
|
||||||
|
db_connection.clone(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
rewrite_rule_service: Arc::new(
|
||||||
|
crate::service::proxy::rewrite_rule::RewriteRuleServiceImpl::new(
|
||||||
|
db_connection.clone(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ssl_certificate_service: Arc::new(
|
||||||
|
crate::service::proxy::ssl_certificate::SslCertificateServiceImpl::new(
|
||||||
|
db_connection.clone(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
config_inheritance_service: Arc::new(
|
||||||
|
crate::service::proxy::config_inheritance::ConfigInheritanceServiceImpl::new(
|
||||||
|
db_connection.clone(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
let axum_router = crate::routes::get_root_router(Arc::new(api_state)).await;
|
||||||
|
|
||||||
// Start the HTTP server
|
// Start the HTTP server
|
||||||
let addr = format!("{}:{}", settings.server.bind_address, settings.server.port)
|
let addr = format!("{}:{}", settings.server.bind_address, settings.server.port)
|
||||||
|
|||||||
Reference in New Issue
Block a user