Fix regression: access log template, gitea manager cli command (#24838)
Close #24836 ![image](https://github.com/go-gitea/gitea/assets/2114189/95b025d2-f25f-4246-a08a-fe44ecb787a9) ![image](https://github.com/go-gitea/gitea/assets/2114189/c3afe1fa-2a23-420d-a016-3b67dcd04cd5)
This commit is contained in:
parent
2d3ebe889e
commit
ec2a01d1e2
|
@ -92,7 +92,7 @@ func AccessLogger() func(http.Handler) http.Handler {
|
||||||
RequestID: &requestID,
|
RequestID: &requestID,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Could not set up chi access logger: %v", err.Error())
|
log.Error("Could not execute access logger template: %v", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("%s", buf.String())
|
logger.Info("%s", buf.String())
|
||||||
|
|
|
@ -13,6 +13,7 @@ type ResponseWriter interface {
|
||||||
http.Flusher
|
http.Flusher
|
||||||
Status() int
|
Status() int
|
||||||
Before(func(ResponseWriter))
|
Before(func(ResponseWriter))
|
||||||
|
Size() int // used by access logger template
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ ResponseWriter = &Response{}
|
var _ ResponseWriter = &Response{}
|
||||||
|
@ -45,6 +46,10 @@ func (r *Response) Write(bs []byte) (int, error) {
|
||||||
return size, nil
|
return size, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Response) Size() int {
|
||||||
|
return r.written
|
||||||
|
}
|
||||||
|
|
||||||
// WriteHeader write status code
|
// WriteHeader write status code
|
||||||
func (r *Response) WriteHeader(statusCode int) {
|
func (r *Response) WriteHeader(statusCode int) {
|
||||||
if !r.beforeExecuted {
|
if !r.beforeExecuted {
|
||||||
|
|
|
@ -244,6 +244,10 @@ func (g *Manager) DoGracefulRestart() {
|
||||||
log.Error("Error whilst forking from PID: %d : %v", os.Getpid(), err)
|
log.Error("Error whilst forking from PID: %d : %v", os.Getpid(), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// doFork calls RestartProcess which starts a new Gitea process, so this parent process needs to exit
|
||||||
|
// Otherwise some resources (eg: leveldb lock) will be held by this parent process and the new process will fail to start
|
||||||
|
log.Info("PID: %d. Shutting down after forking ...", os.Getpid())
|
||||||
|
g.doShutdown()
|
||||||
} else {
|
} else {
|
||||||
log.Info("PID: %d. Not set restartable. Shutting down...", os.Getpid())
|
log.Info("PID: %d. Not set restartable. Shutting down...", os.Getpid())
|
||||||
g.notify(stoppingMsg)
|
g.notify(stoppingMsg)
|
||||||
|
|
|
@ -109,5 +109,7 @@ func RestartProcess() (int, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return process.Pid, nil
|
processPid := process.Pid
|
||||||
|
_ = process.Release() // no wait, so release
|
||||||
|
return processPid, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Email structure holds a data for sending general emails
|
|
||||||
type GenerateTokenRequest struct {
|
type GenerateTokenRequest struct {
|
||||||
Scope string
|
Scope string
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,14 +19,14 @@ import (
|
||||||
func Shutdown(ctx context.Context) ResponseExtra {
|
func Shutdown(ctx context.Context) ResponseExtra {
|
||||||
reqURL := setting.LocalURL + "api/internal/manager/shutdown"
|
reqURL := setting.LocalURL + "api/internal/manager/shutdown"
|
||||||
req := newInternalRequest(ctx, reqURL, "POST")
|
req := newInternalRequest(ctx, reqURL, "POST")
|
||||||
return requestJSONUserMsg(req, "Shutting down")
|
return requestJSONClientMsg(req, "Shutting down")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restart calls the internal restart function
|
// Restart calls the internal restart function
|
||||||
func Restart(ctx context.Context) ResponseExtra {
|
func Restart(ctx context.Context) ResponseExtra {
|
||||||
reqURL := setting.LocalURL + "api/internal/manager/restart"
|
reqURL := setting.LocalURL + "api/internal/manager/restart"
|
||||||
req := newInternalRequest(ctx, reqURL, "POST")
|
req := newInternalRequest(ctx, reqURL, "POST")
|
||||||
return requestJSONUserMsg(req, "Restarting")
|
return requestJSONClientMsg(req, "Restarting")
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlushOptions represents the options for the flush call
|
// FlushOptions represents the options for the flush call
|
||||||
|
@ -42,35 +42,35 @@ func FlushQueues(ctx context.Context, timeout time.Duration, nonBlocking bool) R
|
||||||
if timeout > 0 {
|
if timeout > 0 {
|
||||||
req.SetReadWriteTimeout(timeout + 10*time.Second)
|
req.SetReadWriteTimeout(timeout + 10*time.Second)
|
||||||
}
|
}
|
||||||
return requestJSONUserMsg(req, "Flushed")
|
return requestJSONClientMsg(req, "Flushed")
|
||||||
}
|
}
|
||||||
|
|
||||||
// PauseLogging pauses logging
|
// PauseLogging pauses logging
|
||||||
func PauseLogging(ctx context.Context) ResponseExtra {
|
func PauseLogging(ctx context.Context) ResponseExtra {
|
||||||
reqURL := setting.LocalURL + "api/internal/manager/pause-logging"
|
reqURL := setting.LocalURL + "api/internal/manager/pause-logging"
|
||||||
req := newInternalRequest(ctx, reqURL, "POST")
|
req := newInternalRequest(ctx, reqURL, "POST")
|
||||||
return requestJSONUserMsg(req, "Logging Paused")
|
return requestJSONClientMsg(req, "Logging Paused")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResumeLogging resumes logging
|
// ResumeLogging resumes logging
|
||||||
func ResumeLogging(ctx context.Context) ResponseExtra {
|
func ResumeLogging(ctx context.Context) ResponseExtra {
|
||||||
reqURL := setting.LocalURL + "api/internal/manager/resume-logging"
|
reqURL := setting.LocalURL + "api/internal/manager/resume-logging"
|
||||||
req := newInternalRequest(ctx, reqURL, "POST")
|
req := newInternalRequest(ctx, reqURL, "POST")
|
||||||
return requestJSONUserMsg(req, "Logging Restarted")
|
return requestJSONClientMsg(req, "Logging Restarted")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReleaseReopenLogging releases and reopens logging files
|
// ReleaseReopenLogging releases and reopens logging files
|
||||||
func ReleaseReopenLogging(ctx context.Context) ResponseExtra {
|
func ReleaseReopenLogging(ctx context.Context) ResponseExtra {
|
||||||
reqURL := setting.LocalURL + "api/internal/manager/release-and-reopen-logging"
|
reqURL := setting.LocalURL + "api/internal/manager/release-and-reopen-logging"
|
||||||
req := newInternalRequest(ctx, reqURL, "POST")
|
req := newInternalRequest(ctx, reqURL, "POST")
|
||||||
return requestJSONUserMsg(req, "Logging Restarted")
|
return requestJSONClientMsg(req, "Logging Restarted")
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLogSQL sets database logging
|
// SetLogSQL sets database logging
|
||||||
func SetLogSQL(ctx context.Context, on bool) ResponseExtra {
|
func SetLogSQL(ctx context.Context, on bool) ResponseExtra {
|
||||||
reqURL := setting.LocalURL + "api/internal/manager/set-log-sql?on=" + strconv.FormatBool(on)
|
reqURL := setting.LocalURL + "api/internal/manager/set-log-sql?on=" + strconv.FormatBool(on)
|
||||||
req := newInternalRequest(ctx, reqURL, "POST")
|
req := newInternalRequest(ctx, reqURL, "POST")
|
||||||
return requestJSONUserMsg(req, "Log SQL setting set")
|
return requestJSONClientMsg(req, "Log SQL setting set")
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoggerOptions represents the options for the add logger call
|
// LoggerOptions represents the options for the add logger call
|
||||||
|
@ -90,14 +90,14 @@ func AddLogger(ctx context.Context, logger, writer, mode string, config map[stri
|
||||||
Mode: mode,
|
Mode: mode,
|
||||||
Config: config,
|
Config: config,
|
||||||
})
|
})
|
||||||
return requestJSONUserMsg(req, "Added")
|
return requestJSONClientMsg(req, "Added")
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveLogger removes a logger
|
// RemoveLogger removes a logger
|
||||||
func RemoveLogger(ctx context.Context, logger, writer string) ResponseExtra {
|
func RemoveLogger(ctx context.Context, logger, writer string) ResponseExtra {
|
||||||
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/manager/remove-logger/%s/%s", url.PathEscape(logger), url.PathEscape(writer))
|
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/manager/remove-logger/%s/%s", url.PathEscape(logger), url.PathEscape(writer))
|
||||||
req := newInternalRequest(ctx, reqURL, "POST")
|
req := newInternalRequest(ctx, reqURL, "POST")
|
||||||
return requestJSONUserMsg(req, "Removed")
|
return requestJSONClientMsg(req, "Removed")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Processes return the current processes from this gitea instance
|
// Processes return the current processes from this gitea instance
|
||||||
|
@ -108,6 +108,6 @@ func Processes(ctx context.Context, out io.Writer, flat, noSystem, stacktraces,
|
||||||
callback := func(resp *http.Response, extra *ResponseExtra) {
|
callback := func(resp *http.Response, extra *ResponseExtra) {
|
||||||
_, extra.Error = io.Copy(out, resp.Body)
|
_, extra.Error = io.Copy(out, resp.Body)
|
||||||
}
|
}
|
||||||
_, extra := requestJSONResp(req, &callback)
|
_, extra := requestJSONResp(req, &responseCallback{callback})
|
||||||
return extra
|
return extra
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"unicode"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/httplib"
|
"code.gitea.io/gitea/modules/httplib"
|
||||||
"code.gitea.io/gitea/modules/json"
|
"code.gitea.io/gitea/modules/json"
|
||||||
|
@ -25,7 +24,9 @@ type ResponseExtra struct {
|
||||||
Error error
|
Error error
|
||||||
}
|
}
|
||||||
|
|
||||||
type responseCallback func(resp *http.Response, extra *ResponseExtra)
|
type responseCallback struct {
|
||||||
|
Callback func(resp *http.Response, extra *ResponseExtra)
|
||||||
|
}
|
||||||
|
|
||||||
func (re *ResponseExtra) HasError() bool {
|
func (re *ResponseExtra) HasError() bool {
|
||||||
return re.Error != nil
|
return re.Error != nil
|
||||||
|
@ -43,7 +44,7 @@ func (re responseError) Error() string {
|
||||||
return fmt.Sprintf("internal API error response, status=%d, err=%s", re.statusCode, re.errorString)
|
return fmt.Sprintf("internal API error response, status=%d, err=%s", re.statusCode, re.errorString)
|
||||||
}
|
}
|
||||||
|
|
||||||
// requestJSONUserMsg sends a request to the gitea server and then parses the response.
|
// requestJSONResp sends a request to the gitea server and then parses the response.
|
||||||
// If the status code is not 2xx, or any error occurs, the ResponseExtra.Error field is guaranteed to be non-nil,
|
// If the status code is not 2xx, or any error occurs, the ResponseExtra.Error field is guaranteed to be non-nil,
|
||||||
// and the ResponseExtra.UserMsg field will be set to a message for the end user.
|
// and the ResponseExtra.UserMsg field will be set to a message for the end user.
|
||||||
//
|
//
|
||||||
|
@ -89,10 +90,10 @@ func requestJSONResp[T any](req *httplib.Request, res *T) (ret *T, extra Respons
|
||||||
}
|
}
|
||||||
respText.Text = string(bs)
|
respText.Text = string(bs)
|
||||||
return res, extra
|
return res, extra
|
||||||
} else if callback, ok := v.(*responseCallback); ok {
|
} else if cb, ok := v.(*responseCallback); ok {
|
||||||
// pass the response to callback, and let the callback update the ResponseExtra
|
// pass the response to callback, and let the callback update the ResponseExtra
|
||||||
extra.StatusCode = resp.StatusCode
|
extra.StatusCode = resp.StatusCode
|
||||||
(*callback)(resp, &extra)
|
cb.Callback(resp, &extra)
|
||||||
return nil, extra
|
return nil, extra
|
||||||
} else if err := json.NewDecoder(resp.Body).Decode(res); err != nil {
|
} else if err := json.NewDecoder(resp.Body).Decode(res); err != nil {
|
||||||
// decode the response into the given struct
|
// decode the response into the given struct
|
||||||
|
@ -114,22 +115,13 @@ func requestJSONResp[T any](req *httplib.Request, res *T) (ret *T, extra Respons
|
||||||
return res, extra
|
return res, extra
|
||||||
}
|
}
|
||||||
|
|
||||||
// requestJSONUserMsg sends a request to the gitea server and then parses the response as private.Response
|
// requestJSONClientMsg sends a request to the gitea server, server only responds text message status=200 with "success" body
|
||||||
// If the request succeeds, the successMsg will be used as part of ResponseExtra.UserMsg.
|
// If the request succeeds (200), the argument clientSuccessMsg will be used as ResponseExtra.UserMsg.
|
||||||
func requestJSONUserMsg(req *httplib.Request, successMsg string) ResponseExtra {
|
func requestJSONClientMsg(req *httplib.Request, clientSuccessMsg string) ResponseExtra {
|
||||||
resp, extra := requestJSONResp(req, &Response{})
|
_, extra := requestJSONResp(req, &responseText{})
|
||||||
if extra.HasError() {
|
if extra.HasError() {
|
||||||
return extra
|
return extra
|
||||||
}
|
}
|
||||||
if resp.UserMsg == "" {
|
extra.UserMsg = clientSuccessMsg
|
||||||
extra.UserMsg = successMsg // if UserMsg is empty, then use successMsg as userMsg
|
|
||||||
} else if successMsg != "" {
|
|
||||||
// else, now UserMsg is not empty, if successMsg is not empty, then append successMsg to UserMsg
|
|
||||||
if unicode.IsPunct(rune(extra.UserMsg[len(extra.UserMsg)-1])) {
|
|
||||||
extra.UserMsg = extra.UserMsg + " " + successMsg
|
|
||||||
} else {
|
|
||||||
extra.UserMsg = extra.UserMsg + ". " + successMsg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return extra
|
return extra
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,5 +32,5 @@ func RestoreRepo(ctx context.Context, repoDir, ownerName, repoName string, units
|
||||||
Validation: validation,
|
Validation: validation,
|
||||||
})
|
})
|
||||||
req.SetTimeout(3*time.Second, 0) // since the request will spend much time, don't timeout
|
req.SetTimeout(3*time.Second, 0) // since the request will spend much time, don't timeout
|
||||||
return requestJSONUserMsg(req, fmt.Sprintf("Restore repo %s/%s successfully", ownerName, repoName))
|
return requestJSONClientMsg(req, fmt.Sprintf("Restore repo %s/%s successfully", ownerName, repoName))
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,6 @@ func RestoreRepo(ctx *myCtx.PrivateContext) {
|
||||||
Err: err.Error(),
|
Err: err.Error(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
ctx.Status(http.StatusOK)
|
ctx.PlainText(http.StatusOK, "success")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue