46 lines
1.2 KiB
Go
46 lines
1.2 KiB
Go
package cgi
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"tildegit.org/tjp/gus"
|
|
"tildegit.org/tjp/gus/gopher"
|
|
)
|
|
|
|
// GopherCGIDirectory runs any executable files relative to a root directory on the file system.
|
|
//
|
|
// It will also find and run any executables 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 path.
|
|
func GopherCGIDirectory(pathRoot, fsRoot string) gus.Handler {
|
|
fsRoot = strings.TrimRight(fsRoot, "/")
|
|
return 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 gopher.Error(err).Response()
|
|
}
|
|
if filepath == "" {
|
|
return nil
|
|
}
|
|
|
|
stdout, exitCode, err := RunCGI(ctx, request, filepath, pathinfo)
|
|
if err != nil {
|
|
return gopher.Error(err).Response()
|
|
}
|
|
if exitCode != 0 {
|
|
return gopher.Error(
|
|
fmt.Errorf("CGI process exited with status %d", exitCode),
|
|
).Response()
|
|
}
|
|
|
|
return gopher.File(0, stdout)
|
|
}
|
|
}
|