Skip to content

Commit 215374c

Browse files
committed
Fix access log
1 parent b2c20b6 commit 215374c

File tree

9 files changed

+125
-69
lines changed

9 files changed

+125
-69
lines changed

modules/auth/sso/oauth2.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"code.gitea.io/gitea/models"
1414
"code.gitea.io/gitea/modules/log"
15+
"code.gitea.io/gitea/modules/middlewares"
1516
"code.gitea.io/gitea/modules/timeutil"
1617
)
1718

@@ -121,7 +122,7 @@ func (o *OAuth2) VerifyAuthData(req *http.Request, w http.ResponseWriter, store
121122
return nil
122123
}
123124

124-
if isInternalPath(req) || !isAPIPath(req) && !isAttachmentDownload(req) {
125+
if middlewares.IsInternalPath(req) || !middlewares.IsAPIPath(req) && !isAttachmentDownload(req) {
125126
return nil
126127
}
127128

modules/auth/sso/sso.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,6 @@ func SessionUser(sess SessionStore) *models.User {
9494
return user
9595
}
9696

97-
// isAPIPath returns true if the specified URL is an API path
98-
func isAPIPath(req *http.Request) bool {
99-
return strings.HasPrefix(req.URL.Path, "/api/")
100-
}
101-
102-
// isInternalPath returns true if the specified URL is an internal API path
103-
func isInternalPath(req *http.Request) bool {
104-
return strings.HasPrefix(req.URL.Path, "/api/internal/")
105-
}
106-
10797
// isAttachmentDownload check if request is a file download (GET) with URL to an attachment
10898
func isAttachmentDownload(req *http.Request) bool {
10999
return strings.HasPrefix(req.URL.Path, "/attachments/") && req.Method == "GET"

modules/context/access_log.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright 2020 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package context
6+
7+
import (
8+
"bytes"
9+
"html/template"
10+
"net/http"
11+
"time"
12+
13+
"code.gitea.io/gitea/modules/log"
14+
"code.gitea.io/gitea/modules/setting"
15+
)
16+
17+
type routerLoggerOptions struct {
18+
req *http.Request
19+
Identity *string
20+
Start *time.Time
21+
ResponseWriter http.ResponseWriter
22+
Ctx map[string]interface{}
23+
}
24+
25+
// AccessLogger returns a middleware to log access logger
26+
func AccessLogger() func(http.Handler) http.Handler {
27+
logger := log.GetLogger("access")
28+
logTemplate, _ := template.New("log").Parse(setting.AccessLogTemplate)
29+
return func(next http.Handler) http.Handler {
30+
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
31+
start := time.Now()
32+
next.ServeHTTP(w, req)
33+
identity := "-"
34+
if val := SignedUserName(req); val != "" {
35+
identity = val
36+
}
37+
rw := w.(ResponseWriter)
38+
39+
buf := bytes.NewBuffer([]byte{})
40+
err := logTemplate.Execute(buf, routerLoggerOptions{
41+
req: req,
42+
Identity: &identity,
43+
Start: &start,
44+
ResponseWriter: rw,
45+
Ctx: map[string]interface{}{
46+
"RemoteAddr": req.RemoteAddr,
47+
"Req": req,
48+
},
49+
})
50+
if err != nil {
51+
log.Error("Could not set up chi access logger: %v", err.Error())
52+
}
53+
54+
err = logger.SendLog(log.INFO, "", "", 0, buf.String(), "")
55+
if err != nil {
56+
log.Error("Could not set up chi access logger: %v", err.Error())
57+
}
58+
})
59+
}
60+
}

modules/context/context.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,31 @@ func GetContext(req *http.Request) *Context {
484484
return req.Context().Value(contextKey).(*Context)
485485
}
486486

