summaryrefslogtreecommitdiff
path: root/vendor/github.com/gin-gonic/gin/recovery.go
diff options
context:
space:
mode:
authorLibravatar Terin Stock <terinjokes@gmail.com>2025-03-09 17:47:56 +0100
committerLibravatar Terin Stock <terinjokes@gmail.com>2025-03-10 01:59:49 +0100
commit3ac1ee16f377d31a0fb80c8dae28b6239ac4229e (patch)
treef61faa581feaaeaba2542b9f2b8234a590684413 /vendor/github.com/gin-gonic/gin/recovery.go
parent[chore] update URLs to forked source (diff)
downloadgotosocial-3ac1ee16f377d31a0fb80c8dae28b6239ac4229e.tar.xz
[chore] remove vendor
Diffstat (limited to 'vendor/github.com/gin-gonic/gin/recovery.go')
-rw-r--r--vendor/github.com/gin-gonic/gin/recovery.go174
1 files changed, 0 insertions, 174 deletions
diff --git a/vendor/github.com/gin-gonic/gin/recovery.go b/vendor/github.com/gin-gonic/gin/recovery.go
deleted file mode 100644
index 515f9d2ad..000000000
--- a/vendor/github.com/gin-gonic/gin/recovery.go
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
-// Use of this source code is governed by a MIT style
-// license that can be found in the LICENSE file.
-
-package gin
-
-import (
- "bytes"
- "errors"
- "fmt"
- "io"
- "log"
- "net"
- "net/http"
- "net/http/httputil"
- "os"
- "runtime"
- "strings"
- "time"
-)
-
-var (
- dunno = []byte("???")
- centerDot = []byte("·")
- dot = []byte(".")
- slash = []byte("/")
-)
-
-// RecoveryFunc defines the function passable to CustomRecovery.
-type RecoveryFunc func(c *Context, err any)
-
-// Recovery returns a middleware that recovers from any panics and writes a 500 if there was one.
-func Recovery() HandlerFunc {
- return RecoveryWithWriter(DefaultErrorWriter)
-}
-
-// CustomRecovery returns a middleware that recovers from any panics and calls the provided handle func to handle it.
-func CustomRecovery(handle RecoveryFunc) HandlerFunc {
- return RecoveryWithWriter(DefaultErrorWriter, handle)
-}
-
-// RecoveryWithWriter returns a middleware for a given writer that recovers from any panics and writes a 500 if there was one.
-func RecoveryWithWriter(out io.Writer, recovery ...RecoveryFunc) HandlerFunc {
- if len(recovery) > 0 {
- return CustomRecoveryWithWriter(out, recovery[0])
- }
- return CustomRecoveryWithWriter(out, defaultHandleRecovery)
-}
-
-// CustomRecoveryWithWriter returns a middleware for a given writer that recovers from any panics and calls the provided handle func to handle it.
-func CustomRecoveryWithWriter(out io.Writer, handle RecoveryFunc) HandlerFunc {
- var logger *log.Logger
- if out != nil {
- logger = log.New(out, "\n\n\x1b[31m", log.LstdFlags)
- }
- return func(c *Context) {
- defer func() {
- if err := recover(); err != nil {
- // Check for a broken connection, as it is not really a
- // condition that warrants a panic stack trace.
- var brokenPipe bool
- if ne, ok := err.(*net.OpError); ok {
- var se *os.SyscallError
- if errors.As(ne, &se) {
- seStr := strings.ToLower(se.Error())
- if strings.Contains(seStr, "broken pipe") ||
- strings.Contains(seStr, "connection reset by peer") {
- brokenPipe = true
- }
- }
- }
- if logger != nil {
- stack := stack(3)
- httpRequest, _ := httputil.DumpRequest(c.Request, false)
- headers := strings.Split(string(httpRequest), "\r\n")
- for idx, header := range headers {
- current := strings.Split(header, ":")
- if current[0] == "Authorization" {
- headers[idx] = current[0] + ": *"
- }
- }
- headersToStr := strings.Join(headers, "\r\n")
- if brokenPipe {
- logger.Printf("%s\n%s%s", err, headersToStr, reset)
- } else if IsDebugging() {
- logger.Printf("[Recovery] %s panic recovered:\n%s\n%s\n%s%s",
- timeFormat(time.Now()), headersToStr, err, stack, reset)
- } else {
- logger.Printf("[Recovery] %s panic recovered:\n%s\n%s%s",
- timeFormat(time.Now()), err, stack, reset)
- }
- }
- if brokenPipe {
- // If the connection is dead, we can't write a status to it.
- c.Error(err.(error)) //nolint: errcheck
- c.Abort()
- } else {
- handle(c, err)
- }
- }
- }()
- c.Next()
- }
-}
-
-func defaultHandleRecovery(c *Context, _ any) {
- c.AbortWithStatus(http.StatusInternalServerError)
-}
-
-// stack returns a nicely formatted stack frame, skipping skip frames.
-func stack(skip int) []byte {
- buf := new(bytes.Buffer) // the returned data
- // As we loop, we open files and read them. These variables record the currently
- // loaded file.
- var lines [][]byte
- var lastFile string
- for i := skip; ; i++ { // Skip the expected number of frames
- pc, file, line, ok := runtime.Caller(i)
- if !ok {
- break
- }
- // Print this much at least. If we can't find the source, it won't show.
- fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
- if file != lastFile {
- data, err := os.ReadFile(file)
- if err != nil {
- continue
- }
- lines = bytes.Split(data, []byte{'\n'})
- lastFile = file
- }
- fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
- }
- return buf.Bytes()
-}
-
-// source returns a space-trimmed slice of the n'th line.
-func source(lines [][]byte, n int) []byte {
- n-- // in stack trace, lines are 1-indexed but our array is 0-indexed
- if n < 0 || n >= len(lines) {
- return dunno
- }
- return bytes.TrimSpace(lines[n])
-}
-
-// function returns, if possible, the name of the function containing the PC.
-func function(pc uintptr) []byte {
- fn := runtime.FuncForPC(pc)
- if fn == nil {
- return dunno
- }
- name := []byte(fn.Name())
- // The name includes the path name to the package, which is unnecessary
- // since the file name is already included. Plus, it has center dots.
- // That is, we see
- // runtime/debug.*T·ptrmethod
- // and want
- // *T.ptrmethod
- // Also the package path might contain dot (e.g. code.google.com/...),
- // so first eliminate the path prefix
- if lastSlash := bytes.LastIndex(name, slash); lastSlash >= 0 {
- name = name[lastSlash+1:]
- }
- if period := bytes.Index(name, dot); period >= 0 {
- name = name[period+1:]
- }
- name = bytes.ReplaceAll(name, centerDot, dot)
- return name
-}
-
-// timeFormat returns a customized time string for logger.
-func timeFormat(t time.Time) string {
- return t.Format("2006/01/02 - 15:04:05")
-}