@@ -73,6 +73,10 @@ func (b *Bartender) MaxWait(d time.Duration) {
73
73
b .maxWait = d
74
74
}
75
75
76
+ func (b * Bartender ) getPage () * rod.Page {
77
+ return b .pool .Get (b .newPage )
78
+ }
79
+
76
80
func (b * Bartender ) newPage () * rod.Page {
77
81
page := rod .New ().MustConnect ().MustPage ()
78
82
@@ -93,12 +97,31 @@ func (b *Bartender) newPage() *rod.Page {
93
97
return page
94
98
}
95
99
96
- func (b * Bartender ) WarnUp () {
100
+ // WarmUp pre-creates the headless browsers.
101
+ func (b * Bartender ) WarmUp () {
97
102
for i := 0 ; i < len (b .pool ); i ++ {
98
- b .pool .Put (b .pool . Get ( b . newPage ))
103
+ b .pool .Put (b .getPage ( ))
99
104
}
100
105
}
101
106
107
+ // AutoFree automatically closes the each headless browser after a period of time.
108
+ // It prevent the memory leak of the headless browser.
109
+ func (b * Bartender ) AutoFree () {
110
+ go func () {
111
+ for {
112
+ time .Sleep (10 * time .Minute )
113
+
114
+ err := b .getPage ().Browser ().Close ()
115
+ if err != nil {
116
+ log .Println ("failed to close browser:" , err )
117
+
118
+ continue
119
+ }
120
+ b .pool .Put (nil )
121
+ }
122
+ }()
123
+ }
124
+
102
125
func (b * Bartender ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
103
126
ua := useragent .Parse (r .Header .Get ("User-Agent" ))
104
127
if r .Method != http .MethodGet || b .bypassList [ua .Name ] {
@@ -138,7 +161,7 @@ func (b *Bartender) RenderPage(w http.ResponseWriter, r *http.Request) bool {
138
161
139
162
w .WriteHeader (statusCode )
140
163
141
- page := b .pool . Get ( b . newPage )
164
+ page := b .getPage ( )
142
165
defer b .pool .Put (page )
143
166
144
167
page , cancel := page .WithCancel ()
0 commit comments