Sending Webmentions #10

Merged
h4kor merged 18 commits from webmention into master 2022-09-06 19:49:00 +00:00
2 changed files with 125 additions and 40 deletions
Showing only changes of commit edca158985 - Show all commits

View File

@ -68,6 +68,9 @@ func readResponseBody(resp *http.Response) (string, error) {
func (OwlHtmlParser) ParseHEntry(resp *http.Response) (ParsedHEntry, error) { func (OwlHtmlParser) ParseHEntry(resp *http.Response) (ParsedHEntry, error) {
htmlStr, err := readResponseBody(resp) htmlStr, err := readResponseBody(resp)
if err != nil {
return ParsedHEntry{}, err
}
doc, err := html.Parse(strings.NewReader(htmlStr)) doc, err := html.Parse(strings.NewReader(htmlStr))
if err != nil { if err != nil {
return ParsedHEntry{}, err return ParsedHEntry{}, err
@ -144,7 +147,27 @@ func (OwlHtmlParser) ParseLinksFromString(htmlStr string) ([]string, error) {
} }
func (OwlHtmlParser) GetWebmentionEndpoint(resp *http.Response) (string, error) { func (OwlHtmlParser) GetWebmentionEndpoint(resp *http.Response) (string, error) {
//request url
requestUrl := resp.Request.URL
// Check link headers
for _, link := range resp.Header["Link"] {
if strings.Contains(link, "rel=\"webmention\"") || strings.Contains(link, "rel=webmention") {
link := strings.Split(link, ";")[0]
link = strings.Trim(link, "<>")
linkUrl, err := url.Parse(link)
if err != nil {
return "", err
}
return requestUrl.ResolveReference(linkUrl).String(), nil
}
}
htmlStr, err := readResponseBody(resp) htmlStr, err := readResponseBody(resp)
if err != nil {
return "", err
}
doc, err := html.Parse(strings.NewReader(htmlStr)) doc, err := html.Parse(strings.NewReader(htmlStr))
if err != nil { if err != nil {
return "", err return "", err
@ -154,7 +177,7 @@ func (OwlHtmlParser) GetWebmentionEndpoint(resp *http.Response) (string, error)
findEndpoint = func(n *html.Node) (string, error) { findEndpoint = func(n *html.Node) (string, error) {
if n.Type == html.ElementNode && (n.Data == "link" || n.Data == "a") { if n.Type == html.ElementNode && (n.Data == "link" || n.Data == "a") {
for _, attr := range n.Attr { for _, attr := range n.Attr {
if attr.Key == "rel" && attr.Val == "webmention" { if attr.Key == "rel" && strings.Contains(attr.Val, "webmention") {
for _, attr := range n.Attr { for _, attr := range n.Attr {
if attr.Key == "href" { if attr.Key == "href" {
return attr.Val, nil return attr.Val, nil
@ -171,5 +194,13 @@ func (OwlHtmlParser) GetWebmentionEndpoint(resp *http.Response) (string, error)
} }
return "", errors.New("no webmention endpoint found") return "", errors.New("no webmention endpoint found")
} }
return findEndpoint(doc) linkUrlStr, err := findEndpoint(doc)
if err != nil {
return "", err
}
linkUrl, err := url.Parse(linkUrlStr)
if err != nil {
return "", err
}
return requestUrl.ResolveReference(linkUrl).String(), nil
} }

View File

@ -5,9 +5,20 @@ import (
"h4kor/owl-blogs" "h4kor/owl-blogs"
"io" "io"
"net/http" "net/http"
"net/url"
"testing" "testing"
) )
func constructResponse(html []byte) *http.Response {
url, _ := url.Parse("http://example.com/foo/bar")
return &http.Response{
Request: &http.Request{
URL: url,
},
Body: io.NopCloser(bytes.NewReader([]byte(html))),
}
}
// //
// https://www.w3.org/TR/webmention/#h-webmention-verification // https://www.w3.org/TR/webmention/#h-webmention-verification
// //
@ -41,7 +52,7 @@ func TestParseValidHEntryWithoutTitle(t *testing.T) {
func TestGetWebmentionEndpointLink(t *testing.T) { func TestGetWebmentionEndpointLink(t *testing.T) {
html := []byte("<link rel=\"webmention\" href=\"http://example.com/webmention\" />") html := []byte("<link rel=\"webmention\" href=\"http://example.com/webmention\" />")
parser := &owl.OwlHtmlParser{} parser := &owl.OwlHtmlParser{}
endpoint, err := parser.GetWebmentionEndpoint(&http.Response{Body: io.NopCloser(bytes.NewReader(html))}) endpoint, err := parser.GetWebmentionEndpoint(constructResponse(html))
if err != nil { if err != nil {
t.Errorf("Unable to parse feed: %v", err) t.Errorf("Unable to parse feed: %v", err)
@ -54,7 +65,7 @@ func TestGetWebmentionEndpointLink(t *testing.T) {
func TestGetWebmentionEndpointLinkA(t *testing.T) { func TestGetWebmentionEndpointLinkA(t *testing.T) {
html := []byte("<a rel=\"webmention\" href=\"http://example.com/webmention\" />") html := []byte("<a rel=\"webmention\" href=\"http://example.com/webmention\" />")
parser := &owl.OwlHtmlParser{} parser := &owl.OwlHtmlParser{}
endpoint, err := parser.GetWebmentionEndpoint(&http.Response{Body: io.NopCloser(bytes.NewReader(html))}) endpoint, err := parser.GetWebmentionEndpoint(constructResponse(html))
if err != nil { if err != nil {
t.Errorf("Unable to parse feed: %v", err) t.Errorf("Unable to parse feed: %v", err)
@ -64,42 +75,85 @@ func TestGetWebmentionEndpointLinkA(t *testing.T) {
} }
} }
// func TestRealWorldWebmention(t *testing.T) { func TestGetWebmentionEndpointLinkHeader(t *testing.T) {
// links := []string{ html := []byte("")
// "https://webmention.rocks/test/1", parser := &owl.OwlHtmlParser{}
// "https://webmention.rocks/test/2", resp := constructResponse(html)
// "https://webmention.rocks/test/3", resp.Header = http.Header{"Link": []string{"<http://example.com/webmention>; rel=\"webmention\""}}
// "https://webmention.rocks/test/4", endpoint, err := parser.GetWebmentionEndpoint(resp)
// "https://webmention.rocks/test/5",
// "https://webmention.rocks/test/6",
// "https://webmention.rocks/test/7",
// "https://webmention.rocks/test/8",
// "https://webmention.rocks/test/9",
// "https://webmention.rocks/test/10",
// "https://webmention.rocks/test/11",
// "https://webmention.rocks/test/12",
// "https://webmention.rocks/test/13",
// "https://webmention.rocks/test/14",
// "https://webmention.rocks/test/15",
// "https://webmention.rocks/test/16",
// "https://webmention.rocks/test/17",
// "https://webmention.rocks/test/18",
// "https://webmention.rocks/test/19",
// "https://webmention.rocks/test/20",
// "https://webmention.rocks/test/21",
// "https://webmention.rocks/test/22",
// "https://webmention.rocks/test/23/page",
// }
// for _, link := range links { if err != nil {
// parser := &owl.OwlHtmlParser{} t.Errorf("Unable to parse feed: %v", err)
// client := &owl.OwlHttpClient{} }
// html, _ := client.Get(link) if endpoint != "http://example.com/webmention" {
// _, err := parser.GetWebmentionEndpoint(html) t.Errorf("Wrong endpoint. Expected %v, got %v", "http://example.com/webmention", endpoint)
}
}
// if err != nil { func TestGetWebmentionEndpointRelativeLink(t *testing.T) {
// t.Errorf("Unable to find webmention: %v for link %v", err, link) html := []byte("<link rel=\"webmention\" href=\"/webmention\" />")
// } parser := &owl.OwlHtmlParser{}
// } endpoint, err := parser.GetWebmentionEndpoint(constructResponse(html))
// } if err != nil {
t.Errorf("Unable to parse feed: %v", err)
}
if endpoint != "http://example.com/webmention" {
t.Errorf("Wrong endpoint. Expected %v, got %v", "http://example.com/webmention", endpoint)
}
}
func TestGetWebmentionEndpointRelativeLinkInHeader(t *testing.T) {
html := []byte("<link rel=\"webmention\" href=\"/webmention\" />")
parser := &owl.OwlHtmlParser{}
resp := constructResponse(html)
resp.Header = http.Header{"Link": []string{"</webmention>; rel=\"webmention\""}}
endpoint, err := parser.GetWebmentionEndpoint(resp)
if err != nil {
t.Errorf("Unable to parse feed: %v", err)
}
if endpoint != "http://example.com/webmention" {
t.Errorf("Wrong endpoint. Expected %v, got %v", "http://example.com/webmention", endpoint)
}
}
func TestRealWorldWebmention(t *testing.T) {
links := []string{
"https://webmention.rocks/test/1",
"https://webmention.rocks/test/2",
"https://webmention.rocks/test/3",
"https://webmention.rocks/test/4",
"https://webmention.rocks/test/5",
"https://webmention.rocks/test/6",
"https://webmention.rocks/test/7",
"https://webmention.rocks/test/8",
"https://webmention.rocks/test/9",
// "https://webmention.rocks/test/10", // not supported
"https://webmention.rocks/test/11",
"https://webmention.rocks/test/12",
"https://webmention.rocks/test/13",
"https://webmention.rocks/test/14",
"https://webmention.rocks/test/15",
"https://webmention.rocks/test/16",
"https://webmention.rocks/test/17",
"https://webmention.rocks/test/18",
"https://webmention.rocks/test/19",
"https://webmention.rocks/test/20",
"https://webmention.rocks/test/21",
"https://webmention.rocks/test/22",
"https://webmention.rocks/test/23/page",
}
for _, link := range links {
parser := &owl.OwlHtmlParser{}
client := &owl.OwlHttpClient{}
html, _ := client.Get(link)
_, err := parser.GetWebmentionEndpoint(html)
if err != nil {
t.Errorf("Unable to find webmention: %v for link %v", err, link)
}
}
}