uv-rays 0.2.6 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 11a2e081253e15248cae96c1f6ddeff70c72898e
4
- data.tar.gz: d8eb1fec708fcdc68a2fb2d4a09a08e2a5e77c9b
3
+ metadata.gz: 558fed8aba820a41ca678d1eff92f5ffcfe7ffda
4
+ data.tar.gz: 973e700f3dc30174988ed0e43305bedfd1045adc
5
5
  SHA512:
6
- metadata.gz: 0cb78756f4aa14503eed42df13a0a0cf0b2c1ff69e44ebb6d2104924fdeabb8184937e68b84cb68b85d789ba51bec1088c8e43e40ab22c783f885a23fd0940d7
7
- data.tar.gz: e0a26a535f56e79edc480624c41a64d251b6ff92d206d6ded3ce9fdac412886785bbc32dfd1b441547dc94f184e26a9af7303b850c41a843edb61c9abda1a94c
6
+ metadata.gz: 4b165b0a04fde386e7ec551f1047bf21dd2086c311281f1c243ad39f825cdcd3a99d48ae6ea0ad04b6c4a498ce687c480679ed792a2d7d16f90f1fc062fa9727
7
+ data.tar.gz: 2bd96402a8f3be5ce823a7f8c893c2fea25060125ba21aafd677fd0aeb55f895ae28c2ec82a7efc1a126eed67ccc55052578981c488897c08351dd867cee825d
@@ -45,7 +45,7 @@ module UV
45
45
  @defer.reject(reason)
46
46
  end
47
47
 
48
- def send(transport, error)
48
+ def execute(transport, error)
49
49
  head, body = build_request, @options[:body]
50
50
 
51
51
  @endpoint.middleware.each do |m|
@@ -14,16 +14,14 @@ module UV
14
14
  end
15
15
 
16
16
  class Response
17
- def initialize(requests)
18
- @requests = requests
19
-
17
+ def initialize
20
18
  @parser = ::HttpParser::Parser.new(self)
21
19
  @state = ::HttpParser::Parser.new_instance
22
20
  @state.type = :response
23
21
  end
24
22
 
25
23
 
26
- attr_reader :request
24
+ attr_accessor :request
27
25
 
28
26
 
29
27
  # Called on connection disconnect
@@ -51,7 +49,6 @@ module UV
51
49
  ##
52
50
  # Parser Callbacks:
53
51
  def on_message_begin(parser)
54
- @request = @requests.shift
55
52
  @headers = Headers.new
56
53
  @body = ''
57
54
  @chunked = false
@@ -123,7 +120,7 @@ module UV
123
120
  # We need to flush the response on disconnect if content-length is undefined
124
121
  # As per the HTTP spec
125
122
  def eof
126
- if @headers.nil? && @request.headers[:'Content-Length'].nil?
123
+ if @headers.nil? && @request.headers && @request.headers[:'Content-Length'].nil?
127
124
  on_message_complete(nil)
128
125
  else
129
126
  # Reject if this is a partial response
@@ -47,10 +47,9 @@ module UV
47
47
  }
48
48
 
49
49
  attr_reader :scheme, :host, :port, :using_tls, :loop, :cookiejar
50
- attr_reader :connect_timeout, :inactivity_timeout
50
+ attr_reader :inactivity_timeout
51
51
 
52
52
  def initialize(uri, options = {})
53
- @connect_timeout = options[:connect_timeout] ||= 5 # default connection setup timeout
54
53
  @inactivity_timeout = options[:inactivity_timeout] ||= 10 # default connection inactivity (post-setup) timeout
55
54
 
56
55
 
@@ -66,29 +65,24 @@ module UV
66
65
  #@transport = @loop.tcp
67
66
 
68
67
  # State flags
69
- @ready = false
68
+ @closed = true
69
+ @closing = false
70
70
  @connecting = false
71
71
 
72
72
  # Current requests
73
73
  @pending_requests = []
74
- @pending_responses = []
75
- @connection_pending = []
74
+ @staging_request = nil
75
+ @waiting_response = nil
76
76
  @cookiejar = CookieJar.new
77
77
 
78
78
  # Callback methods