487+
// SignedUserName returns signed user's name via context
488+
func SignedUserName(req *http.Request) string {
489+
if middlewares.IsInternalPath(req) {
490+
return ""
491+
}
492+
if middlewares.IsAPIPath(req) {
493+
ctx, ok := req.Context().Value(apiContextKey).(*APIContext)
494+
if ok {
495+
v := ctx.Data["SignedUserName"]
496+
if res, ok := v.(string); ok {
497+
return res
498+
}
499+
}
500+
} else {
501+
ctx, ok := req.Context().Value(contextKey).(*Context)
502+
if ok {
503+
v := ctx.Data["SignedUserName"]
504+
if res, ok := v.(string); ok {
505+
return res
506+
}
507+
}
508+
}
509+
return ""
510+
}
511+
487512
func getCsrfOpts() CsrfOptions {
488513
return CsrfOptions{
489514
Secret: setting.SecretKey,

modules/context/response.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type ResponseWriter interface {
1212
Flush()
1313
Status() int
1414
Before(func(ResponseWriter))
15+
Size() int
1516
}
1617

1718
var (
@@ -21,11 +22,17 @@ var (
2122
// Response represents a response
2223
type Response struct {
2324
http.ResponseWriter
25+
written int
2426
status int
2527
befores []func(ResponseWriter)
2628
beforeExecuted bool
2729
}
2830

31+
// Size return written size
32+
func (r *Response) Size() int {
33+
return r.written
34+
}
35+
2936
// Write writes bytes to HTTP endpoint
3037
func (r *Response) Write(bs []byte) (int, error) {
3138
if !r.beforeExecuted {
@@ -35,8 +42,9 @@ func (r *Response) Write(bs []byte) (int, error) {
3542
r.beforeExecuted = true
3643
}
3744
size, err := r.ResponseWriter.Write(bs)
45+
r.written += size
3846
if err != nil {
39-
return 0, err
47+
return size, err
4048
}
4149
if r.status == 0 {
4250
r.WriteHeader(200)

modules/middlewares/request.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2020 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package middlewares
6+
7+
import (
8+
"net/http"
9+
"strings"
10+
)
11+
12+
// IsAPIPath returns true if the specified URL is an API path
13+
func IsAPIPath(req *http.Request) bool {
14+
return strings.HasPrefix(req.URL.Path, "/api/")
15+
}
16+
17+
// IsInternalPath returns true if the specified URL is an internal API path
18+
func IsInternalPath(req *http.Request) bool {
19+
return strings.HasPrefix(req.URL.Path, "/api/internal/")
20+
}

routers/api/v1/api.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,11 @@ func Routes() *web.Route {
553553
}))
554554
}
555555
m.Use(context.APIContexter())
556+
557+
if setting.EnableAccessLog {
558+
m.Use(context.AccessLogger())
559+
}
560+
556561
m.Use(context.ToggleAPI(&context.ToggleOptions{
557562
SignInRequired: setting.Service.RequireSignInView,
558563
}))

routers/routes/base.go

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,13 @@
55
package routes
66

77
import (
8-
"bytes"
98
"errors"
109
"fmt"
1110
"io"
1211
"net/http"
1312
"os"
1413
"path"
1514
"strings"
16-
"text/template"
1715
"time"
1816

1917
"code.gitea.io/gitea/modules/auth/sso"
@@ -28,57 +26,6 @@ import (
2826
"gitea.com/go-chi/session"
2927
)
3028

31-
type routerLoggerOptions struct {
32-
req *http.Request
33-
Identity *string
34-
Start *time.Time
35-
ResponseWriter http.ResponseWriter
36-
}
37-
38-
// SignedUserName returns signed user's name via context
39-
func SignedUserName(req *http.Request) string {
40-
ctx := context.GetContext(req)
41-
if ctx != nil {
42-
v := ctx.Data["SignedUserName"]
43-
if res, ok := v.(string); ok {
44-
return res
45-
}
46-
}
47-
return ""
48-
}
49-
50-
func accessLogger() func(http.Handler) http.Handler {
51-
logger := log.GetLogger("access")
52-
logTemplate, _ := template.New("log").Parse(setting.AccessLogTemplate)
53-
return func(next http.Handler) http.Handler {
54-
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
55-
start := time.Now()
56-
next.ServeHTTP(w, req)
57-
identity := "-"
58-
if val := SignedUserName(req); val != "" {
59-
identity = val
60-
}
61-
rw := w
62-
63-
buf := bytes.NewBuffer([]byte{})
64-
err := logTemplate.Execute(buf, routerLoggerOptions{
65-
req: req,
66-
Identity: &identity,
67-
Start: &start,
68-
ResponseWriter: rw,
69-
})
70-
if err != nil {
71-
log.Error("Could not set up chi access logger: %v", err.Error())
72-
}
73-
74-
err = logger.SendLog(log.INFO, "", "", 0, buf.String(), "")
75-
if err != nil {
76-
log.Error("Could not set up chi access logger: %v", err.Error())
77-
}
78-
})
79-
}
80-
}
81-
8229
// LoggerHandler is a handler that will log the routing to the default gitea log
8330
func LoggerHandler(level log.Level) func(next http.Handler) http.Handler {
8431
return func(next http.Handler) http.Handler {

routers/routes/web.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,6 @@ func commonMiddlewares() []func(http.Handler) http.Handler {
8888
next.ServeHTTP(resp, req)
8989
})
9090
})
91-
92-
if setting.EnableAccessLog {
93-
handlers = append(handlers, accessLogger())
94-
}
9591
return handlers
9692
}
9793

@@ -166,6 +162,10 @@ func WebRoutes() *web.Route {
166162
r.Use(context.Contexter())
167163
// Removed: SetAutoHead allow a get request redirect to head if get method is not exist
168164

165+
if setting.EnableAccessLog {
166+
r.Use(context.AccessLogger())
167+
}
168+
169169
r.Use(user.GetNotificationCount)
170170
r.Use(repo.GetActiveStopwatch)
171171
r.Use(func(ctx *context.Context) {

0 commit comments

Comments
 (0)