fix(web): decode percent-encoded slugs in the knowledge content route
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:
@@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/dtoro/oikos/internal/httpapi/gen"
|
"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.
|
// panel needs the entity's own full content when it IS a knowledge entity.
|
||||||
func (s *Server) serveKnowledgeContent(w http.ResponseWriter, req *http.Request) {
|
func (s *Server) serveKnowledgeContent(w http.ResponseWriter, req *http.Request) {
|
||||||
ctx := req.Context()
|
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 title, content, source string
|
||||||
var tags []string
|
var tags []string
|
||||||
var updatedAt 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
|
SELECT ke.title, ke.content, COALESCE(ke.source,''), ke.tags, ke.updated_at::text
|
||||||
FROM knowledge_entities ke
|
FROM knowledge_entities ke
|
||||||
JOIN entities e ON e.id = ke.entity_id
|
JOIN entities e ON e.id = ke.entity_id
|
||||||
|
|||||||
Reference in New Issue
Block a user