- commit
- 29379e6
- parent
- 97df9d9
- author
- Eric Bower
- date
- 2025-07-21 10:24:39 -0400 EDT
feat(prose): allow `robots.txt` to be uploaded and served for blog
4 files changed,
+35,
-2
+27,
-0
1@@ -328,6 +328,32 @@ func postRawHandler(w http.ResponseWriter, r *http.Request) {
2 }
3 }
4
5+func robotsHandler(w http.ResponseWriter, r *http.Request) {
6+ username := shared.GetUsernameFromRequest(r)
7+ cfg := shared.GetCfg(r)
8+ dbpool := shared.GetDB(r)
9+ logger := shared.GetLogger(r)
10+ user, err := dbpool.FindUserByName(username)
11+ if err != nil {
12+ logger.Info("blog not found", "user", username)
13+ http.Error(w, "blog not found", http.StatusNotFound)
14+ return
15+ }
16+ logger = shared.LoggerWithUser(logger, user)
17+ w.Header().Add("Content-Type", "text/plain")
18+
19+ post, err := dbpool.FindPostWithFilename("robots.txt", user.ID, cfg.Space)
20+ txt := ""
21+ if err == nil {
22+ txt = post.Text
23+ }
24+ _, err = w.Write([]byte(txt))
25+ if err != nil {
26+ logger.Error("write to response writer", "err", err)
27+ http.Error(w, "server error", 500)
28+ }
29+}
30+
31 func postHandler(w http.ResponseWriter, r *http.Request) {
32 username := shared.GetUsernameFromRequest(r)
33 subdomain := shared.GetSubdomain(r)
34@@ -945,6 +971,7 @@ func createSubdomainRoutes(staticRoutes []shared.Route) []shared.Route {
35 routes := []shared.Route{
36 shared.NewRoute("GET", "/", blogHandler),
37 shared.NewRoute("GET", "/_styles.css", blogStyleHandler),
38+ shared.NewRoute("GET", "/robots.txt", robotsHandler),
39 shared.NewRoute("GET", "/rss", rssBlogHandler),
40 shared.NewRoute("GET", "/rss.xml", rssBlogHandler),
41 shared.NewRoute("GET", "/atom.xml", rssBlogHandler),
+1,
-1
1@@ -36,7 +36,7 @@ func NewConfigSite(service string) *shared.ConfigSite {
2 ".svg",
3 ".ico",
4 },
5- HiddenPosts: []string{"_readme.md", "_styles.css", "_footer.md", "_404.md"},
6+ HiddenPosts: []string{"_readme.md", "_styles.css", "_footer.md", "_404.md", "robots.txt"},
7 Logger: shared.CreateLogger(service, withPipe),
8 MaxSize: maxSize,
9 MaxAssetSize: maxImgSize,
+6,
-1
1@@ -29,10 +29,15 @@ func (p *MarkdownHooks) FileValidate(s *pssh.SSHServerConnSession, data *filehan
2 return false, err
3 }
4
5+ fp := strings.Replace(data.Filename, "/", "", 1)
6 // special styles css file we want to permit but no other css file.
7 // sometimes the directory is provided in the filename, so we want to
8 // remove that before we perform this check.
9- if strings.Replace(data.Filename, "/", "", 1) == "_styles.css" {
10+ if fp == "_styles.css" {
11+ return true, nil
12+ }
13+ // allow users to upload robots file
14+ if fp == "robots.txt" {
15 return true, nil
16 }
17
+1,
-0
1@@ -53,6 +53,7 @@ func StartSshServer() {
2
3 fileMap := map[string]filehandlers.ReadWriteHandler{
4 ".md": filehandlers.NewScpPostHandler(dbh, cfg, hooks),
5+ ".txt": filehandlers.NewScpPostHandler(dbh, cfg, hooks),
6 ".css": filehandlers.NewScpPostHandler(dbh, cfg, hooks),
7 "fallback": uploadimgs.NewUploadImgHandler(dbh, cfg, st),
8 }