Move websub to own package

- Move websub own package
- Add flag to disable auth (by default enabled)
- Process feed directly when following
This commit is contained in:
Peter Stuifzand 2018-05-23 21:53:00 +02:00
parent 82f9b63b26
commit ddd850db4d
5 changed files with 110 additions and 55 deletions

View File

@ -12,6 +12,10 @@ import (
"github.com/pstuifzand/ekster/pkg/indieauth"
)
func init() {
log.SetFlags(log.Lshortfile | log.Ldate | log.Ltime)
}
func loadAuth(c *client.Client, filename string) error {
f, err := os.Open(filename)
if err != nil {

View File

@ -23,27 +23,29 @@ import (
"io"
"log"
"net/http"
"net/url"
"os"
"regexp"
"time"
"linkheader"
"github.com/garyburd/redigo/redis"
"github.com/pstuifzand/ekster/microsub"
"github.com/pstuifzand/ekster/pkg/util"
"github.com/pstuifzand/ekster/pkg/websub"
)
var (
pool *redis.Pool
port int
auth bool
redisServer = flag.String("redis", "redis:6379", "")
entryRegex = regexp.MustCompile("^entry\\[\\d+\\]$")
)
func init() {
log.SetFlags(log.Lshortfile | log.Ldate | log.Ltime)
flag.IntVar(&port, "port", 80, "port for serving api")
flag.BoolVar(&auth, "auth", true, "use auth")
}
type mainHandler struct {
@ -73,29 +75,6 @@ func (h *hubIncomingBackend) GetSecret(id int64) string {
return secret
}
func (h *hubIncomingBackend) getHubURL(topic string) (string, error) {
client := &http.Client{}
resp, err := client.Head(topic)
if err != nil {
return "", err
}
defer resp.Body.Close()
if headers, e := resp.Header["Link"]; e {
links := linkheader.ParseMultiple(headers)
for _, link := range links {
if link.Rel == "hub" {
log.Printf("WebSub Hub URL found for topic=%s hub=%s\n", topic, link.URL)
return link.URL, nil
}
}
}
log.Printf("WebSub Hub URL not found for topic=%s\n", topic)
return "", nil
}
func (h *hubIncomingBackend) CreateFeed(topic string, channel string) (int64, error) {
conn := pool.Get()
defer conn.Close()
@ -110,29 +89,23 @@ func (h *hubIncomingBackend) CreateFeed(topic string, channel string) (int64, er
secret := util.RandStringBytes(16)
conn.Do("HSET", fmt.Sprintf("feed:%d", id), "secret", secret)
hubURL, err := h.getHubURL(topic)
client := &http.Client{}
hubURL, err := websub.GetHubURL(client, topic)
if hubURL == "" {
log.Printf("WebSub Hub URL not found for topic=%s\n", topic)
} else {
log.Printf("WebSub Hub URL found for topic=%s hub=%s\n", topic, hubURL)
}
if err == nil && hubURL != "" {
conn.Do("HSET", fmt.Sprintf("feed:%d", id), "hub", hubURL)
} else {
return id, nil
}
hub, err := url.Parse(hubURL)
q := hub.Query()
q.Add("hub.mode", "subscribe")
q.Add("hub.callback", fmt.Sprintf("%s/incoming/%d", os.Getenv("EKSTER_BASEURL"), id))
q.Add("hub.topic", topic)
q.Add("hub.secret", secret)
hub.RawQuery = ""
log.Printf("POST %s\n", hub)
client := &http.Client{}
res, err := client.PostForm(hub.String(), q)
if err != nil {
log.Printf("new request: %s\n", err)
return 0, err
}
defer res.Body.Close()
callbackURL := fmt.Sprintf("%s/incoming/%d", os.Getenv("EKSTER_BASEURL"), id)
websub.Subscribe(client, hubURL, topic, callbackURL, secret, 24*3600)
return id, nil
}
@ -168,6 +141,12 @@ func main() {
log.Println("eksterd - microsub server")
flag.Parse()
if auth {
log.Println("Using auth")
} else {
log.Println("Authentication disabled")
}
if _, e := os.LookupEnv("EKSTER_BASEURL"); !e {
log.Fatal("EKSTER_BASEURL environment variable not found, please set with external url: https://example.com")
}

View File

@ -50,7 +50,6 @@ type Debug interface {
}
func init() {
log.SetFlags(log.Lshortfile | log.Ldate | log.Ltime)
}
func (b *memoryBackend) Debug() {
@ -550,7 +549,17 @@ func (b *memoryBackend) FollowGetList(uid string) []microsub.Feed {
func (b *memoryBackend) FollowURL(uid string, url string) microsub.Feed {
defer b.save()
feed := microsub.Feed{Type: "feed", URL: url}
resp, err := b.Fetch3(uid, feed.URL)
if err != nil {
return feed
}
defer resp.Body.Close()
b.Feeds[uid] = append(b.Feeds[uid], feed)
b.ProcessContent(uid, feed.URL, resp.Header.Get("Content-Type"), resp.Body)
return feed
}

View File

@ -26,20 +26,23 @@ func (h *microsubHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
log.Printf("%s %s\n", r.Method, r.URL)
log.Println(r.URL.Query())
log.Println(r.PostForm)
authorization := r.Header.Get("Authorization")
var token TokenResponse
if auth {
authorization := r.Header.Get("Authorization")
if !h.cachedCheckAuthToken(authorization, &token) {
log.Printf("Token could not be validated")
http.Error(w, "Can't validate token", 403)
return
}
var token TokenResponse
if token.Me != h.Backend.(*memoryBackend).Me {
log.Printf("Missing \"me\" in token response: %#v\n", token)
http.Error(w, "Wrong me", 403)
return
if !h.cachedCheckAuthToken(authorization, &token) {
log.Printf("Token could not be validated")
http.Error(w, "Can't validate token", 403)
return
}
if token.Me != h.Backend.(*memoryBackend).Me {
log.Printf("Missing \"me\" in token response: %#v\n", token)
http.Error(w, "Wrong me", 403)
return
}
}
if r.Method == http.MethodGet {

60
pkg/websub/subscribe.go Normal file
View File

@ -0,0 +1,60 @@
package websub
import (
"fmt"
"net/http"
"net/url"
"linkheader"
)
// 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) {
resp, err := client.Head(topic)
if err != nil {
return "", err
}
defer resp.Body.Close()
if headers, e := resp.Header["Link"]; e {
links := linkheader.ParseMultiple(headers)
for _, link := range links {
if link.Rel == "hub" {
return link.URL, nil
}
}
}
return "", nil
}
// Subscribe subscribes topicURL on hubURL
func Subscribe(client *http.Client, hubURL, topicURL, callbackURL, secret string, leaseSeconds int) error {
hub, err := url.Parse(hubURL)
if err != nil {
return err
}
q := hub.Query()
q.Add("hub.mode", "subscribe")
q.Add("hub.callback", callbackURL)
q.Add("hub.topic", topicURL)
q.Add("hub.secret", secret)
q.Add("hub.lease_seconds", fmt.Sprintf("%d", leaseSeconds))
hub.RawQuery = ""
res, err := client.PostForm(hub.String(), q)
if err != nil {
return err
}
defer res.Body.Close()
return nil
}