feat(help-center): expose public sitemap

This commit is contained in:
2026-06-06 08:26:10 +08:00
parent 8edfcda947
commit efceb22b4c
8 changed files with 92 additions and 8 deletions
+53
View File
@@ -2,7 +2,9 @@ package v1
import (
"encoding/json"
"html"
"net/http"
"os"
"strconv"
"strings"
@@ -43,6 +45,36 @@ func (h *PortalHandler) PublicGet(c *gin.Context) {
c.JSON(http.StatusOK, publicPortalPayload(portal))
}
// PublicSitemap returns the public help-center XML sitemap.
// GET /hc/:slug/sitemap.xml
func (h *PortalHandler) PublicSitemap(c *gin.Context) {
portal, ok := h.resolvePublicPortal(c)
if !ok {
return
}
baseURL := publicHelpCenterBaseURL(c, portal)
var b strings.Builder
b.WriteString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
b.WriteString("<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n")
for i := range portal.Articles {
article := &portal.Articles[i]
if article.Status != string(model.ArticleStatusPublished) {
continue
}
b.WriteString(" <url>\n")
b.WriteString(" <loc>")
b.WriteString(html.EscapeString(baseURL + "/hc/" + portal.Slug + "/articles/" + article.Slug))
b.WriteString("</loc>\n")
b.WriteString(" <lastmod>")
b.WriteString(article.UpdatedAt.Format("2006-01-02"))
b.WriteString("</lastmod>\n")
b.WriteString(" </url>\n")
}
b.WriteString("</urlset>\n")
c.Data(http.StatusOK, "application/xml; charset=utf-8", []byte(b.String()))
}
// Create creates a new portal.
// POST /api/v1/accounts/:account_id/portals
func (h *PortalHandler) Create(c *gin.Context) {
@@ -270,6 +302,27 @@ func (h *PortalHandler) resolvePublicPortal(c *gin.Context) (*model.Portal, bool
return portal, true
}
func publicHelpCenterBaseURL(c *gin.Context, portal *model.Portal) string {
baseURL := ""
if portal != nil {
baseURL = strings.TrimSpace(portal.CustomDomain)
}
if baseURL == "" {
baseURL = strings.TrimSpace(os.Getenv("FRONTEND_URL"))
}
if baseURL == "" && c != nil && c.Request != nil {
baseURL = c.Request.Host
}
baseURL = strings.TrimRight(baseURL, "/")
if baseURL == "" {
baseURL = "localhost:3000"
}
if !strings.Contains(baseURL, "://") {
baseURL = "https://" + baseURL
}
return baseURL
}
func portalDefaultLocale(portal *model.Portal) string {
if portal == nil {
return "en"