Skip to content

Commit

Permalink
pass rush exceptions across the connection
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam Wiggins committed Mar 7, 2008
1 parent ccefb4f commit e9aad95
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 10 deletions.
10 changes: 10 additions & 0 deletions lib/rush/exceptions.rb
@@ -1,4 +1,14 @@
module Rush
# Base class for all rush exceptions.
class Exception < ::Exception; end

# Client was not authorized by remote server; check credentials.
class NotAuthorized < Exception; end

# Failed to transmit to the remote server; check if the ssh tunnel is alive,
# and rushd is listening on the other end.
class FailedTransmit < Exception; end

# The entry (file or dir) referenced does not exist. Message is the entry's full path.
class DoesNotExist < Exception; end
end
31 changes: 25 additions & 6 deletions lib/rush/remote.rb
Expand Up @@ -74,9 +74,6 @@ def bash(command)
transmit(:action => 'bash', :command => command)
end

class NotAuthorized < Exception; end
class FailedTransmit < Exception; end

# Given a hash of parameters (converted by the method call on the connection
# object), send it across the wire to the RushServer listening on the other
# side. Uses http basic auth, with credentials fetched from the Rush::Config.
Expand All @@ -97,10 +94,32 @@ def transmit(params)

Net::HTTP.start(tunnel.host, tunnel.port) do |http|
res = http.request(req, payload)
raise NotAuthorized if res.code == "401"
raise FailedTransmit if res.code != "200"
res.body
process_result(res.code, res.body)
end
end

# Take the http result of a transmit and raise an error, or return the body
# of the result when valid.
def process_result(code, body)
raise Rush::NotAuthorized if code == "401"

if code == "400"
klass, message = parse_exception(body)
raise klass, message
end

raise Rush::FailedTransmit if code != "200"

body
end

# Parse an exception returned from the server, with the class name on the
# first line and the message on the second.
def parse_exception(body)
klass, message = body.split("\n", 2)
raise "invalid exception class: #{klass}" unless klass.match(/^Rush::[A-Za-z]+$/)
klass = Object.module_eval(klass)
[ klass, message.strip ]
end

# Set up the tunnel if it is not already running.
Expand Down
13 changes: 10 additions & 3 deletions lib/rush/server.rb
Expand Up @@ -28,10 +28,17 @@ def process(request, response)
log msg

params[:payload] = payload
result = box.connection.receive(params)

response.start(200) do |head, out|
out.write result
begin
result = box.connection.receive(params)

response.start(200) do |head, out|
out.write result
end
rescue Rush::Exception => e
response.start(400) do |head, out|
out.write "#{e.class}\n#{e.message}\n"
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/rush/shell.rb
Expand Up @@ -48,7 +48,7 @@ def run
print_result res
rescue Rush::Exception => e
puts "Exception #{e.class}: #{e}"
rescue Object => e
rescue ::Exception => e
puts "Exception #{e.class}: #{e}"
e.backtrace.each do |t|
puts " #{::File.expand_path(t)}"
Expand Down
21 changes: 21 additions & 0 deletions spec/remote_spec.rb
Expand Up @@ -87,6 +87,27 @@
@con.bash('cmd').should == 'output'
end

it "an http result code of 401 raises NotAuthorized" do
lambda { @con.process_result("401", "") }.should raise_error(Rush::NotAuthorized)
end

it "an http result code of 400 raises the exception passed in the result body" do
@con.stub!(:parse_exception).and_return(Rush::DoesNotExist, "message")
lambda { @con.process_result("400", "") }.should raise_error(Rush::DoesNotExist)
end

it "an http result code of 501 (or anything other than the other defined codes) raises FailedTransmit" do
lambda { @con.process_result("501", "") }.should raise_error(Rush::FailedTransmit)
end

it "parse_exception takes the class from the first line and the message from the second" do
@con.parse_exception("Rush::DoesNotExist\nthe message\n").should == [ Rush::DoesNotExist, "the message" ]
end

it "parse_exception rejects unrecognized exceptions" do
lambda { @con.parse_exception("NotARushException\n") }.should raise_error
end

it "passes through ensure_tunnel" do
@con.tunnel.should_receive(:ensure_tunnel)
@con.ensure_tunnel
Expand Down

0 comments on commit e9aad95

Please sign in to comment.