diff options
| -rw-r--r-- | CHANGELOG.adoc | 21 | ||||
| -rw-r--r-- | lib/http/server.go | 15 | ||||
| -rw-r--r-- | lib/http/server_options.go | 13 | ||||
| -rw-r--r-- | pakakeh.go | 2 |
4 files changed, 48 insertions, 3 deletions
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 85f68dd7..666dbaad 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -37,6 +37,27 @@ Legend, * 🌼: Enhancement * 💧: Chores + +[#v0_61_1] +== pakakeh.go v0.61.1 (2026-xx-xx) +//{{{ + +[#v0_61_1_lib_http] +=== lib/http + +==== 🌱 Add BasePath to the ServerOptions + +The BasePath allow server to serve HTTP from custom prefix, other than "/". + +Each request that server received will remove the BasePath first +from the [http.Request.URL.Path] before passing to the handler. +Each redirect that server sent will add the BasePath as the prefix +to redirect URL. + +Any trailing slash in the BasePath will be removed. + + +//}}} [#v0_61_0] == pakakeh.go v0.61.0 (2026-02-09) //{{{ diff --git a/lib/http/server.go b/lib/http/server.go index 64ac5c14..4501cb9f 100644 --- a/lib/http/server.go +++ b/lib/http/server.go @@ -1,6 +1,5 @@ -// SPDX-FileCopyrightText: 2018 M. Shulhan <ms@kilabit.info> -// // SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileCopyrightText: 2018 M. Shulhan <ms@kilabit.info> package http @@ -83,6 +82,11 @@ func (srv *Server) RedirectTemp(res http.ResponseWriter, redirectURL string) { if len(redirectURL) == 0 { redirectURL = "/" } + endWithSlash := redirectURL[len(redirectURL)-1] == '/' + redirectURL = path.Join(srv.Options.BasePath, redirectURL) + if endWithSlash { + redirectURL += `/` + } res.Header().Set(HeaderLocation, redirectURL) res.WriteHeader(http.StatusTemporaryRedirect) } @@ -319,6 +323,8 @@ func (srv *Server) registerPut(ep *Endpoint) (err error) { // ServeHTTP handle mapping of client request to registered endpoints. func (srv *Server) ServeHTTP(res http.ResponseWriter, req *http.Request) { + req.URL.Path = strings.TrimPrefix(req.URL.Path, srv.Options.BasePath) + switch req.Method { case http.MethodDelete: srv.handleDelete(res, req) @@ -481,6 +487,11 @@ func (srv *Server) HandleFS(res http.ResponseWriter, req *http.Request) { // 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. + endWithSlash := redirectURL.Path[len(redirectURL.Path)-1] == '/' + redirectURL.Path = path.Join(srv.Options.BasePath, redirectURL.Path) + if endWithSlash { + redirectURL.Path += `/` + } http.Redirect(res, req, redirectURL.String(), http.StatusMovedPermanently) return } diff --git a/lib/http/server_options.go b/lib/http/server_options.go index d51fe381..8e168885 100644 --- a/lib/http/server_options.go +++ b/lib/http/server_options.go @@ -8,6 +8,7 @@ import ( "log" "net" "net/http" + "strings" "git.sr.ht/~shulhan/pakakeh.go/lib/memfs" ) @@ -38,6 +39,16 @@ type ServerOptions struct { // This field is optional, default to ":80". Address string + // BasePath define the base path or prefix to serve the HTTP request + // and response. + // Each request that server received will remove the BasePath first + // from the [http.Request.URL.Path] before passing to the handler. + // Each redirect that server sent will add the BasePath as the prefix + // to redirect URL. + // + // Any trailing slash in the BasePath will be removed. + BasePath string + // Conn contains custom HTTP server connection. // This fields is optional. Conn *http.Server @@ -64,6 +75,8 @@ func (opts *ServerOptions) init() { opts.Address = ":80" } + opts.BasePath = strings.TrimRight(opts.BasePath, `/`) + if opts.Conn == nil { opts.Conn = &http.Server{ ReadTimeout: defRWTimeout, @@ -6,4 +6,4 @@ package pakakeh // Version of this module. -var Version = `0.61.0` +var Version = `0.61.1` |
