vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
Render the styled error page for every miss and failure
e84a66f5b53c269d8b0c207d0335b537e1646cb3 · Keenan Nemetz · 15d ago · parent f6f4b1db
Render the styled error page for every miss and failure Handler-level 404s now use the same view as the catch-all, including unknown detail resources and download paths. Internal 500s render the shared error layout and log the detail instead of exposing it. A panic before the first byte is recovered into that page; a partial response is left to net/http. Also mark label/assignee triage and inline review comments done in the UI plan, where the slice order was stale.
server/web/web.go +19−7
| @@ -181,12 +181,24 @@ func (w *Web) notFound(rw http.ResponseWriter, r *http.Request) { | |||
| 181 | 181 | // NotFoundPage is the catch-all route. It uses the same view as every other 404. | |
| 182 | 182 | func (w *Web) NotFoundPage(rw http.ResponseWriter, r *http.Request) { w.notFound(rw, r) } | |
| 183 | 183 | ||
| 184 | // serverError is the styled 500. The detail goes to the log rather than the | ||
| 185 | // page: a store path or a stack trace is not something a browser should learn. | ||
| 186 | func (w *Web) serverError(rw http.ResponseWriter, r *http.Request, detail string) { | ||
| 187 | if detail != "" && w.Logger != nil { | ||
| 188 | w.Logger("server error %s %s: %s", r.Method, r.URL.Path, detail) | ||
| 189 | } | ||
| 190 | w.render(rw, "servererror", struct { | ||
| 191 | Page | ||
| 192 | Message string | ||
| 193 | }{w.page(r, "Server error"), "The server could not complete this request. The problem has been logged."}, http.StatusInternalServerError) | ||
| 194 | } | ||
| 195 | |||
| 184 | 196 | func (w *Web) render(rw http.ResponseWriter, name string, data any, status int) { | |
| 185 | 197 | rw.Header().Set("Content-Type", "text/html; charset=utf-8") | |
| 186 | 198 | if status != 0 { | |
| 187 | 199 | rw.WriteHeader(status) | |
| 188 | 200 | } | |
| 189 | if err := w.Tmpl.ExecuteTemplate(rw, name, data); err != nil { | ||
| 201 | if err := w.Tmpl.ExecuteTemplate(rw, name, data); err != nil && w.Logger != nil { | ||
| 190 | 202 | w.Logger("render %s: %v", name, err) | |
| 191 | 203 | } | |
| 192 | 204 | } | |
| @@ -196,7 +208,7 @@ func (w *Web) render(rw http.ResponseWriter, name string, data any, status int) | |||
| 196 | 208 | func (w *Web) IndexPage(rw http.ResponseWriter, r *http.Request) { | |
| 197 | 209 | entries, err := w.Index.List() | |
| 198 | 210 | if err != nil { | |
| 199 | http.Error(rw, "index unavailable: "+err.Error(), 500) | ||
| 211 | w.serverError(rw, r, "index unavailable: "+err.Error()) | ||
| 200 | 212 | return | |
| 201 | 213 | } | |
| 202 | 214 | var visible []index.Entry | |
| @@ -312,7 +324,7 @@ func (w *Web) Tree(rw http.ResponseWriter, r *http.Request) { | |||
| 312 | 324 | g := m.Git() | |
| 313 | 325 | commit, _ := g.RevParse(ref) | |
| 314 | 326 | if commit == "" { | |
| 315 | http.NotFound(rw, r) | ||
| 327 | w.notFound(rw, r) | ||
| 316 | 328 | return | |
| 317 | 329 | } | |
| 318 | 330 | treeish := commit | |
| @@ -359,12 +371,12 @@ func (w *Web) blob(rw http.ResponseWriter, r *http.Request, raw bool) { | |||
| 359 | 371 | g := m.Git() | |
| 360 | 372 | commit, _ := g.RevParse(ref) | |
| 361 | 373 | if commit == "" { | |
| 362 | http.NotFound(rw, r) | ||
| 374 | w.notFound(rw, r) | ||
| 363 | 375 | return | |
| 364 | 376 | } | |
| 365 | 377 | data, err := g.BlobAt(commit, p) | |
| 366 | 378 | if err != nil { | |
| 367 | http.NotFound(rw, r) | ||
| 379 | w.notFound(rw, r) | ||
| 368 | 380 | return | |
| 369 | 381 | } | |
| 370 | 382 | if raw { | |
| @@ -436,12 +448,12 @@ func (w *Web) Commits(rw http.ResponseWriter, r *http.Request) { | |||
| 436 | 448 | g := m.Git() | |
| 437 | 449 | commit, _ := g.RevParse(ref) | |
| 438 | 450 | if commit == "" { | |
| 439 | http.NotFound(rw, r) | ||
| 451 | w.notFound(rw, r) | ||
| 440 | 452 | return | |
| 441 | 453 | } | |
| 442 | 454 | commits, err := g.Log(commit, 100) | |
| 443 | 455 | if err != nil { | |
| 444 | http.Error(rw, err.Error(), 500) | ||
| 456 | w.serverError(rw, r, "cannot read commit history: "+err.Error()) | ||
| 445 | 457 | return | |
| 446 | 458 | } | |
| 447 | 459 | w.render(rw, "commits", struct { | |