- commit
- 47c751f
- parent
- c0a4aba
- author
- Eric Bower
- date
- 2025-06-09 12:12:55 -0400 EDT
refactor(pgs): "lite" version of pgs with cache and proxy to ash.pgs
2 files changed,
+116,
-24
+88,
-0
1@@ -0,0 +1,88 @@
2+package main
3+
4+import (
5+ "context"
6+ "fmt"
7+ "net"
8+ "net/http"
9+ "net/http/httputil"
10+ "net/url"
11+ "strings"
12+
13+ "github.com/darkweak/souin/pkg/middleware"
14+ "github.com/hashicorp/golang-lru/v2/expirable"
15+ "github.com/picosh/pico/pkg/apps/pgs"
16+ "github.com/picosh/pico/pkg/cache"
17+ "github.com/picosh/pico/pkg/shared"
18+)
19+
20+func main() {
21+ logger := shared.CreateLogger("pgs-web-lite")
22+ ctx := context.Background()
23+ cfg := pgs.NewPgsConfig(logger, nil, nil)
24+ httpCache := pgs.SetupCache(cfg)
25+ router := &pgs.WebRouter{
26+ Cfg: cfg,
27+ RedirectsCache: expirable.NewLRU[string, []*pgs.RedirectRule](2048, nil, cache.CacheTimeout),
28+ HeadersCache: expirable.NewLRU[string, []*pgs.HeaderRule](2048, nil, cache.CacheTimeout),
29+ }
30+ cacher := &cachedHttp{
31+ handler: httpCache,
32+ routes: router,
33+ }
34+
35+ go router.WatchCacheClear()
36+ go router.CacheMgmt(ctx, httpCache, cfg.CacheClearingQueue)
37+
38+ portStr := fmt.Sprintf(":%s", cfg.WebPort)
39+ cfg.Logger.Info(
40+ "starting server on port",
41+ "port", cfg.WebPort,
42+ "domain", cfg.Domain,
43+ )
44+ err := http.ListenAndServe(portStr, cacher)
45+ cfg.Logger.Error("listen and serve", "err", err)
46+}
47+
48+type cachedHttp struct {
49+ handler *middleware.SouinBaseHandler
50+ routes *pgs.WebRouter
51+}
52+
53+func (c *cachedHttp) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
54+ _ = c.handler.ServeHTTP(writer, req, func(w http.ResponseWriter, r *http.Request) error {
55+ url, _ := url.Parse(fullURL(r))
56+ c.routes.Cfg.Logger.Info("proxying request to ash.pgs.sh", "url", url.String())
57+ defaultTransport := http.DefaultTransport.(*http.Transport)
58+ newTransport := defaultTransport.Clone()
59+ oldDialContext := newTransport.DialContext
60+ newTransport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
61+ return oldDialContext(ctx, "tcp", "ash.pgs.sh:443")
62+ }
63+ proxy := httputil.NewSingleHostReverseProxy(url)
64+ proxy.Transport = newTransport
65+
66+ proxy.ServeHTTP(w, r)
67+ return nil
68+ })
69+}
70+
71+func fullURL(r *http.Request) string {
72+ builder := strings.Builder{}
73+ if r.TLS != nil {
74+ builder.WriteString("https://")
75+ } else {
76+ builder.WriteString("http://")
77+ }
78+ builder.WriteString(r.Host)
79+ builder.WriteString(r.URL.Path)
80+
81+ if r.URL.RawQuery != "" {
82+ builder.WriteString("?" + r.URL.RawQuery)
83+ }
84+ if r.URL.Fragment != "" {
85+ builder.WriteString("#" + r.URL.Fragment)
86+ }
87+
88+ return builder.String()
89+}
+28,
-24
1@@ -43,9 +43,7 @@ func (c *CachedHttp) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
2 })
3 }
4
5-func StartApiServer(cfg *PgsConfig) {
6- ctx := context.Background()
7-
8+func SetupCache(cfg *PgsConfig) *middleware.SouinBaseHandler {
9 ttl := configurationtypes.Duration{Duration: cfg.CacheTTL}
10 stale := configurationtypes.Duration{Duration: cfg.CacheTTL * 2}
11 c := &middleware.BaseConfiguration{
12@@ -68,16 +66,22 @@ func StartApiServer(cfg *PgsConfig) {
13 DefaultCacheControl: cfg.CacheControl,
14 },
15 }
16- c.SetLogger(&CompatLogger{cfg.Logger})
17+ c.SetLogger(&CompatLogger{Logger: cfg.Logger})
18 storages.InitFromConfiguration(c)
19- httpCache := middleware.NewHTTPCacheHandler(c)
20+ return middleware.NewHTTPCacheHandler(c)
21+}
22+
23+func StartApiServer(cfg *PgsConfig) {
24+ ctx := context.Background()
25+
26+ httpCache := SetupCache(cfg)
27 routes := NewWebRouter(cfg)
28 cacher := &CachedHttp{
29 handler: httpCache,
30 routes: routes,
31 }
32
33- go routes.cacheMgmt(ctx, httpCache, cfg.CacheClearingQueue)
34+ go routes.CacheMgmt(ctx, httpCache, cfg.CacheClearingQueue)
35
36 portStr := fmt.Sprintf(":%s", cfg.WebPort)
37 cfg.Logger.Info(
38@@ -109,11 +113,11 @@ func NewWebRouter(cfg *PgsConfig) *WebRouter {
39 HeadersCache: expirable.NewLRU[string, []*HeaderRule](2048, nil, cache.CacheTimeout),
40 }
41 router.initRouters()
42- go router.watchCacheClear()
43+ go router.WatchCacheClear()
44 return router
45 }
46
47-func (web *WebRouter) watchCacheClear() {
48+func (web *WebRouter) WatchCacheClear() {
49 for key := range web.Cfg.CacheClearingQueue {
50 web.Cfg.Logger.Info("lru cache clear request", "key", key)
51 rKey := filepath.Join(key, "_redirects")
52@@ -277,7 +281,7 @@ func (web *WebRouter) checkHandler(w http.ResponseWriter, r *http.Request) {
53 w.WriteHeader(http.StatusNotFound)
54 }
55
56-func (web *WebRouter) cacheMgmt(ctx context.Context, httpCache *middleware.SouinBaseHandler, notify chan string) {
57+func (web *WebRouter) CacheMgmt(ctx context.Context, httpCache *middleware.SouinBaseHandler, notify chan string) {
58 storer := httpCache.Storers[0]
59 drain := createSubCacheDrain(ctx, web.Cfg.Logger)
60
61@@ -554,7 +558,7 @@ func (web *WebRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
62 }
63
64 type CompatLogger struct {
65- logger *slog.Logger
66+ Logger *slog.Logger
67 }
68
69 func (cl *CompatLogger) marshall(int ...interface{}) string {
70@@ -568,44 +572,44 @@ func (cl *CompatLogger) marshall(int ...interface{}) string {
71 return res
72 }
73 func (cl *CompatLogger) DPanic(int ...interface{}) {
74- cl.logger.Error("panic", "output", cl.marshall(int))
75+ cl.Logger.Error("panic", "output", cl.marshall(int))
76 }
77 func (cl *CompatLogger) DPanicf(st string, int ...interface{}) {
78- cl.logger.Error(fmt.Sprintf(st, int...))
79+ cl.Logger.Error(fmt.Sprintf(st, int...))
80 }
81 func (cl *CompatLogger) Debug(int ...interface{}) {
82- cl.logger.Debug("debug", "output", cl.marshall(int))
83+ cl.Logger.Debug("debug", "output", cl.marshall(int))
84 }
85 func (cl *CompatLogger) Debugf(st string, int ...interface{}) {
86- cl.logger.Debug(fmt.Sprintf(st, int...))
87+ cl.Logger.Debug(fmt.Sprintf(st, int...))
88 }
89 func (cl *CompatLogger) Error(int ...interface{}) {
90- cl.logger.Error("error", "output", cl.marshall(int))
91+ cl.Logger.Error("error", "output", cl.marshall(int))
92 }
93 func (cl *CompatLogger) Errorf(st string, int ...interface{}) {
94- cl.logger.Error(fmt.Sprintf(st, int...))
95+ cl.Logger.Error(fmt.Sprintf(st, int...))
96 }
97 func (cl *CompatLogger) Fatal(int ...interface{}) {
98- cl.logger.Error("fatal", "outpu", cl.marshall(int))
99+ cl.Logger.Error("fatal", "outpu", cl.marshall(int))
100 }
101 func (cl *CompatLogger) Fatalf(st string, int ...interface{}) {
102- cl.logger.Error(fmt.Sprintf(st, int...))
103+ cl.Logger.Error(fmt.Sprintf(st, int...))
104 }
105 func (cl *CompatLogger) Info(int ...interface{}) {
106- cl.logger.Info("info", "output", cl.marshall(int))
107+ cl.Logger.Info("info", "output", cl.marshall(int))
108 }
109 func (cl *CompatLogger) Infof(st string, int ...interface{}) {
110- cl.logger.Info(fmt.Sprintf(st, int...))
111+ cl.Logger.Info(fmt.Sprintf(st, int...))
112 }
113 func (cl *CompatLogger) Panic(int ...interface{}) {
114- cl.logger.Error("panic", "output", cl.marshall(int))
115+ cl.Logger.Error("panic", "output", cl.marshall(int))
116 }
117 func (cl *CompatLogger) Panicf(st string, int ...interface{}) {
118- cl.logger.Error(fmt.Sprintf(st, int...))
119+ cl.Logger.Error(fmt.Sprintf(st, int...))
120 }
121 func (cl *CompatLogger) Warn(int ...interface{}) {
122- cl.logger.Warn("warn", "output", cl.marshall(int))
123+ cl.Logger.Warn("warn", "output", cl.marshall(int))
124 }
125 func (cl *CompatLogger) Warnf(st string, int ...interface{}) {
126- cl.logger.Warn(fmt.Sprintf(st, int...))
127+ cl.Logger.Warn(fmt.Sprintf(st, int...))
128 }