repos / pico

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

commit
a526333
parent
b910e2a
author
Eric Bower
date
2024-04-03 14:54:19 +0000 UTC
refactor(pgs): redirects and rewrites
3 files changed,  +81, -27
M pgs/api.go
+2, -2
 1@@ -179,7 +179,7 @@ func (h *AssetHandler) handle(w http.ResponseWriter, r *http.Request) {
 2 	status := http.StatusOK
 3 	attempts := []string{}
 4 	for _, fp := range routes {
 5-		if hasProtocol(fp.Filepath) || fp.Status == http.StatusMovedPermanently {
 6+		if checkIsRedirect(fp.Status) {
 7 			h.Logger.Info(
 8 				"redirecting request",
 9 				"bucket", h.Bucket.Name,
10@@ -304,7 +304,7 @@ func (h *AssetHandler) handle(w http.ResponseWriter, r *http.Request) {
11 	_, err = io.Copy(w, contents)
12 
13 	if err != nil {
14-		h.Logger.Error(err.Error())
15+		h.Logger.Error("io copy", "err", err.Error())
16 	}
17 }
18 
M pgs/cal_route.go
+16, -19
 1@@ -69,9 +69,8 @@ func expandRoute(projectName, fp string, status int) []*HttpReply {
 2 	return routes
 3 }
 4 
 5-func hasProtocol(url string) bool {
 6-	isFullUrl := strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://")
 7-	return isFullUrl
 8+func checkIsRedirect(status int) bool {
 9+	return status >= 300 && status <= 399
10 }
11 
12 func calcRoutes(projectName, fp string, userRedirects []*RedirectRule) []*HttpReply {
13@@ -92,35 +91,33 @@ func calcRoutes(projectName, fp string, userRedirects []*RedirectRule) []*HttpRe
14 
15 	// user routes
16 	for _, redirect := range userRedirects {
17+		// this doesn't make sense and it forbidden
18+		if redirect.From == redirect.To {
19+			continue
20+		}
21 		rr := regexp.MustCompile(redirect.From)
22 		match := rr.FindStringSubmatch(fp)
23 		if len(match) > 0 {
24-			userReply := []*HttpReply{}
25-			ruleRoute := redirect.To
26-
27-			// special case for redirects that include http(s)://
28-			isFullUrl := hasProtocol(redirect.To)
29-			if !isFullUrl {
30-				ruleRoute = shared.GetAssetFileName(&utils.FileEntry{
31-					Filepath: filepath.Join(projectName, redirect.To),
32-				})
33+			isRedirect := checkIsRedirect(redirect.Status)
34+			if !isRedirect {
35+				// wipe redirect rules to prevent infinite loops
36+				// as such we only support a single hop for user defined redirects
37+				redirectRoutes := calcRoutes(projectName, redirect.To, []*RedirectRule{})
38+				rts = append(rts, redirectRoutes...)
39+				return rts
40 			}
41 
42+			userReply := []*HttpReply{}
43 			var rule *HttpReply
44-			if redirect.To != "" && redirect.To != "/" {
45+			if redirect.To != "" {
46 				rule = &HttpReply{
47-					Filepath: ruleRoute,
48+					Filepath: redirect.To,
49 					Status:   redirect.Status,
50 					Query:    redirect.Query,
51 				}
52 				userReply = append(userReply, rule)
53 			}
54 
55-			if !isFullUrl {
56-				expandedRoutes := expandRoute(projectName, redirect.To, redirect.Status)
57-				userReply = append(userReply, expandedRoutes...)
58-			}
59-
60 			if redirect.Force {
61 				rts = userReply
62 			} else {
M pgs/calc_route_test.go
+63, -6
  1@@ -1,7 +1,6 @@
  2 package pgs
  3 
  4 import (
  5-	"fmt"
  6 	"testing"
  7 
  8 	"github.com/google/go-cmp/cmp"
  9@@ -103,14 +102,14 @@ func TestCalcRoutes(t *testing.T) {
 10 				[]*RedirectRule{
 11 					{
 12 						From:   "/wow",
 13-						To:     "index.html",
 14+						To:     "/index.html",
 15 						Status: 301,
 16 					},
 17 				},
 18 			),
 19 			Expected: []*HttpReply{
 20 				{Filepath: "test/wow.html", Status: 200},
 21-				{Filepath: "test/index.html", Status: 301},
 22+				{Filepath: "/index.html", Status: 301},
 23 				{Filepath: "/wow/", Status: 301},
 24 				{Filepath: "test/404.html", Status: 404},
 25 			},
 26@@ -162,7 +161,7 @@ func TestCalcRoutes(t *testing.T) {
 27 			),
 28 			Expected: []*HttpReply{
 29 				{Filepath: "test/wow/index.html", Status: 200},
 30-				{Filepath: "test/index.html", Status: 301},
 31+				{Filepath: "/", Status: 301},
 32 				{Filepath: "test/404.html", Status: 404},
 33 			},
 34 		},
 35@@ -181,7 +180,7 @@ func TestCalcRoutes(t *testing.T) {
 36 				},
 37 			),
 38 			Expected: []*HttpReply{
 39-				{Filepath: "test/index.html", Status: 301},
 40+				{Filepath: "/", Status: 301},
 41 				{Filepath: "/wow/", Status: 301},
 42 				{Filepath: "test/404.html", Status: 404},
 43 			},
 44@@ -225,11 +224,69 @@ func TestCalcRoutes(t *testing.T) {
 45 				{Filepath: "test/404.html", Status: 404},
 46 			},
 47 		},
 48+		{
 49+			Name: "redirectDirectory",
 50+			Actual: calcRoutes(
 51+				"public",
 52+				"/stata2",
 53+				[]*RedirectRule{
 54+					{
 55+						From:   "/stata2",
 56+						To:     "/workshop-stata2",
 57+						Status: 301,
 58+					},
 59+				},
 60+			),
 61+			Expected: []*HttpReply{
 62+				{Filepath: "public/stata2.html", Status: 200},
 63+				{Filepath: "/workshop-stata2", Status: 301},
 64+				{Filepath: "/stata2/", Status: 301},
 65+				{Filepath: "public/404.html", Status: 404},
 66+			},
 67+		},
 68+		{
 69+			Name: "redirectSubDirectory",
 70+			Actual: calcRoutes(
 71+				"public",
 72+				"/folder2",
 73+				[]*RedirectRule{
 74+					{
 75+						From:   "/folder2",
 76+						To:     "/folder",
 77+						Status: 200,
 78+					},
 79+				},
 80+			),
 81+			Expected: []*HttpReply{
 82+				{Filepath: "public/folder2.html", Status: 200},
 83+				{Filepath: "public/folder.html", Status: 200},
 84+				{Filepath: "/folder/", Status: 301},
 85+				{Filepath: "public/404.html", Status: 404},
 86+			},
 87+		},
 88+		{
 89+			Name: "redirectFromAndToSame",
 90+			Actual: calcRoutes(
 91+				"public",
 92+				"/folder2",
 93+				[]*RedirectRule{
 94+					{
 95+						From:   "/folder2",
 96+						To:     "/folder2",
 97+						Status: 200,
 98+					},
 99+				},
100+			),
101+			Expected: []*HttpReply{
102+				{Filepath: "public/folder2.html", Status: 200},
103+				{Filepath: "/folder2/", Status: 301},
104+				{Filepath: "public/404.html", Status: 404},
105+			},
106+		},
107 	}
108 
109 	for _, fixture := range fixtures {
110 		t.Run(fixture.Name, func(t *testing.T) {
111-			fmt.Println(fixture.Actual[0].Filepath)
112 			if cmp.Equal(fixture.Actual, fixture.Expected) == false {
113 				t.Fatalf(cmp.Diff(fixture.Expected, fixture.Actual))
114 			}