79
- @connection_method = method(:get_connection)
80
- @next_request_method = method(:next_request)
81
79
  @idle_timeout_method = method(:idle_timeout)
82
- @connect_timeout_method = method(:connect_timeout)
83
-
84
- # Used to indicate when we can start the next send
85
- @breakpoint = ::Libuv::Q::ResolvedPromise.new(@loop, true)
86
80
 
87
81
  # Manages the tokenising of response from the input stream
88
- @response = Http::Response.new(@pending_responses)
82
+ @response = Http::Response.new
89
83
 
90
84
  # Timeout timer
91
- if @connect_timeout || @inactivity_timeout
85
+ if @inactivity_timeout > 0
92
86
  @timer = @loop.timer
93
87
  end
94
88
  end
@@ -109,12 +103,23 @@ module UV
109
103
 
110
104
  # Setup the request with callbacks
111
105
  request = Http::Request.new(self, options)
112
- request.then proc { |result|
113
- if !result[:headers].keep_alive
106
+ request.then(proc { |result|
107
+ @waiting_response = nil
108
+
109
+ if @closed || result[:headers].keep_alive
110
+ next_request
111
+ else
112
+ @closing = true
114
113
  @transport.close
115
114
  end
115
+
116
116
  result
117
- }
117
+ }, proc { |err|
118
+ @waiting_response = nil
119
+ next_request
120
+
121
+ ::Libuv::Q.reject(@loop, err)
122
+ })
118
123
 
119
124
  ##
120
125
  # TODO:: Add response middleware here
@@ -122,54 +127,35 @@ module UV
122
127
 
123
128
  # Add to pending requests and schedule using the breakpoint
124
129
  @pending_requests << request
125
- @breakpoint.finally @next_request_method
126
- if options[:pipeline] == true
127
- options[:keepalive] = true
128
- else
129
- @breakpoint = request
130
+ if !@waiting_response && !@staging_request
131
+ next_request
130
132
  end
131
133
 
132
134
  # return the request
133
135
  request
134
136
  end
135
137
 
136
- def middleware
137
- # TODO:: allow for middle ware
138
- []
139
- end
140
138
 
141
- def on_read(data, *args)
142
- @timer.again if @inactivity_timeout > 0
143
- # returns true on error
144
- # Response rejects the request
145
- if @response.receive(data)
146
- @transport.close
147
- end
139
+ def next_request
140
+ @staging_request = @pending_requests.shift
141
+ process_request unless @staging_request.nil?
148
142
  end
149
143
 
150
- def on_close
151
- @ready = false
152
- @connecting = false
153
- stop_timer
154
-
155
- # Flush any processing request
156
- @response.eof if @response.request
144
+ def process_request
145
+ if @closed && !@connecting
146
+ @transport = @loop.tcp
157
147
 
158
- # Reject any requests waiting on a response
159
- @pending_responses.each do |request|
160
- request.reject(:disconnected)
161
- end
162
- @pending_responses.clear
163
-
164
- # Re-connect if there are pending requests
165
- if not @connection_pending.empty?
166
- do_connect
148
+ @connecting = @staging_request
149
+ ::UV.try_connect(@transport, self, @host, @port)
150
+ elsif !@closing
151
+ try_send
167
152
  end
168
153
  end
169
154
 
155
+
170
156
  def on_connect(transport)
171
157
  @connecting = false
172
- @ready = true
158
+ @closed = false
173
159
 
174
160
  # start tls if connection is encrypted
175
161
  use_tls() if @https
@@ -183,71 +169,89 @@ module UV
183
169
 
184
170
  # Kick off pending requests
185
171
  @response.reset!
186
- @connection_pending.each do |callback|
187
- callback.call
188
- end
189
- @connection_pending.clear
172
+ try_send # we only connect if there is a request waiting
190
173
  end
191
174
 
192
175
 
193
- protected
194
-
195
-
196
- def do_connect
197
- @transport = @loop.tcp
176
+ def on_close
177
+ @closed = true
178
+ clear_staging = @connecting == @staging_request
179
+ @connecting = false
180
+ stop_timer
198
181
 
