internal/website/mux.go (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | package website import ( "encoding/json" "net/http" "regexp" "slices" "strings" ihttp "go.alanpearce.eu/homestead/internal/http" "go.alanpearce.eu/homestead/internal/server" "github.com/kevinpollet/nego" ) func (website *Website) webfinger(w http.ResponseWriter, r *http.Request) *ihttp.Error { if r.URL.Query().Get("resource") == website.acctResource { w.Header().Add("Content-Type", "application/jrd+json") w.Header().Add("Access-Control-Allow-Origin", "*") if err := json.NewEncoder(w).Encode(website.me); err != nil { return &ihttp.Error{ Code: http.StatusInternalServerError, Cause: err, } } } return nil } func (website *Website) ServeHTTP(w http.ResponseWriter, r *http.Request) *ihttp.Error { urlPath, shouldRedirect := website.reader.CanonicalisePath(r.URL.Path) if shouldRedirect { http.Redirect(w, r, urlPath, 302) return nil } file, err := website.reader.GetFile(urlPath) if err != nil { website.log.Warn("Error reading file", "error", err) return &ihttp.Error{ Message: "Error reading file", Code: http.StatusInternalServerError, } } if file == nil { return &ihttp.Error{ Message: "File not found", Code: http.StatusNotFound, } } w.Header().Add("ETag", file.Etag) w.Header().Add("Vary", "Accept-Encoding") w.Header().Add("Content-Security-Policy", website.config.CSP.String()) for k, v := range website.config.Extra.Headers { w.Header().Add(k, v) } enc := nego.NegotiateContentEncoding(r, file.AvailableEncodings()...) if enc != "" { w.Header().Add("Content-Encoding", enc) } w.Header().Add("Content-Type", file.ContentType) http.ServeContent(w, r, file.Path, file.LastModified, file.Encodings[enc]) return nil } func (website *Website) MakeRedirectorApp() *server.App { mux := http.NewServeMux() re := regexp.MustCompile( "^(.*)\\." + strings.ReplaceAll(website.config.WildcardDomain, ".", `\.`) + "$", ) replace := "${1}." + website.config.Domains[0] mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { switch { case slices.Contains(website.config.Domains, r.Host): path, _ := website.reader.CanonicalisePath(r.URL.Path) ihttp.Redirect( w, r, website.config.BaseURL.JoinPath(path), http.StatusMovedPermanently, ) case re.MatchString(r.Host): url := website.config.BaseURL.JoinPath() url.Host = re.ReplaceAllString(r.Host, replace) ihttp.Redirect(w, r, url, http.StatusTemporaryRedirect) case true: http.NotFound(w, r) } }) return &server.App{ WildcardDomain: website.config.WildcardDomain, Domains: website.config.Domains, Handler: mux, } } |