From edca1589858211c94e1c8665b47568b1bf251eb3 Mon Sep 17 00:00:00 2001 From: Niko Abeler Date: Tue, 6 Sep 2022 21:01:08 +0200 Subject: [PATCH] most webmention endpoints working --- webmention.go | 35 +++++++++++- webmention_test.go | 130 ++++++++++++++++++++++++++++++++------------- 2 files changed, 125 insertions(+), 40 deletions(-) diff --git a/webmention.go b/webmention.go index 0e47c43..4a82994 100644 --- a/webmention.go +++ b/webmention.go @@ -68,6 +68,9 @@ func readResponseBody(resp *http.Response) (string, error) { func (OwlHtmlParser) ParseHEntry(resp *http.Response) (ParsedHEntry, error) { htmlStr, err := readResponseBody(resp) + if err != nil { + return ParsedHEntry{}, err + } doc, err := html.Parse(strings.NewReader(htmlStr)) if err != nil { return ParsedHEntry{}, err @@ -144,7 +147,27 @@ func (OwlHtmlParser) ParseLinksFromString(htmlStr string) ([]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) + if err != nil { + return "", err + } doc, err := html.Parse(strings.NewReader(htmlStr)) if err != nil { return "", err @@ -154,7 +177,7 @@ func (OwlHtmlParser) GetWebmentionEndpoint(resp *http.Response) (string, error) findEndpoint = func(n *html.Node) (string, error) { if n.Type == html.ElementNode && (n.Data == "link" || n.Data == "a") { 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 { if attr.Key == "href" { return attr.Val, nil @@ -171,5 +194,13 @@ func (OwlHtmlParser) GetWebmentionEndpoint(resp *http.Response) (string, error) } 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 } diff --git a/webmention_test.go b/webmention_test.go index abb7bea..682587d 100644 --- a/webmention_test.go +++ b/webmention_test.go @@ -5,9 +5,20 @@ import ( "h4kor/owl-blogs" "io" "net/http" + "net/url" "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 // @@ -41,7 +52,7 @@ func TestParseValidHEntryWithoutTitle(t *testing.T) { func TestGetWebmentionEndpointLink(t *testing.T) { html := []byte("") parser := &owl.OwlHtmlParser{} - endpoint, err := parser.GetWebmentionEndpoint(&http.Response{Body: io.NopCloser(bytes.NewReader(html))}) + endpoint, err := parser.GetWebmentionEndpoint(constructResponse(html)) if err != nil { t.Errorf("Unable to parse feed: %v", err) @@ -54,7 +65,7 @@ func TestGetWebmentionEndpointLink(t *testing.T) { func TestGetWebmentionEndpointLinkA(t *testing.T) { html := []byte("") parser := &owl.OwlHtmlParser{} - endpoint, err := parser.GetWebmentionEndpoint(&http.Response{Body: io.NopCloser(bytes.NewReader(html))}) + endpoint, err := parser.GetWebmentionEndpoint(constructResponse(html)) if err != nil { t.Errorf("Unable to parse feed: %v", err) @@ -64,42 +75,85 @@ func TestGetWebmentionEndpointLinkA(t *testing.T) { } } -// 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", -// "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", -// } +func TestGetWebmentionEndpointLinkHeader(t *testing.T) { + html := []byte("") + parser := &owl.OwlHtmlParser{} + resp := constructResponse(html) + resp.Header = http.Header{"Link": []string{"; rel=\"webmention\""}} + endpoint, err := parser.GetWebmentionEndpoint(resp) -// 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 parse feed: %v", err) + } + if endpoint != "http://example.com/webmention" { + t.Errorf("Wrong endpoint. Expected %v, got %v", "http://example.com/webmention", endpoint) + } +} -// if err != nil { -// t.Errorf("Unable to find webmention: %v for link %v", err, link) -// } -// } +func TestGetWebmentionEndpointRelativeLink(t *testing.T) { + html := []byte("") + 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("") + parser := &owl.OwlHtmlParser{} + resp := constructResponse(html) + resp.Header = http.Header{"Link": []string{"; 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) + } + } + +}