Rewrite SCGI support to use prefixes, not regexps, and provide the same SCRIPT_PATH / PATH_INFO break as CGI.

This commit is contained in:
Solderpunk 2020-07-01 16:40:51 +02:00
parent d87ecfd20f
commit 2a263e5e70
3 changed files with 19 additions and 18 deletions

View File

@ -252,8 +252,8 @@ SCGI applications must be started separately (i.e. Molly Brown expects
them to already be running and will not attempt to start them itself),
and as such they can run e.g. as their own user and/or chrooted into
their own filesystem, meaning that they are less of a security threat
in addition to avoiding the overhead of process startup, database
connection etc. on each request.
than CGI applications (in addition to avoiding the overhead of process
startup, database connection etc. on each request).
* `CGIPaths`: A list of filesystem paths, within which
world-executable files will be run as CGI processes. The paths act
@ -265,13 +265,14 @@ connection etc. on each request.
if wildcards are used, the path should *not* end in a trailing slash
- this appears to be a peculiarity of the Go standard library's
`filepath.Glob` function.
* `SCGIPaths`: In this section of the config file, keys are path
regexs and values are paths to unix domain sockets. Any request
whose path matches one of the regexs will cause an SCGI request to
be sent to the corresponding domain socket, and anything sent back
from a program listening on the other end of the socket will be send
as the response to the client. SCGI applications are responsible
for generating their own response headers.
* `SCGIPaths`: In this section of the config file, keys are URL path
prefixes and values are filesystem paths to unix domain sockets.
Any request for a URL whose path begins with one of the specified
prefixes will cause an SCGI request to be sent to the corresponding
domain socket. Anything sent back from a program listening on the
other end of the socket will be sent as the response to the client.
SCGI applications are responsible for generating their own response
headers.
### Certificate zones

View File

@ -82,10 +82,10 @@ func handleCGI(config Config, path string, cgiPath string, URL *url.URL, log *Lo
conn.Write(response)
}
func handleSCGI(socket_path string, config Config, URL *url.URL, log *LogEntry, conn net.Conn) {
func handleSCGI(URL *url.URL, scgiPath string, scgiSocket string, config Config, log *LogEntry, conn net.Conn) {
// Connect to socket
socket, err := net.Dial("unix", socket_path)
socket, err := net.Dial("unix", scgiSocket)
if err != nil {
conn.Write([]byte("42 Error connecting to SCGI service!\r\n"))
log.Status = 42
@ -94,7 +94,7 @@ func handleSCGI(socket_path string, config Config, URL *url.URL, log *LogEntry,
defer socket.Close()
// Send variables
vars := prepareSCGIVariables(config, URL, conn)
vars := prepareSCGIVariables(config, URL, scgiPath, conn)
length := 0
for key, value := range vars {
length += len(key)
@ -150,11 +150,12 @@ func prepareCGIVariables(config Config, URL *url.URL, conn net.Conn, script_path
return vars
}
func prepareSCGIVariables(config Config, URL *url.URL, conn net.Conn) map[string]string {
func prepareSCGIVariables(config Config, URL *url.URL, scgiPath string, conn net.Conn) map[string]string {
vars := prepareGatewayVariables(config, URL, conn)
vars["SCGI"] = "1"
vars["CONTENT_LENGTH"] = "0"
vars["PATH_INFO"] = "/"
vars["SCRIPT_PATH"] = scgiPath
vars["PATH_INFO"] = URL.Path[len(scgiPath):]
return vars
}

View File

@ -91,10 +91,9 @@ func handleGeminiRequest(conn net.Conn, config Config, accessLogEntries chan Log
}
// Check whether this URL is mapped to an SCGI app
for scgi_url, scgi_socket := range config.SCGIPaths {
matched, err := regexp.Match(scgi_url, []byte(URL.Path))
if matched && err == nil {
handleSCGI(scgi_socket, config, URL, &log, conn)
for scgiPath, scgiSocket := range config.SCGIPaths {
if strings.HasPrefix(URL.Path, scgiPath) {
handleSCGI(URL, scgiPath, scgiSocket, config, &log, conn)
return
}
}