Skip to content

Commit 0689c83

Browse files
committed
Gin is very special -- I used the wrong context to force it. I added a test file for testing this in the future, too
1 parent fc696ab commit 0689c83

2 files changed

Lines changed: 114 additions & 1 deletion

File tree

frontend/routes_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package frontend
2+
3+
import (
4+
"net/http"
5+
"net/http/httptest"
6+
"strings"
7+
"testing"
8+
9+
"github.com/gin-gonic/gin"
10+
"github.com/user00265/dxclustergoapi/spot"
11+
)
12+
13+
type mockCache struct {
14+
spots []spot.Spot
15+
}
16+
17+
func (m *mockCache) GetAllSpots() []spot.Spot {
18+
return m.spots
19+
}
20+
21+
func (m *mockCache) AddSpot(newSpot spot.Spot) bool {
22+
m.spots = append(m.spots, newSpot)
23+
return true
24+
}
25+
26+
func setupTestRouter() *gin.Engine {
27+
gin.SetMode(gin.TestMode)
28+
router := gin.New()
29+
router.RedirectTrailingSlash = false
30+
router.RedirectFixedPath = false
31+
32+
// Path normalization middleware
33+
router.Use(func(c *gin.Context) {
34+
path := c.Request.URL.Path
35+
originalPath := path
36+
37+
// Collapse multiple slashes
38+
for strings.Contains(path, "//") {
39+
path = strings.ReplaceAll(path, "//", "/")
40+
}
41+
42+
// Remove trailing slash (except for root)
43+
if len(path) > 1 && strings.HasSuffix(path, "/") {
44+
path = strings.TrimSuffix(path, "/")
45+
}
46+
47+
// If path was modified, we need to re-route the request
48+
if path != originalPath {
49+
c.Request.URL.Path = path
50+
router.HandleContext(c)
51+
c.Abort()
52+
return
53+
}
54+
55+
c.Next()
56+
})
57+
58+
cache := &mockCache{
59+
spots: []spot.Spot{
60+
{Spotted: "TEST1", Band: "20m"},
61+
{Spotted: "TEST2", Band: "40m"},
62+
},
63+
}
64+
65+
SetupRoutes(router.Group("/"), cache, nil, nil)
66+
return router
67+
}
68+
69+
func TestSpotsEndpointVariations(t *testing.T) {
70+
router := setupTestRouter()
71+
72+
tests := []struct {
73+
name string
74+
path string
75+
wantStatus int
76+
}{
77+
{"spots without slash", "/spots", http.StatusOK},
78+
{"spots with trailing slash", "/spots/", http.StatusOK},
79+
{"spots with double slash", "//spots", http.StatusOK},
80+
{"spots with double slash and trailing", "//spots/", http.StatusOK},
81+
{"spots with multiple slashes", "///spots", http.StatusOK},
82+
{"spots with multiple slashes and trailing", "///spots/", http.StatusOK},
83+
}
84+
85+
for _, tt := range tests {
86+
t.Run(tt.name, func(t *testing.T) {
87+
req := httptest.NewRequest("GET", tt.path, nil)
88+
w := httptest.NewRecorder()
89+
router.ServeHTTP(w, req)
90+
91+
if w.Code != tt.wantStatus {
92+
t.Errorf("GET %s returned status %d, want %d. Body: %s",
93+
tt.path, w.Code, tt.wantStatus, w.Body.String())
94+
}
95+
96+
// Verify no redirect
97+
if w.Code >= 300 && w.Code < 400 {
98+
t.Errorf("GET %s returned redirect %d, should return 200", tt.path, w.Code)
99+
}
100+
})
101+
}
102+
}

main.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,15 +343,26 @@ func setupHTTPRouter(cfg *config.Config) *gin.Engine {
343343
// Normalize paths: remove trailing slashes and collapse multiple slashes
344344
router.Use(func(c *gin.Context) {
345345
path := c.Request.URL.Path
346+
originalPath := path
347+
346348
// Collapse multiple slashes
347349
for strings.Contains(path, "//") {
348350
path = strings.ReplaceAll(path, "//", "/")
349351
}
352+
350353
// Remove trailing slash (except for root)
351354
if len(path) > 1 && strings.HasSuffix(path, "/") {
352355
path = strings.TrimSuffix(path, "/")
353356
}
354-
c.Request.URL.Path = path
357+
358+
// If path was modified, re-route with normalized path
359+
if path != originalPath {
360+
c.Request.URL.Path = path
361+
router.HandleContext(c)
362+
c.Abort()
363+
return
364+
}
365+
355366
c.Next()
356367
})
357368

0 commit comments

Comments
 (0)