tavern/fed/webfinger.go

93 lines
2.5 KiB
Go

package fed
import (
"fmt"
"net/http"
"net/url"
"strings"
"go.uber.org/zap"
"github.com/ngerakines/tavern/storage"
)
type HTTPClient interface {
Do(req *http.Request) (*http.Response, error)
}
type WebFingerClient struct {
HTTPClient HTTPClient
Logger *zap.Logger
}
func (client WebFingerClient) Fetch(location string) (storage.Payload, error) {
destination, err := BuildWebFingerURL(location)
if err != nil {
return nil, err
}
client.Logger.Debug("Sending webfinger request", zap.String("url", destination))
_, payload, err := ldJsonGet(client.HTTPClient, destination)
return payload, err
}
func BuildWebFingerURL(location string) (string, error) {
if strings.HasPrefix(location, "@") {
location = strings.TrimPrefix(location, "@")
parts := strings.Split(location, "@")
if len(parts) != 2 {
return "", fmt.Errorf("invalid actor location: %s", location)
}
q := url.QueryEscape(location)
return fmt.Sprintf("https://%s/.well-known/webfinger?resource=acct:%s", parts[1], q), nil
}
if strings.Index(location, "@") != -1 {
parts := strings.Split(strings.TrimPrefix(location, "@"), "@")
if len(parts) != 2 {
return "", fmt.Errorf("invalid actor location: %s", location)
}
q := url.QueryEscape(location)
return fmt.Sprintf("https://%s/.well-known/webfinger?resource=acct:%s", parts[1], q), nil
}
u, err := url.Parse(location)
if err != nil {
return "", err
}
q := url.QueryEscape(location)
return fmt.Sprintf("https://%s/.well-known/webfinger?resource=acct:%s", u.Host, q), nil
}
func ActorIDFromWebFingerPayload(wfp storage.Payload) (string, error) {
if wfp == nil {
return "", fmt.Errorf("unable to get actor href from webfinger content: wfp nil")
}
links, ok := wfp["links"]
if !ok {
return "", fmt.Errorf("unable to get actor href from webfinger content")
}
objLinks, ok := links.([]interface{})
if !ok {
return "", fmt.Errorf("unable to get actor href from webfinger content: links not array")
}
if len(objLinks) < 1 {
return "", fmt.Errorf("unable to get actor href from webfinger content: links empty")
}
first := objLinks[0]
firstMap, ok := first.(map[string]interface{})
if !ok {
return "", fmt.Errorf("unable to get actor href from webfinger content: first link not map")
}
href, ok := firstMap["href"]
if !ok {
return "", fmt.Errorf("unable to get actor href from webfinger content: href present")
}
hrefStr, ok := href.(string)
if !ok {
return "", fmt.Errorf("unable to get actor href from webfinger content: href not string")
}
return hrefStr, nil
}