- commit
- 707a530
- parent
- 06d4bdd
- author
- Eric Bower
- date
- 2023-08-14 14:22:30 +0000 UTC
fix: better object detection and route detection
2 files changed,
+68,
-36
+60,
-35
1@@ -21,15 +21,41 @@ import (
2 )
3
4 type AssetHandler struct {
5- Username string
6- Subdomain string
7- Filepath string
8- Cfg *shared.ConfigSite
9- Dbpool db.DB
10- Storage storage.ObjectStorage
11- Logger *zap.SugaredLogger
12- Cache *gocache.Cache
13- UserID string
14+ Username string
15+ Subdomain string
16+ Filepath string
17+ ProjectDir string
18+ Cfg *shared.ConfigSite
19+ Dbpool db.DB
20+ Storage storage.ObjectStorage
21+ Logger *zap.SugaredLogger
22+ Cache *gocache.Cache
23+ UserID string
24+}
25+
26+func calcPossibleRoutes(projectName, fp string) []string {
27+ fname := filepath.Base(fp)
28+ fdir := filepath.Dir(fp)
29+ fext := filepath.Ext(fp)
30+
31+ // hack: we need to accommodate routes that are just directories
32+ // and point the user to the index.html of each root dir.
33+ if fname == "." || fext == "" {
34+ return []string{
35+ shared.GetAssetFileName(&utils.FileEntry{
36+ Filepath: filepath.Join(projectName, fp, "index.html"),
37+ }),
38+ }
39+ }
40+
41+ return []string{
42+ shared.GetAssetFileName(&utils.FileEntry{
43+ Filepath: filepath.Join(projectName, fdir, fname),
44+ }),
45+ shared.GetAssetFileName(&utils.FileEntry{
46+ Filepath: filepath.Join(projectName, fp, "index.html"),
47+ }),
48+ }
49 }
50
51 func assetHandler(w http.ResponseWriter, h *AssetHandler) {
52@@ -40,22 +66,30 @@ func assetHandler(w http.ResponseWriter, h *AssetHandler) {
53 return
54 }
55
56- fname := shared.GetAssetFileName(&utils.FileEntry{Filepath: h.Filepath})
57+ routes := calcPossibleRoutes(h.ProjectDir, h.Filepath)
58+ var contents storage.ReaderAtCloser
59+ assetFilepath := ""
60+ for _, fp := range routes {
61+ c, err := h.Storage.GetFile(bucket, fp)
62+ if err == nil {
63+ contents = c
64+ assetFilepath = fp
65+ break
66+ }
67+ }
68
69- contents, err := h.Storage.GetFile(bucket, fname)
70- if err != nil {
71+ if assetFilepath == "" {
72 h.Logger.Infof(
73 "asset not found in bucket: bucket:[%s], file:[%s]",
74 bucket.Name,
75- fname,
76+ h.Filepath,
77 )
78 http.Error(w, err.Error(), http.StatusInternalServerError)
79 return
80 }
81 defer contents.Close()
82
83- contentType := shared.GetMimeType(fname)
84-
85+ contentType := shared.GetMimeType(assetFilepath)
86 w.Header().Add("Content-Type", contentType)
87 _, err = io.Copy(w, contents)
88
89@@ -94,7 +128,6 @@ func serveAsset(subdomain string, w http.ResponseWriter, r *http.Request) {
90 http.Error(w, err.Error(), http.StatusNotFound)
91 return
92 }
93- projectDir := props.ProjectName
94
95 user, err := dbpool.FindUserForName(props.Username)
96 if err != nil {
97@@ -102,31 +135,23 @@ func serveAsset(subdomain string, w http.ResponseWriter, r *http.Request) {
98 http.Error(w, "user not found", http.StatusNotFound)
99 return
100 }
101+ projectDir := props.ProjectName
102 project, err := dbpool.FindProjectByName(user.ID, props.ProjectName)
103 if err == nil {
104 projectDir = project.ProjectDir
105 }
106
107- fname := filepath.Base(floc)
108- fdir := filepath.Dir(floc)
109- // hack: we need to accommodate routes that are just directories
110- // and point the user to the index.html of each root dir.
111- if fname == "." || filepath.Ext(floc) == "" {
112- fname = "index.html"
113- fdir = floc
114- }
115- fpath := filepath.Join(projectDir, fdir, fname)
116-
117 assetHandler(w, &AssetHandler{
118- Username: props.Username,
119- UserID: user.ID,
120- Subdomain: subdomain,
121- Filepath: fpath,
122- Cfg: cfg,
123- Dbpool: dbpool,
124- Storage: st,
125- Logger: logger,
126- Cache: cache,
127+ Username: props.Username,
128+ UserID: user.ID,
129+ Subdomain: subdomain,
130+ ProjectDir: projectDir,
131+ Filepath: floc,
132+ Cfg: cfg,
133+ Dbpool: dbpool,
134+ Storage: st,
135+ Logger: logger,
136+ Cache: cache,
137 })
138 }
139
1@@ -125,7 +125,14 @@ func (s *StorageMinio) DeleteBucket(bucket Bucket) error {
2 }
3
4 func (s *StorageMinio) GetFile(bucket Bucket, fpath string) (ReaderAtCloser, error) {
5- obj, err := s.Client.GetObject(context.TODO(), bucket.Name, fpath, minio.GetObjectOptions{})
6+ // we have to stat the object first to see if it exists
7+ // https://github.com/minio/minio-go/issues/654
8+ _, err := s.Client.StatObject(context.Background(), bucket.Name, fpath, minio.StatObjectOptions{})
9+ if err != nil {
10+ return nil, err
11+ }
12+
13+ obj, err := s.Client.GetObject(context.Background(), bucket.Name, fpath, minio.GetObjectOptions{})
14 if err != nil {
15 return nil, err
16 }