Skip to main content

systemprompt_api/routes/content/
query.rs

1//! Content search endpoint over `SearchService`.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use axum::extract::State;
7use axum::http::StatusCode;
8use axum::response::{IntoResponse, Response};
9use axum::{Extension, Json};
10use systemprompt_content::{ContentError, SearchRequest, SearchService};
11use systemprompt_models::RequestContext;
12use systemprompt_runtime::AppContext;
13
14pub async fn query_handler(
15    Extension(_req_ctx): Extension<RequestContext>,
16    State(ctx): State<AppContext>,
17    Json(request): Json<SearchRequest>,
18) -> Response {
19    log_search_start(&request.query);
20
21    let search_service = match SearchService::new(ctx.db_pool()) {
22        Ok(service) => service,
23        Err(e) => return handle_service_error(&e),
24    };
25
26    execute_search(&search_service, &request).await
27}
28
29fn log_search_start(query: &str) {
30    tracing::info!(query = %query, "Searching");
31}
32
33fn handle_service_error(e: &ContentError) -> Response {
34    tracing::error!(error = %e, "Failed to create search service");
35    internal_error(&e.to_string())
36}
37
38async fn execute_search(service: &SearchService, request: &SearchRequest) -> Response {
39    match service.search(request).await {
40        Ok(response) => {
41            tracing::info!(total = response.total, "Search completed");
42            Json(response).into_response()
43        },
44        Err(e) => {
45            tracing::error!(error = %e, "Search error");
46            internal_error(&e.to_string())
47        },
48    }
49}
50
51fn internal_error(message: &str) -> Response {
52    (
53        StatusCode::INTERNAL_SERVER_ERROR,
54        Json(serde_json::json!({"error": message})),
55    )
56        .into_response()
57}