Seed from go-template-repo, renamed to simplexcalc

The template's files at a77fd30, without its history or LICENSE, after
script/rename simplexcalc.

Model: opus-5-5
This commit is contained in:
clawbot
2026-09-26 21:38:57 +00:00
parent e336f46e34
commit f8ce8cef83
79 changed files with 7131 additions and 0 deletions
+59
View File
@@ -0,0 +1,59 @@
package middleware
import (
"net/http"
"runtime/debug"
)
// panicBody is the entire response a recovered panic produces. No
// template, no detail: the client learns that the request failed, and
// everything about why goes to the log and to Sentry, where it is not
// attacker-readable.
const panicBody = "internal server error"
// Recoverer turns a panicking handler into a 500 rather than a dropped
// connection.
//
// net/http already recovers panics, but what it does is close the
// connection without a response, so the client sees a transport error
// and no status. Answering 500 is the difference between "the service
// is broken" and "the network is broken" for everyone downstream.
//
// A panic after the response has started cannot be turned into a 500 —
// the status is already on the wire — so in that case the connection is
// deliberately dropped by re-panicking to net/http, which is the only
// honest signal left that the body is truncated. A truncated 200 that
// looks complete is worse than a broken connection.
func (m *Middleware) Recoverer() func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
rec := newResponseRecorder(w)
defer func() {
v := recover()
if v == nil {
return
}
// http.ErrAbortHandler is net/http's documented way for
// a handler to abandon a response on purpose. It is not
// a bug, so it is not reported; it is re-raised for
// net/http to handle as it always does.
//nolint:errorlint,err113 // a sentinel value, compared as net/http documents.
if v == http.ErrAbortHandler {
panic(v)
}
m.params.Sentry.CapturePanic(v, debug.Stack())
if rec.Written() {
panic(v)
}
http.Error(rec, panicBody, http.StatusInternalServerError)
}()
next.ServeHTTP(rec, r)
})
}
}