repos / pico

pico services - prose.sh, pastes.sh, imgs.sh, feeds.sh, pgs.sh
git clone https://github.com/picosh/pico.git

commit
69a6aef
parent
1133a93
author
Eric Bower
date
2024-10-05 18:47:39 +0000 UTC
feat(pgs): add cache headers etag and last-modified
7 files changed,  +84, -12
M go.mod
M go.sum
M filehandlers/assets/handler.go
+4, -4
 1@@ -135,13 +135,13 @@ func (h *UploadAssetHandler) Read(s ssh.Session, entry *utils.FileEntry) (os.Fil
 2 	}
 3 
 4 	fname := shared.GetAssetFileName(entry)
 5-	contents, size, modTime, err := h.Storage.GetObject(bucket, fname)
 6+	contents, info, err := h.Storage.GetObject(bucket, fname)
 7 	if err != nil {
 8 		return nil, nil, err
 9 	}
10 
11-	fileInfo.FSize = size
12-	fileInfo.FModTime = modTime
13+	fileInfo.FSize = info.Size
14+	fileInfo.FModTime = info.LastModified
15 
16 	reader := pobj.NewAllReaderAt(contents)
17 
18@@ -226,7 +226,7 @@ func (h *UploadAssetHandler) Validate(s ssh.Session) error {
19 }
20 
21 func (h *UploadAssetHandler) findDenylist(bucket sst.Bucket, project *db.Project, logger *slog.Logger) (string, error) {
22-	fp, _, _, err := h.Storage.GetObject(bucket, filepath.Join(project.ProjectDir, "_pgs_ignore"))
23+	fp, _, err := h.Storage.GetObject(bucket, filepath.Join(project.ProjectDir, "_pgs_ignore"))
24 	if err != nil {
25 		return "", fmt.Errorf("_pgs_ignore not found")
26 	}
M filehandlers/imgs/handler.go
+1, -1
1@@ -76,7 +76,7 @@ func (h *UploadImgHandler) Read(s ssh.Session, entry *utils.FileEntry) (os.FileI
2 		return nil, nil, err
3 	}
4 
5-	contents, _, _, err := h.Storage.GetObject(bucket, post.Filename)
6+	contents, _, err := h.Storage.GetObject(bucket, post.Filename)
7 	if err != nil {
8 		return nil, nil, err
9 	}
M go.mod
+20, -1
 1@@ -35,7 +35,7 @@ require (
 2 	github.com/muesli/reflow v0.3.0
 3 	github.com/muesli/termenv v0.15.3-0.20240509142007-81b8f94111d5
 4 	github.com/neurosnap/go-exif-remove v0.0.0-20221010134343-50d1e3c35577
 5-	github.com/picosh/pobj v0.0.0-20240709135546-27097077b26a
 6+	github.com/picosh/pobj v0.0.0-20241005185823-c92bd8ee07f8
 7 	github.com/picosh/pubsub v0.0.0-20241003170126-d92d74f10efe
 8 	github.com/picosh/send v0.0.0-20240820031602-5d3b1a4494cc
 9 	github.com/picosh/tunkit v0.0.0-20240709033345-8315d4f3cd0e
10@@ -61,6 +61,25 @@ require (
11 	github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
12 	github.com/antoniomika/syncmap v1.0.0 // indirect
13 	github.com/atotto/clipboard v0.1.4 // indirect
14+	github.com/aws/aws-sdk-go-v2 v1.30.4 // indirect
15+	github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4 // indirect
16+	github.com/aws/aws-sdk-go-v2/config v1.27.28 // indirect
17+	github.com/aws/aws-sdk-go-v2/credentials v1.17.28 // indirect
18+	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 // indirect
19+	github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.11 // indirect
20+	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 // indirect
21+	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 // indirect
22+	github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
23+	github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.16 // indirect
24+	github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect
25+	github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.18 // indirect
26+	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 // indirect
27+	github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.16 // indirect
28+	github.com/aws/aws-sdk-go-v2/service/s3 v1.59.0 // indirect
29+	github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 // indirect
30+	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect
31+	github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 // indirect
32+	github.com/aws/smithy-go v1.20.4 // indirect
33 	github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
34 	github.com/aymerick/douceur v0.2.0 // indirect
35 	github.com/beorn7/perks v1.0.1 // indirect
M go.sum
+42, -0
 1@@ -23,6 +23,44 @@ github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhP
 2 github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
 3 github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
 4 github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
 5+github.com/aws/aws-sdk-go-v2 v1.30.4 h1:frhcagrVNrzmT95RJImMHgabt99vkXGslubDaDagTk8=
 6+github.com/aws/aws-sdk-go-v2 v1.30.4/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0=
 7+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4 h1:70PVAiL15/aBMh5LThwgXdSQorVr91L127ttckI9QQU=
 8+github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4/go.mod h1:/MQxMqci8tlqDH+pjmoLu1i0tbWCUP1hhyMRuFxpQCw=
 9+github.com/aws/aws-sdk-go-v2/config v1.27.28 h1:OTxWGW/91C61QlneCtnD62NLb4W616/NM1jA8LhJqbg=
10+github.com/aws/aws-sdk-go-v2/config v1.27.28/go.mod h1:uzVRVtJSU5EFv6Fu82AoVFKozJi2ZCY6WRCXj06rbvs=
11+github.com/aws/aws-sdk-go-v2/credentials v1.17.28 h1:m8+AHY/ND8CMHJnPoH7PJIRakWGa4gbfbxuY9TGTUXM=
12+github.com/aws/aws-sdk-go-v2/credentials v1.17.28/go.mod h1:6TF7dSc78ehD1SL6KpRIPKMA1GyyWflIkjqg+qmf4+c=
13+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 h1:yjwoSyDZF8Jth+mUk5lSPJCkMC0lMy6FaCD51jm6ayE=
14+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12/go.mod h1:fuR57fAgMk7ot3WcNQfb6rSEn+SUffl7ri+aa8uKysI=
15+github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.11 h1:FEDZD/Axt5tKSkPAs967KZ++MkvYdBqr0a+cetRbjLM=
16+github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.11/go.mod h1:dvlsbA32KfvCzqwTiX7maABgFek2RyUuYEJ3kyn/PmQ=
17+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 h1:TNyt/+X43KJ9IJJMjKfa3bNTiZbUP7DeCxfbTROESwY=
18+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16/go.mod h1:2DwJF39FlNAUiX5pAc0UNeiz16lK2t7IaFcm0LFHEgc=
19+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 h1:jYfy8UPmd+6kJW5YhY0L1/KftReOGxI/4NtVSTh9O/I=
20+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16/go.mod h1:7ZfEPZxkW42Afq4uQB8H2E2e6ebh6mXTueEpYzjCzcs=
21+github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ=
22+github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
23+github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.16 h1:mimdLQkIX1zr8GIPY1ZtALdBQGxcASiBd2MOp8m/dMc=
24+github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.16/go.mod h1:YHk6owoSwrIsok+cAH9PENCOGoH5PU2EllX4vLtSrsY=
25+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI=
26+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc=
27+github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.18 h1:GckUnpm4EJOAio1c8o25a+b3lVfwVzC9gnSBqiiNmZM=
28+github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.18/go.mod h1:Br6+bxfG33Dk3ynmkhsW2Z/t9D4+lRqdLDNCKi85w0U=
29+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 h1:tJ5RnkHCiSH0jyd6gROjlJtNwov0eGYNz8s8nFcR0jQ=
30+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18/go.mod h1:++NHzT+nAF7ZPrHPsA+ENvsXkOO8wEu+C6RXltAG4/c=
31+github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.16 h1:jg16PhLPUiHIj8zYIW6bqzeQSuHVEiWnGA0Brz5Xv2I=
32+github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.16/go.mod h1:Uyk1zE1VVdsHSU7096h/rwnXDzOzYQVl+FNPhPw7ShY=
33+github.com/aws/aws-sdk-go-v2/service/s3 v1.59.0 h1:Cso4Ev/XauMVsbwdhYEoxg8rxZWw43CFqqaPB5w3W2c=
34+github.com/aws/aws-sdk-go-v2/service/s3 v1.59.0/go.mod h1:BSPI0EfnYUuNHPS0uqIo5VrRwzie+Fp+YhQOUs16sKI=
35+github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 h1:zCsFCKvbj25i7p1u94imVoO447I/sFv8qq+lGJhRN0c=
36+github.com/aws/aws-sdk-go-v2/service/sso v1.22.5/go.mod h1:ZeDX1SnKsVlejeuz41GiajjZpRSWR7/42q/EyA/QEiM=
37+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 h1:SKvPgvdvmiTWoi0GAJ7AsJfOz3ngVkD/ERbs5pUnHNI=
38+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5/go.mod h1:20sz31hv/WsPa3HhU3hfrIet2kxM4Pe0r20eBZ20Tac=
39+github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 h1:iAckBT2OeEK/kBDyN/jDtpEExhjeeA/Im2q4X0rJZT8=
40+github.com/aws/aws-sdk-go-v2/service/sts v1.30.4/go.mod h1:vmSqFK+BVIwVpDAGZB3CoCXHzurt4qBE8lf+I/kRTh0=
41+github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4=
42+github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
43 github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
44 github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
45 github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
46@@ -222,6 +260,10 @@ github.com/picosh/go-rsync-receiver v0.0.0-20240709135253-1daf4b12a9fc h1:bvcsoO
47 github.com/picosh/go-rsync-receiver v0.0.0-20240709135253-1daf4b12a9fc/go.mod h1:i0iR3W4GSm1PuvVxB9OH32E5jP+CYkVb2NQSe0JCtlo=
48 github.com/picosh/pobj v0.0.0-20240709135546-27097077b26a h1:Cr1xODiyd/SjjBRtYA9VX6Do3D+w+DansQzkb4NGeyA=
49 github.com/picosh/pobj v0.0.0-20240709135546-27097077b26a/go.mod h1:VIkR1MZBvxSK2OO47jikxikAO/sKb/vTmXX5ZuYTIvo=
50+github.com/picosh/pobj v0.0.0-20241005184424-366421c762d7 h1:QiKWMuxqhNKfOacqfZl0fJn7Oc53hIoB1WH7eluOqs0=
51+github.com/picosh/pobj v0.0.0-20241005184424-366421c762d7/go.mod h1:tPv/ydMnuXlGVpWUMvBlcWlyn/xu9PsVPdncYibweWY=
52+github.com/picosh/pobj v0.0.0-20241005185823-c92bd8ee07f8 h1:M6GjB28u/sThE3gyKx4V2iqrokdMJAr1pQ41Q3mK04I=
53+github.com/picosh/pobj v0.0.0-20241005185823-c92bd8ee07f8/go.mod h1:tPv/ydMnuXlGVpWUMvBlcWlyn/xu9PsVPdncYibweWY=
54 github.com/picosh/pubsub v0.0.0-20241003170126-d92d74f10efe h1:NQA2eXxqFPjVr/8DX073Vap5kMnJk3/AAAgt/jz8cyc=
55 github.com/picosh/pubsub v0.0.0-20241003170126-d92d74f10efe/go.mod h1:gWhwrStKWJNzp9i44Bc3YQmnC+pIKvI5dYWm1GRHJac=
56 github.com/picosh/send v0.0.0-20240820031602-5d3b1a4494cc h1:IIsJuAFG2ju3cygKVKTIsYYZf21q5S3Dr1H4fGbfgJg=
M pgs/api.go
+15, -4
 1@@ -168,7 +168,7 @@ func hasProtocol(url string) bool {
 2 
 3 func (h *AssetHandler) handle(logger *slog.Logger, w http.ResponseWriter, r *http.Request) {
 4 	var redirects []*RedirectRule
 5-	redirectFp, _, _, err := h.Storage.GetObject(h.Bucket, filepath.Join(h.ProjectDir, "_redirects"))
 6+	redirectFp, _, err := h.Storage.GetObject(h.Bucket, filepath.Join(h.ProjectDir, "_redirects"))
 7 	if err == nil {
 8 		defer redirectFp.Close()
 9 		buf := new(strings.Builder)
10@@ -190,6 +190,7 @@ func (h *AssetHandler) handle(logger *slog.Logger, w http.ResponseWriter, r *htt
11 	var contents io.ReadCloser
12 	contentType := ""
13 	assetFilepath := ""
14+	info := &sst.ObjectInfo{}
15 	status := http.StatusOK
16 	attempts := []string{}
17 	for _, fp := range routes {
18@@ -198,7 +199,7 @@ func (h *AssetHandler) handle(logger *slog.Logger, w http.ResponseWriter, r *htt
19 			// before redirecting, this saves a hop that will just end up a 404
20 			if !hasProtocol(fp.Filepath) && strings.HasSuffix(fp.Filepath, "/") {
21 				next := filepath.Join(h.ProjectDir, fp.Filepath, "index.html")
22-				_, _, _, err := h.Storage.GetObject(h.Bucket, next)
23+				_, _, err := h.Storage.GetObject(h.Bucket, next)
24 				if err != nil {
25 					continue
26 				}
27@@ -248,7 +249,7 @@ func (h *AssetHandler) handle(logger *slog.Logger, w http.ResponseWriter, r *htt
28 				h.ImgProcessOpts,
29 			)
30 		} else {
31-			c, _, _, err = h.Storage.GetObject(h.Bucket, fp.Filepath)
32+			c, info, err = h.Storage.GetObject(h.Bucket, fp.Filepath)
33 		}
34 		if err == nil {
35 			contents = c
36@@ -286,7 +287,7 @@ func (h *AssetHandler) handle(logger *slog.Logger, w http.ResponseWriter, r *htt
37 	}
38 
39 	var headers []*HeaderRule
40-	headersFp, _, _, err := h.Storage.GetObject(h.Bucket, filepath.Join(h.ProjectDir, "_headers"))
41+	headersFp, _, err := h.Storage.GetObject(h.Bucket, filepath.Join(h.ProjectDir, "_headers"))
42 	if err == nil {
43 		defer headersFp.Close()
44 		buf := new(strings.Builder)
45@@ -312,6 +313,16 @@ func (h *AssetHandler) handle(logger *slog.Logger, w http.ResponseWriter, r *htt
46 		}
47 	}
48 
49+	if info != nil {
50+		if info.ETag != "" {
51+			w.Header().Add("etag", info.ETag)
52+		}
53+
54+		if !info.LastModified.IsZero() {
55+			w.Header().Add("last-modified", info.LastModified.Format(http.TimeFormat))
56+		}
57+	}
58+
59 	for _, hdr := range userHeaders {
60 		w.Header().Add(hdr.Name, hdr.Value)
61 	}
M shared/storage/fs.go
+1, -1
1@@ -24,7 +24,7 @@ func NewStorageFS(dir string) (*StorageFS, error) {
2 func (s *StorageFS) ServeObject(bucket sst.Bucket, fpath string, opts *ImgProcessOpts) (io.ReadCloser, string, error) {
3 	if opts == nil || os.Getenv("IMGPROXY_URL") == "" {
4 		contentType := GetMimeType(fpath)
5-		rc, _, _, err := s.GetObject(bucket, fpath)
6+		rc, _, err := s.GetObject(bucket, fpath)
7 		return rc, contentType, err
8 	}
9 
M shared/storage/minio.go
+1, -1
1@@ -26,7 +26,7 @@ func NewStorageMinio(address, user, pass string) (*StorageMinio, error) {
2 func (s *StorageMinio) ServeObject(bucket sst.Bucket, fpath string, opts *ImgProcessOpts) (io.ReadCloser, string, error) {
3 	if opts == nil || os.Getenv("IMGPROXY_URL") == "" {
4 		contentType := GetMimeType(fpath)
5-		rc, _, _, err := s.GetObject(bucket, fpath)
6+		rc, _, err := s.GetObject(bucket, fpath)
7 		return rc, contentType, err
8 	}
9