Skip to content

Commit 37c3e67

Browse files
committed
Make AccessLogApacheMiddleware work with incomplete middleware stack.
This makes AccessLogApacheMiddleware work even if Timer and Recorder are missing. In that case, there is not much to log, but it should not fail. Note, AccessLogJsonMiddleware already behaves that way.
1 parent 68230c8 commit 37c3e67

File tree

2 files changed

+52
-7
lines changed

2 files changed

+52
-7
lines changed

Diff for: rest/access_log_apache.go

+19-7
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const (
5151
)
5252

5353
// AccessLogApacheMiddleware produces the access log following a format inspired by Apache
54-
// mod_log_config. It depends on TimerMiddleware and RecorderMiddleware that must be in the wrapped
54+
// mod_log_config. It depends on TimerMiddleware and RecorderMiddleware that should be in the wrapped
5555
// middlewares. It also uses request.Env["REMOTE_USER"].(string) set by the auth middlewares.
5656
type AccessLogApacheMiddleware struct {
5757

@@ -105,8 +105,8 @@ var apacheAdapter = strings.NewReplacer(
105105
"%r", "{{.R.Method}} {{.R.URL.RequestURI}} {{.R.Proto}}",
106106
"%s", "{{.StatusCode}}",
107107
"%S", "\033[{{.StatusCode | statusCodeColor}}m{{.StatusCode}}",
108-
"%t", "{{.StartTime.Format \"02/Jan/2006:15:04:05 -0700\"}}",
109-
"%T", "{{.ResponseTime.Seconds | printf \"%.3f\"}}",
108+
"%t", "{{if .StartTime}}{{.StartTime.Format \"02/Jan/2006:15:04:05 -0700\"}}{{end}}",
109+
"%T", "{{if .ResponseTime}}{{.ResponseTime.Seconds | printf \"%.3f\"}}{{end}}",
110110
"%u", "{{.RemoteUser | dashIfEmptyStr}}",
111111
"%{User-Agent}i", "{{.R.UserAgent | dashIfEmptyStr}}",
112112
"%{Referer}i", "{{.R.Referer | dashIfEmptyStr}}",
@@ -185,7 +185,10 @@ func (u *accessLogUtil) ApacheQueryString() string {
185185

186186
// When the request entered the timer middleware.
187187
func (u *accessLogUtil) StartTime() *time.Time {
188-
return u.R.Env["START_TIME"].(*time.Time)
188+
if u.R.Env["START_TIME"] != nil {
189+
return u.R.Env["START_TIME"].(*time.Time)
190+
}
191+
return nil
189192
}
190193

191194
// If remoteAddr is set then return is without the port number, apache log style.
@@ -200,12 +203,18 @@ func (u *accessLogUtil) ApacheRemoteAddr() string {
200203

201204
// As recorded by the recorder middleware.
202205
func (u *accessLogUtil) StatusCode() int {
203-
return u.R.Env["STATUS_CODE"].(int)
206+
if u.R.Env["STATUS_CODE"] != nil {
207+
return u.R.Env["STATUS_CODE"].(int)
208+
}
209+
return 0
204210
}
205211

206212
// As mesured by the timer middleware.
207213
func (u *accessLogUtil) ResponseTime() *time.Duration {
208-
return u.R.Env["ELAPSED_TIME"].(*time.Duration)
214+
if u.R.Env["ELAPSED_TIME"] != nil {
215+
return u.R.Env["ELAPSED_TIME"].(*time.Duration)
216+
}
217+
return nil
209218
}
210219

211220
// Process id.
@@ -215,5 +224,8 @@ func (u *accessLogUtil) Pid() int {
215224

216225
// As recorded by the recorder middleware.
217226
func (u *accessLogUtil) BytesWritten() int64 {
218-
return u.R.Env["BYTES_WRITTEN"].(int64)
227+
if u.R.Env["BYTES_WRITTEN"] != nil {
228+
return u.R.Env["BYTES_WRITTEN"].(int64)
229+
}
230+
return 0
219231
}

Diff for: rest/access_log_apache_test.go

+33
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,36 @@ func TestAccessLogApacheMiddleware(t *testing.T) {
4343
t.Errorf("Got: %s", buffer.String())
4444
}
4545
}
46+
47+
func TestAccessLogApacheMiddlewareMissingData(t *testing.T) {
48+
49+
api := NewApi()
50+
51+
// the uncomplete middlewares stack
52+
buffer := bytes.NewBufferString("")
53+
api.Use(&AccessLogApacheMiddleware{
54+
Logger: log.New(buffer, "", 0),
55+
Format: CommonLogFormat,
56+
textTemplate: nil,
57+
})
58+
59+
// a simple app
60+
api.SetApp(AppSimple(func(w ResponseWriter, r *Request) {
61+
w.WriteJson(map[string]string{"Id": "123"})
62+
}))
63+
64+
// wrap all
65+
handler := api.MakeHandler()
66+
67+
req := test.MakeSimpleRequest("GET", "http://localhost/", nil)
68+
recorded := test.RunRequest(t, handler, req)
69+
recorded.CodeIs(200)
70+
recorded.ContentTypeIsJson()
71+
72+
// not much to log when the Env data is missing, but this should still work
73+
apacheCommon := regexp.MustCompile(` - - "GET / HTTP/1.1" 0 -`)
74+
75+
if !apacheCommon.Match(buffer.Bytes()) {
76+
t.Errorf("Got: %s", buffer.String())
77+
}
78+
}

0 commit comments

Comments
 (0)