diff options
| author | Shulhan <ms@kilabit.info> | 2026-01-06 23:00:07 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2026-01-06 23:05:47 +0700 |
| commit | e91954b5a65847970903e0d8294e54d918c8bc0b (patch) | |
| tree | 95d971ce7c35fdc1d586e52ba53189ca2d88d93a /lib/http | |
| parent | f9567f0d4fc5cf6d0e1cea2d22289250c6b1cb2b (diff) | |
| download | pakakeh.go-e91954b5a65847970903e0d8294e54d918c8bc0b.tar.xz | |
lib/http: add second return value, statusCode, to FSHandler
Non-zero status code indicates that the function already response
to the request, and the server will return immediately.
Zero status code indicates that the function did not process the request,
it is up to server to process the returned node `out`.
Diffstat (limited to 'lib/http')
| -rw-r--r-- | lib/http/fs_handler.go | 19 | ||||
| -rw-r--r-- | lib/http/http_test.go | 29 | ||||
| -rw-r--r-- | lib/http/server.go | 14 | ||||
| -rw-r--r-- | lib/http/server_test.go | 6 |
4 files changed, 44 insertions, 24 deletions
diff --git a/lib/http/fs_handler.go b/lib/http/fs_handler.go index b88c13b4..7dfca198 100644 --- a/lib/http/fs_handler.go +++ b/lib/http/fs_handler.go @@ -15,11 +15,16 @@ import ( // The node parameter contains the requested file inside the memfs or nil // if the file does not exist. // -// If the handler return non-nil [*memfs.Node], server will continue -// processing the node, writing the [memfs.Node] content type, body, and so -// on. +// This function return two values: the node `out` that is used to process the +// request and response; and the HTTP status code `statusCode` returned in +// response. // -// If the handler return nil, server stop processing the node and return -// immediately, which means the function should have already handle writing -// the header, status code, and/or body. -type FSHandler func(node *memfs.Node, res http.ResponseWriter, req *http.Request) (out *memfs.Node) +// Non-zero status code indicates that the function already response +// to the request, and the server will return immediately. +// +// Zero status code indicates that the function did not process the request, +// it is up to server to process the returned node `out`. +// The returned node `out` may be the same as `node`, modified, of completely +// new. +type FSHandler func(node *memfs.Node, res http.ResponseWriter, req *http.Request) ( + out *memfs.Node, statusCode int) diff --git a/lib/http/http_test.go b/lib/http/http_test.go index 4cb40856..fa0c9975 100644 --- a/lib/http/http_test.go +++ b/lib/http/http_test.go @@ -106,30 +106,33 @@ var ( // If the node path is start with "/auth/" and cookie name "sid" exist // with value "authz" it will return true; // otherwise it will redirect to "/" and return false. -func handleFS(node *memfs.Node, res http.ResponseWriter, req *http.Request) *memfs.Node { - if node == nil { - res.WriteHeader(http.StatusNotFound) - return nil - } - +func handleFS(node *memfs.Node, res http.ResponseWriter, req *http.Request) ( + out *memfs.Node, statusCode int, +) { var ( - lowerPath = strings.ToLower(node.Path) - + lowerPath string cookieSid *http.Cookie err error ) + if node == nil { + lowerPath = strings.ToLower(req.URL.Path) + } else { + lowerPath = strings.ToLower(node.Path) + } if strings.HasPrefix(lowerPath, "/auth/") { cookieSid, err = req.Cookie("sid") if err != nil { - http.Redirect(res, req, "/", http.StatusSeeOther) - return nil + statusCode = http.StatusSeeOther + http.Redirect(res, req, "/", statusCode) + return nil, statusCode } if cookieSid.Value != "authz" { - http.Redirect(res, req, "/", http.StatusSeeOther) - return nil + statusCode = http.StatusSeeOther + http.Redirect(res, req, "/", statusCode) + return nil, statusCode } } - return node + return node, 0 } func registerEndpoints() { diff --git a/lib/http/server.go b/lib/http/server.go index 5801832f..4c89032b 100644 --- a/lib/http/server.go +++ b/lib/http/server.go @@ -449,11 +449,13 @@ func (srv *Server) handleDelete(res http.ResponseWriter, req *http.Request) { // This method only works if the [ServerOptions.Memfs] is not nil. // // If the request Path exists and [ServerOptions.HandleFS] is set and -// returning false, it will return immediately. +// returning [*memfs.Node] with non-zero HTTP `statusCode`, server will return +// immediately. // // If the request Path exists in file system, it will return 200 OK with the // header Content-Type set accordingly to the detected file type and the // response body set to the content of file. +// // If the request Method is HEAD, only the header will be sent back to client. // // If the request Path is not exist it will return 404 Not Found. @@ -485,11 +487,17 @@ func (srv *Server) HandleFS(res http.ResponseWriter, req *http.Request) { } if srv.Options.HandleFS != nil { - node = srv.Options.HandleFS(node, res, req) - if node == nil { + var statusCode int + node, statusCode = srv.Options.HandleFS(node, res, req) + if statusCode != 0 { + // HandleFS already response to the request. return } } + if node == nil { + res.WriteHeader(http.StatusNotFound) + return + } res.Header().Set(HeaderContentType, node.ContentType) diff --git a/lib/http/server_test.go b/lib/http/server_test.go index a3a82d9e..6542d833 100644 --- a/lib/http/server_test.go +++ b/lib/http/server_test.go @@ -995,6 +995,10 @@ func TestServer_Options_HandleFS(t *testing.T) { }, expStatusCode: http.StatusOK, expResBody: "<html><body>Hello, /auth/sub!</body></html>\n", + }, { + desc: `With public path not exists`, + reqPath: `/index.php`, + expStatusCode: http.StatusNotFound, }} for _, c = range cases { @@ -1025,7 +1029,7 @@ func TestServer_Options_HandleFS(t *testing.T) { t.Fatalf("%s: %s", c.desc, err) } - test.Assert(t, "response body", c.expResBody, string(gotBody)) + test.Assert(t, c.desc+`: response body`, c.expResBody, string(gotBody)) } } |
