feat: add source_url config option for footer source link
Thread source_url through: config.ServerConfig → Handler.sourceURL → PageData.SourceURL → template footer. Footer only shows Source link when source_url is set.
This commit is contained in:
parent
bb0b97820b
commit
805e7ffdc2
6 changed files with 18 additions and 9 deletions
|
|
@ -77,7 +77,7 @@ func main() {
|
||||||
|
|
||||||
acSvc := autocomplete.NewService(cfg.Upstream.URL, cfg.HTTPTimeout())
|
acSvc := autocomplete.NewService(cfg.Upstream.URL, cfg.HTTPTimeout())
|
||||||
|
|
||||||
h := httpapi.NewHandler(svc, acSvc.Suggestions)
|
h := httpapi.NewHandler(svc, acSvc.Suggestions, cfg.Server.SourceURL)
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.HandleFunc("/", h.Index)
|
mux.HandleFunc("/", h.Index)
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,11 @@ http_timeout = "10s"
|
||||||
# Example: "https://search.example.com"
|
# Example: "https://search.example.com"
|
||||||
base_url = ""
|
base_url = ""
|
||||||
|
|
||||||
|
# Link to the source code (shown in footer as "Source" link)
|
||||||
|
# Defaults to the upstream kafka repo if not set.
|
||||||
|
# Example: "https://git.example.com/my-kafka-fork"
|
||||||
|
source_url = ""
|
||||||
|
|
||||||
[upstream]
|
[upstream]
|
||||||
# URL of an upstream metasearch instance for unported engines (env: UPSTREAM_SEARXNG_URL)
|
# URL of an upstream metasearch instance for unported engines (env: UPSTREAM_SEARXNG_URL)
|
||||||
# Leave empty to run without an upstream proxy.
|
# Leave empty to run without an upstream proxy.
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,8 @@ type Config struct {
|
||||||
type ServerConfig struct {
|
type ServerConfig struct {
|
||||||
Port int `toml:"port"`
|
Port int `toml:"port"`
|
||||||
HTTPTimeout string `toml:"http_timeout"`
|
HTTPTimeout string `toml:"http_timeout"`
|
||||||
BaseURL string `toml:"base_url"` // Public URL for OpenSearch XML (e.g. "https://search.example.com")
|
BaseURL string `toml:"base_url"` // Public URL for OpenSearch XML (e.g. "https://search.example.com")
|
||||||
|
SourceURL string `toml:"source_url"` // Link to the source code (e.g. "https://git.example.com/fork/kafka")
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpstreamConfig struct {
|
type UpstreamConfig struct {
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,14 @@ import (
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
searchSvc *search.Service
|
searchSvc *search.Service
|
||||||
autocompleteSvc func(ctx context.Context, query string) ([]string, error)
|
autocompleteSvc func(ctx context.Context, query string) ([]string, error)
|
||||||
|
sourceURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandler(searchSvc *search.Service, autocompleteSuggestions func(ctx context.Context, query string) ([]string, error)) *Handler {
|
func NewHandler(searchSvc *search.Service, autocompleteSuggestions func(ctx context.Context, query string) ([]string, error), sourceURL string) *Handler {
|
||||||
return &Handler{
|
return &Handler{
|
||||||
searchSvc: searchSvc,
|
searchSvc: searchSvc,
|
||||||
autocompleteSvc: autocompleteSuggestions,
|
autocompleteSvc: autocompleteSuggestions,
|
||||||
|
sourceURL: sourceURL,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,7 +53,7 @@ func (h *Handler) Index(w http.ResponseWriter, r *http.Request) {
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := views.RenderIndex(w); err != nil {
|
if err := views.RenderIndex(w, h.sourceURL); err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -80,7 +82,7 @@ func (h *Handler) Search(w http.ResponseWriter, r *http.Request) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// For HTML, render error on the results page.
|
// For HTML, render error on the results page.
|
||||||
if req.Format == contracts.FormatHTML || r.FormValue("format") == "html" {
|
if req.Format == contracts.FormatHTML || r.FormValue("format") == "html" {
|
||||||
pd := views.PageData{Query: r.FormValue("q")}
|
pd := views.PageData{SourceURL: h.sourceURL, Query: r.FormValue("q")}
|
||||||
if views.IsHTMXRequest(r) {
|
if views.IsHTMXRequest(r) {
|
||||||
views.RenderSearchFragment(w, pd)
|
views.RenderSearchFragment(w, pd)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -95,7 +97,7 @@ func (h *Handler) Search(w http.ResponseWriter, r *http.Request) {
|
||||||
resp, err := h.searchSvc.Search(r.Context(), req)
|
resp, err := h.searchSvc.Search(r.Context(), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if req.Format == contracts.FormatHTML {
|
if req.Format == contracts.FormatHTML {
|
||||||
pd := views.PageData{Query: req.Query}
|
pd := views.PageData{SourceURL: h.sourceURL, Query: req.Query}
|
||||||
if views.IsHTMXRequest(r) {
|
if views.IsHTMXRequest(r) {
|
||||||
views.RenderSearchFragment(w, pd)
|
views.RenderSearchFragment(w, pd)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<p>Powered by <a href="https://git.ashisgreat.xyz/penal-colony/kafka">kafka</a> — a privacy-respecting, open metasearch engine · <a href="https://git.ashisgreat.xyz/penal-colony/kafka">Source</a> · <a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPLv3</a></p>
|
<p>Powered by <a href="https://git.ashisgreat.xyz/penal-colony/kafka">kafka</a> — a privacy-respecting, open metasearch engine{{if .SourceURL}} · <a href="{{.SourceURL}}">Source</a>{{end}} · <a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPLv3</a></p>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script src="/static/js/settings.js"></script>
|
<script src="/static/js/settings.js"></script>
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ var staticFS embed.FS
|
||||||
|
|
||||||
// PageData holds all data passed to templates.
|
// PageData holds all data passed to templates.
|
||||||
type PageData struct {
|
type PageData struct {
|
||||||
|
SourceURL string
|
||||||
Query string
|
Query string
|
||||||
Pageno int
|
Pageno int
|
||||||
PrevPage int
|
PrevPage int
|
||||||
|
|
@ -187,9 +188,9 @@ func FromResponse(resp contracts.SearchResponse, query string, pageno int) PageD
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenderIndex renders the homepage (search box only).
|
// RenderIndex renders the homepage (search box only).
|
||||||
func RenderIndex(w http.ResponseWriter) error {
|
func RenderIndex(w http.ResponseWriter, sourceURL string) error {
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
return tmplIndex.ExecuteTemplate(w, "base", PageData{ShowHeader: true})
|
return tmplIndex.ExecuteTemplate(w, "base", PageData{ShowHeader: true, SourceURL: sourceURL})
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenderSearch renders the full search results page (with base layout).
|
// RenderSearch renders the full search results page (with base layout).
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue