- commit
- 81fd732
- parent
- 5b57de3
- author
- Eric Bower
- date
- 2023-11-16 20:12:59 +0000 UTC
fix(pgs): period in route redirects to 404 (#59) Closes #58
3 files changed,
+144,
-36
+51,
-36
1@@ -147,14 +147,46 @@ func calcPossibleRoutes(projectName, fp string, userRedirects []*RedirectRule) [
2 fname := filepath.Base(fp)
3 fdir := filepath.Dir(fp)
4 fext := filepath.Ext(fp)
5+ mimeType := storage.GetMimeType(fp)
6+ rts := []*HttpReply{}
7+ notFound := &HttpReply{
8+ Filepath: filepath.Join(projectName, "404.html"),
9+ Status: 404,
10+ }
11
12- dirRoute := shared.GetAssetFileName(&utils.FileEntry{
13- Filepath: filepath.Join(projectName, fp, "index.html"),
14- })
15+ for _, redirect := range userRedirects {
16+ rr := regexp.MustCompile(redirect.From)
17+ match := rr.FindStringSubmatch(fp)
18+ if len(match) > 0 {
19+ ruleRoute := shared.GetAssetFileName(&utils.FileEntry{
20+ Filepath: filepath.Join(projectName, redirect.To),
21+ })
22+ rule := &HttpReply{
23+ Filepath: ruleRoute,
24+ Status: redirect.Status,
25+ Query: redirect.Query,
26+ }
27+ if redirect.Force {
28+ rts = append([]*HttpReply{rule}, rts...)
29+ } else {
30+ rts = append(rts, rule)
31+ }
32+ }
33+ }
34
35- // hack: we need to accommodate routes that are just directories
36- // and point the user to the index.html of each root dir.
37- if fname == "." || fext == "" {
38+ // user routes take precedence
39+ if len(rts) > 0 {
40+ rts = append(rts, notFound)
41+ return rts
42+ }
43+
44+ // file extension is unknown
45+ if mimeType == "text/plain" && fext != ".txt" {
46+ dirRoute := shared.GetAssetFileName(&utils.FileEntry{
47+ Filepath: filepath.Join(projectName, fp, "index.html"),
48+ })
49+ // we need to accommodate routes that are just directories
50+ // and point the user to the index.html of each root dir.
51 nameRoute := shared.GetAssetFileName(&utils.FileEntry{
52 Filepath: filepath.Join(
53 projectName,
54@@ -162,32 +194,11 @@ func calcPossibleRoutes(projectName, fp string, userRedirects []*RedirectRule) [
55 fmt.Sprintf("%s.html", fname),
56 ),
57 })
58-
59- rts := []*HttpReply{
60- {Filepath: dirRoute, Status: 200},
61- {Filepath: nameRoute, Status: 200},
62- }
63-
64- for _, redirect := range userRedirects {
65- rr := regexp.MustCompile(redirect.From)
66- match := rr.FindStringSubmatch(fp)
67- if len(match) > 0 {
68- ruleRoute := shared.GetAssetFileName(&utils.FileEntry{
69- Filepath: filepath.Join(projectName, redirect.To),
70- })
71- rule := &HttpReply{
72- Filepath: ruleRoute,
73- Status: redirect.Status,
74- Query: redirect.Query,
75- }
76- if redirect.Force {
77- rts = append([]*HttpReply{rule}, rts...)
78- } else {
79- rts = append(rts, rule)
80- }
81- }
82- }
83-
84+ rts = append(rts,
85+ &HttpReply{Filepath: nameRoute, Status: 200},
86+ &HttpReply{Filepath: dirRoute, Status: 200},
87+ notFound,
88+ )
89 return rts
90 }
91
92@@ -195,10 +206,14 @@ func calcPossibleRoutes(projectName, fp string, userRedirects []*RedirectRule) [
93 Filepath: filepath.Join(projectName, fdir, fname),
94 })
95
96- return []*HttpReply{
97- {Filepath: defRoute, Status: 200},
98- {Filepath: dirRoute, Status: 200},
99- }
100+ rts = append(rts,
101+ &HttpReply{
102+ Filepath: defRoute, Status: 200,
103+ },
104+ notFound,
105+ )
106+
107+ return rts
108 }
109
110 func assetHandler(w http.ResponseWriter, h *AssetHandler) {
+91,
-0
1@@ -0,0 +1,91 @@
2+package pgs
3+
4+import (
5+ "fmt"
6+ "testing"
7+
8+ "github.com/google/go-cmp/cmp"
9+)
10+
11+type RouteFixture struct {
12+ Name string
13+ Actual []*HttpReply
14+ Expected []*HttpReply
15+}
16+
17+func TestCalcPossibleRoutes(t *testing.T) {
18+ fixtures := []RouteFixture{
19+ {
20+ Name: "basic-index",
21+ Actual: calcPossibleRoutes("test", "index.html", []*RedirectRule{}),
22+ Expected: []*HttpReply{
23+ {Filepath: "test/index.html", Status: 200},
24+ {Filepath: "test/404.html", Status: 404},
25+ },
26+ },
27+ {
28+ Name: "basic-txt",
29+ Actual: calcPossibleRoutes("test", "index.txt", []*RedirectRule{}),
30+ Expected: []*HttpReply{
31+ {Filepath: "test/index.txt", Status: 200},
32+ {Filepath: "test/404.html", Status: 404},
33+ },
34+ },
35+ {
36+ Name: "basic-named",
37+ Actual: calcPossibleRoutes("test", "wow.html", []*RedirectRule{}),
38+ Expected: []*HttpReply{
39+ {Filepath: "test/wow.html", Status: 200},
40+ {Filepath: "test/404.html", Status: 404},
41+ },
42+ },
43+ {
44+ Name: "subdirectory-index",
45+ Actual: calcPossibleRoutes("test", "nice/index.html", []*RedirectRule{}),
46+ Expected: []*HttpReply{
47+ {Filepath: "test/nice/index.html", Status: 200},
48+ {Filepath: "test/404.html", Status: 404},
49+ },
50+ },
51+ {
52+ Name: "subdirectory-named",
53+ Actual: calcPossibleRoutes("test", "nice/wow.html", []*RedirectRule{}),
54+ Expected: []*HttpReply{
55+ {Filepath: "test/nice/wow.html", Status: 200},
56+ {Filepath: "test/404.html", Status: 404},
57+ },
58+ },
59+ {
60+ Name: "subdirectory-bare",
61+ Actual: calcPossibleRoutes("test", "nice", []*RedirectRule{}),
62+ Expected: []*HttpReply{
63+ {Filepath: "test/nice.html", Status: 200},
64+ {Filepath: "test/nice/index.html", Status: 200},
65+ {Filepath: "test/404.html", Status: 404},
66+ },
67+ },
68+ {
69+ Name: "spa",
70+ Actual: calcPossibleRoutes("test", "nice", []*RedirectRule{
71+ {
72+ From: "/*",
73+ To: "/index.html",
74+ Status: 200,
75+ },
76+ }),
77+ Expected: []*HttpReply{
78+ {Filepath: "test/index.html", Status: 200},
79+ {Filepath: "test/404.html", Status: 404},
80+ },
81+ },
82+ }
83+
84+ for _, fixture := range fixtures {
85+ t.Run(fixture.Name, func(t *testing.T) {
86+ fmt.Println(fixture.Actual[0].Filepath)
87+ if cmp.Equal(fixture.Actual, fixture.Expected) == false {
88+ t.Fatalf(cmp.Diff(fixture.Expected, fixture.Actual))
89+ }
90+ })
91+ }
92+}
1@@ -52,6 +52,8 @@ func GetMimeType(fpath string) string {
2 return "application/atom+xml"
3 } else if ext == ".webmanifest" {
4 return "application/manifest+json"
5+ } else if ext == ".txt" {
6+ return "text/plain"
7 }
8
9 return "text/plain"