"log"
"net"
"net/http"
+ "net/textproto"
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
"strings"
+
+ "golang.org/x/net/http/httpguts"
)
var trailingPort = regexp.MustCompile(`:([0-9]+)$`)
var osDefaultInheritEnv = func() []string {
switch runtime.GOOS {
- case "darwin":
+ case "darwin", "ios":
return []string{"DYLD_LIBRARY_PATH"}
- case "linux", "freebsd", "openbsd":
+ case "android", "linux", "freebsd", "netbsd", "openbsd":
return []string{"LD_LIBRARY_PATH"}
case "hpux":
return []string{"LD_LIBRARY_PATH", "SHLIB_PATH"}
case "irix":
return []string{"LD_LIBRARY_PATH", "LD_LIBRARYN32_PATH", "LD_LIBRARY64_PATH"}
- case "solaris":
+ case "illumos", "solaris":
return []string{"LD_LIBRARY_PATH", "LD_LIBRARY_PATH_32", "LD_LIBRARY_PATH_64"}
case "windows":
return []string{"SystemRoot", "COMSPEC", "PATHEXT", "WINDIR"}
// removeLeadingDuplicates remove leading duplicate in environments.
// It's possible to override environment like following.
-// cgi.Handler{
-// ...
-// Env: []string{"SCRIPT_FILENAME=foo.php"},
-// }
+//
+// cgi.Handler{
+// ...
+// Env: []string{"SCRIPT_FILENAME=foo.php"},
+// }
func removeLeadingDuplicates(env []string) (ret []string) {
for i, e := range env {
found := false
}
func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
- root := h.Root
- if root == "" {
- root = "/"
- }
-
if len(req.TransferEncoding) > 0 && req.TransferEncoding[0] == "chunked" {
rw.WriteHeader(http.StatusBadRequest)
rw.Write([]byte("Chunked request bodies are not supported by CGI."))
return
}
- pathInfo := req.URL.Path
- if root != "/" && strings.HasPrefix(pathInfo, root) {
- pathInfo = pathInfo[len(root):]
- }
+ root := strings.TrimRight(h.Root, "/")
+ pathInfo := strings.TrimPrefix(req.URL.Path, root)
port := "80"
+ if req.TLS != nil {
+ port = "443"
+ }
if matches := trailingPort.FindStringSubmatch(req.Host); len(matches) != 0 {
port = matches[1]
}
env := []string{
"SERVER_SOFTWARE=go",
- "SERVER_NAME=" + req.Host,
"SERVER_PROTOCOL=HTTP/1.1",
"HTTP_HOST=" + req.Host,
"GATEWAY_INTERFACE=CGI/1.1",
env = append(env, "REMOTE_ADDR="+req.RemoteAddr, "REMOTE_HOST="+req.RemoteAddr)
}
+ if hostDomain, _, err := net.SplitHostPort(req.Host); err == nil {
+ env = append(env, "SERVER_NAME="+hostDomain)
+ } else {
+ env = append(env, "SERVER_NAME="+req.Host)
+ }
+
if req.TLS != nil {
env = append(env, "HTTPS=on")
}
break
}
headerLines++
- parts := strings.SplitN(string(line), ":", 2)
- if len(parts) < 2 {
+ header, val, ok := strings.Cut(string(line), ":")
+ if !ok {
h.printf("cgi: bogus header line: %s", string(line))
continue
}
- header, val := parts[0], parts[1]
- header = strings.TrimSpace(header)
- val = strings.TrimSpace(val)
+ if !httpguts.ValidHeaderFieldName(header) {
+ h.printf("cgi: invalid header name: %q", header)
+ continue
+ }
+ val = textproto.TrimString(val)
switch {
case header == "Status":
if len(val) < 3 {
}
}
-func (h *Handler) printf(format string, v ...interface{}) {
+func (h *Handler) printf(format string, v ...any) {
if h.Logger != nil {
h.Logger.Printf(format, v...)
} else {