199
- if @connect_timeout > 0
200
- @timer.progress @connect_timeout_method
201
- @timer.start @connect_timeout * 1000
182
+ # On close may be called before on data
183
+ @loop.next_tick do
184
+ if @closing
185
+ @closing = false
186
+ @connecting = false
187
+
188
+ if @staging_request
189
+ process_request
190
+ else
191
+ next_request
192
+ end
193
+ else
194
+ if clear_staging
195
+ @staging_request.reject(:connection_refused)
196
+ elsif @waiting_response
197
+ # Flush any processing request
198
+ @response.eof if @response.request
199
+
200
+ # Reject any requests waiting on a response
201
+ @waiting_response.reject(:disconnected)
202
+ elsif @staging_request
203
+ # Try reconnect
204
+ process_request
205
+ end
206
+ end
202
207
  end
208
+ end
209
+
210
+ def try_send
211
+ @waiting_response = @staging_request
212
+ @response.request = @staging_request
213
+ @staging_request = nil
203
214
 
204
- @connecting = true
205
- ::UV.try_connect(@transport, self, @host, @port)
215
+ @timer.again if @inactivity_timeout > 0
216
+ @waiting_response.execute(@transport, proc { |err|
217
+ @transport.close
218
+ @waiting_response.reject(err)
219
+ })
206
220
  end
207
221
 
208
- def get_connection(callback = nil, &blk)
209
- callback ||= blk
210
-
211
- if @connecting
212
- @connection_pending << callback
213
- elsif !@ready
214
- @connection_pending << callback
215
- do_connect
216
- elsif @transport.closing?
217
- @connection_pending << callback
218
- else
219
- callback.call(@connection)
220
- end
222
+
223
+ def middleware
224
+ # TODO:: allow for middle ware
225
+ []
221
226
  end
222
227
 
223
- def connect_timeout
224
- @timer.stop
225
- @transport.close
226
- @connection_pending.clear
228
+ def on_read(data, *args)
229
+ @timer.again if @inactivity_timeout > 0
230
+
231
+ # returns true on error
232
+ # Response rejects the request
233
+ if @response.receive(data)
234
+ @transport.close
235
+ end
227
236
  end
228
237
 
229
- def idle_timeout
230
- @timer.stop
231
- @transport.close
232
- @pending_responses.each do |request|
233
- request.reject(:idle_timeout)
238
+ def close_connection(after_writing = false)
239
+ stop_timer
240
+ reqs = @pending_requests
241
+ @pending_requests.clear
242
+ reqs.each do |request|
243
+ request.reject(:close_connection)
234
244
  end
245
+ super(after_writing)
235
246
  end
236
247
 
237
- def next_request
238
- request = @pending_requests.shift
239
248
 
240
- get_connection do
241
- @pending_responses << request
249
+ protected
242
250
 
243
- @timer.again if @inactivity_timeout > 0
244
251
 
245
- # TODO:: have request deal with the error internally
246
- request.send(@transport, proc { |err|
247
- @transport.close
248
- request.reject(err)
249
- })
250
- end
252
+ def idle_timeout
253
+ @timer.stop
254
+ @transport.close
251
255
  end
252
256
 
253
257
  def stop_timer
@@ -1,3 +1,3 @@
1
1
  module UV
2
- VERSION = '0.2.6'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -40,33 +40,6 @@ module OldServer
40
40
  end
41
41
 
42
42
 
43
- #
44
- # TODO:: Write tests for bad server responses
45
- # Need to be able to recover when:
46
- # * no response is sent
47
- # * disconnect
48
- # * bad length etc
49
- #
50
- module BadServer
51
- def post_init
52
- @parser = ::HttpParser::Parser.new(self)
53
- @state = ::HttpParser::Parser.new_instance
54
- @state.type = :request
55
- end
56
-
57
- def on_message_complete(parser)
58
- write("HTTP/1.0 200 OK\r\nContent-type: text/html\r\nContent-length: 0\r\n\r\n")
59
- end
60
-
61
- def on_read(data, connection)
62
- if @parser.parse(@state, data)
63
- p 'parse error'
64
- p @state.error
65
- end
66
- end
67
- end
68
-
69
-
70
43
  describe UV::HttpEndpoint do
71
44
  before :each do
