package main import ( "crypto/x509" "encoding/json" "encoding/pem" "fmt" "net/http" "strings" ) func hostMetaHandler(w http.ResponseWriter, r *http.Request) { headers := w.Header() headers.Add("Content-Type", "application/xrd+xml") headers.Add("Content-Type", "charset=utf-8") fmt.Fprintf(w, ``, host) } func handlerUserPage(w http.ResponseWriter, r *http.Request) { parts := strings.SplitN(strings.Trim(r.URL.Path, " /"), "/", 2) if len(parts) < 2 { http.Error(w, "page not found", http.StatusNotFound) return } name := parts[1] app, ok := apps[name] if !ok { http.Error(w, "page not found", http.StatusNotFound) return } userURL := fmt.Sprintf("%s/u/%s", fullhost, name) contextes := []string{ "https://www.w3.org/ns/activitystreams", } var pubkey *pubKeyBlock = nil if app.PublicKey != nil { pubKeyBytes := x509.MarshalPKCS1PublicKey(app.PublicKey) pubKeyPem := string(pem.EncodeToMemory(&pem.Block{ Type: "PUBLIC KEY", Bytes: pubKeyBytes, })) contextes = append(contextes, "https://w3id.org/security/v1") pubkey = &pubKeyBlock{ ID: userURL + "#main-key", Owner: userURL, PEM: pubKeyPem, } } headers := w.Header() headers.Add("Content-Type", "application/activity+json") headers.Add("Content-Type", "charset=utf-8") err := json.NewEncoder(w).Encode(profilePage{ Context: contextes, ID: userURL, Type: "Person", PreferredUsername: name, Name: app.Name, Inbox: fmt.Sprintf("%s/inbox", fullhost), Followers: fmt.Sprintf("%s/followers", userURL), PublicKey: pubkey, }) if err != nil { http.Error(w, "Error encoding page: "+err.Error(), http.StatusInternalServerError) } } func handlerWebFinger(w http.ResponseWriter, r *http.Request) { params := r.URL.Query() resource := params.Get("resource") if resource == "" { http.Error(w, "must include a valid resource", http.StatusBadRequest) return } parts := strings.SplitN(resource, ":", 2) if len(parts) < 2 { http.Error(w, "invalid resource specified", http.StatusBadRequest) return } switch parts[0] { case "acct": // Split user by host userParts := strings.SplitN(parts[1], "@", 2) if len(userParts) < 2 || strings.ToLower(userParts[1]) != host { http.Error(w, "Invalid user specified", http.StatusBadRequest) return } // Check if user is a registered app _, ok := apps[userParts[0]] if !ok { http.Error(w, "user not found", http.StatusNotFound) return } headers := w.Header() headers.Add("Content-Type", "application/json") headers.Add("Content-Type", "charset=utf-8") err := json.NewEncoder(w).Encode(profileWebFingerData{ Subject: resource, Links: []profileLink{ { Rel: "self", Type: "application/activity+json", Href: fmt.Sprintf("%s/u/%s", fullhost, userParts[0]), }, }, }) if err != nil { http.Error(w, "Error encoding webfinger: "+err.Error(), http.StatusInternalServerError) } } }