mirror of
https://tildegit.org/solderpunk/molly-brown.git
synced 2025-04-13 09:29:46 +00:00
Factor out header parsing code for CGI and SCGI into one function, so the checks from last commit can be applied to both.
This commit is contained in:
parent
0f833ba57b
commit
565f54bff8
1 changed files with 49 additions and 38 deletions
87
dynamic.go
87
dynamic.go
|
@ -4,6 +4,7 @@ import (
|
|||
"bufio"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
|
@ -15,6 +16,35 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func extractStatusFromDynamicResponse(reader *bufio.Reader, source string) (int, error) {
|
||||
rawHeader, _, err := reader.ReadLine()
|
||||
if err != nil {
|
||||
log.Println("Unable to read header in dynamic output from " + source + ".")
|
||||
return 0, err
|
||||
}
|
||||
header := string(rawHeader)
|
||||
logErrorMsg := "Unable to parse first line of dynamic output from " +
|
||||
source +
|
||||
" as valid Gemini response header. Line was: " +
|
||||
header
|
||||
header_fields := strings.Fields(header)
|
||||
if len(header_fields) == 0 {
|
||||
log.Println(logErrorMsg)
|
||||
return 0, errors.New("")
|
||||
}
|
||||
status, err := strconv.Atoi(header_fields[0])
|
||||
if err != nil {
|
||||
log.Println(logErrorMsg)
|
||||
return 0, err
|
||||
}
|
||||
if status < 10 || status > 70 {
|
||||
log.Println(logErrorMsg)
|
||||
return 0, errors.New("")
|
||||
}
|
||||
|
||||
return status, nil
|
||||
}
|
||||
|
||||
func handleCGI(config SysConfig, path string, cgiPath string, URL *url.URL, logEntry *LogEntry, conn net.Conn) {
|
||||
// Find the shortest leading part of path which maps to an executable file.
|
||||
// Call this part scriptPath, and everything after it pathInfo.
|
||||
|
@ -72,6 +102,7 @@ func handleCGI(config SysConfig, path string, cgiPath string, URL *url.URL, logE
|
|||
logEntry.Status = 42
|
||||
return
|
||||
}
|
||||
|
||||
// Extract response header
|
||||
responseString := string(response)
|
||||
if len(responseString) == 0 {
|
||||
|
@ -80,28 +111,16 @@ func handleCGI(config SysConfig, path string, cgiPath string, URL *url.URL, logE
|
|||
logEntry.Status = 42
|
||||
return
|
||||
}
|
||||
header, _, err := bufio.NewReader(strings.NewReader(string(response))).ReadLine()
|
||||
if err != nil || len(header) == 0 {
|
||||
log.Println("Unable to parse first line of output from CGI process " + path + " as valid Gemini response header. Line was: " + string(header))
|
||||
|
||||
responseReader := bufio.NewReader(strings.NewReader(string(response)))
|
||||
status, err := extractStatusFromDynamicResponse(responseReader, path)
|
||||
if err != nil {
|
||||
conn.Write([]byte("42 CGI error!\r\n"))
|
||||
logEntry.Status = 42
|
||||
return
|
||||
} else {
|
||||
logEntry.Status = status
|
||||
}
|
||||
header_fields := strings.Fields(string(header))
|
||||
if len(header_fields) == 0 {
|
||||
log.Println("Unable to parse first line of output from CGI process " + path + " as valid Gemini response header. Line was: " + string(header))
|
||||
conn.Write([]byte("42 CGI error!\r\n"))
|
||||
logEntry.Status = 42
|
||||
return
|
||||
}
|
||||
status, err := strconv.Atoi(header_fields[0])
|
||||
if err != nil || status < 10 || status > 70 {
|
||||
log.Println("Unable to parse first line of output from CGI process " + path + " as valid Gemini response header. Line was: " + string(header))
|
||||
conn.Write([]byte("42 CGI error!\r\n"))
|
||||
logEntry.Status = 42
|
||||
return
|
||||
}
|
||||
logEntry.Status = status
|
||||
|
||||
// Write response
|
||||
conn.Write(response)
|
||||
|
@ -135,36 +154,28 @@ func handleSCGI(URL *url.URL, scgiPath string, scgiSocket string, config SysConf
|
|||
socket.Write([]byte(","))
|
||||
|
||||
// Read and relay response
|
||||
responseReader := bufio.NewReader(socket)
|
||||
status, err := extractStatusFromDynamicResponse(responseReader, scgiSocket)
|
||||
if err != nil {
|
||||
conn.Write([]byte("42 SCGI error!\r\n"))
|
||||
logEntry.Status = 42
|
||||
return
|
||||
} else {
|
||||
logEntry.Status = status
|
||||
}
|
||||
|
||||
buffer := make([]byte, 1027)
|
||||
first := true
|
||||
for {
|
||||
n, err := socket.Read(buffer)
|
||||
n, err := responseReader.Read(buffer)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if !first {
|
||||
} else {
|
||||
// Err
|
||||
log.Println("Error reading from SCGI socket " + scgiSocket + ": " + err.Error())
|
||||
conn.Write([]byte("42 Error reading from SCGI service!\r\n"))
|
||||
logEntry.Status = 42
|
||||
return
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
// Extract status code from first line
|
||||
if first {
|
||||
first = false
|
||||
lines := strings.SplitN(string(buffer), "\r\n", 2)
|
||||
status, err := strconv.Atoi(strings.Fields(lines[0])[0])
|
||||
if err != nil || status < 10 || status > 70 {
|
||||
conn.Write([]byte("42 CGI error!\r\n"))
|
||||
log.Println("Unable to parse first line of output from SCGI socket " + scgiSocket + " as valid Gemini response header. Line was: " + lines[0])
|
||||
logEntry.Status = 42
|
||||
return
|
||||
}
|
||||
logEntry.Status = status
|
||||
}
|
||||
// Send to client
|
||||
conn.Write(buffer[:n])
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue