fix: filtered total

This commit is contained in:
2025-12-12 22:52:03 +08:00
parent 6336a451da
commit 094c871218
4 changed files with 45 additions and 30 deletions

View File

@@ -35,6 +35,7 @@
pkg-config
sqlite
gemini-cli
claude-code
biome
sqlx-cli
typos

View File

@@ -325,21 +325,19 @@ pub async fn list_logs(
State(state): State<Arc<AppContext>>,
Query(params): Query<ListLogsParams>,
) -> Result<Json<PaginatedRequestLogs>, (StatusCode, Json<ApiError>)> {
match (
db::repositories::logs::list(
&state.db,
params.method.as_deref(),
params.search.as_deref(),
params.limit,
params
.limit
.map(|limit| limit * (params.page.unwrap_or(1) - 1)),
)
.await,
db::repositories::logs::total(&state.db).await,
) {
(Ok(logs), Ok(total)) => Ok(Json(PaginatedRequestLogs { total, data: logs })),
(Err(e), _) | (_, Err(e)) => {
match db::repositories::logs::list(
&state.db,
params.method.as_deref(),
params.search.as_deref(),
params.limit,
params
.limit
.map(|limit| limit * (params.page.unwrap_or(1) - 1)),
)
.await
{
Ok((logs, total)) => Ok(Json(PaginatedRequestLogs { total, data: logs })),
Err(e) => {
error!("Failed to list logs: {}", e);
Err((
StatusCode::INTERNAL_SERVER_ERROR,

View File

@@ -1,26 +1,23 @@
use crate::db::models::{InterceptionAction, RequestLog};
use sqlx::{QueryBuilder, SqlitePool};
pub async fn total(pool: &SqlitePool) -> anyhow::Result<usize> {
Ok(
sqlx::query_scalar::<_, i64>("SELECT COUNT(*) FROM request_logs;")
.fetch_one(pool)
.await? as usize,
)
}
pub async fn list(
pool: &SqlitePool,
method: Option<&str>,
search: Option<&str>,
limit: Option<usize>,
offset: Option<usize>,
) -> anyhow::Result<Vec<RequestLog>> {
) -> anyhow::Result<(Vec<RequestLog>, usize)> {
let mut tx = pool.begin().await?;
let mut builder: QueryBuilder<sqlx::Sqlite> = QueryBuilder::new("SELECT * FROM request_logs");
let mut total_builder: QueryBuilder<sqlx::Sqlite> =
QueryBuilder::new("SELECT COUNT(*) FROM request_logs");
if let Some(method_val) = method {
builder.push(" WHERE method = ");
builder.push_bind(method_val);
total_builder.push(" WHERE method = ");
total_builder.push_bind(method_val);
}
if let Some(search_val) = search {
@@ -32,8 +29,18 @@ pub async fn list(
}
builder.push_bind(pattern.clone());
builder.push(" OR response_body LIKE ");
builder.push_bind(pattern);
builder.push_bind(pattern.clone());
builder.push(")");
if method.is_some() {
total_builder.push(" AND (request_body LIKE ");
} else {
total_builder.push(" WHERE (request_body LIKE ");
}
total_builder.push_bind(pattern.clone());
total_builder.push(" OR response_body LIKE ");
total_builder.push_bind(pattern);
total_builder.push(")");
}
if let Some(limit) = limit {
@@ -49,14 +56,22 @@ pub async fn list(
builder.push(" ORDER BY created_at DESC");
let query = builder.build_query_as();
Ok(query.fetch_all(pool).await?)
let logs = query.fetch_all(&mut *tx).await?;
let total = builder
.build_query_scalar::<i64>()
.fetch_one(&mut *tx)
.await? as usize;
tx.commit().await?;
Ok((logs, total))
}
pub async fn list_methods(pool: &SqlitePool) -> anyhow::Result<Vec<String>> {
Ok(
sqlx::query_scalar::<_, String>("SELECT DISTINCT method FROM request_logs ORDER BY method;")
.fetch_all(pool)
.await?
sqlx::query_scalar::<_, String>(
"SELECT DISTINCT method FROM request_logs ORDER BY method;",
)
.fetch_all(pool)
.await?,
)
}

View File

@@ -198,7 +198,8 @@ async fn process_response(body: String, method: &str, ctx: &Arc<AppContext>) ->
}
};
let modified_body_str = serde_json::to_string(&response_value).expect("serialization succeeded");
let modified_body_str =
serde_json::to_string(&response_value).expect("serialization succeeded");
let encrypted = ctx.cryptor.encrypt(modified_body_str.clone());
let final_ = action.map(|action| (modified_body_str.clone(), action));