mirror of
https://github.com/nkanaev/yarr.git
synced 2025-05-24 00:33:14 +00:00
single http client to rule them all
This commit is contained in:
parent
14ec19a3a6
commit
8a1314902b
@ -10,6 +10,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FeedSource struct {
|
type FeedSource struct {
|
||||||
@ -31,6 +32,22 @@ const feedLinks = `
|
|||||||
a:contains("FEED")
|
a:contains("FEED")
|
||||||
`
|
`
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
httpClient *http.Client
|
||||||
|
userAgent string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) get(url string) (*http.Response, error) {
|
||||||
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("User-Agent", c.userAgent)
|
||||||
|
return c.httpClient.Do(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultClient *Client
|
||||||
|
|
||||||
func searchFeedLinks(html []byte, siteurl string) ([]FeedSource, error) {
|
func searchFeedLinks(html []byte, siteurl string) ([]FeedSource, error) {
|
||||||
sources := make([]FeedSource, 0, 0)
|
sources := make([]FeedSource, 0, 0)
|
||||||
|
|
||||||
@ -57,15 +74,14 @@ func searchFeedLinks(html []byte, siteurl string) ([]FeedSource, error) {
|
|||||||
return sources, nil
|
return sources, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func discoverFeed(url, userAgent string) (*gofeed.Feed, *[]FeedSource, error) {
|
func discoverFeed(url string) (*gofeed.Feed, *[]FeedSource, error) {
|
||||||
// Query URL
|
// Query URL
|
||||||
feedreq, _ := http.NewRequest("GET", url, nil)
|
res, err := defaultClient.get(url)
|
||||||
feedreq.Header.Set("user-agent", userAgent)
|
|
||||||
feedclient := &http.Client{}
|
|
||||||
res, err := feedclient.Do(feedreq)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
} else if res.StatusCode != 200 {
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
if res.StatusCode != 200 {
|
||||||
errmsg := fmt.Sprintf("Failed to fetch feed %s (status: %d)", url, res.StatusCode)
|
errmsg := fmt.Sprintf("Failed to fetch feed %s (status: %d)", url, res.StatusCode)
|
||||||
return nil, nil, errors.New(errmsg)
|
return nil, nil, errors.New(errmsg)
|
||||||
}
|
}
|
||||||
@ -95,7 +111,7 @@ func discoverFeed(url, userAgent string) (*gofeed.Feed, *[]FeedSource, error) {
|
|||||||
if sources[0].Url == url {
|
if sources[0].Url == url {
|
||||||
return nil, nil, errors.New("Recursion!")
|
return nil, nil, errors.New("Recursion!")
|
||||||
}
|
}
|
||||||
return discoverFeed(sources[0].Url, userAgent)
|
return discoverFeed(sources[0].Url)
|
||||||
}
|
}
|
||||||
return nil, &sources, nil
|
return nil, &sources, nil
|
||||||
}
|
}
|
||||||
@ -134,8 +150,6 @@ func findFavicon(websiteUrl, feedUrl string) (*[]byte, error) {
|
|||||||
candidateUrls = append(candidateUrls, c)
|
candidateUrls = append(candidateUrls, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
client := http.Client{}
|
|
||||||
|
|
||||||
imageTypes := [4]string{
|
imageTypes := [4]string{
|
||||||
"image/x-icon",
|
"image/x-icon",
|
||||||
"image/png",
|
"image/png",
|
||||||
@ -143,7 +157,12 @@ func findFavicon(websiteUrl, feedUrl string) (*[]byte, error) {
|
|||||||
"image/gif",
|
"image/gif",
|
||||||
}
|
}
|
||||||
for _, url := range candidateUrls {
|
for _, url := range candidateUrls {
|
||||||
if res, err := client.Get(url); err == nil && res.StatusCode == 200 {
|
res, err := defaultClient.get(url)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
if res.StatusCode == 200 {
|
||||||
if content, err := ioutil.ReadAll(res.Body); err == nil {
|
if content, err := ioutil.ReadAll(res.Body); err == nil {
|
||||||
ctype := http.DetectContentType(content)
|
ctype := http.DetectContentType(content)
|
||||||
for _, itype := range imageTypes {
|
for _, itype := range imageTypes {
|
||||||
@ -186,10 +205,22 @@ func convertItems(items []*gofeed.Item, feed storage.Feed) []storage.Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func listItems(f storage.Feed) ([]storage.Item, error) {
|
func listItems(f storage.Feed) ([]storage.Item, error) {
|
||||||
fp := gofeed.NewParser()
|
res, err := defaultClient.get(f.FeedLink)
|
||||||
feed, err := fp.ParseURL(f.FeedLink)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
feedparser := gofeed.NewParser()
|
||||||
|
feed, err := feedparser.Parse(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return convertItems(feed.Items, f), nil
|
return convertItems(feed.Items, f), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
defaultClient = &Client{
|
||||||
|
httpClient: &http.Client{Timeout: time.Second * 5},
|
||||||
|
userAgent: "Yarr/1.0",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -227,7 +227,7 @@ func FeedListHandler(rw http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
feed, sources, err := discoverFeed(form.Url, req.Header.Get("user-agent"))
|
feed, sources, err := discoverFeed(form.Url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handler(req).log.Print(err)
|
handler(req).log.Print(err)
|
||||||
writeJSON(rw, map[string]string{"status": "notfound"})
|
writeJSON(rw, map[string]string{"status": "notfound"})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user