aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2015-11-06 09:32:17 +0900
committerKazuki Yamaguchi <k@rhe.jp>2015-11-06 09:32:17 +0900
commit49f0eceb57f1ae13694f970a600b6915e1bc31e9 (patch)
tree165e27f323c13752b208180a03585e39d6fa40eb /lib
parent0588a60dd5b73db2dcdbe6fee094f1b1d229cfbe (diff)
downloadplum-49f0eceb57f1ae13694f970a600b6915e1bc31e9.tar.gz
update tests
Diffstat (limited to 'lib')
-rw-r--r--lib/plum/client.rb35
-rw-r--r--lib/plum/client/response.rb10
-rw-r--r--lib/plum/connection.rb19
-rw-r--r--lib/plum/errors.rb4
4 files changed, 45 insertions, 23 deletions
diff --git a/lib/plum/client.rb b/lib/plum/client.rb
index fa5bdd8..3749482 100644
--- a/lib/plum/client.rb
+++ b/lib/plum/client.rb
@@ -48,19 +48,23 @@ module Plum
# @param response [Response] if specified, waits only for the response
def wait(response = nil)
if response
- _succ while !response.finished?
+ _succ while !response.failed? && !response.finished?
else
_succ while !@responses.empty?
end
end
+ # Waits for the response headers.
+ # @param response [Response] the incomplete response.
+ def wait_headers(response)
+ _succ while !response.failed? && !response.headers
+ end
+
# Closes the connection.
def close
- begin
- @plum.close if @plum
- ensure
- @socket.close if @socket
- end
+ @plum.close if @plum && @plum.state != :closed
+ ensure
+ @socket.close if @socket
end
# Creates a new HTTP request.
@@ -169,18 +173,22 @@ module Plum
}
plum = ClientConnection.new(sock.method(:write), local_settings)
plum.on(:protocol_error) { |ex|
- _fail
+ _fail(ex)
raise ex
}
+ plum.on(:close) { _fail(RuntimeError.new(:closed)) }
plum.on(:stream_error) { |stream, ex|
if res = @responses.delete(stream)
- res._fail unless res.finished?
+ res._fail(ex) unless res.finished?
end
raise ex
}
plum.on(:headers) { |stream, headers|
response = @responses[stream]
response._headers(headers)
+ if handler = @response_handlers.delete(stream)
+ handler.call(response)
+ end
}
plum.on(:data) { |stream, chunk|
response = @responses[stream]
@@ -189,21 +197,18 @@ module Plum
plum.on(:end_stream) { |stream|
response = @responses.delete(stream)
response._finish
- if handler = @response_handlers.delete(stream)
- handler.call(response)
- end
}
plum
end
def _succ
- _fail if @socket.closed? || @socket.eof?
@plum << @socket.readpartial(1024)
end
- def _fail
- while res = @responses.pop
- res._fail unless res.finished?
+ def _fail(ex)
+ while sr = @responses.shift
+ stream, res = sr
+ res._fail(ex) unless res.finished?
end
ensure
close
diff --git a/lib/plum/client/response.rb b/lib/plum/client/response.rb
index 6afa4f9..ee23971 100644
--- a/lib/plum/client/response.rb
+++ b/lib/plum/client/response.rb
@@ -43,9 +43,9 @@ module Plum
def each_chunk(&block)
raise "Body already read" if @body_read
@body_read = true
- while chunk = @body.pop
- if chunk == :failed
- raise EOFError
+ while !(finished? && @body.empty?) && chunk = @body.pop
+ if Exception === chunk
+ raise chunk
else
yield chunk
end
@@ -78,9 +78,9 @@ module Plum
end
# @api private
- def _fail
+ def _fail(ex)
@failed = true
- @body << :failed
+ @body << ex
end
end
end
diff --git a/lib/plum/connection.rb b/lib/plum/connection.rb
index 68ba07d..f365861 100644
--- a/lib/plum/connection.rb
+++ b/lib/plum/connection.rb
@@ -38,6 +38,7 @@ module Plum
# Emits :close event. Doesn't actually close socket.
def close
+ @state = :closed
# TODO: server MAY wait streams
callback(:close)
end
@@ -45,6 +46,7 @@ module Plum
# Receives the specified data and process.
# @param new_data [String] The data received from the peer.
def receive(new_data)
+ return if @state == :closed
return if new_data.empty?
@buffer << new_data
consume_buffer
@@ -135,9 +137,7 @@ module Plum
when :ping
receive_ping(frame)
when :goaway
- callback(:goaway, frame)
- goaway
- close
+ receive_goaway(frame)
when :data, :headers, :priority, :rst_stream, :push_promise, :continuation
raise Plum::ConnectionError.new(:protocol_error)
else
@@ -184,5 +184,18 @@ module Plum
send_immediately Frame.ping(:ack, opaque_data)
end
end
+
+ def receive_goaway(frame)
+ callback(:goaway, frame)
+ goaway
+ close
+
+ last_id = frame.payload.uint32(0)
+ error_code = frame.payload.uint32(4)
+ message = frame.payload.byteslice(8, frame.length - 8)
+ if error_code > 0
+ raise LocalConnectionError.new(HTTPError::ERROR_CODES.key(error_code), message)
+ end
+ end
end
end
diff --git a/lib/plum/errors.rb b/lib/plum/errors.rb
index 9df4668..d5cce48 100644
--- a/lib/plum/errors.rb
+++ b/lib/plum/errors.rb
@@ -43,4 +43,8 @@ module Plum
@parser = parser
end
end
+
+ # Client
+ class LocalConnectionError < HTTPError; end
+ class LocalStreamError < HTTPError; end
end