pico

created pr with 66.1 on 2025-04-18T17:16:07Z · by c8ef7d19
changed pr name to chore(pobj.fs): feature parity with minio on 2025-04-18T17:18:11Z · by c8ef7d19
added 66.2 on 2025-04-21T18:44:44Z · by c8ef7d19
1: a3f9ef2 = 1: a3f9ef2 chore: rm UserMetadata
2: ccd89b0 = 2: ccd89b0 refactor(shared): mime type pkg
3: 8621e35 = 3: 8621e35 chore(pobj.fs): provide metadata
-: ------- > 4: 831b150 chore(storage.fs): add tests
cmds
checkout latest patchset:
ssh pr.pico.sh print 66 | git am -3
checkout any patchset in a patch request:
ssh pr.pico.sh print 66.[rev] | git am -3
add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 66
+2 -2 pkg/apps/pgs/calc_route.go #
......@@ -10,7 +10,7 @@ import (
1010
1111 "github.com/picosh/pico/pkg/send/utils"
1212 "github.com/picosh/pico/pkg/shared"
13- "github.com/picosh/pico/pkg/shared/storage"
13+ "github.com/picosh/pico/pkg/shared/mime"
1414 )
1515
1616 type HttpReply struct {
......@@ -23,7 +23,7 @@ func expandRoute(projectName, fp string, status int) []*HttpReply {
2323 if fp == "" {
2424 fp = "/"
2525 }
26- mimeType := storage.GetMimeType(fp)
26+ mimeType := mime.GetMimeType(fp)
2727 fname := filepath.Base(fp)
2828 fdir := filepath.Dir(fp)
2929 fext := filepath.Ext(fp)
+82 -0 pkg/shared/mime/mime.go #
......@@ -0,0 +1,82 @@
1+package mime
2+
3+import "path/filepath"
4+
5+func GetMimeType(fpath string) string {
6+ ext := filepath.Ext(fpath)
7+ if ext == ".svg" {
8+ return "image/svg+xml"
9+ } else if ext == ".css" {
10+ return "text/css"
11+ } else if ext == ".js" {
12+ return "text/javascript"
13+ } else if ext == ".ico" {
14+ return "image/x-icon"
15+ } else if ext == ".pdf" {
16+ return "application/pdf"
17+ } else if ext == ".html" || ext == ".htm" {
18+ return "text/html"
19+ } else if ext == ".jpg" || ext == ".jpeg" {
20+ return "image/jpeg"
21+ } else if ext == ".png" {
22+ return "image/png"
23+ } else if ext == ".gif" {
24+ return "image/gif"
25+ } else if ext == ".webp" {
26+ return "image/webp"
27+ } else if ext == ".otf" {
28+ return "font/otf"
29+ } else if ext == ".woff" {
30+ return "font/woff"
31+ } else if ext == ".woff2" {
32+ return "font/woff2"
33+ } else if ext == ".ttf" {
34+ return "font/ttf"
35+ } else if ext == ".md" {
36+ return "text/markdown; charset=UTF-8"
37+ } else if ext == ".json" || ext == ".map" {
38+ return "application/json"
39+ } else if ext == ".rss" {
40+ return "application/rss+xml"
41+ } else if ext == ".atom" {
42+ return "application/atom+xml"
43+ } else if ext == ".webmanifest" {
44+ return "application/manifest+json"
45+ } else if ext == ".xml" {
46+ return "application/xml"
47+ } else if ext == ".xsl" {
48+ return "application/xml"
49+ } else if ext == ".avif" {
50+ return "image/avif"
51+ } else if ext == ".heif" {
52+ return "image/heif"
53+ } else if ext == ".heic" {
54+ return "image/heif"
55+ } else if ext == ".opus" {
56+ return "audio/opus"
57+ } else if ext == ".wav" {
58+ return "audio/wav"
59+ } else if ext == ".mp3" {
60+ return "audio/mpeg"
61+ } else if ext == ".mp4" {
62+ return "video/mp4"
63+ } else if ext == ".mpeg" {
64+ return "video/mpeg"
65+ } else if ext == ".wasm" {
66+ return "application/wasm"
67+ } else if ext == ".opml" {
68+ return "text/x-opml"
69+ } else if ext == ".eot" {
70+ return "application/vnd.ms-fontobject"
71+ } else if ext == ".yml" || ext == ".yaml" {
72+ return "text/x-yaml"
73+ } else if ext == ".zip" {
74+ return "application/zip"
75+ } else if ext == ".rar" {
76+ return "application/vnd.rar"
77+ } else if ext == ".txt" {
78+ return "text/plain"
79+ }
80+
81+ return "text/plain"
82+}
+2 -1 pkg/shared/storage/fs.go #
......@@ -9,6 +9,7 @@ import (
99 "strings"
1010
1111 sst "github.com/picosh/pico/pkg/pobj/storage"
12+ "github.com/picosh/pico/pkg/shared/mime"
1213 )
1314
1415 type StorageFS struct {
......@@ -28,7 +29,7 @@ func (s *StorageFS) ServeObject(bucket sst.Bucket, fpath string, opts *ImgProces
2829 var rc io.ReadCloser
2930 info := &sst.ObjectInfo{}
3031 var err error
31- mimeType := GetMimeType(fpath)
32+ mimeType := mime.GetMimeType(fpath)
3233 if !strings.HasPrefix(mimeType, "image/") || opts == nil || os.Getenv("IMGPROXY_URL") == "" {
3334 rc, info, err = s.GetObject(bucket, fpath)
3435 if info.Metadata == nil {
+2 -1 pkg/shared/storage/memory.go #
......@@ -6,6 +6,7 @@ import (
66 "time"
77
88 sst "github.com/picosh/pico/pkg/pobj/storage"
9+ "github.com/picosh/pico/pkg/shared/mime"
910 )
1011
1112 type StorageMemory struct {
......@@ -32,7 +33,7 @@ func (s *StorageMemory) ServeObject(bucket sst.Bucket, fpath string, opts *ImgPr
3233 if info.ETag == "" {
3334 info.ETag = "static-etag-for-testing-purposes"
3435 }
35- mimeType := GetMimeType(fpath)
36+ mimeType := mime.GetMimeType(fpath)
3637 info.Metadata.Set("content-type", mimeType)
3738 return obj, info, err
3839 }
+2 -1 pkg/shared/storage/minio.go #
......@@ -9,6 +9,7 @@ import (
99 "strings"
1010
1111 sst "github.com/picosh/pico/pkg/pobj/storage"
12+ "github.com/picosh/pico/pkg/shared/mime"
1213 )
1314
1415 type StorageMinio struct {
......@@ -27,7 +28,7 @@ func (s *StorageMinio) ServeObject(bucket sst.Bucket, fpath string, opts *ImgPro
2728 var rc io.ReadCloser
2829 info := &sst.ObjectInfo{}
2930 var err error
30- mimeType := GetMimeType(fpath)
31+ mimeType := mime.GetMimeType(fpath)
3132 if !strings.HasPrefix(mimeType, "image/") || opts == nil || os.Getenv("IMGPROXY_URL") == "" {
3233 rc, info, err = s.GetObject(bucket, fpath)
3334 if info.Metadata == nil {
+0 -80 pkg/shared/storage/proxy.go #
......@@ -10,7 +10,6 @@ import (
1010 "log/slog"
1111 "net/http"
1212 "os"
13- "path/filepath"
1413 "strconv"
1514 "strings"
1615 "time"
......@@ -18,85 +17,6 @@ import (
1817 "github.com/picosh/pico/pkg/pobj/storage"
1918 )
2019
21-func GetMimeType(fpath string) string {
22- ext := filepath.Ext(fpath)
23- if ext == ".svg" {
24- return "image/svg+xml"
25- } else if ext == ".css" {
26- return "text/css"
27- } else if ext == ".js" {
28- return "text/javascript"
29- } else if ext == ".ico" {
30- return "image/x-icon"
31- } else if ext == ".pdf" {
32- return "application/pdf"
33- } else if ext == ".html" || ext == ".htm" {
34- return "text/html"
35- } else if ext == ".jpg" || ext == ".jpeg" {
36- return "image/jpeg"
37- } else if ext == ".png" {
38- return "image/png"
39- } else if ext == ".gif" {
40- return "image/gif"
41- } else if ext == ".webp" {
42- return "image/webp"
43- } else if ext == ".otf" {
44- return "font/otf"
45- } else if ext == ".woff" {
46- return "font/woff"
47- } else if ext == ".woff2" {
48- return "font/woff2"
49- } else if ext == ".ttf" {
50- return "font/ttf"
51- } else if ext == ".md" {
52- return "text/markdown; charset=UTF-8"
53- } else if ext == ".json" || ext == ".map" {
54- return "application/json"
55- } else if ext == ".rss" {
56- return "application/rss+xml"
57- } else if ext == ".atom" {
58- return "application/atom+xml"
59- } else if ext == ".webmanifest" {
60- return "application/manifest+json"
61- } else if ext == ".xml" {
62- return "application/xml"
63- } else if ext == ".xsl" {
64- return "application/xml"
65- } else if ext == ".avif" {
66- return "image/avif"
67- } else if ext == ".heif" {
68- return "image/heif"
69- } else if ext == ".heic" {
70- return "image/heif"
71- } else if ext == ".opus" {
72- return "audio/opus"
73- } else if ext == ".wav" {
74- return "audio/wav"
75- } else if ext == ".mp3" {
76- return "audio/mpeg"
77- } else if ext == ".mp4" {
78- return "video/mp4"
79- } else if ext == ".mpeg" {
80- return "video/mpeg"
81- } else if ext == ".wasm" {
82- return "application/wasm"
83- } else if ext == ".opml" {
84- return "text/x-opml"
85- } else if ext == ".eot" {
86- return "application/vnd.ms-fontobject"
87- } else if ext == ".yml" || ext == ".yaml" {
88- return "text/x-yaml"
89- } else if ext == ".zip" {
90- return "application/zip"
91- } else if ext == ".rar" {
92- return "application/vnd.rar"
93- } else if ext == ".txt" {
94- return "text/plain"
95- }
96-
97- return "text/plain"
98-}
99-
10020 func UriToImgProcessOpts(uri string) (*ImgProcessOpts, error) {
10121 opts := &ImgProcessOpts{}
10222 parts := strings.Split(uri, "/")
Back to top