Mercurial Hosting > d2o
comparison main.go @ 1:3e7247db5c6e
show index.html
| author | Atarwn Gard <a@qwa.su> |
|---|---|
| date | Mon, 09 Mar 2026 01:04:16 +0500 |
| parents | 48bdab3eec8a |
| children | d19133be91ba |
comparison
equal
deleted
inserted
replaced
| 0:48bdab3eec8a | 1:3e7247db5c6e |
|---|---|
| 34 f.Close() | 34 f.Close() |
| 35 if err != nil { | 35 if err != nil { |
| 36 log.Fatalf("d2o: config error: %v", err) | 36 log.Fatalf("d2o: config error: %v", err) |
| 37 } | 37 } |
| 38 | 38 |
| 39 // Apply @d2o global settings | |
| 40 for _, d := range cfg.Abstract("d2o") { | 39 for _, d := range cfg.Abstract("d2o") { |
| 41 switch d.Key { | 40 switch d.Key { |
| 42 case "threads": | 41 case "threads": |
| 43 n, err := strconv.Atoi(safeArg(d.Args, 0)) | 42 n, err := strconv.Atoi(safeArg(d.Args, 0)) |
| 44 if err == nil && n > 0 { | 43 if err == nil && n > 0 { |
| 92 } | 91 } |
| 93 log.Printf("d2o: listening on %s (https)", pc.addr) | 92 log.Printf("d2o: listening on %s (https)", pc.addr) |
| 94 return http.Serve(ln, h) | 93 return http.Serve(ln, h) |
| 95 } | 94 } |
| 96 | 95 |
| 97 // collectPorts scans all blocks for port / port+tls directives. | |
| 98 func collectPorts(cfg *icf.Config) []portConfig { | 96 func collectPorts(cfg *icf.Config) []portConfig { |
| 99 seen := make(map[string]bool) | 97 seen := make(map[string]bool) |
| 100 var out []portConfig | 98 var out []portConfig |
| 101 | 99 |
| 102 for _, b := range cfg.Blocks { | 100 for _, b := range cfg.Blocks { |
| 103 dirs := cfg.ResolveBlock(b, nil) | 101 dirs := cfg.ResolveBlock(b, nil) |
| 104 | 102 |
| 105 // Collect tls paths defined in this block | |
| 106 var cert, key string | 103 var cert, key string |
| 107 for _, d := range dirs { | 104 for _, d := range dirs { |
| 108 if d.Key == "tls" { | 105 if d.Key == "tls" { |
| 109 cert = safeArg(d.Args, 0) | 106 cert = safeArg(d.Args, 0) |
| 110 key = safeArg(d.Args, 1) | 107 key = safeArg(d.Args, 1) |
| 147 | 144 |
| 148 func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { | 145 func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
| 149 host := stripPort(r.Host) | 146 host := stripPort(r.Host) |
| 150 reqPath := path.Clean(r.URL.Path) | 147 reqPath := path.Clean(r.URL.Path) |
| 151 | 148 |
| 152 // Try host+path first, then host alone | |
| 153 dirs, caps := h.cfg.Match(host + reqPath) | 149 dirs, caps := h.cfg.Match(host + reqPath) |
| 154 if dirs == nil { | 150 if dirs == nil { |
| 155 dirs, caps = h.cfg.Match(host) | 151 dirs, caps = h.cfg.Match(host) |
| 156 } | 152 } |
| 157 if dirs == nil { | 153 if dirs == nil { |
| 162 h.serve(w, r, dirs, caps) | 158 h.serve(w, r, dirs, caps) |
| 163 } | 159 } |
| 164 | 160 |
| 165 func (h *handler) serve(w http.ResponseWriter, r *http.Request, dirs []icf.Directive, _ map[string]string) { | 161 func (h *handler) serve(w http.ResponseWriter, r *http.Request, dirs []icf.Directive, _ map[string]string) { |
| 166 var ( | 162 var ( |
| 167 rootDir string | 163 rootDir string |
| 168 rootShow bool | 164 rootIndex []string |
| 169 fcgiAddr string | 165 fcgiAddr string |
| 170 fcgiPat string | 166 fcgiPat string |
| 171 rprxAddr string | 167 rprxAddr string |
| 172 ) | 168 ) |
| 173 | 169 |
| 174 for _, d := range dirs { | 170 for _, d := range dirs { |
| 175 switch d.Key { | 171 switch d.Key { |
| 176 case "root": | 172 case "root": |
| 177 rootDir = safeArg(d.Args, 0) | 173 rootDir = safeArg(d.Args, 0) |
| 178 switch safeArg(d.Args, 1) { | 174 switch safeArg(d.Args, 1) { |
| 179 case "show": | 175 case "show": |
| 180 rootShow = true | 176 if len(d.Args) >= 3 { |
| 177 rootIndex = d.Args[2:] | |
| 178 } else { | |
| 179 rootIndex = []string{"index.html"} | |
| 180 } | |
| 181 case "hide", "": | 181 case "hide", "": |
| 182 rootShow = false | 182 rootIndex = nil |
| 183 default: | 183 default: |
| 184 log.Printf("d2o: root: unknown mode %q (want show|hide)", safeArg(d.Args, 1)) | 184 log.Printf("d2o: root: unknown mode %q (want show|hide)", safeArg(d.Args, 1)) |
| 185 } | 185 } |
| 186 case "fcgi": | 186 case "fcgi": |
| 187 fcgiAddr = safeArg(d.Args, 0) | 187 fcgiAddr = safeArg(d.Args, 0) |
| 192 case "rprx": | 192 case "rprx": |
| 193 rprxAddr = safeArg(d.Args, 0) | 193 rprxAddr = safeArg(d.Args, 0) |
| 194 } | 194 } |
| 195 } | 195 } |
| 196 | 196 |
| 197 // Priority: rprx > fcgi > static root | |
| 198 if rprxAddr != "" { | 197 if rprxAddr != "" { |
| 199 serveReverseProxy(w, r, rprxAddr) | 198 serveReverseProxy(w, r, rprxAddr) |
| 200 return | 199 return |
| 201 } | 200 } |
| 202 if fcgiAddr != "" && matchGlob(fcgiPat, r.URL.Path) { | 201 if fcgiAddr != "" && matchGlob(fcgiPat, r.URL.Path) { |
| 205 http.Error(w, "gateway error", http.StatusBadGateway) | 204 http.Error(w, "gateway error", http.StatusBadGateway) |
| 206 } | 205 } |
| 207 return | 206 return |
| 208 } | 207 } |
| 209 if rootDir != "" { | 208 if rootDir != "" { |
| 210 serveStatic(w, r, rootDir, rootShow) | 209 serveStatic(w, r, rootDir, rootIndex) |
| 211 return | 210 return |
| 212 } | 211 } |
| 213 | 212 |
| 214 http.Error(w, "not found", http.StatusNotFound) | 213 http.Error(w, "not found", http.StatusNotFound) |
| 215 } | 214 } |
| 216 | 215 |
| 217 // --- Static ----------------------------------------------------------------- | 216 // --- Static ----------------------------------------------------------------- |
| 218 | 217 |
| 219 func serveStatic(w http.ResponseWriter, r *http.Request, rootDir string, showDir bool) { | 218 func serveStatic(w http.ResponseWriter, r *http.Request, rootDir string, rootIndex []string) { |
| 220 fpath := filepath.Join(rootDir, filepath.FromSlash(path.Clean(r.URL.Path))) | 219 fpath := filepath.Join(rootDir, filepath.FromSlash(path.Clean(r.URL.Path))) |
| 221 | 220 |
| 222 info, err := os.Stat(fpath) | 221 info, err := os.Stat(fpath) |
| 223 if os.IsNotExist(err) { | 222 if os.IsNotExist(err) { |
| 224 http.Error(w, "not found", http.StatusNotFound) | 223 http.Error(w, "not found", http.StatusNotFound) |
| 226 } | 225 } |
| 227 if err != nil { | 226 if err != nil { |
| 228 http.Error(w, "internal error", http.StatusInternalServerError) | 227 http.Error(w, "internal error", http.StatusInternalServerError) |
| 229 return | 228 return |
| 230 } | 229 } |
| 230 | |
| 231 if info.IsDir() { | 231 if info.IsDir() { |
| 232 if !showDir { | 232 if rootIndex == nil { |
| 233 http.Error(w, "forbidden", http.StatusForbidden) | 233 http.Error(w, "forbidden", http.StatusForbidden) |
| 234 return | 234 return |
| 235 } | 235 } |
| 236 for _, idx := range rootIndex { | |
| 237 idxPath := filepath.Join(fpath, idx) | |
| 238 if _, err := os.Stat(idxPath); err == nil { | |
| 239 http.ServeFile(w, r, idxPath) | |
| 240 return | |
| 241 } | |
| 242 } | |
| 236 listDir(w, r, fpath, r.URL.Path) | 243 listDir(w, r, fpath, r.URL.Path) |
| 237 return | 244 return |
| 238 } | 245 } |
| 246 | |
| 239 http.ServeFile(w, r, fpath) | 247 http.ServeFile(w, r, fpath) |
| 240 } | 248 } |
| 241 | 249 |
| 242 func listDir(w http.ResponseWriter, r *http.Request, dir, urlPath string) { | 250 func listDir(w http.ResponseWriter, r *http.Request, dir, urlPath string) { |
| 243 entries, err := os.ReadDir(dir) | 251 entries, err := os.ReadDir(dir) |
