From e8d32e87d1d6e4927250ad5794ba5965e0260153 Mon Sep 17 00:00:00 2001 From: goingforstudying-ctrl Date: Tue, 2 Jun 2026 11:02:21 -0400 Subject: [PATCH] fix: support in link previews (#6000) Co-authored-by: goingforstudying-ctrl --- internal/httpgetter/html_meta.go | 13 ++--- internal/httpgetter/html_meta_test.go | 68 +++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 6 deletions(-) diff --git a/internal/httpgetter/html_meta.go b/internal/httpgetter/html_meta.go index 2e72f1aac..8a5f31491 100644 --- a/internal/httpgetter/html_meta.go +++ b/internal/httpgetter/html_meta.go @@ -7,6 +7,7 @@ import ( "net" "net/http" "net/url" + "strings" "time" "github.com/pkg/errors" @@ -175,11 +176,6 @@ func extractHTMLMeta(resp io.Reader) *HTMLMeta { token := tokenizer.Token() htmlMeta.Title = token.Data } else if token.DataAtom == atom.Meta { - description, ok := extractMetaProperty(token, "description") - if ok { - htmlMeta.Description = description - } - ogTitle, ok := extractMetaProperty(token, "og:title") if ok { htmlMeta.Title = ogTitle @@ -194,6 +190,11 @@ func extractHTMLMeta(resp io.Reader) *HTMLMeta { if ok { htmlMeta.Image = ogImage } + + description, ok := extractMetaProperty(token, "description") + if ok && htmlMeta.Description == "" { + htmlMeta.Description = description + } } } } @@ -204,7 +205,7 @@ func extractHTMLMeta(resp io.Reader) *HTMLMeta { func extractMetaProperty(token html.Token, prop string) (content string, ok bool) { content, ok = "", false for _, attr := range token.Attr { - if attr.Key == "property" && attr.Val == prop { + if (attr.Key == "property" || attr.Key == "name") && strings.EqualFold(attr.Val, prop) { ok = true } if attr.Key == "content" { diff --git a/internal/httpgetter/html_meta_test.go b/internal/httpgetter/html_meta_test.go index d5d77bad1..f10e5ac83 100644 --- a/internal/httpgetter/html_meta_test.go +++ b/internal/httpgetter/html_meta_test.go @@ -55,6 +55,74 @@ func TestGetHTMLMeta(t *testing.T) { }, *metadata) } +func TestGetHTMLMetaWithNameOnly(t *testing.T) { + originalHTTPClient := httpClient + t.Cleanup(func() { + httpClient = originalHTTPClient + }) + + httpClient = &http.Client{ + Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) { + require.Equal(t, "http://93.184.216.34/blog", req.URL.String()) + return &http.Response{ + StatusCode: http.StatusOK, + Header: http.Header{"Content-Type": []string{"text/html; charset=utf-8"}}, + Body: io.NopCloser(strings.NewReader(` + + + Sample Page + + +Hello +`)), + Request: req, + }, nil + }), + } + + metadata, err := GetHTMLMeta("http://93.184.216.34/blog") + require.NoError(t, err) + require.Equal(t, HTMLMeta{ + Title: "Sample Page", + Description: "This description should appear in the link preview.", + Image: "", + }, *metadata) +} + +func TestGetHTMLMetaWithNameCaseInsensitive(t *testing.T) { + originalHTTPClient := httpClient + t.Cleanup(func() { + httpClient = originalHTTPClient + }) + + httpClient = &http.Client{ + Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) { + require.Equal(t, "http://93.184.216.34/blog", req.URL.String()) + return &http.Response{ + StatusCode: http.StatusOK, + Header: http.Header{"Content-Type": []string{"text/html; charset=utf-8"}}, + Body: io.NopCloser(strings.NewReader(` + + + Sample Page + + +Hello +`)), + Request: req, + }, nil + }), + } + + metadata, err := GetHTMLMeta("http://93.184.216.34/blog") + require.NoError(t, err) + require.Equal(t, HTMLMeta{ + Title: "Sample Page", + Description: "Case insensitive description match.", + Image: "", + }, *metadata) +} + func TestGetHTMLMetaForInternal(t *testing.T) { // test for internal IP if _, err := GetHTMLMeta("http://192.168.0.1"); !errors.Is(err, ErrInternalIP) {