Skip to content

Commit f19f000

Browse files
committed
Implement with transport cloning option
1 parent ee64d07 commit f19f000

11 files changed

+105
-34
lines changed

README.md

+10-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ isucandar は [ISUCON](http://isucon.net/) などの負荷試験で使える機
2020
// NewAgent の引数には可変長で func(*Agent) error な関数を渡せます。
2121
// その中で Agent の初期設定を完了させてください。
2222
// 簡易につかえるように、いくつかの AgentOption を返す関数が用意されています。
23-
agent, err := NewAgent(WithBaseURL("http://isucon.net"))
23+
agent, err := NewAgent(WithBaseURL("http://isucon.net"), WithDefaultTransport())
2424

2525
// 通常の http.NewRequest のように呼び出せます。
2626
req, err := agent.NewRequest(http.MethodGet, "/", nil)
@@ -52,10 +52,18 @@ resources, err := agent.ProcessHTML(context.TODO(), req, req.Body)
5252
// Agent は CacheStore を持ち、それを利用してブラウザに似せた Conditinal GET や、
5353
// キャッシュを利用して、メモリからレスポンスを復元したりします。
5454
// もし Cache が必要ないようであれば、 WithNoCache() を NewAgent の引数へ渡してください。
55-
agent, _ := NewAgent(WithNoCache())
55+
agent, _ := NewAgent(WithNoCache(), WithDefaultTransport())
5656

5757
// また、なんらかの理由でキャッシュをクリアしたくなった場合は agent.CacheStore.Clear() で削除できます。
5858
agent.CacheStore.Clear()
59+
60+
//// Transport
61+
// Agent は HTTPClient とその Transport を持ちます。
62+
// TCP 接続単位で共有を拒否したい場合は WithCloneTransport(DefaultTransport) などを利用し、
63+
// 接続が共有されても構わない場合は WithDefatultTransport() を利用してください。
64+
agent, _ := NewAgent(WithDefaultTransport())
65+
// or
66+
agent, _ := NewAgent(WithCloneTransport(DefaultTransport));
5967
```
6068

6169
#### 補足

agent/agent.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package agent
33
import (
44
"context"
55
"crypto/tls"
6+
"errors"
67
"io"
78
"net"
89
"net/http"
@@ -26,6 +27,10 @@ var (
2627
DefaultTransport *http.Transport
2728
)
2829

30+
var (
31+
ErrTransportInvalid = errors.New("Specify transport option(WithCloneTransport or WithDefaultTransport)")
32+
)
33+
2934
func init() {
3035
DefaultDialer = &net.Dialer{
3136
Timeout: 0,
@@ -70,7 +75,7 @@ func NewAgent(opts ...AgentOption) (*Agent, error) {
7075
CacheStore: NewCacheStore(),
7176
HttpClient: &http.Client{
7277
CheckRedirect: useLastResponse,
73-
Transport: DefaultTransport,
78+
Transport: nil,
7479
Jar: jar,
7580
Timeout: DefaultRequestTimeout,
7681
},
@@ -82,6 +87,10 @@ func NewAgent(opts ...AgentOption) (*Agent, error) {
8287
}
8388
}
8489

90+
if agent.HttpClient.Transport == nil {
91+
return nil, ErrTransportInvalid
92+
}
93+
8594
return agent, nil
8695
}
8796

agent/agent_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,13 @@ func TestAgent(t *testing.T) {
5858
}
5959

6060
func TestAgentClearCookie(t *testing.T) {
61-
agent, err := NewAgent(WithBaseURL("http://example.com/"))
61+
agent, err := NewAgent(WithBaseURL("http://example.com/"), WithDefaultTransport())
6262
if err != nil {
6363
t.Fatal(err)
6464
}
6565

6666
agent.HttpClient.Jar.SetCookies(agent.BaseURL, []*http.Cookie{
67-
&http.Cookie{},
67+
{},
6868
})
6969
if len(agent.HttpClient.Jar.Cookies(agent.BaseURL)) != 1 {
7070
t.Fatal("Set cookie failed")
@@ -76,7 +76,7 @@ func TestAgentClearCookie(t *testing.T) {
7676
}
7777

7878
func TestAgentNewRequest(t *testing.T) {
79-
agent, err := NewAgent()
79+
agent, err := NewAgent(WithDefaultTransport())
8080
if err != nil {
8181
t.Fatalf("%+v", err)
8282
}
@@ -96,7 +96,7 @@ func TestAgentRequest(t *testing.T) {
9696
srv := newHTTPServer()
9797
defer srv.Close()
9898

99-
agent, err := NewAgent(WithBaseURL(srv.URL))
99+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
100100
if err != nil {
101101
t.Fatalf("%+v", err)
102102
}
@@ -120,7 +120,7 @@ func TestAgentRequest(t *testing.T) {
120120
}
121121

122122
func TestAgentMethods(t *testing.T) {
123-
agent, err := NewAgent()
123+
agent, err := NewAgent(WithDefaultTransport())
124124
if err != nil {
125125
t.Fatalf("%+v", err)
126126
}

agent/cache_test.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func TestCacheCondition(t *testing.T) {
4242
}))
4343
defer srv.Close()
4444

45-
agent, err := NewAgent(WithBaseURL(srv.URL))
45+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
4646
if err != nil {
4747
t.Fatal(err)
4848
}
@@ -96,7 +96,7 @@ func TestCacheWithLastModified(t *testing.T) {
9696
}))
9797
defer srv.Close()
9898

99-
agent, err := NewAgent(WithBaseURL(srv.URL))
99+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
100100
if err != nil {
101101
t.Fatal(err)
102102
}
@@ -165,7 +165,7 @@ func TestCacheWithETag(t *testing.T) {
165165
}))
166166
defer srv.Close()
167167

168-
agent, err := NewAgent(WithBaseURL(srv.URL))
168+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
169169
if err != nil {
170170
t.Fatal(err)
171171
}
@@ -239,7 +239,7 @@ func TestCacheWithMaxAge(t *testing.T) {
239239
}))
240240
defer srv.Close()
241241

242-
agent, err := NewAgent(WithBaseURL(srv.URL))
242+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
243243
if err != nil {
244244
t.Fatal(err)
245245
}
@@ -285,7 +285,7 @@ func TestCacheWithExpires(t *testing.T) {
285285
}))
286286
defer srv.Close()
287287

288-
agent, err := NewAgent(WithBaseURL(srv.URL))
288+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
289289
if err != nil {
290290
t.Fatal(err)
291291
}
@@ -331,7 +331,7 @@ func TestCacheWithVary(t *testing.T) {
331331
}))
332332
defer srv.Close()
333333

334-
agent, err := NewAgent(WithBaseURL(srv.URL))
334+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
335335
if err != nil {
336336
t.Fatal(err)
337337
}
@@ -369,7 +369,7 @@ func TestCacheWithClear(t *testing.T) {
369369
}))
370370
defer srv.Close()
371371

372-
agent, err := NewAgent(WithBaseURL(srv.URL))
372+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
373373
if err != nil {
374374
t.Fatal(err)
375375
}
@@ -393,7 +393,7 @@ func BenchmarkCacheWithMaxAge(b *testing.B) {
393393
}))
394394
defer srv.Close()
395395

396-
agent, err := NewAgent(WithBaseURL(srv.URL))
396+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
397397
if err != nil {
398398
b.Fatal(err)
399399
}

agent/decompress_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ func TestBrotliResponse(t *testing.T) {
9191
srv := newCompressHTTPServer()
9292
defer srv.Close()
9393

94-
agent, err := NewAgent(WithBaseURL(srv.URL))
94+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
9595
if err != nil {
9696
t.Fatalf("%+v", err)
9797
}
@@ -134,7 +134,7 @@ func TestGzipResponse(t *testing.T) {
134134
srv := newCompressHTTPServer()
135135
defer srv.Close()
136136

137-
agent, err := NewAgent(WithBaseURL(srv.URL))
137+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
138138
if err != nil {
139139
t.Fatalf("%+v", err)
140140
}
@@ -178,7 +178,7 @@ func TestDeflateResponse(t *testing.T) {
178178
srv := newCompressHTTPServer()
179179
defer srv.Close()
180180

181-
agent, err := NewAgent(WithBaseURL(srv.URL))
181+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
182182
if err != nil {
183183
t.Fatalf("%+v", err)
184184
}
@@ -228,7 +228,7 @@ func TestWithEcho(t *testing.T) {
228228
srv := httptest.NewServer(e)
229229
defer srv.Close()
230230

231-
agent, err := NewAgent(WithBaseURL(srv.URL))
231+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
232232
if err != nil {
233233
t.Fatalf("%+v", err)
234234
}

agent/html_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func TestHTMLParse(t *testing.T) {
4949
}))
5050
defer srv.Close()
5151

52-
agent, err := NewAgent(WithBaseURL(srv.URL))
52+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
5353
if err != nil {
5454
t.Fatal(err)
5555
}
@@ -65,7 +65,7 @@ func TestHTMLParse(t *testing.T) {
6565
}
6666

6767
if len(resources) != 12 {
68-
for k, _ := range resources {
68+
for k := range resources {
6969
t.Log(k)
7070
}
7171
t.Fatalf("resouces count missmatch: %d", len(resources))
@@ -101,7 +101,7 @@ func BenchmarkHTMLParse(b *testing.B) {
101101
}))
102102
defer srv.Close()
103103

104-
agent, err := NewAgent(WithBaseURL(srv.URL))
104+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
105105
if err != nil {
106106
b.Fatal(err)
107107
}
@@ -118,7 +118,7 @@ func BenchmarkHTMLParse(b *testing.B) {
118118
}
119119

120120
if len(resources) != 12 {
121-
for k, _ := range resources {
121+
for k := range resources {
122122
b.Log(k)
123123
}
124124
b.Fatalf("resouces count missmatch: %d", len(resources))
@@ -163,7 +163,7 @@ func TestFavicon(t *testing.T) {
163163
}))
164164
defer srv.Close()
165165

166-
agent, err := NewAgent(WithBaseURL(srv.URL))
166+
agent, err := NewAgent(WithBaseURL(srv.URL), WithDefaultTransport())
167167
if err != nil {
168168
t.Fatal(err)
169169
}

agent/option.go

+17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package agent
22

33
import (
4+
"net/http"
45
"net/url"
56
"time"
67
)
@@ -40,3 +41,19 @@ func WithTimeout(d time.Duration) AgentOption {
4041
return nil
4142
}
4243
}
44+
45+
func WithDefaultTransport() AgentOption {
46+
return func(a *Agent) error {
47+
a.HttpClient.Transport = DefaultTransport
48+
49+
return nil
50+
}
51+
}
52+
53+
func WithCloneTransport(trs *http.Transport) AgentOption {
54+
return func(a *Agent) error {
55+
a.HttpClient.Transport = trs.Clone()
56+
57+
return nil
58+
}
59+
}

agent/option_test.go

+42-5
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ import (
99
"time"
1010

1111
"github.com/isucon/isucandar/failure"
12+
"github.com/stretchr/testify/assert"
1213
)
1314

1415
func TestNoCookie(t *testing.T) {
15-
agent, err := NewAgent(WithNoCookie())
16+
agent, err := NewAgent(WithNoCookie(), WithDefaultTransport())
1617
if err != nil {
1718
t.Fatal(err)
1819
}
@@ -23,7 +24,7 @@ func TestNoCookie(t *testing.T) {
2324
}
2425

2526
func TestNoCache(t *testing.T) {
26-
agent, err := NewAgent(WithNoCache())
27+
agent, err := NewAgent(WithNoCache(), WithDefaultTransport())
2728
if err != nil {
2829
t.Fatal(err)
2930
}
@@ -34,7 +35,7 @@ func TestNoCache(t *testing.T) {
3435
}
3536

3637
func TestUserAgent(t *testing.T) {
37-
agent, err := NewAgent(WithUserAgent("Hello"))
38+
agent, err := NewAgent(WithUserAgent("Hello"), WithDefaultTransport())
3839
if err != nil {
3940
t.Fatal(err)
4041
}
@@ -45,7 +46,7 @@ func TestUserAgent(t *testing.T) {
4546
}
4647

4748
func TestBaseURL(t *testing.T) {
48-
agent, err := NewAgent(WithBaseURL("http://base.example.com"))
49+
agent, err := NewAgent(WithBaseURL("http://base.example.com"), WithDefaultTransport())
4950
if err != nil {
5051
t.Fatal(err)
5152
}
@@ -67,7 +68,7 @@ func TestTimeout(t *testing.T) {
6768
go srv.Close()
6869
}()
6970

70-
agent, err := NewAgent(WithTimeout(1*time.Microsecond), WithBaseURL(srv.URL))
71+
agent, err := NewAgent(WithTimeout(1*time.Microsecond), WithBaseURL(srv.URL), WithDefaultTransport())
7172
if err != nil {
7273
t.Fatal(err)
7374
}
@@ -78,3 +79,39 @@ func TestTimeout(t *testing.T) {
7879
t.Fatalf("expected timeout error: %+v", err)
7980
}
8081
}
82+
83+
func TestWithoutTransport(t *testing.T) {
84+
_, err := NewAgent()
85+
assert.NotNil(t, err)
86+
if err != nil {
87+
assert.Same(t, ErrTransportInvalid, err)
88+
}
89+
}
90+
91+
func TestDefaultTransport(t *testing.T) {
92+
agent1, err := NewAgent(WithDefaultTransport())
93+
if err != nil {
94+
t.Fatal(err)
95+
}
96+
97+
agent2, err := NewAgent(WithDefaultTransport())
98+
if err != nil {
99+
t.Fatal(err)
100+
}
101+
102+
assert.Same(t, agent1.HttpClient.Transport, agent2.HttpClient.Transport)
103+
}
104+
105+
func TestCloneTransport(t *testing.T) {
106+
agent1, err := NewAgent(WithCloneTransport(DefaultTransport))
107+
if err != nil {
108+
t.Fatal(err)
109+
}
110+
111+
agent2, err := NewAgent(WithCloneTransport(DefaultTransport))
112+
if err != nil {
113+
t.Fatal(err)
114+
}
115+
116+
assert.NotSame(t, agent1.HttpClient.Transport, agent2.HttpClient.Transport)
117+
}

demo/agent/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ func main() {
1111
ctx, cancel := context.WithCancel(context.Background())
1212
defer cancel()
1313

14-
agent, err := agent.NewAgent(agent.WithBaseURL("https://github.com/"))
14+
agent, err := agent.NewAgent(agent.WithDefaultTransport(), agent.WithBaseURL("https://github.com/"))
1515
if err != nil {
1616
panic(err)
1717
}

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ require (
1010
github.com/labstack/echo v3.3.10+incompatible
1111
github.com/labstack/gommon v0.3.0 // indirect
1212
github.com/pquerna/cachecontrol v0.0.0-20200819021114-67c6ae64274f
13+
github.com/stretchr/testify v1.7.0
1314
golang.org/x/net v0.0.0-20200904194848-62affa334b73
1415
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
1516
)

0 commit comments

Comments
 (0)