Mercurial Hosting > d2o
changeset 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 | 560d4103e12e |
| children | |
| files | main.go man/d2obase.5.md |
| diffstat | 2 files changed, 57 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
diff -r 560d4103e12e -r 350589d762a0 main.go --- 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 {
diff -r 560d4103e12e -r 350589d762a0 man/d2obase.5.md --- a/man/d2obase.5.md Tue Mar 17 22:27:30 2026 +0500 +++ b/man/d2obase.5.md Thu Mar 19 20:00:49 2026 +0500 @@ -80,11 +80,8 @@ **port** *number* : Listen for plain HTTP on the given port. -**port+tls** *number* [*cert* *key*] -: Listen for HTTPS on the given port. Certificate and key paths are optional if a **tls** directive is present in the same block. - -**tls** *cert* *key* -: Set the default certificate and key for **port+tls** directives in this block that do not specify their own paths. +**port+tls** *number* *cert* *key* +: Listen for HTTPS on the given port. Certificate and key paths are required. ## Serving @@ -92,11 +89,14 @@ : Serve static files from *path*. Without **show**, directory listing is forbidden (403). With **show**, an HTML directory listing is returned. **ndex** *file...* -: List of index filenames to try when a directory is requested, checked left to right. If a matching file passes the **fcgi** pattern, it is handled by FastCGI instead of served directly. +: List of index filenames to try when a directory is requested, checked left to right. If a matching file passes the **fcgi** or **cgi** pattern, it is handled accordingly instead of served directly. **fcgi** *address* [*pattern*] : Forward matching requests to a FastCGI server. *address* is either `unix:///path/to/socket` or `host:port`. *pattern* is a glob matched against the request path (default `*`). When used together with **root**, only requests matching the pattern are forwarded; everything else is served as static. +**cgi** *executable* [*pattern*] +: Run *executable* as a CGI program for matching requests. *pattern* is a glob matched against the request path (default `*`). The executable is invoked per-request with standard CGI environment variables (`REQUEST_METHOD`, `QUERY_STRING`, `PATH_INFO`, etc.). When used together with **root**, only requests matching the pattern are handled by CGI; everything else is served as static. Useful for simple CGI programs such as **cgit**(1). + **rprx** *address* : Reverse-proxy all requests to *address*. The `http://` scheme is assumed if not specified. @@ -150,8 +150,17 @@ |> port+tls 443 $TLS.{crt,key} |> root $WWW show +A minimal setup with cgit: + + git.example.org + |> port 80 + |> port+tls 443 /etc/acme/git.example.org.{crt,key} + |> root /usr/share/cgit + |> ndex cgit.cgi + |> cgi /usr/lib/cgit/cgit.cgi *.cgi + # CAVEATS -1. ICF does not support strings with spaces - there are **no quotes or escapes**. Every character except space is treated as part of a token, including `!`, `*`, `/`, and so on. Glob patterns passed to **fcgi** are forwarded as-is to the server. +1. ICF does not support strings with spaces - there are **no quotes or escapes**. Every character except space is treated as part of a token, including `!`, `*`, `/`, and so on. Glob patterns passed to **fcgi** and **cgi** are forwarded as-is to the server. 2. Variables are evaluated top-down at the point of declaration. Forward references do not work: if `B=$A` appears before `A=value`, `B` will contain the literal `$A`.
