feat: add OpenSearch XML endpoint

- Serve /opensearch.xml with configurable base URL
- Browsers can now add gosearch as a search engine from the address bar
- Configurable via [server] base_url or BASE_URL env var
- XML template embedded in the binary via go:embed
- Added base_url to config.example.toml
This commit is contained in:
Franz Kafka 2026-03-21 17:40:05 +00:00
parent 3caf702c4f
commit 4ec600f6c0
6 changed files with 51 additions and 0 deletions

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>gosearch</ShortName>
<Description>A privacy-respecting, open metasearch engine</Description>
<InputEncoding>UTF-8</InputEncoding>
<OutputEncoding>UTF-8</OutputEncoding>
<LongName>gosearch — Privacy-respecting metasearch</LongName>
<Image width="16" height="16" type="image/svg+xml">/static/img/favicon.svg</Image>
<Contact>https://git.ashisgreat.xyz/penal-colony/gosearch</Contact>
<Url type="text/html" method="GET" template="{baseUrl}/search?q={searchTerms}&amp;format=html">
<Param name="pageno" value="{startPage?}" />
<Param name="language" value="{language?}" />
</Url>
<Url type="application/json" method="GET" template="{baseUrl}/search?q={searchTerms}&amp;format=json" />
<Query role="example" searchTerms="golang" />
</OpenSearchDescription>

View file

@ -80,6 +80,18 @@ func StaticFS() (fs.FS, error) {
return fs.Sub(staticFS, "static")
}
// OpenSearchXML returns the OpenSearch description XML with {baseUrl}
// replaced by the provided base URL.
func OpenSearchXML(baseURL string) ([]byte, error) {
tmplFS, _ := fs.Sub(templatesFS, "templates")
data, err := fs.ReadFile(tmplFS, "opensearch.xml")
if err != nil {
return nil, err
}
result := strings.ReplaceAll(string(data), "{baseUrl}", baseURL)
return []byte(result), nil
}
// FromResponse builds PageData from a search response and request params.
func FromResponse(resp contracts.SearchResponse, query string, pageno int) PageData {
pd := PageData{