test: added create location with proxy pass tests
All checks were successful
Test / test-frontend (pull_request) Successful in 24s
Test / lint-frontend (pull_request) Successful in 27s
Test / frontend-build (pull_request) Successful in 31s
Verify / verify-generated-agent-code (pull_request) Successful in 1m37s
Verify / verify-generated-database-code (pull_request) Successful in 3m4s
Verify / verify-openapi-spec (pull_request) Successful in 3m0s
Verify / verify-frontend-api-client (pull_request) Successful in 20s
Test / lint-crates (pull_request) Successful in 1m3s
Test / test-crates (pull_request) Successful in 2m50s
All checks were successful
Test / test-frontend (pull_request) Successful in 24s
Test / lint-frontend (pull_request) Successful in 27s
Test / frontend-build (pull_request) Successful in 31s
Verify / verify-generated-agent-code (pull_request) Successful in 1m37s
Verify / verify-generated-database-code (pull_request) Successful in 3m4s
Verify / verify-openapi-spec (pull_request) Successful in 3m0s
Verify / verify-frontend-api-client (pull_request) Successful in 20s
Test / lint-crates (pull_request) Successful in 1m3s
Test / test-crates (pull_request) Successful in 2m50s
This commit is contained in:
@@ -49,6 +49,87 @@ pub struct CreateLocationRequestBodyByProxyPass {
|
||||
pub custom_config: Option<String>,
|
||||
}
|
||||
|
||||
impl From<(uuid::Uuid, CreateLocationRequestBody)> for CreateLocationInfo {
|
||||
fn from(val: (uuid::Uuid, CreateLocationRequestBody)) -> Self {
|
||||
match val.1 {
|
||||
CreateLocationRequestBody::UpstreamId(body) => Self::from((val.0, body)),
|
||||
CreateLocationRequestBody::ProxyPass(body) => Self::from((val.0, body)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(uuid::Uuid, CreateLocationRequestBodyByUpstreamId)> for CreateLocationInfo {
|
||||
fn from((proxy_id, payload): (uuid::Uuid, CreateLocationRequestBodyByUpstreamId)) -> Self {
|
||||
Self {
|
||||
host_id: proxy_id,
|
||||
path: payload.path,
|
||||
match_type: payload.match_type,
|
||||
order: payload.order,
|
||||
upstream_id: Some(payload.upstream_id),
|
||||
proxy_pass_protocol: None,
|
||||
proxy_pass_host: None,
|
||||
proxy_pass_port: None,
|
||||
preserve_host_header: payload.preserve_host_header,
|
||||
allowed_methods: payload.allowed_methods,
|
||||
custom_config: payload.custom_config,
|
||||
enabled: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(uuid::Uuid, CreateLocationRequestBodyByProxyPass)> for CreateLocationInfo {
|
||||
fn from((proxy_id, payload): (uuid::Uuid, CreateLocationRequestBodyByProxyPass)) -> Self {
|
||||
Self {
|
||||
host_id: proxy_id,
|
||||
path: payload.path,
|
||||
match_type: payload.match_type,
|
||||
order: payload.order,
|
||||
upstream_id: None,
|
||||
proxy_pass_protocol: Some(payload.proxy_pass_protocol),
|
||||
proxy_pass_host: Some(payload.proxy_pass_host),
|
||||
proxy_pass_port: Some(payload.proxy_pass_port),
|
||||
preserve_host_header: payload.preserve_host_header,
|
||||
allowed_methods: payload.allowed_methods,
|
||||
custom_config: payload.custom_config,
|
||||
enabled: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[axum::debug_handler]
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/nginx/proxy_hosts/{proxy_id}/locations",
|
||||
request_body = CreateLocationRequestBody,
|
||||
responses(
|
||||
(status = 200, description = "Location created", body = LocationInfoResponse),
|
||||
(status = 401, description = "Unauthorized"),
|
||||
(status = 422, description = "Invalid request"),
|
||||
(status = 500, description = "Internal server error"),
|
||||
),
|
||||
tag = NGINX_TAG,
|
||||
)]
|
||||
pub async fn create_location(
|
||||
_request_info: AuthenticatedRequestInfo,
|
||||
axum::extract::Path(proxy_id): axum::extract::Path<uuid::Uuid>,
|
||||
State(state): State<Arc<AppState>>,
|
||||
Json(payload): Json<CreateLocationRequestBody>,
|
||||
) -> AxumResult<Json<LocationInfoResponse>, ApiError> {
|
||||
let svc = &state.service.nginx.get_location_service();
|
||||
let create_info: CreateLocationInfo = (proxy_id, payload).into();
|
||||
|
||||
let mut tx = state.database_connection.begin().await?;
|
||||
let info = svc.create_location(create_info, Some(&mut tx)).await?;
|
||||
state
|
||||
.service
|
||||
.nginx
|
||||
.regenerate_and_apply_config(state.service.agent_client.clone(), &Some(&mut tx))
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
|
||||
Ok(Json(info.into()))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::sync::Arc;
|
||||
@@ -63,6 +144,7 @@ mod tests {
|
||||
configs::{FromConfig, ProgramSettings},
|
||||
middlewares::require_auth::mock::REQUEST_AUTH_USER_INVALID_HEADER,
|
||||
routes::api::restricted::nginx::proxy_host::{
|
||||
create_location::CreateLocationRequestBodyByProxyPass,
|
||||
create_location::CreateLocationRequestBodyByUpstreamId, get_proxy_router,
|
||||
},
|
||||
services::{agent_client::MockAgentService, get_mock_app_service},
|
||||
@@ -162,6 +244,84 @@ mod tests {
|
||||
assert_eq!(body.id, loc_id);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn handler_create_location_proxy_pass_succeeds_returns_created() {
|
||||
let ph_id = uuid::Uuid::new_v4();
|
||||
let loc_id = uuid::Uuid::new_v4();
|
||||
|
||||
let loc_model = location::Model {
|
||||
id: loc_id,
|
||||
host_id: ph_id,
|
||||
path: "/".to_string(),
|
||||
match_type: "prefix".to_string(),
|
||||
order: 1,
|
||||
upstream_id: None,
|
||||
proxy_pass_protocol: Some("http".to_string()),
|
||||
proxy_pass_host: Some("127.0.0.1".to_string()),
|
||||
proxy_pass_port: Some(8080),
|
||||
preserve_host_header: None,
|
||||
allowed_methods: None,
|
||||
custom_config: None,
|
||||
enabled: true,
|
||||
created_at: chrono::Utc::now(),
|
||||
updated_at: chrono::Utc::now(),
|
||||
};
|
||||
|
||||
let up_id = uuid::Uuid::new_v4();
|
||||
let up_model = upstream::Model {
|
||||
id: up_id,
|
||||
name: "u1".to_string(),
|
||||
protocol: "http".to_string(),
|
||||
algorithm: "rr".to_string(),
|
||||
sticky_session: false,
|
||||
created_by: None,
|
||||
created_at: chrono::Utc::now(),
|
||||
updated_at: chrono::Utc::now(),
|
||||
};
|
||||
let target_model = upstream_target::Model {
|
||||
id: uuid::Uuid::new_v4(),
|
||||
upstream_id: up_id,
|
||||
target_host: "127.0.0.1".to_string(),
|
||||
target_port: 8080,
|
||||
weight: 1,
|
||||
is_backup: false,
|
||||
enabled: true,
|
||||
created_at: chrono::Utc::now(),
|
||||
updated_at: chrono::Utc::now(),
|
||||
};
|
||||
let dummy_row: Vec<MockRow> = vec![];
|
||||
|
||||
let db = MockDatabase::new(DatabaseBackend::Sqlite)
|
||||
.append_query_results(vec![vec![loc_model.clone()]])
|
||||
// additional query result for regenerate_and_apply_config -> generate_config
|
||||
.append_query_results(vec![vec![(up_model.clone(), Some(target_model.clone()))]])
|
||||
.append_query_results(vec![dummy_row])
|
||||
.into_connection();
|
||||
|
||||
let router = get_router_with_state(db.clone());
|
||||
let server = TestServer::new(router).expect("failed to create test server");
|
||||
|
||||
let payload = CreateLocationRequestBodyByProxyPass {
|
||||
path: "/".to_string(),
|
||||
match_type: "prefix".to_string(),
|
||||
order: 1,
|
||||
proxy_pass_protocol: "http".to_string(),
|
||||
proxy_pass_host: "127.0.0.1".to_string(),
|
||||
proxy_pass_port: 8080,
|
||||
preserve_host_header: None,
|
||||
allowed_methods: None,
|
||||
custom_config: None,
|
||||
};
|
||||
|
||||
let res = server
|
||||
.post(&format!("/proxy_hosts/{}/locations", ph_id))
|
||||
.json(&payload)
|
||||
.await;
|
||||
res.assert_status_ok();
|
||||
let body = res.json::<crate::routes::api::restricted::nginx::proxy_host::info::response::LocationInfoResponse>();
|
||||
assert_eq!(body.id, loc_id);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn handler_create_location_invalid_payload_returns_bad_request() {
|
||||
let db = MockDatabase::new(DatabaseBackend::Sqlite).into_connection();
|
||||
@@ -200,84 +360,3 @@ mod tests {
|
||||
res.assert_status(StatusCode::UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(uuid::Uuid, CreateLocationRequestBody)> for CreateLocationInfo {
|
||||
fn from(val: (uuid::Uuid, CreateLocationRequestBody)) -> Self {
|
||||
match val.1 {
|
||||
CreateLocationRequestBody::UpstreamId(body) => Self::from((val.0, body)),
|
||||
CreateLocationRequestBody::ProxyPass(body) => Self::from((val.0, body)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(uuid::Uuid, CreateLocationRequestBodyByUpstreamId)> for CreateLocationInfo {
|
||||
fn from((proxy_id, payload): (uuid::Uuid, CreateLocationRequestBodyByUpstreamId)) -> Self {
|
||||
Self {
|
||||
host_id: proxy_id,
|
||||
path: payload.path,
|
||||
match_type: payload.match_type,
|
||||
order: payload.order,
|
||||
upstream_id: Some(payload.upstream_id),
|
||||
proxy_pass_protocol: None,
|
||||
proxy_pass_host: None,
|
||||
proxy_pass_port: None,
|
||||
preserve_host_header: payload.preserve_host_header,
|
||||
allowed_methods: payload.allowed_methods,
|
||||
custom_config: payload.custom_config,
|
||||
enabled: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(uuid::Uuid, CreateLocationRequestBodyByProxyPass)> for CreateLocationInfo {
|
||||
fn from((proxy_id, payload): (uuid::Uuid, CreateLocationRequestBodyByProxyPass)) -> Self {
|
||||
Self {
|
||||
host_id: proxy_id,
|
||||
path: payload.path,
|
||||
match_type: payload.match_type,
|
||||
order: payload.order,
|
||||
upstream_id: None,
|
||||
proxy_pass_protocol: Some(payload.proxy_pass_protocol),
|
||||
proxy_pass_host: Some(payload.proxy_pass_host),
|
||||
proxy_pass_port: Some(payload.proxy_pass_port),
|
||||
preserve_host_header: payload.preserve_host_header,
|
||||
allowed_methods: payload.allowed_methods,
|
||||
custom_config: payload.custom_config,
|
||||
enabled: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[axum::debug_handler]
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/nginx/proxy_hosts/{proxy_id}/locations",
|
||||
request_body = CreateLocationRequestBody,
|
||||
responses(
|
||||
(status = 200, description = "Location created", body = LocationInfoResponse),
|
||||
(status = 401, description = "Unauthorized"),
|
||||
(status = 422, description = "Invalid request"),
|
||||
(status = 500, description = "Internal server error"),
|
||||
),
|
||||
tag = NGINX_TAG,
|
||||
)]
|
||||
pub async fn create_location(
|
||||
_request_info: AuthenticatedRequestInfo,
|
||||
axum::extract::Path(proxy_id): axum::extract::Path<uuid::Uuid>,
|
||||
State(state): State<Arc<AppState>>,
|
||||
Json(payload): Json<CreateLocationRequestBody>,
|
||||
) -> AxumResult<Json<LocationInfoResponse>, ApiError> {
|
||||
let svc = &state.service.nginx.get_location_service();
|
||||
let create_info: CreateLocationInfo = (proxy_id, payload).into();
|
||||
|
||||
let mut tx = state.database_connection.begin().await?;
|
||||
let info = svc.create_location(create_info, Some(&mut tx)).await?;
|
||||
state
|
||||
.service
|
||||
.nginx
|
||||
.regenerate_and_apply_config(state.service.agent_client.clone(), &Some(&mut tx))
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
|
||||
Ok(Json(info.into()))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user