diff main.go @ 11:350589d762a0 default tip

add cgi, remove tls, update docs
author Atarwn Gard <a@qwa.su>
date Thu, 19 Mar 2026 20:00:49 +0500
parents ec97184ea63d
children
line wrap: on
line diff
--- a/main.go	Tue Mar 17 22:27:30 2026 +0500
+++ b/main.go	Thu Mar 19 20:00:49 2026 +0500
@@ -8,6 +8,7 @@
 	"log"
 	"net"
 	"net/http"
+	"net/http/cgi"
 	"net/http/httputil"
 	"net/textproto"
 	"net/url"
@@ -155,14 +156,6 @@
 	for _, b := range cfg.Blocks {
 		dirs := cfg.ResolveBlock(b, nil)
 
-		var cert, key string
-		for _, d := range dirs {
-			if d.Key == "tls" {
-				cert = safeArg(d.Args, 0)
-				key = safeArg(d.Args, 1)
-			}
-		}
-
 		for _, d := range dirs {
 			switch d.Key {
 			case "port":
@@ -172,15 +165,10 @@
 					out = append(out, portConfig{addr: addr})
 				}
 			case "port+tls":
+				// port+tls <port> <cert> <key>
 				addr := ":" + safeArg(d.Args, 0)
 				c := safeArg(d.Args, 1)
 				k := safeArg(d.Args, 2)
-				if c == "" {
-					c = cert
-				}
-				if k == "" {
-					k = key
-				}
 				if !seen[addr] {
 					seen[addr] = true
 					out = append(out, portConfig{addr: addr, certFile: c, keyFile: k, isTLS: true})
@@ -227,6 +215,8 @@
 		ndex     []string
 		fcgiAddr string
 		fcgiPat  string
+		cgiExec  string
+		cgiPat   string
 		rprxAddr string
 		rdirCode int
 		rdirURL  string
@@ -245,6 +235,13 @@
 			if fcgiPat == "" {
 				fcgiPat = "*"
 			}
+		case "cgi":
+			// cgi <executable> [<glob-pattern>]
+			cgiExec = safeArg(d.Args, 0)
+			cgiPat = safeArg(d.Args, 1)
+			if cgiPat == "" {
+				cgiPat = "*"
+			}
 		case "rprx":
 			rprxAddr = safeArg(d.Args, 0)
 		case "rdir":
@@ -274,6 +271,11 @@
 		}
 		return
 	}
+	if cgiExec != "" && matchGlob(cgiPat, r.URL.Path) {
+		verbosePrintf("d2o: cgi -> %s (%s)", cgiExec, r.URL.Path)
+		serveCGI(w, r, cgiExec, rootDir)
+		return
+	}
 	if rootDir != "" {
 		fsPath := path.Clean(r.URL.Path)
 		displayPath := fsPath
@@ -289,7 +291,7 @@
 		}
 
 		verbosePrintf("d2o: static -> %s (%s)", rootDir, r.URL.Path)
-		serveStatic(w, r, rootDir, rootShow, ndex, fcgiAddr, fcgiPat, fsPath, displayPath)
+		serveStatic(w, r, rootDir, rootShow, ndex, fcgiAddr, fcgiPat, cgiExec, cgiPat, fsPath, displayPath)
 		return
 	}
 
@@ -301,7 +303,7 @@
 // serveStatic serves files from rootDir.
 // rootIndex == nil: directory listing forbidden (hide).
 // rootIndex != nil: try each as index candidate; if none found, show listing.
-func serveStatic(w http.ResponseWriter, r *http.Request, rootDir string, show bool, ndex []string, fcgiAddr, fcgiPat string, fsPath, displayPath string) {
+func serveStatic(w http.ResponseWriter, r *http.Request, rootDir string, show bool, ndex []string, fcgiAddr, fcgiPat, cgiExec, cgiPat string, fsPath, displayPath string) {
 	fpath := filepath.Join(rootDir, filepath.FromSlash(path.Clean(fsPath)))
 
 	info, err := os.Stat(fpath)
@@ -327,6 +329,12 @@
 					}
 					return
 				}
+				if cgiExec != "" && matchGlob(cgiPat, idx) {
+					r2 := r.Clone(r.Context())
+					r2.URL.Path = path.Join(r.URL.Path, idx)
+					serveCGI(w, r2, cgiExec, rootDir)
+					return
+				}
 				http.ServeFile(w, r, idxPath)
 				return
 			}
@@ -394,6 +402,23 @@
 	proxy.ServeHTTP(w, r)
 }
 
+// --- CGI --------------------------------------------------------------------
+
+// serveCGI runs a CGI executable using net/http/cgi.
+// cgiExec is the path to the executable (e.g. /usr/lib/cgit/cgit.cgi).
+// docRoot is set as DOCUMENT_ROOT; may be empty.
+func serveCGI(w http.ResponseWriter, r *http.Request, cgiExec, docRoot string) {
+	h := &cgi.Handler{
+		Path: cgiExec,
+		Dir:  docRoot,
+		Env: []string{
+			"DOCUMENT_ROOT=" + docRoot,
+			"SERVER_SOFTWARE=d2o/1.1",
+		},
+	}
+	h.ServeHTTP(w, r)
+}
+
 // --- FastCGI ----------------------------------------------------------------
 
 func serveFCGI(w http.ResponseWriter, r *http.Request, addr, docRoot string) error {