Skip to content

Commit 4b58ea1

Browse files
authored
Merge pull request #29 from slok/hijacker-flusher
Internal http.ResponseWriter interceptor now satisifies http.Hijackerand http.Flusher interfaces
2 parents a3a42eb + 118ddbe commit 4b58ea1

File tree

3 files changed

+54
-26
lines changed

3 files changed

+54
-26
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## [Unreleased]
44

5+
### Changed
6+
7+
- Internal response writer interceptor implements `http.Hijacker` and `http.Flusher` interface.
8+
9+
510
## [0.6.0] - 2019-12-11
611

712
### Breaking changes

middleware/middleware.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
package middleware
66

77
import (
8+
"bufio"
9+
"errors"
810
"fmt"
11+
"net"
912
"net/http"
1013
"strconv"
1114
"time"
@@ -148,3 +151,27 @@ func (w *responseWriterInterceptor) Write(p []byte) (int, error) {
148151
w.bytesWritten += len(p)
149152
return w.ResponseWriter.Write(p)
150153
}
154+
155+
func (w *responseWriterInterceptor) Hijack() (net.Conn, *bufio.ReadWriter, error) {
156+
h, ok := w.ResponseWriter.(http.Hijacker)
157+
if !ok {
158+
return nil, nil, errors.New("type assertion failed http.ResponseWriter not a http.Hijacker")
159+
}
160+
return h.Hijack()
161+
}
162+
163+
func (w *responseWriterInterceptor) Flush() {
164+
f, ok := w.ResponseWriter.(http.Flusher)
165+
if !ok {
166+
return
167+
}
168+
169+
f.Flush()
170+
}
171+
172+
// Check interface implementations.
173+
var (
174+
_ http.ResponseWriter = &responseWriterInterceptor{}
175+
_ http.Hijacker = &responseWriterInterceptor{}
176+
_ http.Flusher = &responseWriterInterceptor{}
177+
)

middleware/middleware_test.go

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ func getFakeHandler(statusCode int, responseBody string) http.Handler {
1919
}
2020

2121
func TestMiddlewareHandler(t *testing.T) {
22-
tests := []struct {
23-
name string
22+
tests := map[string]struct {
2423
handlerID string
2524
body string
2625
statusCode int
@@ -32,8 +31,7 @@ func TestMiddlewareHandler(t *testing.T) {
3231
expSize int64
3332
expStatusCode string
3433
}{
35-
{
36-
name: "A default HTTP middleware should call the recorder to measure.",
34+
"A default HTTP middleware should call the recorder to measure.": {
3735
statusCode: http.StatusAccepted,
3836
body: "Я бэтмен",
3937
req: httptest.NewRequest(http.MethodGet, "/test", nil),
@@ -43,8 +41,8 @@ func TestMiddlewareHandler(t *testing.T) {
4341
expMethod: http.MethodGet,
4442
expStatusCode: "202",
4543
},
46-
{
47-
name: "Using custom ID in the middleware should call the recorder to measure with that ID.",
44+
45+
"Using custom ID in the middleware should call the recorder to measure with that ID.": {
4846
handlerID: "customID",
4947
body: "I'm Batman",
5048
statusCode: http.StatusTeapot,
@@ -55,8 +53,8 @@ func TestMiddlewareHandler(t *testing.T) {
5553
expMethod: http.MethodPost,
5654
expStatusCode: "418",
5755
},
58-
{
59-
name: "Using grouped status code should group the status code.",
56+
57+
"Using grouped status code should group the status code.": {
6058
config: middleware.Config{GroupedStatus: true},
6159
statusCode: http.StatusGatewayTimeout,
6260
req: httptest.NewRequest(http.MethodPatch, "/test", nil),
@@ -65,8 +63,8 @@ func TestMiddlewareHandler(t *testing.T) {
6563
expMethod: http.MethodPatch,
6664
expStatusCode: "5xx",
6765
},
68-
{
69-
name: "Using the service middleware option should set the service on the metrics.",
66+
67+
"Using the service middleware option should set the service on the metrics.": {
7068
config: middleware.Config{Service: "Yoda"},
7169
statusCode: http.StatusContinue,
7270
body: "May the force be with you",
@@ -79,8 +77,8 @@ func TestMiddlewareHandler(t *testing.T) {
7977
},
8078
}
8179

82-
for _, test := range tests {
83-
t.Run(test.name, func(t *testing.T) {
80+
for name, test := range tests {
81+
t.Run(name, func(t *testing.T) {
8482
// Mocks.
8583
mr := &mmetrics.Recorder{}
8684
expHTTPReqProps := metrics.HTTPReqProperties{
@@ -112,45 +110,43 @@ func TestMiddlewareHandler(t *testing.T) {
112110
func BenchmarkMiddlewareHandler(b *testing.B) {
113111
b.StopTimer()
114112

115-
benchs := []struct {
116-
name string
113+
benchs := map[string]struct {
117114
handlerID string
118115
cfg middleware.Config
119116
}{
120-
{
121-
name: "benchmark with default settings.",
117+
"benchmark with default settings.": {
122118
handlerID: "",
123119
cfg: middleware.Config{},
124120
},
125-
{
126-
name: "benchmark disabling measuring size.",
121+
122+
"benchmark disabling measuring size.": {
127123
handlerID: "",
128124
cfg: middleware.Config{
129125
DisableMeasureSize: true,
130126
},
131127
},
132-
{
133-
name: "benchmark disabling inflights.",
128+
129+
"benchmark disabling inflights.": {
134130
handlerID: "",
135131
cfg: middleware.Config{
136132
DisableMeasureInflight: true,
137133
},
138134
},
139-
{
140-
name: "benchmark with grouped status code.",
135+
136+
"benchmark with grouped status code.": {
141137
cfg: middleware.Config{
142138
GroupedStatus: true,
143139
},
144140
},
145-
{
146-
name: "benchmark with predefined handler ID",
141+
142+
"benchmark with predefined handler ID": {
147143
handlerID: "benchmark1",
148144
cfg: middleware.Config{},
149145
},
150146
}
151147

152-
for _, bench := range benchs {
153-
b.Run(bench.name, func(b *testing.B) {
148+
for name, bench := range benchs {
149+
b.Run(name, func(b *testing.B) {
154150
// Prepare.
155151
bench.cfg.Recorder = metrics.Dummy
156152
m := middleware.New(bench.cfg)

0 commit comments

Comments
 (0)