annotate main.go @ 5:07b6f06899e0

my tired ass deleted a fix that was partially working
author Atarwn Gard <a@qwa.su>
date Mon, 09 Mar 2026 03:35:47 +0500
parents eb705d4cdcd7
children 8e4813b4e509
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
1 package main
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
2
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
3 import (
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
4 "crypto/tls"
3
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
5 "bufio"
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
6 "fmt"
3
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
7 "io"
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
8 "log"
3
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
9 "net/textproto"
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
10 "net"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
11 "net/http"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
12 "net/http/httputil"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
13 "net/url"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
14 "os"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
15 "path"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
16 "path/filepath"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
17 "regexp"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
18 "runtime"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
19 "strconv"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
20 "strings"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
21
3
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
22
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
23 "d2o/fcgi"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
24 "d2o/icf"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
25 )
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
26
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
27 func main() {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
28 cfgPath := "/etc/d2obase"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
29 if len(os.Args) > 1 {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
30 cfgPath = os.Args[1]
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
31 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
32
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
33 f, err := os.Open(cfgPath)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
34 if err != nil {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
35 log.Fatalf("d2o: cannot open config: %v", err)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
36 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
37 cfg, err := icf.Parse(f)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
38 f.Close()
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
39 if err != nil {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
40 log.Fatalf("d2o: config error: %v", err)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
41 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
42
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
43 for _, d := range cfg.Abstract("d2o") {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
44 switch d.Key {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
45 case "threads":
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
46 n, err := strconv.Atoi(safeArg(d.Args, 0))
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
47 if err == nil && n > 0 {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
48 runtime.GOMAXPROCS(n)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
49 log.Printf("d2o: GOMAXPROCS = %d", n)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
50 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
51 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
52 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
53
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
54 ports := collectPorts(cfg)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
55 if len(ports) == 0 {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
56 log.Fatal("d2o: no port directives found in config")
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
57 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
58
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
59 h := &handler{cfg: cfg}
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
60 errCh := make(chan error, len(ports))
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
61
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
62 for _, pc := range ports {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
63 go func(pc portConfig) {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
64 errCh <- pc.listen(h)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
65 }(pc)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
66 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
67
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
68 log.Fatal(<-errCh)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
69 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
70
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
71 // --- Port collection --------------------------------------------------------
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
72
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
73 type portConfig struct {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
74 addr string
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
75 certFile string
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
76 keyFile string
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
77 isTLS bool
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
78 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
79
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
80 func (pc portConfig) listen(h http.Handler) error {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
81 if !pc.isTLS {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
82 log.Printf("d2o: listening on %s (http)", pc.addr)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
83 return http.ListenAndServe(pc.addr, h)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
84 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
85 cert, err := tls.LoadX509KeyPair(pc.certFile, pc.keyFile)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
86 if err != nil {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
87 return fmt.Errorf("d2o: tls: %w", err)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
88 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
89 ln, err := tls.Listen("tcp", pc.addr, &tls.Config{
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
90 Certificates: []tls.Certificate{cert},
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
91 MinVersion: tls.VersionTLS12,
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
92 })
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
93 if err != nil {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
94 return fmt.Errorf("d2o: listen %s: %w", pc.addr, err)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
95 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
96 log.Printf("d2o: listening on %s (https)", pc.addr)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
97 return http.Serve(ln, h)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
98 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
99
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
100 func collectPorts(cfg *icf.Config) []portConfig {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
101 seen := make(map[string]bool)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
102 var out []portConfig
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
103
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
104 for _, b := range cfg.Blocks {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
105 dirs := cfg.ResolveBlock(b, nil)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
106
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
107 var cert, key string
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
108 for _, d := range dirs {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
109 if d.Key == "tls" {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
110 cert = safeArg(d.Args, 0)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
111 key = safeArg(d.Args, 1)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
112 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
113 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
114
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
115 for _, d := range dirs {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
116 switch d.Key {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
117 case "port":
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
118 addr := ":" + safeArg(d.Args, 0)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
119 if !seen[addr] {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
120 seen[addr] = true
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
121 out = append(out, portConfig{addr: addr})
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
122 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
123 case "port+tls":
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
124 addr := ":" + safeArg(d.Args, 0)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
125 c := safeArg(d.Args, 1)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
126 k := safeArg(d.Args, 2)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
127 if c == "" {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
128 c = cert
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
129 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
130 if k == "" {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
131 k = key
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
132 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
133 if !seen[addr] {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
134 seen[addr] = true
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
135 out = append(out, portConfig{addr: addr, certFile: c, keyFile: k, isTLS: true})
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
136 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
137 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
138 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
139 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
140 return out
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
141 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
142
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
143 // --- HTTP Handler -----------------------------------------------------------
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
144
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
145 type handler struct {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
146 cfg *icf.Config
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
147 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
148
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
149 func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
150 host := stripPort(r.Host)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
151 reqPath := path.Clean(r.URL.Path)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
152
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
153 dirs, caps := h.cfg.Match(host + reqPath)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
154 if dirs == nil {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
155 dirs, caps = h.cfg.Match(host)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
156 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
157 if dirs == nil {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
158 http.Error(w, "not found", http.StatusNotFound)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
159 return
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
160 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
161
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
162 h.serve(w, r, dirs, caps)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
163 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
164
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
165 func (h *handler) serve(w http.ResponseWriter, r *http.Request, dirs []icf.Directive, _ map[string]string) {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
166 var (
5
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
167 rootDir string
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
168 rootShow bool
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
169 ndex []string
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
170 fcgiAddr string
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
171 fcgiPat string
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
172 rprxAddr string
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
173 rdirCode int
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
174 rdirURL string
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
175 )
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
176
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
177 for _, d := range dirs {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
178 switch d.Key {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
179 case "root":
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
180 rootDir = safeArg(d.Args, 0)
5
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
181 rootShow = safeArg(d.Args, 1) == "show"
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
182 case "ndex":
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
183 ndex = d.Args
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
184 case "fcgi":
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
185 fcgiAddr = safeArg(d.Args, 0)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
186 fcgiPat = safeArg(d.Args, 1)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
187 if fcgiPat == "" {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
188 fcgiPat = "*"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
189 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
190 case "rprx":
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
191 rprxAddr = safeArg(d.Args, 0)
5
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
192 case "rdir":
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
193 rdirCode, _ = strconv.Atoi(safeArg(d.Args, 0))
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
194 rdirURL = safeArg(d.Args, 1)
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
195 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
196 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
197
5
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
198 if rdirURL != "" {
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
199 if rdirCode == 0 {
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
200 rdirCode = http.StatusFound
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
201 }
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
202 http.Redirect(w, r, rdirURL, rdirCode)
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
203 return
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
204 }
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
205 if rprxAddr != "" {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
206 serveReverseProxy(w, r, rprxAddr)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
207 return
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
208 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
209 if fcgiAddr != "" && matchGlob(fcgiPat, r.URL.Path) {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
210 if err := serveFCGI(w, r, fcgiAddr, rootDir); err != nil {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
211 log.Printf("d2o: fcgi error: %v", err)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
212 http.Error(w, "gateway error", http.StatusBadGateway)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
213 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
214 return
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
215 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
216 if rootDir != "" {
5
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
217 serveStatic(w, r, rootDir, rootShow, ndex, fcgiAddr, fcgiPat)
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
218 return
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
219 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
220
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
221 http.Error(w, "not found", http.StatusNotFound)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
222 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
223
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
224 // --- Static -----------------------------------------------------------------
3
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
225
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
226 // serveStatic serves files from rootDir.
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
227 // rootIndex == nil: directory listing forbidden (hide).
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
228 // rootIndex != nil: try each as index candidate; if none found, show listing.
5
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
229 func serveStatic(w http.ResponseWriter, r *http.Request, rootDir string, show bool, ndex []string, fcgiAddr, fcgiPat string) {
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
230 fpath := filepath.Join(rootDir, filepath.FromSlash(path.Clean(r.URL.Path)))
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
231
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
232 info, err := os.Stat(fpath)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
233 if os.IsNotExist(err) {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
234 http.Error(w, "not found", http.StatusNotFound)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
235 return
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
236 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
237 if err != nil {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
238 http.Error(w, "internal error", http.StatusInternalServerError)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
239 return
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
240 }
1
3e7247db5c6e show index.html
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
241
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
242 if info.IsDir() {
5
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
243 for _, idx := range ndex {
1
3e7247db5c6e show index.html
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
244 idxPath := filepath.Join(fpath, idx)
3e7247db5c6e show index.html
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
245 if _, err := os.Stat(idxPath); err == nil {
5
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
246 if fcgiAddr != "" && matchGlob(fcgiPat, idx) {
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
247 r2 := r.Clone(r.Context())
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
248 r2.URL.Path = path.Join(r.URL.Path, idx)
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
249 if err := serveFCGI(w, r2, fcgiAddr, rootDir); err != nil {
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
250 log.Printf("d2o: fcgi error: %v", err)
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
251 http.Error(w, "gateway error", http.StatusBadGateway)
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
252 }
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
253 return
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
254 }
1
3e7247db5c6e show index.html
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
255 http.ServeFile(w, r, idxPath)
3e7247db5c6e show index.html
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
256 return
3e7247db5c6e show index.html
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
257 }
3e7247db5c6e show index.html
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
258 }
5
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
259 if !show {
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
260 http.Error(w, "forbidden", http.StatusForbidden)
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
261 return
07b6f06899e0 my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents: 3
diff changeset
262 }
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
263 listDir(w, r, fpath, r.URL.Path)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
264 return
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
265 }
1
3e7247db5c6e show index.html
Atarwn Gard <a@qwa.su>
parents: 0
diff changeset
266
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
267 http.ServeFile(w, r, fpath)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
268 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
269
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
270 func listDir(w http.ResponseWriter, r *http.Request, dir, urlPath string) {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
271 entries, err := os.ReadDir(dir)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
272 if err != nil {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
273 http.Error(w, "cannot read directory", http.StatusInternalServerError)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
274 return
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
275 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
276 w.Header().Set("Content-Type", "text/html; charset=utf-8")
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
277 fmt.Fprintf(w, "<html><head><title>Index of %s</title></head><body>\n", urlPath)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
278 fmt.Fprintf(w, "<h2>Index of %s</h2><hr><pre>\n", urlPath)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
279 if urlPath != "/" {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
280 fmt.Fprintf(w, "<a href=\"..\">..</a>\n")
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
281 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
282 for _, e := range entries {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
283 name := e.Name()
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
284 if e.IsDir() {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
285 name += "/"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
286 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
287 fmt.Fprintf(w, "<a href=\"%s\">%s</a>\n", path.Join(urlPath, name), name)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
288 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
289 fmt.Fprintf(w, "</pre><hr><i>d2o webserver</i></body></html>")
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
290 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
291
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
292 // --- Reverse proxy ----------------------------------------------------------
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
293
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
294 func serveReverseProxy(w http.ResponseWriter, r *http.Request, target string) {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
295 if !strings.HasPrefix(target, "http://") && !strings.HasPrefix(target, "https://") {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
296 target = "http://" + target
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
297 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
298 u, err := url.Parse(target)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
299 if err != nil {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
300 http.Error(w, "bad gateway config", http.StatusInternalServerError)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
301 return
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
302 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
303 proxy := httputil.NewSingleHostReverseProxy(u)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
304 proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
305 log.Printf("d2o: rprx error: %v", err)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
306 http.Error(w, "bad gateway", http.StatusBadGateway)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
307 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
308 proxy.ServeHTTP(w, r)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
309 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
310
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
311 // --- FastCGI ----------------------------------------------------------------
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
312
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
313 func serveFCGI(w http.ResponseWriter, r *http.Request, addr, docRoot string) error {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
314 network, address := parseFCGIAddr(addr)
3
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
315 client, err := fcgi.Dial(network, address)
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
316 if err != nil {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
317 return fmt.Errorf("connect %s: %w", addr, err)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
318 }
3
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
319 defer client.Close()
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
320
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
321 scriptPath := r.URL.Path
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
322 if docRoot != "" {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
323 scriptPath = filepath.Join(docRoot, filepath.FromSlash(r.URL.Path))
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
324 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
325
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
326 params := map[string]string{
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
327 "REQUEST_METHOD": r.Method,
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
328 "SCRIPT_FILENAME": scriptPath,
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
329 "SCRIPT_NAME": r.URL.Path,
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
330 "REQUEST_URI": r.URL.RequestURI(),
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
331 "QUERY_STRING": r.URL.RawQuery,
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
332 "SERVER_PROTOCOL": r.Proto,
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
333 "SERVER_NAME": stripPort(r.Host),
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
334 "DOCUMENT_ROOT": docRoot,
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
335 "GATEWAY_INTERFACE": "CGI/1.1",
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
336 "SERVER_SOFTWARE": "d2o/1.0",
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
337 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
338 if r.TLS != nil {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
339 params["HTTPS"] = "on"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
340 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
341 for k, vs := range r.Header {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
342 key := "HTTP_" + strings.ToUpper(strings.ReplaceAll(k, "-", "_"))
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
343 params[key] = strings.Join(vs, ", ")
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
344 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
345 if ct := r.Header.Get("Content-Type"); ct != "" {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
346 params["CONTENT_TYPE"] = ct
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
347 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
348 if r.ContentLength >= 0 {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
349 params["CONTENT_LENGTH"] = strconv.FormatInt(r.ContentLength, 10)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
350 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
351
3
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
352 // Use Do() instead of Request() — php-fpm returns CGI response (no HTTP status line),
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
353 // not a full HTTP response. Request() expects "HTTP/1.1 200 OK" and panics on code 0.
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
354 cgiReader, err := client.Do(params, r.Body)
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
355 if err != nil {
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
356 return fmt.Errorf("fcgi request: %w", err)
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
357 }
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
358
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
359 // Parse CGI headers manually
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
360 br := bufio.NewReader(cgiReader)
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
361 tp := textproto.NewReader(br)
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
362 mime, err := tp.ReadMIMEHeader()
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
363 if err != nil && len(mime) == 0 {
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
364 return fmt.Errorf("fcgi response headers: %w", err)
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
365 }
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
366
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
367 status := http.StatusOK
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
368 if s := mime.Get("Status"); s != "" {
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
369 code, _, _ := strings.Cut(s, " ")
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
370 if n, err := strconv.Atoi(code); err == nil && n > 0 {
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
371 status = n
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
372 }
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
373 mime.Del("Status")
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
374 }
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
375
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
376 for k, vs := range mime {
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
377 for _, v := range vs {
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
378 w.Header().Add(k, v)
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
379 }
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
380 }
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
381 w.WriteHeader(status)
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
382 io.Copy(w, br)
eb705d4cdcd7 fix fcgi
Atarwn Gard <a@qwa.su>
parents: 2
diff changeset
383 return nil
0
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
384 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
385
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
386 func parseFCGIAddr(addr string) (network, address string) {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
387 if strings.HasPrefix(addr, "unix:") {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
388 return "unix", strings.TrimPrefix(addr, "unix:")
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
389 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
390 return "tcp", addr
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
391 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
392
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
393 // --- Helpers ----------------------------------------------------------------
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
394
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
395 func stripPort(host string) string {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
396 if h, _, err := net.SplitHostPort(host); err == nil {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
397 return h
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
398 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
399 return host
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
400 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
401
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
402 func safeArg(args []string, i int) string {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
403 if i < len(args) {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
404 return args[i]
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
405 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
406 return ""
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
407 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
408
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
409 func matchGlob(pattern, s string) bool {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
410 if pattern == "*" {
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
411 return true
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
412 }
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
413 regPat := "^" + strings.ReplaceAll(regexp.QuoteMeta(pattern), regexp.QuoteMeta("*"), ".*") + "$"
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
414 matched, err := regexp.MatchString(regPat, s)
48bdab3eec8a Initial
Atarwn Gard <a@qwa.su>
parents:
diff changeset
415 return err == nil && matched
2
d19133be91ba ndex and smarter parser
Atarwn Gard <a@qwa.su>
parents: 1
diff changeset
416 }