fix: support <meta name=description> in link previews (#6000)
Co-authored-by: goingforstudying-ctrl <goingforstudying-ctrl@users.noreply.github.com>
This commit is contained in:
parent
0d31e3c2fb
commit
e8d32e87d1
2 changed files with 75 additions and 6 deletions
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
@ -175,11 +176,6 @@ func extractHTMLMeta(resp io.Reader) *HTMLMeta {
|
||||||
token := tokenizer.Token()
|
token := tokenizer.Token()
|
||||||
htmlMeta.Title = token.Data
|
htmlMeta.Title = token.Data
|
||||||
} else if token.DataAtom == atom.Meta {
|
} else if token.DataAtom == atom.Meta {
|
||||||
description, ok := extractMetaProperty(token, "description")
|
|
||||||
if ok {
|
|
||||||
htmlMeta.Description = description
|
|
||||||
}
|
|
||||||
|
|
||||||
ogTitle, ok := extractMetaProperty(token, "og:title")
|
ogTitle, ok := extractMetaProperty(token, "og:title")
|
||||||
if ok {
|
if ok {
|
||||||
htmlMeta.Title = ogTitle
|
htmlMeta.Title = ogTitle
|
||||||
|
|
@ -194,6 +190,11 @@ func extractHTMLMeta(resp io.Reader) *HTMLMeta {
|
||||||
if ok {
|
if ok {
|
||||||
htmlMeta.Image = ogImage
|
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) {
|
func extractMetaProperty(token html.Token, prop string) (content string, ok bool) {
|
||||||
content, ok = "", false
|
content, ok = "", false
|
||||||
for _, attr := range token.Attr {
|
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
|
ok = true
|
||||||
}
|
}
|
||||||
if attr.Key == "content" {
|
if attr.Key == "content" {
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,74 @@ func TestGetHTMLMeta(t *testing.T) {
|
||||||
}, *metadata)
|
}, *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(`<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Sample Page</title>
|
||||||
|
<meta name="description" content="This description should appear in the link preview.">
|
||||||
|
</head>
|
||||||
|
<body>Hello</body>
|
||||||
|
</html>`)),
|
||||||
|
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(`<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Sample Page</title>
|
||||||
|
<meta name="Description" content="Case insensitive description match.">
|
||||||
|
</head>
|
||||||
|
<body>Hello</body>
|
||||||
|
</html>`)),
|
||||||
|
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) {
|
func TestGetHTMLMetaForInternal(t *testing.T) {
|
||||||
// test for internal IP
|
// test for internal IP
|
||||||
if _, err := GetHTMLMeta("http://192.168.0.1"); !errors.Is(err, ErrInternalIP) {
|
if _, err := GetHTMLMeta("http://192.168.0.1"); !errors.Is(err, ErrInternalIP) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue