fix(web): decode percent-encoded slugs in the knowledge content route
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled

chi.URLParam returns the raw, still-encoded path segment — unlike the
OpenAPI-generated routes, which decode via
runtime.BindStyledParameterWithOptions before the handler sees them. Slugs
like "document:containers/101-jellyfin" (encoded by the frontend's
encodeURIComponent) were arriving undecoded and matching no row. Found via
a standalone chi repro, not by patching the live deploy checkout.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-13 10:29:42 +02:00
parent 61ad785fef
commit d1243aceac

View File

@@ -5,6 +5,7 @@ import (
"encoding/json"
"log/slog"
"net/http"
"net/url"
"strconv"
"github.com/dtoro/oikos/internal/httpapi/gen"
@@ -116,12 +117,21 @@ func (s *Server) serveRecentKnowledge(w http.ResponseWriter, req *http.Request)
// panel needs the entity's own full content when it IS a knowledge entity.
func (s *Server) serveKnowledgeContent(w http.ResponseWriter, req *http.Request) {
ctx := req.Context()
idOrSlug := chi.URLParam(req, "id")
// chi.URLParam returns the raw, still-percent-encoded segment (unlike
// the OpenAPI-generated routes, which decode via
// runtime.BindStyledParameterWithOptions before reaching the handler) —
// slugs like "document:containers/101-jellyfin" arrive as
// "document%3Acontainers%2F101-jellyfin" and must be unescaped here.
idOrSlug, err := url.PathUnescape(chi.URLParam(req, "id"))
if err != nil {
writeProblem(w, req, http.StatusBadRequest, "invalid id", err.Error())
return
}
var title, content, source string
var tags []string
var updatedAt string
err := s.pool.QueryRow(ctx, `
err = s.pool.QueryRow(ctx, `
SELECT ke.title, ke.content, COALESCE(ke.source,''), ke.tags, ke.updated_at::text
FROM knowledge_entities ke
JOIN entities e ON e.id = ke.entity_id