72
45
  @loop = Libuv::Loop.new
@@ -155,47 +128,6 @@ describe UV::HttpEndpoint do
155
128
  expect(@response2[:headers].cookies).to eq({})
156
129
  expect(@response2[:headers].keep_alive).to eq(true)
157
130
  end
158
-
159
- it "should send pipelined requests on the same connection" do
160
- @loop.run { |logger|
161
- logger.progress do |level, errorid, error|
162
- begin
163
- @general_failure << "Log called: #{level}: #{errorid}\n#{error.message}\n#{error.backtrace.join("\n")}\n"
164
- rescue Exception
165
- @general_failure << 'error in logger'
166
- end
167
- end
168
-
169
- tcp = UV.start_server '127.0.0.1', 3250, HttpServer
170
- server = UV::HttpEndpoint.new 'http://127.0.0.1:3250'
171
-
172
- request = server.get(:path => '/', :pipeline => true)
173
- request.then(proc { |response|
174
- @response = response
175
- #@loop.stop
176
- }, @request_failure)
177
-
178
- request2 = server.get(:path => '/', :pipeline => true)
179
- request2.then(proc { |response|
180
- @response2 = response
181
- tcp.close
182
- @loop.stop
183
- }, @request_failure)
184
- }
185
-
186
- expect(@general_failure).to eq([])
187
- expect(@response[:headers][:"Content-type"]).to eq('text/html')
188
- expect(@response[:headers].http_version).to eq('1.1')
189
- expect(@response[:headers].status).to eq(200)
190
- expect(@response[:headers].cookies).to eq({})
191
- expect(@response[:headers].keep_alive).to eq(true)
192
-
193
- expect(@response2[:headers][:"Content-type"]).to eq('text/html')
194
- expect(@response2[:headers].http_version).to eq('1.1')
195
- expect(@response2[:headers].status).to eq(200)
196
- expect(@response2[:headers].cookies).to eq({})
197
- expect(@response2[:headers].keep_alive).to eq(true)
198
- end
199
131
  end
200
132
 
201
133
  describe 'old http request' do
@@ -268,41 +200,5 @@ describe UV::HttpEndpoint do
268
200
  expect(@response2[:headers].cookies).to eq({})
269
201
  expect(@response2[:headers].keep_alive).to eq(false)
270
202
  end
271
-
272
- it "should fail to send pipelined requests" do
273
- @loop.run { |logger|
274
- logger.progress do |level, errorid, error|
275
- begin
276
- @general_failure << "Log called: #{level}: #{errorid}\n#{error.message}\n#{error.backtrace.join("\n")}\n"
277
- rescue Exception
278
- @general_failure << 'error in logger'
279
- end
280
- end
281
-
282
- tcp = UV.start_server '127.0.0.1', 3250, OldServer
283
- server = UV::HttpEndpoint.new 'http://127.0.0.1:3250'
284
-
285
- request = server.get(:path => '/', :pipeline => true)
286
- request.then(proc { |response|
287
- @response = response
288
- #@loop.stop
289
- }, @request_failure)
290
-
291
- request2 = server.get(:path => '/', :pipeline => true)
292
- request2.then(proc { |response|
293
- @response2 = response
294
- tcp.close
295
- @loop.stop
296
- }, @request_failure)
297
- }
298
-
299
- expect(@general_failure).to eq([:disconnected])
300
- expect(@response[:headers][:"Content-type"]).to eq('text/html')
301
- expect(@response[:headers].http_version).to eq('1.0')
302
- expect(@response[:headers].status).to eq(200)
303
- expect(@response[:headers].cookies).to eq({})
304
- expect(@response[:headers].keep_alive).to eq(false)
305
- # Response 2 was the general failure
306
- end
307
203
  end
308
204
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uv-rays
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen von Takach
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-20 00:00:00.000000000 Z
11
+ date: 2014-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: libuv
@@ -202,7 +202,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
202
202
  version: '0'
203
203
  requirements: []
204
204
  rubyforge_project:
205
- rubygems_version: 2.1.11
205
+ rubygems_version: 2.0.14
206
206
  signing_key:
207
207
  specification_version: 4
208
208
  summary: Abstractions for working with Libuv