repos / pico

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

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
M pgs/api.go
+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) {
A pgs/calc_route_test.go
+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+}
M shared/storage/proxy.go
+2, -0
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"