annotate main.go @ 14:a51dfcb0faeb default tip

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