// Copyright (c) 2024 mStar // // Licensed under the EUPL, Version 1.2 // // You may not use this work except in compliance with the Licence. // You should have received a copy of the Licence along with this work. If not, see: // . // See the Licence for the specific language governing permissions and limitations under the Licence. // package ap import ( "encoding/json" "errors" "fmt" "net/http" "net/url" "strings" "github.com/julienschmidt/httprouter" "gitlab.com/mstarongitlab/goutils/other" "gitlab.com/mstarongitlab/linstrom/server" "gitlab.com/mstarongitlab/linstrom/types" ) var ErrInvalidResource = errors.New("invalid resource") type webfingerLink struct { Rel string `json:"self"` Type string `json:"type"` Target url.URL `json:"href"` } type WebfingerResponse struct { Subject string `json:"subject"` Links []webfingerLink `json:"links"` } func WebfingerEndpoint(server *server.Server) func(http.ResponseWriter, *http.Request, httprouter.Params) { return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { r.ParseForm() req := r.FormValue("resource") if req == "" { http.NotFound(w, r) return } acc, err := getAccountFromWebfingerResource(req) if errors.Is(err, ErrInvalidResource) { http.Error(w, err.Error(), http.StatusBadRequest) return } if acc.Host.Hostname() != server.Config.General.Domain { http.Error(w, fmt.Sprintf("wrong host, try %s", &acc.Host), http.StatusNotFound) return } response := WebfingerResponse{ Links: []webfingerLink{ { Rel: "me", Type: "application/activity+json", Target: *other.Must(url.Parse("https://example.com")), // TODO: Replace this with actual link generation }, }, } json.Marshal(response) } } // acct:bugle@bugle.lol func getAccountFromWebfingerResource(r string) (*types.AccountHandle, error) { acctCheck, acc, found := strings.Cut(r, ":") if !found || acctCheck != "acct" { return nil, ErrInvalidResource } name, rawHost, found := strings.Cut(acc, "@") if !found { return nil, ErrInvalidResource } host, err := url.Parse(rawHost) if err != nil { return nil, fmt.Errorf("%w: Invalid url: %w", ErrInvalidResource, err) } return &types.AccountHandle{ Name: name, Host: *host, }, nil }