Commit 29379e6

Eric Bower  ·  2025-07-21 10:24:39 -0400 EDT
parent 97df9d9
feat(prose): allow `robots.txt` to be uploaded and served for blog
4 files changed,  +35, -2
+27, -0
......@@ -328,6 +328,32 @@ func postRawHandler(w http.ResponseWriter, r *http.Request) {
328328 }
329329 }
330330
331+func robotsHandler(w http.ResponseWriter, r *http.Request) {
332+ username := shared.GetUsernameFromRequest(r)
333+ cfg := shared.GetCfg(r)
334+ dbpool := shared.GetDB(r)
335+ logger := shared.GetLogger(r)
336+ user, err := dbpool.FindUserByName(username)
337+ if err != nil {
338+ logger.Info("blog not found", "user", username)
339+ http.Error(w, "blog not found", http.StatusNotFound)
340+ return
341+ }
342+ logger = shared.LoggerWithUser(logger, user)
343+ w.Header().Add("Content-Type", "text/plain")
344+
345+ post, err := dbpool.FindPostWithFilename("robots.txt", user.ID, cfg.Space)
346+ txt := ""
347+ if err == nil {
348+ txt = post.Text
349+ }
350+ _, err = w.Write([]byte(txt))
351+ if err != nil {
352+ logger.Error("write to response writer", "err", err)
353+ http.Error(w, "server error", 500)
354+ }
355+}
356+
331357 func postHandler(w http.ResponseWriter, r *http.Request) {
332358 username := shared.GetUsernameFromRequest(r)
333359 subdomain := shared.GetSubdomain(r)
......@@ -945,6 +971,7 @@ func createSubdomainRoutes(staticRoutes []shared.Route) []shared.Route {
945971 routes := []shared.Route{
946972 shared.NewRoute("GET", "/", blogHandler),
947973 shared.NewRoute("GET", "/_styles.css", blogStyleHandler),
974+ shared.NewRoute("GET", "/robots.txt", robotsHandler),
948975 shared.NewRoute("GET", "/rss", rssBlogHandler),
949976 shared.NewRoute("GET", "/rss.xml", rssBlogHandler),
950977 shared.NewRoute("GET", "/atom.xml", rssBlogHandler),
+1, -1
......@@ -36,7 +36,7 @@ func NewConfigSite(service string) *shared.ConfigSite {
3636 ".svg",
3737 ".ico",
3838 },
39- HiddenPosts: []string{"_readme.md", "_styles.css", "_footer.md", "_404.md"},
39+ HiddenPosts: []string{"_readme.md", "_styles.css", "_footer.md", "_404.md", "robots.txt"},
4040 Logger: shared.CreateLogger(service, withPipe),
4141 MaxSize: maxSize,
4242 MaxAssetSize: maxImgSize,
+6, -1
......@@ -29,10 +29,15 @@ func (p *MarkdownHooks) FileValidate(s *pssh.SSHServerConnSession, data *filehan
2929 return false, err
3030 }
3131
32+ fp := strings.Replace(data.Filename, "/", "", 1)
3233 // special styles css file we want to permit but no other css file.
3334 // sometimes the directory is provided in the filename, so we want to
3435 // remove that before we perform this check.
35- if strings.Replace(data.Filename, "/", "", 1) == "_styles.css" {
36+ if fp == "_styles.css" {
37+ return true, nil
38+ }
39+ // allow users to upload robots file
40+ if fp == "robots.txt" {
3641 return true, nil
3742 }
3843
+1, -0
......@@ -53,6 +53,7 @@ func StartSshServer() {
5353
5454 fileMap := map[string]filehandlers.ReadWriteHandler{
5555 ".md": filehandlers.NewScpPostHandler(dbh, cfg, hooks),
56+ ".txt": filehandlers.NewScpPostHandler(dbh, cfg, hooks),
5657 ".css": filehandlers.NewScpPostHandler(dbh, cfg, hooks),
5758 "fallback": uploadimgs.NewUploadImgHandler(dbh, cfg, st),
5859 }