github.com/leplay/upcn@v0.7.0/http/redirects/redirects_test.go (about) 1 package redirects 2 3 import ( 4 "fmt" 5 "net/http" 6 "net/http/httptest" 7 "os" 8 "strings" 9 "testing" 10 11 "github.com/apex/up" 12 "github.com/tj/assert" 13 14 "github.com/apex/up/internal/redirect" 15 ) 16 17 func TestRedirects(t *testing.T) { 18 t.Run("from config", func(t *testing.T) { 19 c := &up.Config{ 20 Redirects: redirect.Rules{ 21 "/blog": { 22 Location: "https://blog.apex.sh", 23 Status: 301, 24 }, 25 "/enterprise": { 26 Location: "/docs/enterprise", 27 Status: 302, 28 }, 29 "/api": { 30 Location: "/api/v1", 31 Status: 200, 32 }, 33 "/products": { 34 Location: "/store", 35 Status: 301, 36 }, 37 "/app/*": { 38 Location: "/", 39 }, 40 "/app/login": { 41 Location: "https://app.apex.sh", 42 Status: 301, 43 }, 44 "/documentation/:product/guides/:guide": { 45 Location: "/docs/:product/:guide", 46 Status: 200, 47 }, 48 "/shop/:brand": { 49 Location: "/products/:brand", 50 Status: 301, 51 }, 52 "/settings/*": { 53 Location: "/admin/:splat", 54 Status: 200, 55 Force: true, 56 }, 57 }, 58 } 59 60 handle := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 61 switch { 62 case r.URL.Path == "/": 63 fmt.Fprintln(w, "Index") 64 case r.URL.Path == "/api/v1": 65 fmt.Fprintln(w, "API V1") 66 case r.URL.Path == "/products": 67 fmt.Fprintln(w, "products") 68 case strings.Contains(r.URL.Path, "/docs"): 69 fmt.Fprintf(w, "docs %s", r.URL.Path) 70 case strings.HasPrefix(r.URL.Path, "/brand"): 71 fmt.Fprintf(w, "shop %s", r.URL.Path) 72 case strings.HasPrefix(r.URL.Path, "/setting"): 73 fmt.Fprintf(w, "settings %s", r.URL.Path) 74 case strings.HasPrefix(r.URL.Path, "/admin"): 75 fmt.Fprintf(w, "admin %s", r.URL.Path) 76 default: 77 http.NotFound(w, r) 78 } 79 }) 80 81 h, err := New(c, handle) 82 assert.NoError(t, err, "init") 83 84 test(t, h) 85 }) 86 } 87 88 func test(t *testing.T, h http.Handler) { 89 os.Chdir("testdata") 90 defer os.Chdir("..") 91 92 t.Run("mismatch", func(t *testing.T) { 93 res := httptest.NewRecorder() 94 req := httptest.NewRequest("GET", "/", nil) 95 96 h.ServeHTTP(res, req) 97 98 assert.Equal(t, 200, res.Code) 99 assert.Equal(t, "Index\n", res.Body.String()) 100 }) 101 102 t.Run("exact match", func(t *testing.T) { 103 res := httptest.NewRecorder() 104 req := httptest.NewRequest("GET", "/blog", nil) 105 106 h.ServeHTTP(res, req) 107 108 assert.Equal(t, 301, res.Code) 109 assert.Equal(t, "text/plain; charset=utf-8", res.Header().Get("Content-Type")) 110 assert.Equal(t, "Moved Permanently\n", res.Body.String()) 111 }) 112 113 t.Run("exact match status", func(t *testing.T) { 114 res := httptest.NewRecorder() 115 req := httptest.NewRequest("GET", "/enterprise", nil) 116 117 h.ServeHTTP(res, req) 118 119 assert.Equal(t, 302, res.Code) 120 assert.Equal(t, "/docs/enterprise", res.Header().Get("Location")) 121 assert.Equal(t, "text/plain; charset=utf-8", res.Header().Get("Content-Type")) 122 assert.Equal(t, "Found\n", res.Body.String()) 123 }) 124 125 t.Run("exact match rewrite", func(t *testing.T) { 126 res := httptest.NewRecorder() 127 req := httptest.NewRequest("GET", "/api", nil) 128 129 h.ServeHTTP(res, req) 130 131 assert.Equal(t, 200, res.Code) 132 assert.Equal(t, "/api", req.Header.Get("X-Original-Path")) 133 assert.Empty(t, res.Header().Get("Location"), "location") 134 assert.Equal(t, "API V1\n", res.Body.String()) 135 }) 136 137 t.Run("shadowed exact", func(t *testing.T) { 138 res := httptest.NewRecorder() 139 req := httptest.NewRequest("GET", "/products", nil) 140 141 h.ServeHTTP(res, req) 142 143 assert.Equal(t, 301, res.Code) 144 assert.Equal(t, "/store", res.Header().Get("Location")) 145 assert.Equal(t, "Moved Permanently\n", res.Body.String()) 146 }) 147 148 t.Run("shadowed dynamic", func(t *testing.T) { 149 res := httptest.NewRecorder() 150 req := httptest.NewRequest("GET", "/app/contact", nil) 151 152 h.ServeHTTP(res, req) 153 154 assert.Equal(t, 200, res.Code) 155 assert.Equal(t, "text/html; charset=utf-8", res.Header().Get("Content-Type")) 156 assert.Equal(t, "Index\n", res.Body.String()) 157 }) 158 159 t.Run("match precedence", func(t *testing.T) { 160 res := httptest.NewRecorder() 161 req := httptest.NewRequest("GET", "/app/login", nil) 162 163 h.ServeHTTP(res, req) 164 165 assert.Equal(t, 301, res.Code) 166 assert.Equal(t, "https://app.apex.sh", res.Header().Get("Location")) 167 assert.Equal(t, "Moved Permanently\n", res.Body.String()) 168 }) 169 170 t.Run("rewrite with placeholders", func(t *testing.T) { 171 res := httptest.NewRecorder() 172 req := httptest.NewRequest("GET", "/documentation/ping/guides/alerting", nil) 173 174 h.ServeHTTP(res, req) 175 176 assert.Equal(t, 200, res.Code) 177 assert.Equal(t, "docs /docs/ping/alerting", res.Body.String()) 178 }) 179 180 t.Run("redirect with placeholders", func(t *testing.T) { 181 res := httptest.NewRecorder() 182 req := httptest.NewRequest("GET", "/shop/apple", nil) 183 184 h.ServeHTTP(res, req) 185 186 assert.Equal(t, 301, res.Code) 187 assert.Equal(t, "Moved Permanently\n", res.Body.String()) 188 }) 189 190 t.Run("forced rewrite", func(t *testing.T) { 191 res := httptest.NewRecorder() 192 req := httptest.NewRequest("GET", "/settings/login", nil) 193 194 h.ServeHTTP(res, req) 195 196 assert.Equal(t, 200, res.Code) 197 assert.Equal(t, "admin /admin/login", res.Body.String()) 198 }) 199 }