mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Fix regression: access log template, gitea manager cli command (#24838)
Close #24836  
This commit is contained in:
		@@ -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")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user