uv-rays 2.3.0 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,296 +1,296 @@
1
- # frozen_string_literal: true
2
-
3
- require 'uri'
4
-
5
- module UV
6
- class CookieJar
7
- def initialize
8
- @jar = ::CookieJar::Jar.new
9
- end
10
-
11
- def set(uri, string)
12
- @jar.set_cookie(uri, string) rescue nil # drop invalid cookies
13
- end
14
-
15
- def get(uri)
16
- uri = URI.parse(uri) rescue nil
17
- uri ? @jar.get_cookies(uri).map(&:to_s) : []
18
- end
19
-
20
- def get_hash(uri)
21
- uri = URI.parse(uri) rescue nil
22
- cookies = {}
23
- if uri
24
- @jar.get_cookies(uri).each do |cookie|
25
- cookies[cookie.name.to_sym] = cookie.value
26
- end
27
- end
28
- cookies
29
- end
30
-
31
- def clear_cookies
32
- @jar = ::CookieJar::Jar.new
33
- end
34
- end # CookieJar
35
-
36
- # HTTPS Proxy - connect to proxy
37
- # CONNECT #{target_host}:#{target_port} HTTP/1.0\r\n"
38
- # Proxy-Authorization: Basic #{encoded_credentials}\r\n
39
- # \r\n
40
- # Parse response =~ %r{\AHTTP/1\.[01] 200 .*\r\n\r\n}m
41
- # use_tls
42
- # send requests as usual
43
-
44
- # HTTP Proxy - connect to proxy
45
- # GET #{url_with_host} HTTP/1.1\r\n"
46
- # Proxy-Authorization: Basic #{encoded_credentials}\r\n
47
- # \r\n
48
-
49
- class HttpEndpoint
50
- class Connection < OutboundConnection
51
- def initialize(host, port, tls, proxy, client)
52
- @target_host = host
53
- @client = client
54
- @request = nil
55
-
56
- if proxy
57
- super(proxy[:host], proxy[:port])
58
- connect_send_handshake(host, port, proxy) if tls
59
- else
60
- super(host, port)
61
- start_tls if tls
62
- end
63
- end
64
-
65
- def start_tls
66
- opts = {host_name: @target_host}.merge(@client.tls_options)
67
- use_tls(opts)
68
- end
69
-
70
- def connect_send_handshake(target_host, target_port, proxy)
71
- @negotiating = true
72
- header = String.new("CONNECT #{target_host}:#{target_port} HTTP/1.0\r\n")
73
- if proxy[:username] || proxy[:password]
74
- encoded_credentials = Base64.strict_encode64([proxy[:username], proxy[:password]].join(":"))
75
- header << "Proxy-Authorization: Basic #{encoded_credentials}\r\n"
76
- end
77
- header << "\r\n"
78
- write(header)
79
- end
80
-
81
- attr_accessor :request, :reason
82
-
83
- def on_read(data, *args)
84
- if @negotiating
85
- @negotiating = false
86
- if data =~ %r{\AHTTP/1\.[01] 200 .*\r\n\r\n}m
87
- start_tls
88
- @client.connection_ready
89
- else
90
- @reason = "Unexpected response from proxy: #{data}"
91
- close_connection
92
- end
93
- else
94
- @client.data_received(data)
95
- end
96
- end
97
-
98
- def post_init(*args)
99
- end
100
-
101
- def on_connect(transport)
102
- @client.connection_ready unless @negotiating
103
- end
104
-
105
- def on_close
106
- @client.connection_closed(@request, @reason)
107
- ensure
108
- @request = nil
109
- @client = nil
110
- @reason = nil
111
- end
112
-
113
- def close_connection(request = nil)
114
- if request.is_a? Http::Request
115
- @request = request
116
- super(:after_writing)
117
- else
118
- super(request)
119
- end
120
- end
121
- end
122
-
123
-
124
- @@defaults = {
125
- :path => '/',
126
- :keepalive => true
127
- }
128
-
129
-
130
- def initialize(host, options = {})
131
- @queue = []
132
- @parser = Http::Parser.new
133
- @thread = reactor
134
- @connection = nil
135
-
136
- @options = @@defaults.merge(options)
137
- @tls_options = options[:tls_options] || {}
138
- @inactivity_timeout = options[:inactivity_timeout] || 10000
139
-
140
- uri = host.is_a?(::URI) ? host : ::URI.parse(host)
141
- @port = uri.port
142
- @host = uri.host
143
-
144
- default_port = uri.port == uri.default_port
145
- @encoded_host = default_port ? @host : "#{@host}:#{@port}"
146
- @proxy = @options[:proxy]
147
-
148
- @scheme = uri.scheme
149
- @tls = @scheme == 'https'
150
- @cookiejar = CookieJar.new
151
- @middleware = []
152
- end
153
-
154
-
155
- attr_accessor :inactivity_timeout
156
- attr_reader :tls_options, :port, :host, :tls, :scheme, :encoded_host
157
- attr_reader :cookiejar, :middleware, :thread, :proxy
158
-
159
-
160
- def get(options = {}); request(:get, options); end
161
- def head(options = {}); request(:head, options); end
162
- def delete(options = {}); request(:delete, options); end
163
- def put(options = {}); request(:put, options); end
164
- def post(options = {}); request(:post, options); end
165
- def patch(options = {}); request(:patch, options); end
166
- def options(options = {}); request(:options, options); end
167
-
168
-
169
- def request(method, options = {})
170
- options = @options.merge(options)
171
- options[:method] = method.to_sym
172
-
173
- # Setup the request with callbacks
174
- request = Http::Request.new(self, options)
175
- request.then(proc { |response|
176
- if response.keep_alive
177
- restart_timer
178
- else
179
- close_connection
180
- end
181
-
182
- next_request
183
-
184
- response
185
- }, proc { |err|
186
- @parser.eof
187
- close_connection
188
- next_request
189
- ::Libuv::Q.reject(@thread, err)
190
- })
191
-
192
- @queue.unshift(request)
193
-
194
- next_request
195
- request
196
- end
197
-
198
- # Callbacks
199
- def connection_ready
200
- if @queue.length > 0
201
- restart_timer
202
- next_request
203
- else
204
- close_connection
205
- end
206
- end
207
-
208
- def connection_closed(request, reason)
209
- # We may have closed a previous connection
210
- if @parser.request && (request.nil? || request == @parser.request)
211
- @connection = nil
212
- stop_timer
213
-
214
- @parser.eof
215
- elsif request.nil? && @parser.request.nil? && @queue.length > 0
216
- req = @queue.pop
217
- req.reject(reason || :connection_failure)
218
- end
219
- end
220
-
221
- def data_received(data)
222
- restart_timer
223
- close_connection if @parser.received(data)
224
- end
225
-
226
- def cancel_all
227
- @queue.each do |request|
228
- request.reject(:cancelled)
229
- end
230
- if @parser.request
231
- @parser.request.reject(:cancelled)
232
- @parser.eof
233
- end
234
- @queue = []
235
- close_connection
236
- end
237
-
238
- def http_proxy?
239
- @proxy && !@tls
240
- end
241
-
242
-
243
- private
244
-
245
-
246
- def next_request
247
- return if @parser.request || @queue.length == 0
248
-
249
- if @connection
250
- req = @queue.pop
251
- @connection.request = req
252
- @parser.new_request(req)
253
-
254
- req.execute(@connection)
255
- else
256
- new_connection
257
- end
258
- end
259
-
260
- def new_connection
261
- if @queue.length > 0 && @connection.nil?
262
- @connection = Connection.new(@host, @port, @tls, @proxy, self)
263
- start_timer
264
- end
265
- @connection
266
- end
267
-
268
- def close_connection
269
- return if @connection.nil?
270
- @connection.close_connection(@parser.request)
271
- stop_timer
272
- @connection = nil
273
- end
274
-
275
-
276
- def start_timer
277
- @timer.cancel if @timer
278
- @timer = @thread.scheduler.in(@inactivity_timeout) do
279
- @timer = nil
280
- idle_timeout
281
- end
282
- end
283
- alias_method :restart_timer, :start_timer
284
-
285
- def stop_timer
286
- @timer.cancel unless @timer.nil?
287
- @timer = nil
288
- end
289
-
290
- def idle_timeout
291
- @parser.reason = :timeout if @parser.request
292
- @connection.reason = :timeout
293
- close_connection
294
- end
295
- end
296
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+
5
+ module UV
6
+ class CookieJar
7
+ def initialize
8
+ @jar = ::CookieJar::Jar.new
9
+ end
10
+
11
+ def set(uri, string)
12
+ @jar.set_cookie(uri, string) rescue nil # drop invalid cookies
13
+ end
14
+
15
+ def get(uri)
16
+ uri = URI.parse(uri) rescue nil
17
+ uri ? @jar.get_cookies(uri).map(&:to_s) : []
18
+ end
19
+
20
+ def get_hash(uri)
21
+ uri = URI.parse(uri) rescue nil
22
+ cookies = {}
23
+ if uri
24
+ @jar.get_cookies(uri).each do |cookie|
25
+ cookies[cookie.name.to_sym] = cookie.value
26
+ end
27
+ end
28
+ cookies
29
+ end
30
+
31
+ def clear_cookies
32
+ @jar = ::CookieJar::Jar.new
33
+ end
34
+ end # CookieJar
35
+
36
+ # HTTPS Proxy - connect to proxy
37
+ # CONNECT #{target_host}:#{target_port} HTTP/1.0\r\n"
38
+ # Proxy-Authorization: Basic #{encoded_credentials}\r\n
39
+ # \r\n
40
+ # Parse response =~ %r{\AHTTP/1\.[01] 200 .*\r\n\r\n}m
41
+ # use_tls
42
+ # send requests as usual
43
+
44
+ # HTTP Proxy - connect to proxy
45
+ # GET #{url_with_host} HTTP/1.1\r\n"
46
+ # Proxy-Authorization: Basic #{encoded_credentials}\r\n
47
+ # \r\n
48
+
49
+ class HttpEndpoint
50
+ class Connection < OutboundConnection
51
+ def initialize(host, port, tls, proxy, client)
52
+ @target_host = host
53
+ @client = client
54
+ @request = nil
55
+
56
+ if proxy
57
+ super(proxy[:host], proxy[:port])
58
+ connect_send_handshake(host, port, proxy) if tls
59
+ else
60
+ super(host, port)
61
+ start_tls if tls
62
+ end
63
+ end
64
+
65
+ def start_tls
66
+ opts = {host_name: @target_host}.merge(@client.tls_options)
67
+ use_tls(opts)
68
+ end
69
+
70
+ def connect_send_handshake(target_host, target_port, proxy)
71
+ @negotiating = true
72
+ header = String.new("CONNECT #{target_host}:#{target_port} HTTP/1.0\r\n")
73
+ if proxy[:username] || proxy[:password]
74
+ encoded_credentials = Base64.strict_encode64([proxy[:username], proxy[:password]].join(":"))
75
+ header << "Proxy-Authorization: Basic #{encoded_credentials}\r\n"
76
+ end
77
+ header << "\r\n"
78
+ write(header)
79
+ end
80
+
81
+ attr_accessor :request, :reason
82
+
83
+ def on_read(data, *args)
84
+ if @negotiating
85
+ @negotiating = false
86
+ if data =~ %r{\AHTTP/1\.[01] 200 .*\r\n\r\n}m
87
+ start_tls
88
+ @client.connection_ready
89
+ else
90
+ @reason = "Unexpected response from proxy: #{data}"
91
+ close_connection
92
+ end
93
+ else
94
+ @client.data_received(data)
95
+ end
96
+ end
97
+
98
+ def post_init(*args)
99
+ end
100
+
101
+ def on_connect(transport)
102
+ @client.connection_ready unless @negotiating
103
+ end
104
+
105
+ def on_close
106
+ @client.connection_closed(@request, @reason)
107
+ ensure
108
+ @request = nil
109
+ @client = nil
110
+ @reason = nil
111
+ end
112
+
113
+ def close_connection(request = nil)
114
+ if request.is_a? Http::Request
115
+ @request = request
116
+ super(:after_writing)
117
+ else
118
+ super(request)
119
+ end
120
+ end
121
+ end
122
+
123
+
124
+ @@defaults = {
125
+ :path => '/',
126
+ :keepalive => true
127
+ }
128
+
129
+
130
+ def initialize(host, options = {})
131
+ @queue = []
132
+ @parser = Http::Parser.new
133
+ @thread = reactor
134
+ @connection = nil
135
+
136
+ @options = @@defaults.merge(options)
137
+ @tls_options = options[:tls_options] || {}
138
+ @inactivity_timeout = options[:inactivity_timeout] || 10000
139
+
140
+ uri = host.is_a?(::URI) ? host : ::URI.parse(host)
141
+ @port = uri.port
142
+ @host = uri.host
143
+
144
+ default_port = uri.port == uri.default_port
145
+ @encoded_host = default_port ? @host : "#{@host}:#{@port}"
146
+ @proxy = @options[:proxy]
147
+
148
+ @scheme = uri.scheme
149
+ @tls = @scheme == 'https'
150
+ @cookiejar = CookieJar.new
151
+ @middleware = []
152
+ end
153
+
154
+
155
+ attr_accessor :inactivity_timeout
156
+ attr_reader :tls_options, :port, :host, :tls, :scheme, :encoded_host
157
+ attr_reader :cookiejar, :middleware, :thread, :proxy
158
+
159
+
160
+ def get(options = {}); request(:get, options); end
161
+ def head(options = {}); request(:head, options); end
162
+ def delete(options = {}); request(:delete, options); end
163
+ def put(options = {}); request(:put, options); end
164
+ def post(options = {}); request(:post, options); end
165
+ def patch(options = {}); request(:patch, options); end
166
+ def options(options = {}); request(:options, options); end
167
+
168
+
169
+ def request(method, options = {})
170
+ options = @options.merge(options)
171
+ options[:method] = method.to_sym
172
+
173
+ # Setup the request with callbacks
174
+ request = Http::Request.new(self, options)
175
+ request.then(proc { |response|
176
+ if response.keep_alive
177
+ restart_timer
178
+ else
179
+ close_connection
180
+ end
181
+
182
+ next_request
183
+
184
+ response
185
+ }, proc { |err|
186
+ @parser.eof
187
+ close_connection
188
+ next_request
189
+ ::Libuv::Q.reject(@thread, err)
190
+ })
191
+
192
+ @queue.unshift(request)
193
+
194
+ next_request
195
+ request
196
+ end
197
+
198
+ # Callbacks
199
+ def connection_ready
200
+ if @queue.length > 0
201
+ restart_timer
202
+ next_request
203
+ else
204
+ close_connection
205
+ end
206
+ end
207
+
208
+ def connection_closed(request, reason)
209
+ # We may have closed a previous connection
210
+ if @parser.request && (request.nil? || request == @parser.request)
211
+ @connection = nil
212
+ stop_timer
213
+
214
+ @parser.eof
215
+ elsif request.nil? && @parser.request.nil? && @queue.length > 0
216
+ req = @queue.pop
217
+ req.reject(reason || :connection_failure)
218
+ end
219
+ end
220
+
221
+ def data_received(data)
222
+ restart_timer
223
+ close_connection if @parser.received(data)
224
+ end
225
+
226
+ def cancel_all
227
+ @queue.each do |request|
228
+ request.reject(:cancelled)
229
+ end
230
+ if @parser.request
231
+ @parser.request.reject(:cancelled)
232
+ @parser.eof
233
+ end
234
+ @queue = []
235
+ close_connection
236
+ end
237
+
238
+ def http_proxy?
239
+ @proxy && !@tls
240
+ end
241
+
242
+
243
+ private
244
+
245
+
246
+ def next_request
247
+ return if @parser.request || @queue.length == 0
248
+
249
+ if @connection
250
+ req = @queue.pop
251
+ @connection.request = req
252
+ @parser.new_request(req)
253
+
254
+ req.execute(@connection)
255
+ else
256
+ new_connection
257
+ end
258
+ end
259
+
260
+ def new_connection
261
+ if @queue.length > 0 && @connection.nil?
262
+ @connection = Connection.new(@host, @port, @tls, @proxy, self)
263
+ start_timer
264
+ end
265
+ @connection
266
+ end
267
+
268
+ def close_connection
269
+ return if @connection.nil?
270
+ @connection.close_connection(@parser.request)
271
+ stop_timer
272
+ @connection = nil
273
+ end
274
+
275
+
276
+ def start_timer
277
+ @timer.cancel if @timer
278
+ @timer = @thread.scheduler.in(@inactivity_timeout) do
279
+ @timer = nil
280
+ idle_timeout
281
+ end
282
+ end
283
+ alias_method :restart_timer, :start_timer
284
+
285
+ def stop_timer
286
+ @timer.cancel unless @timer.nil?
287
+ @timer = nil
288
+ end
289
+
290
+ def idle_timeout
291
+ @parser.reason = :timeout if @parser.request
292
+ @connection.reason = :timeout
293
+ close_connection
294
+ end
295
+ end
296
+ end