summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortjpcc <tjp@ctrl-c.club>2023-04-30 17:31:35 -0600
committertjpcc <tjp@ctrl-c.club>2023-04-30 17:31:35 -0600
commit21e2758145d100d74013060f7090d84679cae683 (patch)
tree6723c4fa7eea0f9f5398150a22d0dda59e12a75f
parent7a021631cd9e02abe62610f66567f81062cecfbe (diff)
spartan handler for a CGI directory
-rw-r--r--contrib/cgi/spartan.go46
1 files changed, 46 insertions, 0 deletions
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
+ })
+}