Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0973dfd

Browse files
committed
FEATURE: support Hijacker, CloseNotifier, Flusher; export Size() and Written()
Add support and tests for http's Hijacker, CloseNotifier, and Flusher interfaces in the ResponseWriter.Also, export some more methods on ResponseWriter: Size() and Written() which return how many bytes were written and whether the header was written yet.
1 parent889502e commit0973dfd

File tree

3 files changed

+155
-9
lines changed

3 files changed

+155
-9
lines changed

‎TODO

Lines changed: 0 additions & 4 deletions
This file was deleted.

‎response_writer.go

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,76 @@
11
package web
22

33
import (
4+
"bufio"
5+
"fmt"
6+
"net"
47
"net/http"
58
)
69

710
// ResponseWriter includes net/http's ResponseWriter and adds a StatusCode() method to obtain the written status code.
811
// A ResponseWriter is sent to handlers on each request.
912
typeResponseWriterinterface {
1013
http.ResponseWriter
14+
http.Flusher
15+
http.Hijacker
16+
http.CloseNotifier
1117

1218
// StatusCode returns the written status code, or 0 if none has been written yet.
1319
StatusCode()int
20+
// Written returns whether the header has been written yet.
21+
Written()bool
22+
// Size returns the size in bytes of the body written so far.
23+
Size()int
1424
}
1525

1626
typeappResponseWriterstruct {
1727
http.ResponseWriter
1828
statusCodeint
19-
writtenbool
29+
sizeint
2030
}
2131

2232
// Don't need this yet because we get it for free:
2333
func (w*appResponseWriter)Write(data []byte) (nint,errerror) {
24-
if!w.written {
34+
ifw.statusCode==0 {
2535
w.statusCode=http.StatusOK
26-
w.written=true
2736
}
28-
returnw.ResponseWriter.Write(data)
37+
size,err:=w.ResponseWriter.Write(data)
38+
w.size+=size
39+
returnsize,err
2940
}
3041

3142
func (w*appResponseWriter)WriteHeader(statusCodeint) {
3243
w.statusCode=statusCode
33-
w.written=true
3444
w.ResponseWriter.WriteHeader(statusCode)
3545
}
3646

3747
func (w*appResponseWriter)StatusCode()int {
3848
returnw.statusCode
3949
}
50+
51+
func (w*appResponseWriter)Written()bool {
52+
returnw.statusCode!=0
53+
}
54+
55+
func (w*appResponseWriter)Size()int {
56+
returnw.size
57+
}
58+
59+
func (w*appResponseWriter)Hijack() (net.Conn,*bufio.ReadWriter,error) {
60+
hijacker,ok:=w.ResponseWriter.(http.Hijacker)
61+
if!ok {
62+
returnnil,nil,fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
63+
}
64+
returnhijacker.Hijack()
65+
}
66+
67+
func (w*appResponseWriter)CloseNotify()<-chanbool {
68+
returnw.ResponseWriter.(http.CloseNotifier).CloseNotify()
69+
}
70+
71+
func (w*appResponseWriter)Flush() {
72+
flusher,ok:=w.ResponseWriter.(http.Flusher)
73+
ifok {
74+
flusher.Flush()
75+
}
76+
}

‎response_writer_test.go

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package web
2+
3+
import (
4+
"bufio"
5+
"github.com/stretchr/testify/assert"
6+
"net"
7+
"net/http"
8+
"net/http/httptest"
9+
"testing"
10+
"time"
11+
)
12+
13+
typehijackableResponsestruct {
14+
Hijackedbool
15+
}
16+
17+
func (h*hijackableResponse)Header() http.Header {
18+
returnnil
19+
}
20+
func (h*hijackableResponse)Write(buf []byte) (int,error) {
21+
return0,nil
22+
}
23+
func (h*hijackableResponse)WriteHeader(codeint) {
24+
// no-op
25+
}
26+
func (h*hijackableResponse)Flush() {
27+
// no-op
28+
}
29+
func (h*hijackableResponse)Hijack() (net.Conn,*bufio.ReadWriter,error) {
30+
h.Hijacked=true
31+
returnnil,nil,nil
32+
}
33+
func (h*hijackableResponse)CloseNotify()<-chanbool {
34+
returnnil
35+
}
36+
37+
typecloseNotifyingRecorderstruct {
38+
*httptest.ResponseRecorder
39+
closedchanbool
40+
}
41+
42+
func (c*closeNotifyingRecorder)close() {
43+
c.closed<-true
44+
}
45+
46+
func (c*closeNotifyingRecorder)CloseNotify()<-chanbool {
47+
returnc.closed
48+
}
49+
50+
funcTestResponseWriterWrite(t*testing.T) {
51+
rec:=httptest.NewRecorder()
52+
rw:=ResponseWriter(&appResponseWriter{ResponseWriter:rec})
53+
54+
assert.Equal(t,rw.Written(),false)
55+
56+
n,err:=rw.Write([]byte("Hello world"))
57+
assert.Equal(t,n,11)
58+
assert.NoError(t,err)
59+
60+
assert.Equal(t,n,11)
61+
assert.Equal(t,rec.Code,rw.StatusCode())
62+
assert.Equal(t,rec.Code,http.StatusOK)
63+
assert.Equal(t,rec.Body.String(),"Hello world")
64+
assert.Equal(t,rw.Size(),11)
65+
assert.Equal(t,rw.Written(),true)
66+
}
67+
68+
funcTestResponseWriterWriteHeader(t*testing.T) {
69+
rec:=httptest.NewRecorder()
70+
rw:=ResponseWriter(&appResponseWriter{ResponseWriter:rec})
71+
72+
rw.WriteHeader(http.StatusNotFound)
73+
assert.Equal(t,rec.Code,rw.StatusCode())
74+
assert.Equal(t,rec.Code,http.StatusNotFound)
75+
}
76+
77+
funcTestResponseWriterHijack(t*testing.T) {
78+
hijackable:=&hijackableResponse{}
79+
rw:=ResponseWriter(&appResponseWriter{ResponseWriter:hijackable})
80+
hijacker,ok:=rw.(http.Hijacker)
81+
assert.True(t,ok)
82+
_,_,err:=hijacker.Hijack()
83+
assert.NoError(t,err)
84+
assert.True(t,hijackable.Hijacked)
85+
}
86+
87+
funcTestResponseWriterHijackNotOK(t*testing.T) {
88+
rw:=ResponseWriter(&appResponseWriter{ResponseWriter:httptest.NewRecorder()})
89+
_,_,err:=rw.Hijack()
90+
assert.Error(t,err)
91+
}
92+
93+
funcTestResponseWriterFlush(t*testing.T) {
94+
rw:=ResponseWriter(&appResponseWriter{ResponseWriter:httptest.NewRecorder()})
95+
rw.Flush()
96+
}
97+
98+
funcTestResponseWriterCloseNotify(t*testing.T) {
99+
rec:=&closeNotifyingRecorder{
100+
httptest.NewRecorder(),
101+
make(chanbool,1),
102+
}
103+
rw:=ResponseWriter(&appResponseWriter{ResponseWriter:rec})
104+
closed:=false
105+
notifier:=rw.(http.CloseNotifier).CloseNotify()
106+
rec.close()
107+
select {
108+
case<-notifier:
109+
closed=true
110+
case<-time.After(time.Second):
111+
}
112+
assert.True(t,closed)
113+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp