Eric Bower
·
29 Aug 24
api.go
1package feeds
2
3import (
4 "fmt"
5 "net/http"
6 "net/url"
7 "time"
8
9 "github.com/picosh/pico/db/postgres"
10 "github.com/picosh/pico/shared"
11 "github.com/picosh/pico/shared/storage"
12)
13
14func createStaticRoutes() []shared.Route {
15 return []shared.Route{
16 shared.NewRoute("GET", "/main.css", shared.ServeFile("main.css", "text/css")),
17 shared.NewRoute("GET", "/card.png", shared.ServeFile("card.png", "image/png")),
18 shared.NewRoute("GET", "/favicon-16x16.png", shared.ServeFile("favicon-16x16.png", "image/png")),
19 shared.NewRoute("GET", "/favicon-32x32.png", shared.ServeFile("favicon-32x32.png", "image/png")),
20 shared.NewRoute("GET", "/apple-touch-icon.png", shared.ServeFile("apple-touch-icon.png", "image/png")),
21 shared.NewRoute("GET", "/favicon.ico", shared.ServeFile("favicon.ico", "image/x-icon")),
22 shared.NewRoute("GET", "/robots.txt", shared.ServeFile("robots.txt", "text/plain")),
23 }
24}
25
26func keepAliveHandler(w http.ResponseWriter, r *http.Request) {
27 dbpool := shared.GetDB(r)
28 logger := shared.GetLogger(r)
29 postID, _ := url.PathUnescape(shared.GetField(r, 0))
30
31 post, err := dbpool.FindPost(postID)
32 if err != nil {
33 logger.Info("post not found")
34 http.Error(w, "post not found", http.StatusNotFound)
35 return
36 }
37
38 now := time.Now()
39 expiresAt := now.AddDate(0, 3, 0)
40 post.ExpiresAt = &expiresAt
41 _, err = dbpool.UpdatePost(post)
42 if err != nil {
43 logger.Error("could not update post", "err", err.Error())
44 http.Error(w, "server error", 500)
45 return
46 }
47
48 w.Header().Add("Content-Type", "text/plain")
49
50 txt := fmt.Sprintf(
51 "Success! This feed will stay active until %s or by clicking the link in your digest email again",
52 time.Now(),
53 )
54 _, err = w.Write([]byte(txt))
55 if err != nil {
56 logger.Error("could not write to writer", "err", err.Error())
57 http.Error(w, "server error", 500)
58 }
59}
60
61func createMainRoutes(staticRoutes []shared.Route) []shared.Route {
62 routes := []shared.Route{
63 shared.NewRoute("GET", "/", shared.CreatePageHandler("html/marketing.page.tmpl")),
64 shared.NewRoute("GET", "/keep-alive/(.+)", keepAliveHandler),
65 }
66
67 routes = append(
68 routes,
69 staticRoutes...,
70 )
71
72 return routes
73}
74
75func StartApiServer() {
76 cfg := NewConfigSite()
77 db := postgres.NewDB(cfg.DbURL, cfg.Logger)
78 defer db.Close()
79 logger := cfg.Logger
80
81 var st storage.StorageServe
82 var err error
83 if cfg.MinioURL == "" {
84 st, err = storage.NewStorageFS(cfg.StorageDir)
85 } else {
86 st, err = storage.NewStorageMinio(cfg.MinioURL, cfg.MinioUser, cfg.MinioPass)
87 }
88
89 if err != nil {
90 logger.Error(err.Error())
91 }
92
93 // cron daily digest
94 fetcher := NewFetcher(db, cfg)
95 go fetcher.Loop()
96
97 staticRoutes := createStaticRoutes()
98
99 if cfg.Debug {
100 staticRoutes = shared.CreatePProfRoutes(staticRoutes)
101 }
102
103 mainRoutes := createMainRoutes(staticRoutes)
104
105 apiConfig := &shared.ApiConfig{
106 Cfg: cfg,
107 Dbpool: db,
108 Storage: st,
109 }
110 handler := shared.CreateServe(mainRoutes, []shared.Route{}, apiConfig)
111 router := http.HandlerFunc(handler)
112
113 portStr := fmt.Sprintf(":%s", cfg.Port)
114 logger.Info(
115 "Starting server on port",
116 "port", cfg.Port,
117 "domain", cfg.Domain,
118 )
119
120 logger.Error(http.ListenAndServe(portStr, router).Error())
121}