Parse HubURL from RSS 2.0 feeds
This commit is contained in:
parent
ddd850db4d
commit
6b66e5d548
|
@ -2,24 +2,81 @@ package websub
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"linkheader"
|
||||
"rss"
|
||||
)
|
||||
|
||||
// Fetcher return the response for a url
|
||||
type Fetcher interface {
|
||||
Fetch(url string) (*http.Response, error)
|
||||
}
|
||||
|
||||
// GetHubURL finds the HubURL for topic
|
||||
func GetHubURL(client *http.Client, topic string) (string, error) {
|
||||
hubURL, err := parseLinkHeaders(client, topic)
|
||||
if err == nil {
|
||||
return hubURL, err
|
||||
}
|
||||
|
||||
hubURL, err = parseBodyLinks(client, topic)
|
||||
if err == nil {
|
||||
return hubURL, err
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("No hub url found for topic %s", topic)
|
||||
}
|
||||
|
||||
func isFeedContentType(contentType string) bool {
|
||||
if strings.HasPrefix(contentType, "application/rss+xml") {
|
||||
return true
|
||||
}
|
||||
if strings.HasPrefix(contentType, "application/atom+xml") {
|
||||
return true
|
||||
}
|
||||
if strings.HasPrefix(contentType, "application/xml") {
|
||||
return true
|
||||
}
|
||||
if strings.HasPrefix(contentType, "text/xml") {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func parseBodyLinks(client *http.Client, topic string) (string, error) {
|
||||
resp, err := client.Get(topic)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if isFeedContentType(resp.Header.Get("Content-Type")) {
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
feed, err := rss.Parse(body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if feed.HubURL != "" {
|
||||
return feed.HubURL, nil
|
||||
}
|
||||
return "", fmt.Errorf("No hub url found in RSS feed")
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("Unknown content type of response: %s", resp.Header.Get("Content-Type"))
|
||||
}
|
||||
|
||||
func parseLinkHeaders(client *http.Client, topic string) (string, error) {
|
||||
resp, err := client.Head(topic)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
if headers, e := resp.Header["Link"]; e {
|
||||
|
@ -31,7 +88,7 @@ func GetHubURL(client *http.Client, topic string) (string, error) {
|
|||
}
|
||||
}
|
||||
|
||||
return "", nil
|
||||
return "", fmt.Errorf("No hub url found in HTTP Link headers")
|
||||
}
|
||||
|
||||
// Subscribe subscribes topicURL on hubURL
|
||||
|
|
1
vendor/rss/rss.go
vendored
1
vendor/rss/rss.go
vendored
|
@ -91,6 +91,7 @@ type Feed struct {
|
|||
Description string `json:"description"`
|
||||
Link string `json:"link"` // Link to the creator's website.
|
||||
UpdateURL string `json:"updateurl"` // URL of the feed itself.
|
||||
HubURL string `json:"huburl"` // URL of the WebSub hub
|
||||
Image *Image `json:"image"` // Feed icon.
|
||||
Items []*Item `json:"items"`
|
||||
ItemMap map[string]struct{} `json:"itemmap"` // Used in checking whether an item has been seen before.
|
||||
|
|
5
vendor/rss/rss_2.0.go
vendored
5
vendor/rss/rss_2.0.go
vendored
|
@ -30,9 +30,12 @@ func parseRSS2(data []byte) (*Feed, error) {
|
|||
for _, link := range channel.Link {
|
||||
if link.Rel == "" && link.Type == "" && link.Href == "" && link.Chardata != "" {
|
||||
out.Link = link.Chardata
|
||||
break
|
||||
}
|
||||
if link.Rel == "hub" {
|
||||
out.HubURL = link.Href
|
||||
}
|
||||
}
|
||||
|
||||
out.Image = channel.Image.Image()
|
||||
if channel.MinsToLive != 0 {
|
||||
sort.Ints(channel.SkipHours)
|
||||
|
|
Loading…
Reference in New Issue
Block a user