commit 25defcd00c6af26d1c6cb4e23f784cdd1257465b
parent 58fb7a43091a0951bf0dea20950ff6895dd3f5a4
Author: David Eisinger <[email protected]>
Date: Sat, 11 Oct 2025 17:05:13 -0400
Strip UTM params
Diffstat:
1 file changed, 28 insertions(+), 0 deletions(-)
diff --git a/internal/api.go b/internal/api.go
@@ -498,6 +498,9 @@ func NewHandlerWithConfig(db *DB, cfg HandlerConfig) (http.Handler, error) {
http.Error(w, "invalid url", http.StatusBadRequest)
return
}
+ // Strip marketing params (utm*) from the URL before processing
+ sanitizedURL := stripUTMParams(req.URL)
+ req.URL = sanitizedURL
ctx, cancel := context.WithTimeout(r.Context(), 45*time.Second)
defer cancel()
isHTML := IsHTMLURL(ctx, req.URL)
@@ -1084,6 +1087,31 @@ func toRespWithArchive(ctx context.Context, db *DB, b *Bookmark) bookmarkRespons
return br
}
+// stripUTMParams removes query parameters whose keys start with "utm" (case-insensitive).
+func stripUTMParams(raw string) string {
+ u, err := url.Parse(raw)
+ if err != nil {
+ return raw
+ }
+ if u.RawQuery == "" {
+ return raw
+ }
+ q := u.Query()
+ changed := false
+ for key := range q {
+ if len(key) >= 3 && strings.HasPrefix(strings.ToLower(key), "utm") {
+ q.Del(key)
+ changed = true
+ }
+ }
+ if !changed {
+ return raw
+ }
+ u.RawQuery = q.Encode()
+ // If nothing left, ensure the URL doesn't end with a bare '?'
+ return u.String()
+}
+
// RSS structures and writer
type rssFeed struct {
XMLName xml.Name `xml:"rss"`