aboutsummaryrefslogtreecommitdiff
path: root/internal/web/server.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/web/server.go')
-rw-r--r--internal/web/server.go33
1 files changed, 26 insertions, 7 deletions
diff --git a/internal/web/server.go b/internal/web/server.go
index d484b69..5886f0f 100644
--- a/internal/web/server.go
+++ b/internal/web/server.go
@@ -270,9 +270,12 @@ type lookupColumn struct {
// applies to a section's own citation via render.GatherVersion, not a
// free-typed lookup) against each requested version. Shared by lookupHandler
// (the HTMX partial) and indexHandler (so a bookmarked/shared "/?ref=..."
-// link shows the same result instead of an empty pane). An empty ref
-// renders nothing, matching lookupHandler's previous no-op behavior.
+// link shows the same result instead of an empty pane). ref is trimmed of
+// surrounding whitespace here so both routes treat a whitespace-only ref
+// identically; an empty (or now-empty) ref renders nothing, matching
+// lookupHandler's previous no-op behavior.
func renderLookup(ref string, versions []string) template.HTML {
+ ref = strings.TrimSpace(ref)
if ref == "" {
return ""
}
@@ -293,7 +296,7 @@ func renderLookup(ref string, versions []string) template.HTML {
// its doc comment for the lookup semantics).
func lookupHandler(cfg config.Config) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
- ref := strings.TrimSpace(r.URL.Query().Get("ref"))
+ ref := r.URL.Query().Get("ref") // renderLookup trims whitespace
w.Header().Set("Content-Type", "text/html; charset=utf-8")
io.WriteString(w, string(renderLookup(ref, requestVersions(cfg, r))))
}
@@ -322,11 +325,27 @@ func themeCSSHandler(cfg config.Config) http.HandlerFunc {
}
}
-// Run starts lectio-web: listens on cfg.WebPort (0 picks a free OS port),
-// prints the URL, best-effort opens it in a browser, and serves until the
-// listener errors.
+// defaultWebPort is the port chooseListener prefers when cfg.WebPort is 0.
+const defaultWebPort = 1099
+
+// chooseListener binds the port to serve on. port==0 means "prefer
+// defaultWebPort (1099), else let the OS pick a free port"; a non-zero port
+// is bound exactly (and its bind error surfaced if the port is in use).
+func chooseListener(port int) (net.Listener, error) {
+ if port != 0 {
+ return net.Listen("tcp", fmt.Sprintf(":%d", port))
+ }
+ if ln, err := net.Listen("tcp", fmt.Sprintf(":%d", defaultWebPort)); err == nil {
+ return ln, nil
+ }
+ return net.Listen("tcp", ":0") // 1099 taken -> any free port
+}
+
+// Run starts lectio-web: listens on cfg.WebPort via chooseListener (0
+// prefers 1099, falling back to a free OS port), prints the URL, best-effort
+// opens it in a browser, and serves until the listener errors.
func Run(cfg config.Config) error {
- ln, err := net.Listen("tcp", fmt.Sprintf(":%d", cfg.WebPort))
+ ln, err := chooseListener(cfg.WebPort)
if err != nil {
return err
}