diff --git a/config/config.exs b/config/config.exs
index 5753fad48..86622e1e6 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -151,6 +151,7 @@ config :logger, :ex_syslogger,
config :mime, :types, %{
"application/xml" => ["xml"],
"application/xrd+xml" => ["xrd+xml"],
+ "application/opensearchdescription+xml" => ["xml"],
"application/jrd+json" => ["jrd+json"],
"application/activity+json" => ["activity+json"],
"application/ld+json" => ["activity+json"]
diff --git a/lib/pleroma/web/opensearch_controller.ex b/lib/pleroma/web/opensearch_controller.ex
new file mode 100644
index 000000000..aac11a768
--- /dev/null
+++ b/lib/pleroma/web/opensearch_controller.ex
@@ -0,0 +1,16 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.OpenSearchController do
+ use Pleroma.Web, :controller
+
+ plug(:skip_auth when action == :show)
+
+ @doc "GET /opensearch.xml"
+ def show(conn, _params) do
+ conn
+ |> put_resp_content_type("application/opensearchdescription+xml")
+ |> render("opensearch.xml")
+ end
+end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index ca4995281..bb5091711 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -156,6 +156,10 @@ defmodule Pleroma.Web.Router do
plug(Pleroma.Web.Plugs.StaticFEPlug)
end
+ pipeline :accepts_opensearch do
+ plug(:accepts, ["xml"])
+ end
+
scope "/api/v1/pleroma", Pleroma.Web.TwitterAPI do
pipe_through(:pleroma_api)
@@ -865,6 +869,12 @@ defmodule Pleroma.Web.Router do
get("/web/manifest.json", MastoFEController, :manifest)
end
+ scope "/", Pleroma.Web do
+ pipe_through(:accepts_opensearch)
+
+ get("/opensearch.xml", OpenSearchController, :show)
+ end
+
scope "/", Pleroma.Web do
pipe_through(:mastodon_html)
diff --git a/lib/pleroma/web/templates/open_search/opensearch.xml.eex b/lib/pleroma/web/templates/open_search/opensearch.xml.eex
new file mode 100644
index 000000000..2f94fae85
--- /dev/null
+++ b/lib/pleroma/web/templates/open_search/opensearch.xml.eex
@@ -0,0 +1,9 @@
+
+
+ <%= Config.get([:instance, :name]) %>
+ Search through <%= Config.get([:instance, :name]) %>
+ UTF-8
+ <%= Endpoint.url() %>/favicon.ico
+ <%= Endpoint.url() %>/favicon.png
+
+
diff --git a/lib/pleroma/web/views/opensearch_view.ex b/lib/pleroma/web/views/opensearch_view.ex
new file mode 100644
index 000000000..437d0229f
--- /dev/null
+++ b/lib/pleroma/web/views/opensearch_view.ex
@@ -0,0 +1,9 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.OpenSearchView do
+ use Pleroma.Web, :view
+ alias Pleroma.Config
+ alias Pleroma.Web.Endpoint
+end
diff --git a/test/pleroma/web/opensearch_controller_test.exs b/test/pleroma/web/opensearch_controller_test.exs
new file mode 100644
index 000000000..24e118d66
--- /dev/null
+++ b/test/pleroma/web/opensearch_controller_test.exs
@@ -0,0 +1,21 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.OpenSearchControllerTest do
+ use Pleroma.Web.ConnCase, async: false
+ alias Pleroma.Config
+ alias Pleroma.Web.Endpoint
+
+ test "opensearch.xml", %{conn: conn} do
+ resp =
+ conn
+ |> put_req_header("accept", "application/opensearchdescription+xml")
+ |> get("/opensearch.xml")
+ |> response(200)
+
+ assert resp =~ "#{Config.get([:instance, :name])}"
+ assert resp =~ "Search through #{Config.get([:instance, :name])}"
+ assert resp =~ "template=\"#{Endpoint.url()}/search?query={searchTerms}\""
+ end
+end