Add force flag to server redirects config
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Mon, 5 Oct 2020 15:56:28 +0000 (17:56 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Mon, 5 Oct 2020 20:20:00 +0000 (22:20 +0200)
Fixes #7778

commands/server.go
config/commonConfig.go
docs/content/en/getting-started/configuration.md

index 602527253194f0e6e66b8a9542fb027140ac49f3..7d604b97d55ef797cddecd51434997aec6e0425a 100644 (file)
@@ -376,17 +376,36 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, string, string, erro
                        }
 
                        if redirect := f.c.serverConfig.MatchRedirect(requestURI); !redirect.IsZero() {
+                               doRedirect := true
                                // This matches Netlify's behaviour and is needed for SPA behaviour.
                                // See https://docs.netlify.com/routing/redirects/rewrites-proxies/
-                               if redirect.Status == 200 {
-                                       if r2 := f.rewriteRequest(r, strings.TrimPrefix(redirect.To, u.Path)); r2 != nil {
-                                               requestURI = redirect.To
-                                               r = r2
+                               if !redirect.Force {
+                                       path := filepath.Clean(strings.TrimPrefix(requestURI, u.Path))
+                                       fi, err := f.c.hugo().BaseFs.PublishFs.Stat(path)
+                                       if err == nil {
+                                               if fi.IsDir() {
+                                                       // There will be overlapping directories, so we
+                                                       // need to check for a file.
+                                                       _, err = f.c.hugo().BaseFs.PublishFs.Stat(filepath.Join(path, "index.html"))
+                                                       doRedirect = err != nil
+                                               } else {
+                                                       doRedirect = false
+                                               }
+
+                                       }
+                               }
+
+                               if doRedirect {
+                                       if redirect.Status == 200 {
+                                               if r2 := f.rewriteRequest(r, strings.TrimPrefix(redirect.To, u.Path)); r2 != nil {
+                                                       requestURI = redirect.To
+                                                       r = r2
+                                               }
+                                       } else {
+                                               w.Header().Set("Content-Type", "")
+                                               http.Redirect(w, r, redirect.To, redirect.Status)
+                                               return
                                        }
-                               } else {
-                                       w.Header().Set("Content-Type", "")
-                                       http.Redirect(w, r, redirect.To, redirect.Status)
-                                       return
                                }
 
                        }
@@ -416,7 +435,6 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, string, string, erro
 
        fileserver := decorate(http.FileServer(fs))
        mu := http.NewServeMux()
-
        if u.Path == "" || u.Path == "/" {
                mu.Handle("/", fileserver)
        } else {
index ac82dc3bc98c3059098049b32b8078b032904b1e..522ced85412561a54cc04bbccd1c9a03753f0252 100644 (file)
@@ -184,6 +184,7 @@ type Redirect struct {
        From   string
        To     string
        Status int
+       Force  bool
 }
 
 func (r Redirect) IsZero() bool {
index 076d9161ccf564c505403690ea1f225ac7f417ce..9cbe988f1980dd8cf51a4e25c4dae52d7fcc2d7b 100644 (file)
@@ -360,10 +360,10 @@ Note that a `status` code of 200 will trigger a [URL rewrite](https://docs.netli
 from = "/myspa/**"
 to = "/myspa/"
 status = 200
+force = false
 {{< /code-toggle >}}
 
-
-
+{{< new-in "0.76.0" >}} Setting `force=true` will make a redirect even if there is existing content in the path. Note that before Hugo 0.76  `force` was the default behaviour, but this is inline with how Netlify does it.
 
 ## Configure Title Case