mirror of
https://github.com/project-zot/zot.git
synced 2026-06-15 11:37:56 +08:00
2402296e9a
* fix: migrate to Go module v2 for proper semantic versioning This change updates the module path from 'zotregistry.dev/zot' to 'zotregistry.dev/zot/v2' to comply with Go's semantic versioning rules. According to Go's module versioning requirements, major version v2+ must include the major version in the module path. The current module path 'zotregistry.dev/zot' only supports v0.x.x and v1.x.x versions, making existing v2.x.x tags (like v2.1.8) unusable. Changes: - Updated go.mod module path to zotregistry.dev/zot/v2 - Updated all internal import paths across 280+ Go source files - Updated configuration files (golangcilint.yaml, gqlgen.yml) - Updated README.md Go reference badge This fix enables proper use of existing v2.x.x Git tags and allows external packages to import zot v2+ versions without compatibility errors. Resolves: Go module import compatibility for v2+ versions Fixes: #3071 Signed-off-by: Luca Muscariello <muscariello@ieee.org> * fix: regenerate GraphQL files with updated v2 import paths The gqlgen tool needs to regenerate the GraphQL schema files after the module path change to use the new v2 imports. Signed-off-by: Luca Muscariello <muscariello@ieee.org> --------- Signed-off-by: Luca Muscariello <muscariello@ieee.org>
86 lines
1.7 KiB
Go
86 lines
1.7 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"runtime"
|
|
|
|
"github.com/gorilla/mux"
|
|
|
|
"zotregistry.dev/zot/v2/pkg/log"
|
|
)
|
|
|
|
type Stack struct {
|
|
Frames []Frame `json:"stack"`
|
|
}
|
|
|
|
type Frame struct {
|
|
Name string `json:"function"`
|
|
File string `json:"file"`
|
|
Line int `json:"line"`
|
|
}
|
|
|
|
// RecoveryHandler is a HTTP middleware that recovers from a panic.
|
|
// It logs the panic and its traceback in json format, writes http.StatusInternalServerError
|
|
// and continues to the next handler.
|
|
func RecoveryHandler(log log.Logger) mux.MiddlewareFunc {
|
|
return func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
|
|
defer func() {
|
|
if err := recover(); err != nil {
|
|
response.WriteHeader(http.StatusInternalServerError)
|
|
|
|
stack := Stack{
|
|
Frames: getStacktrace(),
|
|
}
|
|
|
|
recoveredErr, ok := err.(error)
|
|
if ok {
|
|
buf, err := json.Marshal(stack)
|
|
if err == nil {
|
|
log.Error().Err(recoveredErr).RawJSON("traceback", buf).Msg("panic recovered") //nolint: check-logs
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
|
|
// Process request
|
|
next.ServeHTTP(response, request)
|
|
})
|
|
}
|
|
}
|
|
|
|
func getStacktrace() []Frame {
|
|
stack := []Frame{}
|
|
//nolint: varnamelen
|
|
pc := make([]uintptr, 64)
|
|
|
|
n := runtime.Callers(0, pc)
|
|
if n == 0 {
|
|
return []Frame{}
|
|
}
|
|
|
|
// first three frames are from this file, don't need them.
|
|
pc = pc[3:]
|
|
frames := runtime.CallersFrames(pc)
|
|
|
|
// loop to get frames.
|
|
for {
|
|
frame, more := frames.Next()
|
|
|
|
// store this frame
|
|
stack = append(stack, Frame{
|
|
Name: frame.Function,
|
|
File: frame.File,
|
|
Line: frame.Line,
|
|
})
|
|
|
|
// check whether there are more frames to process after this one.
|
|
if !more {
|
|
break
|
|
}
|
|
}
|
|
|
|
return stack
|
|
}
|