fix(searxng): use POST instead of GET for SearXNG search API
All checks were successful
CI / Format (push) Successful in 2s
CI / Clippy (push) Successful in 2m8s
CI / Security Audit (push) Has been skipped
CI / Tests (push) Has been skipped
CI / Deploy (push) Has been skipped

SearXNG's default config sets `method: "POST"` which rejects GET
requests with 405. Switch both search_topic and get_trending_topics
to POST with form-encoded parameters.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-02-20 06:52:00 +01:00
parent 07e4433061
commit ba936543f4

View File

@@ -122,23 +122,21 @@ pub async fn search_topic(query: String) -> Result<Vec<NewsCard>, ServerFnError>
// similar to how Perplexity reformulates queries before searching. // similar to how Perplexity reformulates queries before searching.
let enriched_query = format!("{query} latest news"); let enriched_query = format!("{query} latest news");
// Build URL with query parameters using the url crate's encoder // Use POST with form-encoded body because SearXNG's default config
// to avoid reqwest version conflicts between our dep and dioxus's. // sets `method: "POST"` which rejects GET requests with 405.
// Key SearXNG params: let search_url = format!("{searxng_url}/search");
// categories=news,general - prioritize news sources + supplement with general let params = [
// time_range=month - only recent results (last 30 days) ("q", enriched_query.as_str()),
// language=en - English results ("format", "json"),
// format=json - machine-readable output ("language", "en"),
let encoded_query: String = ("categories", "news,general"),
url::form_urlencoded::byte_serialize(enriched_query.as_bytes()).collect(); ("time_range", "month"),
let search_url = format!( ];
"{searxng_url}/search?q={encoded_query}&format=json&language=en\
&categories=news,general&time_range=month"
);
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let resp = client let resp = client
.get(&search_url) .post(&search_url)
.form(&params)
.send() .send()
.await .await
.map_err(|e| ServerFnError::new(format!("SearXNG request failed: {e}")))?; .map_err(|e| ServerFnError::new(format!("SearXNG request failed: {e}")))?;
@@ -207,12 +205,15 @@ pub async fn get_trending_topics() -> Result<Vec<String>, ServerFnError> {
let searxng_url = let searxng_url =
std::env::var("SEARXNG_URL").unwrap_or_else(|_| "http://localhost:8888".into()); std::env::var("SEARXNG_URL").unwrap_or_else(|_| "http://localhost:8888".into());
let encoded_query: String = // Use POST to match SearXNG's default `method: "POST"` setting
url::form_urlencoded::byte_serialize(b"trending technology AI").collect(); let search_url = format!("{searxng_url}/search");
let search_url = format!( let params = [
"{searxng_url}/search?q={encoded_query}&format=json&language=en\ ("q", "trending technology AI"),
&categories=news&time_range=week" ("format", "json"),
); ("language", "en"),
("categories", "news"),
("time_range", "week"),
];
let client = reqwest::Client::builder() let client = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(5)) .timeout(std::time::Duration::from_secs(5))
@@ -220,7 +221,8 @@ pub async fn get_trending_topics() -> Result<Vec<String>, ServerFnError> {
.map_err(|e| ServerFnError::new(format!("HTTP client error: {e}")))?; .map_err(|e| ServerFnError::new(format!("HTTP client error: {e}")))?;
let resp = client let resp = client
.get(&search_url) .post(&search_url)
.form(&params)
.send() .send()
.await .await
.map_err(|e| ServerFnError::new(format!("SearXNG trending search failed: {e}")))?; .map_err(|e| ServerFnError::new(format!("SearXNG trending search failed: {e}")))?;