Commit 3640880
Eric Bower
·
2026-04-04 20:01:33 -0400 EDT
parent 6a3121d
fix(pgs): force redirect from root
3 files changed,
+59,
-4
+24,
-4
| ... | ... | @@ -112,6 +112,11 @@ func correlatePlaceholder(orig, pattern string) (string, string) { | |
| 112 | 112 | _type = "variable" | |
| 113 | 113 | } | |
| 114 | 114 | ||
| 115 | + | // special case: root path matches root path | |
| 116 | + | if orig == "/" && pattern == "/" { | |
| 117 | + | return "/", "match" | |
| 118 | + | } | |
| 119 | + | ||
| 115 | 120 | return filepath.Join(nextList...), _type | |
| 116 | 121 | } | |
| 117 | 122 |
| ... | ... | @@ -250,10 +255,25 @@ func calcRoutes(projectName, fp string, userRedirects []*RedirectRule) []*HttpRe | |
| 250 | 255 | userReply := []*HttpReply{} | |
| 251 | 256 | var rule *HttpReply | |
| 252 | 257 | if redirect.To != "" { | |
| 253 | - | rule = &HttpReply{ | |
| 254 | - | Filepath: route, | |
| 255 | - | Status: redirect.Status, | |
| 256 | - | Query: redirect.Query, | |
| 258 | + | // expand redirect target to find actual file (e.g., directory -> index.html) | |
| 259 | + | // but only if Force is true, it's not a full URL, and it's a directory path (ends with / but not just /) | |
| 260 | + | if redirect.Force && !hasProtocol(redirect.To) && strings.HasSuffix(route, "/") && route != "/" { | |
| 261 | + | expanded := expandRoute(projectName, route, redirect.Status) | |
| 262 | + | if len(expanded) > 0 { | |
| 263 | + | rule = expanded[0] | |
| 264 | + | } else { | |
| 265 | + | rule = &HttpReply{ | |
| 266 | + | Filepath: route, | |
| 267 | + | Status: redirect.Status, | |
| 268 | + | Query: redirect.Query, | |
| 269 | + | } | |
| 270 | + | } | |
| 271 | + | } else { | |
| 272 | + | rule = &HttpReply{ | |
| 273 | + | Filepath: route, | |
| 274 | + | Status: redirect.Status, | |
| 275 | + | Query: redirect.Query, | |
| 276 | + | } | |
| 257 | 277 | } | |
| 258 | 278 | userReply = append(userReply, rule) | |
| 259 | 279 | } |
+19,
-0
| ... | ... | @@ -663,6 +663,25 @@ func TestCalcRoutes(t *testing.T) { | |
| 663 | 663 | {Filepath: "public/404.html", Status: 404}, | |
| 664 | 664 | }, | |
| 665 | 665 | }, | |
| 666 | + | { | |
| 667 | + | Name: "root-redirect", | |
| 668 | + | Actual: calcRoutes( | |
| 669 | + | "public", | |
| 670 | + | "/", | |
| 671 | + | []*RedirectRule{ | |
| 672 | + | { | |
| 673 | + | From: "/", | |
| 674 | + | To: "/dax/cool/wow/", | |
| 675 | + | Status: 302, | |
| 676 | + | Force: true, | |
| 677 | + | }, | |
| 678 | + | }, | |
| 679 | + | ), | |
| 680 | + | Expected: []*HttpReply{ | |
| 681 | + | {Filepath: "public/dax/cool/wow/index.html", Status: 302}, | |
| 682 | + | {Filepath: "public/404.html", Status: 404}, | |
| 683 | + | }, | |
| 684 | + | }, | |
| 666 | 685 | } | |
| 667 | 686 | ||
| 668 | 687 | for _, fixture := range fixtures { |
+16,
-0
| ... | ... | @@ -141,6 +141,21 @@ func TestParseRedirectText(t *testing.T) { | |
| 141 | 141 | }, | |
| 142 | 142 | } | |
| 143 | 143 | ||
| 144 | + | rootRedirect := RedirectFixture{ | |
| 145 | + | name: "root-redirect", | |
| 146 | + | input: "/ /dax/cool/wow/ 302!", | |
| 147 | + | expect: []*RedirectRule{ | |
| 148 | + | { | |
| 149 | + | From: "/", | |
| 150 | + | To: "/dax/cool/wow/", | |
| 151 | + | Status: 302, | |
| 152 | + | Query: empty, | |
| 153 | + | Conditions: empty, | |
| 154 | + | Force: true, | |
| 155 | + | }, | |
| 156 | + | }, | |
| 157 | + | } | |
| 158 | + | ||
| 144 | 159 | fixtures := []RedirectFixture{ | |
| 145 | 160 | spa, | |
| 146 | 161 | rss, |