mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00: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
	 wxiaoguang
					wxiaoguang