Mercurial Hosting > d2o
annotate main.go @ 10:560d4103e12e default tip
Added tag 1.1 for changeset ec97184ea63d
| author | Atarwn Gard <a@qwa.su> |
|---|---|
| date | Tue, 17 Mar 2026 22:27:30 +0500 |
| parents | ec97184ea63d |
| children |
| rev | line source |
|---|---|
| 0 | 1 package main |
| 2 | |
| 3 import ( | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
4 "bufio" |
| 0 | 5 "crypto/tls" |
| 6 "fmt" | |
| 3 | 7 "io" |
| 0 | 8 "log" |
| 9 "net" | |
| 10 "net/http" | |
| 11 "net/http/httputil" | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
12 "net/textproto" |
| 0 | 13 "net/url" |
| 14 "os" | |
| 15 "path" | |
| 16 "path/filepath" | |
| 17 "regexp" | |
| 18 "runtime" | |
| 19 "strconv" | |
| 20 "strings" | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
21 "time" |
| 0 | 22 |
| 23 "d2o/fcgi" | |
| 24 "d2o/icf" | |
| 25 ) | |
| 26 | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
27 type loggingMode uint8 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
28 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
29 const ( |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
30 logNone loggingMode = iota |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
31 logAccess |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
32 logVerbose |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
33 ) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
34 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
35 var ( |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
36 curLoggingMode loggingMode = logVerbose |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
37 accessLogger = log.New(os.Stderr, "", log.LstdFlags) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
38 ) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
39 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
40 func setLoggingMode(m loggingMode) { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
41 curLoggingMode = m |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
42 switch m { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
43 case logNone: |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
44 log.SetOutput(io.Discard) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
45 case logAccess: |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
46 log.SetOutput(io.Discard) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
47 case logVerbose: |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
48 // keep standard logger output |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
49 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
50 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
51 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
52 func accessEnabled() bool { return curLoggingMode == logAccess || curLoggingMode == logVerbose } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
53 func verboseEnabled() bool { return curLoggingMode == logVerbose } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
54 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
55 func accessPrintf(format string, args ...any) { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
56 if accessEnabled() { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
57 accessLogger.Printf(format, args...) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
58 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
59 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
60 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
61 func verbosePrintf(format string, args ...any) { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
62 if verboseEnabled() { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
63 log.Printf(format, args...) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
64 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
65 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
66 |
| 0 | 67 func main() { |
| 68 cfgPath := "/etc/d2obase" | |
| 69 if len(os.Args) > 1 { | |
| 70 cfgPath = os.Args[1] | |
| 71 } | |
| 72 | |
| 73 f, err := os.Open(cfgPath) | |
| 74 if err != nil { | |
| 75 log.Fatalf("d2o: cannot open config: %v", err) | |
| 76 } | |
| 77 cfg, err := icf.Parse(f) | |
| 78 f.Close() | |
| 79 if err != nil { | |
| 80 log.Fatalf("d2o: config error: %v", err) | |
| 81 } | |
| 82 | |
| 83 for _, d := range cfg.Abstract("d2o") { | |
| 84 switch d.Key { | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
85 case "logging": |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
86 switch strings.ToLower(safeArg(d.Args, 0)) { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
87 case "", "verbose": |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
88 setLoggingMode(logVerbose) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
89 case "none": |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
90 setLoggingMode(logNone) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
91 case "access": |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
92 setLoggingMode(logAccess) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
93 default: |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
94 log.Fatalf("d2o: unknown logging mode %q (expected none|access|verbose)", safeArg(d.Args, 0)) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
95 } |
| 0 | 96 case "threads": |
| 97 n, err := strconv.Atoi(safeArg(d.Args, 0)) | |
| 98 if err == nil && n > 0 { | |
| 99 runtime.GOMAXPROCS(n) | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
100 verbosePrintf("d2o: GOMAXPROCS = %d", n) |
| 0 | 101 } |
| 102 } | |
| 103 } | |
| 104 | |
| 105 ports := collectPorts(cfg) | |
| 106 if len(ports) == 0 { | |
| 107 log.Fatal("d2o: no port directives found in config") | |
| 108 } | |
| 109 | |
| 110 h := &handler{cfg: cfg} | |
| 111 errCh := make(chan error, len(ports)) | |
| 112 | |
| 113 for _, pc := range ports { | |
| 114 go func(pc portConfig) { | |
| 115 errCh <- pc.listen(h) | |
| 116 }(pc) | |
| 117 } | |
| 118 | |
| 119 log.Fatal(<-errCh) | |
| 120 } | |
| 121 | |
| 122 // --- Port collection -------------------------------------------------------- | |
| 123 | |
| 124 type portConfig struct { | |
| 125 addr string | |
| 126 certFile string | |
| 127 keyFile string | |
| 128 isTLS bool | |
| 129 } | |
| 130 | |
| 131 func (pc portConfig) listen(h http.Handler) error { | |
| 132 if !pc.isTLS { | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
133 verbosePrintf("d2o: listening on %s (http)", pc.addr) |
| 0 | 134 return http.ListenAndServe(pc.addr, h) |
| 135 } | |
| 136 cert, err := tls.LoadX509KeyPair(pc.certFile, pc.keyFile) | |
| 137 if err != nil { | |
| 138 return fmt.Errorf("d2o: tls: %w", err) | |
| 139 } | |
| 140 ln, err := tls.Listen("tcp", pc.addr, &tls.Config{ | |
| 141 Certificates: []tls.Certificate{cert}, | |
| 142 MinVersion: tls.VersionTLS12, | |
| 143 }) | |
| 144 if err != nil { | |
| 145 return fmt.Errorf("d2o: listen %s: %w", pc.addr, err) | |
| 146 } | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
147 verbosePrintf("d2o: listening on %s (https)", pc.addr) |
| 0 | 148 return http.Serve(ln, h) |
| 149 } | |
| 150 | |
| 151 func collectPorts(cfg *icf.Config) []portConfig { | |
| 152 seen := make(map[string]bool) | |
| 153 var out []portConfig | |
| 154 | |
| 155 for _, b := range cfg.Blocks { | |
| 156 dirs := cfg.ResolveBlock(b, nil) | |
| 157 | |
| 158 var cert, key string | |
| 159 for _, d := range dirs { | |
| 160 if d.Key == "tls" { | |
| 161 cert = safeArg(d.Args, 0) | |
| 162 key = safeArg(d.Args, 1) | |
| 163 } | |
| 164 } | |
| 165 | |
| 166 for _, d := range dirs { | |
| 167 switch d.Key { | |
| 168 case "port": | |
| 169 addr := ":" + safeArg(d.Args, 0) | |
| 170 if !seen[addr] { | |
| 171 seen[addr] = true | |
| 172 out = append(out, portConfig{addr: addr}) | |
| 173 } | |
| 174 case "port+tls": | |
| 175 addr := ":" + safeArg(d.Args, 0) | |
| 176 c := safeArg(d.Args, 1) | |
| 177 k := safeArg(d.Args, 2) | |
| 178 if c == "" { | |
| 179 c = cert | |
| 180 } | |
| 181 if k == "" { | |
| 182 k = key | |
| 183 } | |
| 184 if !seen[addr] { | |
| 185 seen[addr] = true | |
| 186 out = append(out, portConfig{addr: addr, certFile: c, keyFile: k, isTLS: true}) | |
| 187 } | |
| 188 } | |
| 189 } | |
| 190 } | |
| 191 return out | |
| 192 } | |
| 193 | |
| 194 // --- HTTP Handler ----------------------------------------------------------- | |
| 195 | |
| 196 type handler struct { | |
| 197 cfg *icf.Config | |
| 198 } | |
| 199 | |
| 200 func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
201 start := time.Now() |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
202 rr := &respRecorder{ResponseWriter: w, status: 0} |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
203 |
| 0 | 204 host := stripPort(r.Host) |
| 205 reqPath := path.Clean(r.URL.Path) | |
| 206 | |
| 207 dirs, caps := h.cfg.Match(host + reqPath) | |
| 208 if dirs == nil { | |
| 209 dirs, caps = h.cfg.Match(host) | |
| 210 } | |
| 211 if dirs == nil { | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
212 http.Error(rr, "not found", http.StatusNotFound) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
213 rr.ensureStatus(http.StatusNotFound) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
214 accessPrintf("d2o: %s %s%s -> %d %dB (%s)", r.Method, r.Host, r.URL.RequestURI(), rr.status, rr.bytes, time.Since(start).Truncate(time.Millisecond)) |
| 0 | 215 return |
| 216 } | |
| 217 | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
218 h.serve(rr, r, dirs, caps) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
219 rr.ensureStatus(http.StatusOK) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
220 accessPrintf("d2o: %s %s%s -> %d %dB (%s)", r.Method, r.Host, r.URL.RequestURI(), rr.status, rr.bytes, time.Since(start).Truncate(time.Millisecond)) |
| 0 | 221 } |
| 222 | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
223 func (h *handler) serve(w http.ResponseWriter, r *http.Request, dirs []icf.Directive, caps map[string]string) { |
| 0 | 224 var ( |
|
5
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
225 rootDir string |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
226 rootShow bool |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
227 ndex []string |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
228 fcgiAddr string |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
229 fcgiPat string |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
230 rprxAddr string |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
231 rdirCode int |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
232 rdirURL string |
| 0 | 233 ) |
| 234 | |
| 235 for _, d := range dirs { | |
| 236 switch d.Key { | |
| 237 case "root": | |
| 238 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
|
239 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
|
240 case "ndex": |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
241 ndex = d.Args |
| 0 | 242 case "fcgi": |
| 243 fcgiAddr = safeArg(d.Args, 0) | |
| 244 fcgiPat = safeArg(d.Args, 1) | |
| 245 if fcgiPat == "" { | |
| 246 fcgiPat = "*" | |
| 247 } | |
| 248 case "rprx": | |
| 249 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
|
250 case "rdir": |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
251 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
|
252 rdirURL = safeArg(d.Args, 1) |
| 0 | 253 } |
| 254 } | |
| 255 | |
|
5
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
256 if rdirURL != "" { |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
257 if rdirCode == 0 { |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
258 rdirCode = http.StatusFound |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
259 } |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
260 verbosePrintf("d2o: rdir %d -> %s", rdirCode, rdirURL) |
|
5
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
261 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
|
262 return |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
263 } |
| 0 | 264 if rprxAddr != "" { |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
265 verbosePrintf("d2o: rprx -> %s", rprxAddr) |
| 0 | 266 serveReverseProxy(w, r, rprxAddr) |
| 267 return | |
| 268 } | |
| 269 if fcgiAddr != "" && matchGlob(fcgiPat, r.URL.Path) { | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
270 verbosePrintf("d2o: fcgi -> %s (%s)", fcgiAddr, r.URL.Path) |
| 0 | 271 if err := serveFCGI(w, r, fcgiAddr, rootDir); err != nil { |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
272 verbosePrintf("d2o: fcgi error: %v", err) |
| 0 | 273 http.Error(w, "gateway error", http.StatusBadGateway) |
| 274 } | |
| 275 return | |
| 276 } | |
| 277 if rootDir != "" { | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
278 fsPath := path.Clean(r.URL.Path) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
279 displayPath := fsPath |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
280 if user, ok := caps["user"]; ok && user != "" { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
281 mount := "/~" + user |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
282 if fsPath == mount || strings.HasPrefix(fsPath, mount+"/") { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
283 trimmed := strings.TrimPrefix(fsPath, mount) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
284 if trimmed == "" { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
285 trimmed = "/" |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
286 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
287 fsPath = trimmed |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
288 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
289 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
290 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
291 verbosePrintf("d2o: static -> %s (%s)", rootDir, r.URL.Path) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
292 serveStatic(w, r, rootDir, rootShow, ndex, fcgiAddr, fcgiPat, fsPath, displayPath) |
| 0 | 293 return |
| 294 } | |
| 295 | |
| 296 http.Error(w, "not found", http.StatusNotFound) | |
| 297 } | |
| 298 | |
| 299 // --- Static ----------------------------------------------------------------- | |
| 3 | 300 |
| 301 // serveStatic serves files from rootDir. | |
| 302 // rootIndex == nil: directory listing forbidden (hide). | |
| 303 // rootIndex != nil: try each as index candidate; if none found, show listing. | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
304 func serveStatic(w http.ResponseWriter, r *http.Request, rootDir string, show bool, ndex []string, fcgiAddr, fcgiPat string, fsPath, displayPath string) { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
305 fpath := filepath.Join(rootDir, filepath.FromSlash(path.Clean(fsPath))) |
| 0 | 306 |
| 307 info, err := os.Stat(fpath) | |
| 308 if os.IsNotExist(err) { | |
| 309 http.Error(w, "not found", http.StatusNotFound) | |
| 310 return | |
| 311 } | |
| 312 if err != nil { | |
| 313 http.Error(w, "internal error", http.StatusInternalServerError) | |
| 314 return | |
| 315 } | |
| 1 | 316 |
| 0 | 317 if info.IsDir() { |
|
5
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
318 for _, idx := range ndex { |
| 1 | 319 idxPath := filepath.Join(fpath, idx) |
| 320 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
|
321 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
|
322 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
|
323 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
|
324 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
|
325 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
|
326 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
|
327 } |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
328 return |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
329 } |
| 1 | 330 http.ServeFile(w, r, idxPath) |
| 331 return | |
| 332 } | |
| 333 } | |
|
5
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
334 if !show { |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
335 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
|
336 return |
|
07b6f06899e0
my tired ass deleted a fix that was partially working
Atarwn Gard <a@qwa.su>
parents:
3
diff
changeset
|
337 } |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
338 listDir(w, r, fpath, displayPath) |
| 0 | 339 return |
| 340 } | |
| 1 | 341 |
| 0 | 342 http.ServeFile(w, r, fpath) |
| 343 } | |
| 344 | |
| 345 func listDir(w http.ResponseWriter, r *http.Request, dir, urlPath string) { | |
| 346 entries, err := os.ReadDir(dir) | |
| 347 if err != nil { | |
| 348 http.Error(w, "cannot read directory", http.StatusInternalServerError) | |
| 349 return | |
| 350 } | |
| 351 w.Header().Set("Content-Type", "text/html; charset=utf-8") | |
|
7
8e4813b4e509
update index style + justfile additions
Atarwn Gard <a@qwa.su>
parents:
5
diff
changeset
|
352 fmt.Fprintf(w, "<html><head><title>Index of %s</title><style>body{font-family:monospace}</style></head><body>\n", urlPath) |
|
8e4813b4e509
update index style + justfile additions
Atarwn Gard <a@qwa.su>
parents:
5
diff
changeset
|
353 fmt.Fprintf(w, "<h2>Index of %s</h2><pre>\n", urlPath) |
| 0 | 354 if urlPath != "/" { |
| 355 fmt.Fprintf(w, "<a href=\"..\">..</a>\n") | |
| 356 } | |
| 357 for _, e := range entries { | |
| 358 name := e.Name() | |
| 359 if e.IsDir() { | |
| 360 name += "/" | |
| 361 } | |
| 362 fmt.Fprintf(w, "<a href=\"%s\">%s</a>\n", path.Join(urlPath, name), name) | |
| 363 } | |
|
7
8e4813b4e509
update index style + justfile additions
Atarwn Gard <a@qwa.su>
parents:
5
diff
changeset
|
364 fmt.Fprintf(w, "</pre><i>d2o webserver</i></body></html>") |
| 0 | 365 } |
| 366 | |
| 367 // --- Reverse proxy ---------------------------------------------------------- | |
| 368 | |
| 369 func serveReverseProxy(w http.ResponseWriter, r *http.Request, target string) { | |
| 370 if !strings.HasPrefix(target, "http://") && !strings.HasPrefix(target, "https://") { | |
| 371 target = "http://" + target | |
| 372 } | |
| 373 u, err := url.Parse(target) | |
| 374 if err != nil { | |
| 375 http.Error(w, "bad gateway config", http.StatusInternalServerError) | |
| 376 return | |
| 377 } | |
| 378 proxy := httputil.NewSingleHostReverseProxy(u) | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
379 if verboseEnabled() { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
380 origDirector := proxy.Director |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
381 proxy.Director = func(req *http.Request) { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
382 origDirector(req) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
383 log.Printf("d2o: rprx upstream request: %s %s", req.Method, req.URL.String()) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
384 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
385 proxy.ModifyResponse = func(resp *http.Response) error { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
386 log.Printf("d2o: rprx upstream response: %d %s", resp.StatusCode, resp.Status) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
387 return nil |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
388 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
389 } |
| 0 | 390 proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) { |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
391 verbosePrintf("d2o: rprx error: %v", err) |
| 0 | 392 http.Error(w, "bad gateway", http.StatusBadGateway) |
| 393 } | |
| 394 proxy.ServeHTTP(w, r) | |
| 395 } | |
| 396 | |
| 397 // --- FastCGI ---------------------------------------------------------------- | |
| 398 | |
| 399 func serveFCGI(w http.ResponseWriter, r *http.Request, addr, docRoot string) error { | |
| 400 network, address := parseFCGIAddr(addr) | |
| 3 | 401 client, err := fcgi.Dial(network, address) |
| 0 | 402 if err != nil { |
| 403 return fmt.Errorf("connect %s: %w", addr, err) | |
| 404 } | |
| 3 | 405 defer client.Close() |
| 0 | 406 |
| 407 scriptPath := r.URL.Path | |
| 408 if docRoot != "" { | |
| 409 scriptPath = filepath.Join(docRoot, filepath.FromSlash(r.URL.Path)) | |
| 410 } | |
| 411 | |
| 412 params := map[string]string{ | |
| 413 "REQUEST_METHOD": r.Method, | |
| 414 "SCRIPT_FILENAME": scriptPath, | |
| 415 "SCRIPT_NAME": r.URL.Path, | |
| 416 "REQUEST_URI": r.URL.RequestURI(), | |
| 417 "QUERY_STRING": r.URL.RawQuery, | |
| 418 "SERVER_PROTOCOL": r.Proto, | |
| 419 "SERVER_NAME": stripPort(r.Host), | |
| 420 "DOCUMENT_ROOT": docRoot, | |
| 421 "GATEWAY_INTERFACE": "CGI/1.1", | |
| 9 | 422 "SERVER_SOFTWARE": "d2o/1.1", |
| 0 | 423 } |
| 424 if r.TLS != nil { | |
| 425 params["HTTPS"] = "on" | |
| 426 } | |
| 427 for k, vs := range r.Header { | |
| 428 key := "HTTP_" + strings.ToUpper(strings.ReplaceAll(k, "-", "_")) | |
| 429 params[key] = strings.Join(vs, ", ") | |
| 430 } | |
| 431 if ct := r.Header.Get("Content-Type"); ct != "" { | |
| 432 params["CONTENT_TYPE"] = ct | |
| 433 } | |
| 434 if r.ContentLength >= 0 { | |
| 435 params["CONTENT_LENGTH"] = strconv.FormatInt(r.ContentLength, 10) | |
| 436 } | |
| 437 | |
| 3 | 438 // Use Do() instead of Request() — php-fpm returns CGI response (no HTTP status line), |
| 439 // not a full HTTP response. Request() expects "HTTP/1.1 200 OK" and panics on code 0. | |
| 440 cgiReader, err := client.Do(params, r.Body) | |
| 441 if err != nil { | |
| 442 return fmt.Errorf("fcgi request: %w", err) | |
| 443 } | |
| 444 | |
| 445 // Parse CGI headers manually | |
| 446 br := bufio.NewReader(cgiReader) | |
| 447 tp := textproto.NewReader(br) | |
| 448 mime, err := tp.ReadMIMEHeader() | |
| 449 if err != nil && len(mime) == 0 { | |
| 450 return fmt.Errorf("fcgi response headers: %w", err) | |
| 451 } | |
| 452 | |
| 453 status := http.StatusOK | |
| 454 if s := mime.Get("Status"); s != "" { | |
| 455 code, _, _ := strings.Cut(s, " ") | |
| 456 if n, err := strconv.Atoi(code); err == nil && n > 0 { | |
| 457 status = n | |
| 458 } | |
| 459 mime.Del("Status") | |
| 460 } | |
| 461 | |
| 462 for k, vs := range mime { | |
| 463 for _, v := range vs { | |
| 464 w.Header().Add(k, v) | |
| 465 } | |
| 466 } | |
| 467 w.WriteHeader(status) | |
| 468 io.Copy(w, br) | |
| 469 return nil | |
| 0 | 470 } |
| 471 | |
| 472 func parseFCGIAddr(addr string) (network, address string) { | |
| 473 if strings.HasPrefix(addr, "unix:") { | |
| 474 return "unix", strings.TrimPrefix(addr, "unix:") | |
| 475 } | |
| 476 return "tcp", addr | |
| 477 } | |
| 478 | |
| 479 // --- Helpers ---------------------------------------------------------------- | |
| 480 | |
| 481 func stripPort(host string) string { | |
| 482 if h, _, err := net.SplitHostPort(host); err == nil { | |
| 483 return h | |
| 484 } | |
| 485 return host | |
| 486 } | |
| 487 | |
| 488 func safeArg(args []string, i int) string { | |
| 489 if i < len(args) { | |
| 490 return args[i] | |
| 491 } | |
| 492 return "" | |
| 493 } | |
| 494 | |
| 495 func matchGlob(pattern, s string) bool { | |
| 496 if pattern == "*" { | |
| 497 return true | |
| 498 } | |
| 499 regPat := "^" + strings.ReplaceAll(regexp.QuoteMeta(pattern), regexp.QuoteMeta("*"), ".*") + "$" | |
| 500 matched, err := regexp.MatchString(regPat, s) | |
| 501 return err == nil && matched | |
|
8
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
502 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
503 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
504 type respRecorder struct { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
505 http.ResponseWriter |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
506 status int |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
507 bytes int64 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
508 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
509 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
510 func (rr *respRecorder) Hijack() (net.Conn, *bufio.ReadWriter, error) { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
511 h, ok := rr.ResponseWriter.(http.Hijacker) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
512 if !ok { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
513 return nil, nil, fmt.Errorf("hijack not supported") |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
514 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
515 return h.Hijack() |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
516 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
517 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
518 func (rr *respRecorder) Flush() { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
519 if f, ok := rr.ResponseWriter.(http.Flusher); ok { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
520 f.Flush() |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
521 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
522 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
523 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
524 func (rr *respRecorder) Push(target string, opts *http.PushOptions) error { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
525 if p, ok := rr.ResponseWriter.(http.Pusher); ok { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
526 return p.Push(target, opts) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
527 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
528 return http.ErrNotSupported |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
529 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
530 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
531 func (rr *respRecorder) ReadFrom(src io.Reader) (int64, error) { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
532 // Preserve io.Copy optimizations and count bytes. |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
533 rf, ok := rr.ResponseWriter.(io.ReaderFrom) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
534 if !ok { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
535 return io.Copy(rr, src) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
536 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
537 if rr.status == 0 { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
538 rr.status = http.StatusOK |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
539 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
540 n, err := rf.ReadFrom(src) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
541 rr.bytes += n |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
542 return n, err |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
543 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
544 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
545 func (rr *respRecorder) WriteHeader(code int) { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
546 rr.status = code |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
547 rr.ResponseWriter.WriteHeader(code) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
548 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
549 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
550 func (rr *respRecorder) Write(p []byte) (int, error) { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
551 if rr.status == 0 { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
552 rr.status = http.StatusOK |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
553 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
554 n, err := rr.ResponseWriter.Write(p) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
555 rr.bytes += int64(n) |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
556 return n, err |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
557 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
558 |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
559 func (rr *respRecorder) ensureStatus(defaultCode int) { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
560 if rr.status == 0 { |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
561 rr.status = defaultCode |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
562 } |
|
2ffb8028ccbb
add loggingmodes and fix path matching
Atarwn Gard <a@qwa.su>
parents:
7
diff
changeset
|
563 } |
