diff options
| author | Shulhan <ms@kilabit.info> | 2023-05-25 23:44:21 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2023-05-25 23:44:21 +0700 |
| commit | 06e6cbdd511cdd0b969d34c2e5a5e975566cbdc8 (patch) | |
| tree | 3d3847720026141ad4b50f7b5494491ee98ecdcf /lib/http/server.go | |
| parent | 83c2863122df9e550406c525cc57dfe5fb9843f2 (diff) | |
| download | pakakeh.go-06e6cbdd511cdd0b969d34c2e5a5e975566cbdc8.tar.xz | |
lib/http: redirect path with slash if request is directory
If request path is a directory and it is not end with slash, redirect
request to location with slash to allow relative links works inside the
HTML content.
For example, a "/page/index.html" contains links href="sub.html" (where
"sub.html" is inside "/page" directory).
If request to "/page" (without end with slash) return content of
"/page/index.html", then when user click on sub.html it will request to
"/sub.html" instead of "/page/sub.html".
Diffstat (limited to 'lib/http/server.go')
| -rw-r--r-- | lib/http/server.go | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/lib/http/server.go b/lib/http/server.go index 181607e1..3bf96049 100644 --- a/lib/http/server.go +++ b/lib/http/server.go @@ -296,7 +296,18 @@ func (srv *Server) Stop(wait time.Duration) (err error) { return srv.Server.Shutdown(ctx) } -func (srv *Server) getFSNode(reqPath string) (node *memfs.Node) { +// getFSNode get the memfs Node based on the request path. +// +// If the path is not exist, try path with index.html; +// if it still not exist try path with suffix .html. +// +// If the path is directory and contains index.html, the node for index.html +// with true will be returned. +// +// If the path is directory and does not contains index.html and +// EnableIndexHtml is true, server will generate list of content for +// index.html. +func (srv *Server) getFSNode(reqPath string) (node *memfs.Node, isDir bool) { var ( nodeIndexHtml *memfs.Node pathHtml string @@ -304,7 +315,7 @@ func (srv *Server) getFSNode(reqPath string) (node *memfs.Node) { ) if srv.Options.Memfs == nil { - return nil + return nil, false } pathHtml = path.Join(reqPath, `index.html`) @@ -312,7 +323,7 @@ func (srv *Server) getFSNode(reqPath string) (node *memfs.Node) { node, err = srv.Options.Memfs.Get(reqPath) if err != nil { if !errors.Is(err, os.ErrNotExist) { - return nil + return nil, false } node, err = srv.Options.Memfs.Get(pathHtml) @@ -320,26 +331,26 @@ func (srv *Server) getFSNode(reqPath string) (node *memfs.Node) { pathHtml = reqPath + `.html` node, err = srv.Options.Memfs.Get(pathHtml) if err != nil { - return nil + return nil, false } - return node + return node, false } } if node.IsDir() { nodeIndexHtml, err = srv.Options.Memfs.Get(pathHtml) if err == nil { - return nodeIndexHtml + return nodeIndexHtml, true } if !srv.Options.EnableIndexHtml { - return nil + return nil, false } node.GenerateIndexHtml() } - return node + return node, false } // handleCORS handle the CORS request. @@ -465,15 +476,24 @@ func (srv *Server) HandleFS(res http.ResponseWriter, req *http.Request) { requestETag string size int64 err error + isDir bool ok bool ) - node = srv.getFSNode(req.URL.Path) + node, isDir = srv.getFSNode(req.URL.Path) if node == nil { res.WriteHeader(http.StatusNotFound) return } + if isDir && req.URL.Path[len(req.URL.Path)-1] != '/' { + // If request path is a directory and it is not end with + // slash, redirect request to location with slash to allow + // relative links works inside the HTML content. + http.Redirect(res, req, req.URL.Path+"/", http.StatusFound) + return + } + if srv.Options.HandleFS != nil { ok = srv.Options.HandleFS(node, res, req) if !ok { @@ -592,7 +612,7 @@ func (srv *Server) handleHead(res http.ResponseWriter, req *http.Request) { func (srv *Server) handleOptions(res http.ResponseWriter, req *http.Request) { methods := make(map[string]bool) - node := srv.getFSNode(req.URL.Path) + node, _ := srv.getFSNode(req.URL.Path) if node != nil { methods[http.MethodGet] = true methods[http.MethodHead] = true |
