Skip to content

Commit a257971

Browse files
committed
move HTTP middleware
Modify logging, based on github.com/gorilla/handlers.
1 parent e405ab8 commit a257971

File tree

5 files changed

+116
-8
lines changed

5 files changed

+116
-8
lines changed

Diff for: service/middleware/clean_multipart.go

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package middleware
2+
3+
import (
4+
"log"
5+
"net/http"
6+
)
7+
8+
func CleanMultipart(next http.Handler) http.Handler {
9+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
10+
next.ServeHTTP(w, r)
11+
12+
if r.MultipartForm == nil {
13+
return
14+
}
15+
if err := r.MultipartForm.RemoveAll(); err != nil {
16+
id, _ := GetRequestID(r)
17+
log.Printf("%s: failed to cleanup multipart/form-data residues: %v", id, err)
18+
}
19+
})
20+
}

Diff for: service/middleware/logging.go

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package middleware
2+
3+
import (
4+
"bytes"
5+
"net"
6+
"net/http"
7+
"os"
8+
"strconv"
9+
)
10+
11+
type responseLogger struct {
12+
status, n int
13+
http.ResponseWriter
14+
}
15+
16+
func (l *responseLogger) Write(b []byte) (n int, err error) {
17+
n, err = l.ResponseWriter.Write(b)
18+
l.n += n
19+
return
20+
}
21+
22+
func (l *responseLogger) WriteHeader(status int) {
23+
l.ResponseWriter.WriteHeader(status)
24+
l.status = status
25+
}
26+
27+
// Logging performs request logging. This method takes heavy inspiration
28+
// from (github.com/gorilla/handlers).CombinedLoggingHandler.
29+
func Logging(next http.Handler) http.Handler {
30+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
31+
rl := &responseLogger{ResponseWriter: w}
32+
url := *r.URL
33+
34+
next.ServeHTTP(rl, r)
35+
36+
username := "-"
37+
if url.User != nil {
38+
if name := url.User.Username(); name != "" {
39+
username = name
40+
}
41+
}
42+
43+
host, _, err := net.SplitHostPort(r.RemoteAddr)
44+
if err != nil {
45+
host = r.RemoteAddr
46+
}
47+
48+
uri := r.RequestURI
49+
50+
// Requests using the CONNECT method over HTTP/2.0 must use
51+
// the authority field (aka r.Host) to identify the target.
52+
// Refer: https://httpwg.github.io/specs/rfc7540.html#CONNECT
53+
if r.ProtoMajor == 2 && r.Method == "CONNECT" {
54+
uri = r.Host
55+
}
56+
if uri == "" {
57+
uri = url.RequestURI()
58+
}
59+
60+
id, haveID := GetRequestID(r)
61+
62+
var buf bytes.Buffer
63+
buf.Grow(len(id) + len(r.Method) + len(host) + len(username) + len(uri) + 50) // reduce allocs
64+
if haveID {
65+
buf.WriteString(id)
66+
buf.WriteString(": ")
67+
}
68+
buf.WriteString(host)
69+
buf.WriteString(" - ")
70+
buf.WriteString(username)
71+
buf.WriteString(" - ")
72+
buf.WriteString(r.Method)
73+
buf.WriteByte(' ')
74+
buf.WriteString(uri)
75+
buf.WriteString(" - ")
76+
buf.WriteString(strconv.Itoa(rl.status))
77+
buf.WriteByte(' ')
78+
buf.WriteString(strconv.Itoa(rl.n))
79+
buf.WriteByte('\n')
80+
_, _ = buf.WriteTo(os.Stderr)
81+
})
82+
}

Diff for: requestid/requestid.go renamed to service/middleware/requestid.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package requestid
1+
package middleware
22

33
import (
44
"context"
@@ -13,7 +13,7 @@ type contextKey string
1313

1414
const ContextKey = contextKey("request-id")
1515

16-
func Middleware(next http.Handler) http.Handler {
16+
func RequestID(next http.Handler) http.Handler {
1717
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1818
id := uuid.Must(uuid.NewRandom()).String()
1919
r = r.WithContext(context.WithValue(r.Context(), ContextKey, id))
@@ -22,3 +22,8 @@ func Middleware(next http.Handler) http.Handler {
2222
next.ServeHTTP(w, r)
2323
})
2424
}
25+
26+
func GetRequestID(r *http.Request) (string, bool) {
27+
id, ok := r.Context().Value(ContextKey).(string)
28+
return id, ok
29+
}

Diff for: requestid/requestid_test.go renamed to service/middleware/requestid_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package requestid
1+
package middleware
22

33
import (
44
"net/http"
@@ -26,7 +26,7 @@ func TestMiddleware(t *testing.T) {
2626
}
2727

2828
w := httptest.NewRecorder()
29-
Middleware(http.HandlerFunc(captureContextID)).ServeHTTP(w,
29+
RequestID(http.HandlerFunc(captureContextID)).ServeHTTP(w,
3030
httptest.NewRequest(http.MethodGet, "/", nil))
3131
assert.Equal(t, http.StatusOK, w.Code)
3232

Diff for: service/service.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@ import (
66
"fmt"
77
"log"
88
"net/http"
9-
"os"
109
"time"
1110

1211
"github.com/digineo/texd/exec"
13-
"github.com/digineo/texd/requestid"
12+
"github.com/digineo/texd/service/middleware"
1413
"github.com/digineo/texd/tex"
1514
"github.com/gorilla/handlers"
1615
"github.com/gorilla/mux"
@@ -62,12 +61,14 @@ func Start(opts Options) func(context.Context) error {
6261
r.HandleFunc("/metrics", svc.HandleMetrics).Methods(http.MethodGet)
6362

6463
// r.Use(handlers.RecoveryHandler())
65-
r.Use(requestid.Middleware)
64+
r.Use(middleware.RequestID)
6665
r.Use(handlers.CompressHandler)
66+
r.Use(middleware.Logging)
67+
r.Use(middleware.CleanMultipart)
6768

6869
srv := http.Server{
6970
Addr: opts.Addr,
70-
Handler: handlers.CombinedLoggingHandler(os.Stdout, r),
71+
Handler: r,
7172
}
7273

7374
go func() {

0 commit comments

Comments
 (0)