diff --git a/cmd/noxy/main.go b/cmd/noxy/main.go index bd9c4fb..c014149 100644 --- a/cmd/noxy/main.go +++ b/cmd/noxy/main.go @@ -130,7 +130,7 @@ func main() { log.Printf("listening on %s", *listenAddr) log.Printf("known relays: %s", strings.Join(knownRelays, ", ")) - http.ListenAndServe(*listenAddr, logHandler(mux)) + http.ListenAndServe(*listenAddr, logHandler(cors(mux))) } // handles requests to / @@ -198,6 +198,21 @@ func writeError(w http.ResponseWriter, err error) { fmt.Fprint(w, err.Error()) } +func cors(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Headers", "*") // nb: wildcard prevents authentication + w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS") + if r.Method == "OPTIONS" { + w.Header().Set("Access-Control-Max-Age", "2592000") // valid for 30 days + w.WriteHeader(http.StatusNoContent) + return + } + w.Header().Set("Access-Control-Expose-Headers", "*"); + h.ServeHTTP(w, r) + }) +} + func logHandler(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Printf("%s %s", r.Method, r.RequestURI) diff --git a/noxy.go b/noxy.go index f2d321e..0282e91 100644 --- a/noxy.go +++ b/noxy.go @@ -284,18 +284,12 @@ func (x *Noxer) verifyEventLink(ctx context.Context, eventID, relayURL, link str // link not found in the event text/json. // check URLs in OGP metadata for each suitable link found in the event. for _, urlStr := range eventURLs { - u, err := url.Parse(urlStr) - if err != nil { - continue // invalid url - } - if ext := path.Ext(u.Path); ext != "" { - if !strings.HasSuffix(ext, "html") && !strings.HasSuffix(ext, "htm") { - continue // assume not an html page - } + if !validOGPCandidate(urlStr) { + continue } meta, err := x.slurpLinkMeta(ctx, urlStr) if err != nil { - log.Printf("verifyEventLink slurpLinkMeta(%s): %v", u, err) + log.Printf("verifyEventLink slurpLinkMeta(%s): %v", urlStr, err) continue } for _, imgURL := range meta.ImageURLs { @@ -591,3 +585,23 @@ func validURL(urlStr string) bool { } return u.Scheme == "" || u.Scheme == "http" || u.Scheme == "https" } + +// must be sorted in lexical order +var knownOGPHosts = []string{ + "opengraph.githubassets.com", +} + +// reports whether urlStr looks like a URL to an html page. +func validOGPCandidate(urlStr string) bool { + u, err := url.Parse(urlStr) + if err != nil { + return false + } + ext := path.Ext(u.Path) + if ext == "" || strings.HasSuffix(ext, "html") || strings.HasSuffix(ext, "htm") { + return true + } + host := u.Hostname() + i := sort.SearchStrings(knownOGPHosts, host) + return i < len(knownOGPHosts) && knownOGPHosts[i] == host +}