@@ -18,13 +18,14 @@ import (
1818 "code.gitea.io/gitea/modules/web/middleware"
1919)
2020
21- type routerLoggerOptions struct {
22- req * http.Request
21+ type accessLoggerTmplData struct {
2322 Identity * string
2423 Start * time.Time
25- ResponseWriter http.ResponseWriter
26- Ctx map [string ]any
27- RequestID * string
24+ ResponseWriter struct {
25+ Status , Size int
26+ }
27+ Ctx map [string ]any
28+ RequestID * string
2829}
2930
3031const keyOfRequestIDInTemplate = ".RequestID"
@@ -51,51 +52,65 @@ func parseRequestIDFromRequestHeader(req *http.Request) string {
5152 return requestID
5253}
5354
55+ type accessLogRecorder struct {
56+ logger log.BaseLogger
57+ logTemplate * template.Template
58+ needRequestID bool
59+ }
60+
61+ func (lr * accessLogRecorder ) record (start time.Time , respWriter ResponseWriter , req * http.Request ) {
62+ var requestID string
63+ if lr .needRequestID {
64+ requestID = parseRequestIDFromRequestHeader (req )
65+ }
66+
67+ reqHost , _ , err := net .SplitHostPort (req .RemoteAddr )
68+ if err != nil {
69+ reqHost = req .RemoteAddr
70+ }
71+
72+ identity := "-"
73+ data := middleware .GetContextData (req .Context ())
74+ if signedUser , ok := data [middleware .ContextDataKeySignedUser ].(* user_model.User ); ok {
75+ identity = signedUser .Name
76+ }
77+ buf := bytes .NewBuffer ([]byte {})
78+ tmplData := accessLoggerTmplData {
79+ Identity : & identity ,
80+ Start : & start ,
81+ Ctx : map [string ]any {
82+ "RemoteAddr" : req .RemoteAddr ,
83+ "RemoteHost" : reqHost ,
84+ "Req" : req ,
85+ },
86+ RequestID : & requestID ,
87+ }
88+ tmplData .ResponseWriter .Status = respWriter .Status ()
89+ tmplData .ResponseWriter .Size = respWriter .WrittenSize ()
90+ err = lr .logTemplate .Execute (buf , tmplData )
91+ if err != nil {
92+ log .Error ("Could not execute access logger template: %v" , err .Error ())
93+ }
94+
95+ lr .logger .Log (1 , log .INFO , "%s" , buf .String ())
96+ }
97+
98+ func newAccessLogRecorder () * accessLogRecorder {
99+ return & accessLogRecorder {
100+ logger : log .GetLogger ("access" ),
101+ logTemplate : template .Must (template .New ("log" ).Parse (setting .Log .AccessLogTemplate )),
102+ needRequestID : len (setting .Log .RequestIDHeaders ) > 0 && strings .Contains (setting .Log .AccessLogTemplate , keyOfRequestIDInTemplate ),
103+ }
104+ }
105+
54106// AccessLogger returns a middleware to log access logger
55107func AccessLogger () func (http.Handler ) http.Handler {
56- logger := log .GetLogger ("access" )
57- needRequestID := len (setting .Log .RequestIDHeaders ) > 0 && strings .Contains (setting .Log .AccessLogTemplate , keyOfRequestIDInTemplate )
58- logTemplate , _ := template .New ("log" ).Parse (setting .Log .AccessLogTemplate )
108+ recorder := newAccessLogRecorder ()
59109 return func (next http.Handler ) http.Handler {
60110 return http .HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
61111 start := time .Now ()
62-
63- var requestID string
64- if needRequestID {
65- requestID = parseRequestIDFromRequestHeader (req )
66- }
67-
68- reqHost , _ , err := net .SplitHostPort (req .RemoteAddr )
69- if err != nil {
70- reqHost = req .RemoteAddr
71- }
72-
73112 next .ServeHTTP (w , req )
74- rw := w .(ResponseWriter )
75-
76- identity := "-"
77- data := middleware .GetContextData (req .Context ())
78- if signedUser , ok := data [middleware .ContextDataKeySignedUser ].(* user_model.User ); ok {
79- identity = signedUser .Name
80- }
81- buf := bytes .NewBuffer ([]byte {})
82- err = logTemplate .Execute (buf , routerLoggerOptions {
83- req : req ,
84- Identity : & identity ,
85- Start : & start ,
86- ResponseWriter : rw ,
87- Ctx : map [string ]any {
88- "RemoteAddr" : req .RemoteAddr ,
89- "RemoteHost" : reqHost ,
90- "Req" : req ,
91- },
92- RequestID : & requestID ,
93- })
94- if err != nil {
95- log .Error ("Could not execute access logger template: %v" , err .Error ())
96- }
97-
98- logger .Info ("%s" , buf .String ())
113+ recorder .record (start , w .(ResponseWriter ), req )
99114 })
100115 }
101116}
0 commit comments