From 21e2758145d100d74013060f7090d84679cae683 Mon Sep 17 00:00:00 2001 From: tjpcc Date: Sun, 30 Apr 2023 17:31:35 -0600 Subject: spartan handler for a CGI directory --- contrib/cgi/spartan.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 contrib/cgi/spartan.go (limited to 'contrib') diff --git a/contrib/cgi/spartan.go b/contrib/cgi/spartan.go new file mode 100644 index 0000000..01ebb19 --- /dev/null +++ b/contrib/cgi/spartan.go @@ -0,0 +1,46 @@ +package cgi + +import ( + "context" + "fmt" + "strings" + + "tildegit.org/tjp/gus" + "tildegit.org/tjp/gus/spartan" +) + +// SpartanCGIDirectory runs executable files relative to a root directory in the file system. +// +// It will also find any run any executable _part way_ through the path, so for example a +// request for /foo/bar/baz can also run an executable found at /foo or /foo/bar. In such +// a case the PATH_INFO environment variable will include the remaining portion of the URI. +func SpartanCGIDirectory(pathRoot, fsRoot string) gus.Handler { + fsRoot = strings.TrimRight(fsRoot, "/") + return gus.HandlerFunc(func(ctx context.Context, request *gus.Request) *gus.Response { + if !strings.HasPrefix(request.Path, pathRoot) { + return nil + } + + filepath, pathinfo, err := ResolveCGI(request.Path[len(pathRoot):], fsRoot) + if err != nil { + return spartan.ServerError(err) + } + if filepath == "" { + return nil + } + + stdout, exitCode, err := RunCGI(ctx, request, filepath, pathinfo) + if err != nil { + return spartan.ServerError(err) + } + if exitCode != 0 { + return spartan.ServerError(fmt.Errorf("CGI process exited with status %d", exitCode)) + } + + response, err := spartan.ParseResponse(stdout) + if err != nil { + return spartan.ServerError(err) + } + return response + }) +} -- cgit v1.2.3