uv-rays 0.2.6 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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