diff --git a/src/web/assets/index.html b/src/web/assets/index.html
index 62868cf..4dd28e4 100644
--- a/src/web/assets/index.html
+++ b/src/web/assets/index.html
@@ -6,6 +6,7 @@
metasearch
+
diff --git a/src/web/mod.rs b/src/web/mod.rs
index e21975f..f7608f5 100644
--- a/src/web/mod.rs
+++ b/src/web/mod.rs
@@ -1,4 +1,5 @@
pub mod autocomplete;
+pub mod opensearch;
pub mod search;
use std::net::SocketAddr;
@@ -36,6 +37,7 @@ pub async fn run() {
)
}),
)
+ .route("/opensearch.xml", get(opensearch::route))
.route("/search", get(search::route))
.route("/autocomplete", get(autocomplete::route));
diff --git a/src/web/opensearch.rs b/src/web/opensearch.rs
new file mode 100644
index 0000000..690a858
--- /dev/null
+++ b/src/web/opensearch.rs
@@ -0,0 +1,29 @@
+use axum::{
+ http::{header, HeaderMap},
+ response::IntoResponse,
+};
+
+pub async fn route(headers: HeaderMap) -> impl IntoResponse {
+ let host = headers
+ .get("host")
+ .and_then(|host| host.to_str().ok())
+ .unwrap_or("localhost");
+
+ (
+ [(
+ header::CONTENT_TYPE,
+ "application/opensearchdescription+xml",
+ )],
+ format!(
+ r#"
+
+ metasearch
+ Search metasearch
+ UTF-8
+
+
+ "#
+ ),
+ )
+}
diff --git a/src/web/search.rs b/src/web/search.rs
index 27f4978..0246b99 100644
--- a/src/web/search.rs
+++ b/src/web/search.rs
@@ -22,6 +22,7 @@ fn render_beginning_of_html(query: &str) -> String {
{} - metasearch
+
@@ -149,6 +150,7 @@ pub async fn route(
let query = SearchQuery {
query,
request_headers: headers
+ .clone()
.into_iter()
.map(|(k, v)| {
(
@@ -157,7 +159,12 @@ pub async fn route(
)
})
.collect(),
- ip: addr.ip().to_string(),
+ ip: headers
+ // this could be exploited under some setups, but the ip is only used for the
+ // "what is my ip" answer so it doesn't really matter
+ .get("x-forwarded-for")
+ .map(|ip| ip.to_str().unwrap_or_default().to_string())
+ .unwrap_or_else(|| addr.ip().to_string()),
};
let s = stream! {