- Notifications
You must be signed in to change notification settings - Fork 27
Add XMLRPC::RackApplication #56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
test/test_rack_server.rb Outdated
require 'xmlrpc/parser' | ||
require 'xmlrpc/utils' | ||
| ||
module TestXMLRPC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can remove this because this gem is no longer a default gem. Our test names never conflict with others.
module TestXMLRPC |
test/test_rack_server.rb Outdated
require 'xmlrpc/utils' | ||
| ||
module TestXMLRPC | ||
class Test_Rack < Test::Unit::TestCase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
class Test_Rack < Test::Unit::TestCase | |
class TestRack < Test::Unit::TestCase |
test/test_rack_server.rb Outdated
@@ -0,0 +1,79 @@ | |||
# coding: utf-8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need this because it's the default in recent Ruby.
# coding: utf-8 |
test/test_rack_server.rb Outdated
| ||
s.add_introspection | ||
| ||
return s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return s | |
s |
test/test_rack_server.rb Outdated
module TestXMLRPC | ||
class Test_Rack < Test::Unit::TestCase | ||
include Rack::Test::Methods | ||
include XMLRPC::ParserWriterChooseMixin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use XMLRPC::Create.new(XMLRPC::Config.default_writer.new)
and XMLRPC::Config.default_parser.new
instead?
test/test_rack_server.rb Outdated
def assert_call_success(expect, methodname, *args) | ||
request = create().methodCall(methodname, *args) | ||
post("/", request, 'CONTENT_TYPE' => 'text/xml') | ||
ok, param = parser().parseMethodResponse(last_response.body) | ||
assert(ok) | ||
assert_equal(expect, param) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about using call
helper method like the following and assert_equal
?
def call(method_name, *args) create = XMLRPC::Create.new(XMLRPC::Config.default_writer.new) request = create.methodCall(method_name, *args) post("/", request, "CONTENT_TYPE" => "text/xml") parser = XMLRPC::Config.default_parser.new parser.parseMethodResponse(last_response.body) end def test_rack assert_equal([true, 9], call("test.add", 4, 5)) assert_equal([false, XMLRPC::FaultException.new(1, "division by zero")], call("test.div", 1, 0)) # ... end
test/test_rack_server.rb Outdated
def test_rack | ||
# simple call | ||
assert_call_success(9, "test.add", 4, 5) | ||
| ||
# fault exception | ||
assert_call_failure(1, "division by zero", "test.div", 1, 0) | ||
| ||
# introspection | ||
assert_call_success(["test.add", "test.div", "system.listMethods", "system.methodSignature", "system.methodHelp"], "system.listMethods") | ||
| ||
# default handler (missing handler) | ||
assert_call_failure(-99, "Method test.nonexisting missing or wrong number of parameters!", "test.nonexisting") | ||
| ||
# default handler (wrong number of arguments) | ||
assert_call_failure(-99, "Method test.add missing or wrong number of parameters!", "test.add", 1, 2, 3) | ||
| ||
# multibyte characters | ||
assert_call_success("あいうえおかきくけこ", 'test.add', "あいうえお", "かきくけこ") | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you create one test per test pattern?
For example:
def test_success assert_call_success(9, "test.add", 4, 5) end def test_exception assert_call_failure(1, "division by zero", "test.div", 1, 0) end
a7463e8
to c3f00ce
Compare I think I addressed all the issues above. Most of them were to keep the code consistent with the other code/tests. I see this has had a very recent cleanup. |
lib/xmlrpc/server.rb Outdated
| ||
| ||
# Implements a XML-RPC server, which works with Rack | ||
class RackServer < BasicServer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, Rack server means Puma, Passenger and so on.
class RackServer < BasicServer | |
class RackApplication < BasicServer |
test/test_rack_server.rb Outdated
end | ||
| ||
def test_successful_call | ||
assert_equal([true, 9], call("test.add", 4, 5)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you align arguments for easy to read?
assert_equal([true, 9], call("test.add", 4, 5)) | |
assert_equal([true, 9], | |
call("test.add", 4, 5)) |
test/test_rack_server.rb Outdated
| ||
request = create.methodCall(methodname, *args) | ||
post("/", request, 'CONTENT_TYPE' => 'text/xml') | ||
assert(last_response.ok?) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you use power assert for easy to debug? BTW, when does ok?
return false
?
assert(last_response.ok?) | |
assert do | |
last_response.ok? | |
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/rack/rack/blob/main/lib/rack/response.rb#L189
ok?
checks the HTTP status code for 200. This is mostly relevant for the exceptions, where XMLRPC will still return a HTTP OK (200) status, as opposed to using the HTTP status to signal an error like most REST-based APIs do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This results in output like this:
| | | false #<Rack::MockResponse:0x00007fbc70b25aa0 @original_headers={"Content-type"=>"text/xml; charset=utf-8"}, @errors="", @status=201, @headers={"content-type"=>"text/xml; charset=utf-8", "content-length"=>"296"}, @writer=#<Method: Rack::MockResponse(Rack::Response::Helpers)#append(chunk) /home/herwin/xmlrpc/vendor/bundle/ruby/3.1.0/gems/rack-3.1.13/lib/rack/response.rb:359>, @block=nil, @body=["<?xml version=\"1.0\" ?><methodResponse><fault><value><struct><member><name>faultCode</name><value><i4>-99</i4></value></member><member><name>faultString</name><value><string>Method test.add missing or wrong number of parameters!</string></value></member></struct></value></fault></methodResponse>\n"], @buffered=true, @length=296, @cookies={}> /home/herwin/xmlrpc/test/test_rack_server.rb:73:in `call' /home/herwin/xmlrpc/test/test_rack_server.rb:59:in `test_wrong_number_of_arguments' 56: 57: def test_wrong_number_of_arguments 58: assert_equal([false, XMLRPC::FaultException.new(-99, "Method test.add missing or wrong number of parameters!")], => 59: call("test.add", 1, 2, 3)) 60: end
I don't think this is the most readable output, I think the better option would be something like:
assert(last_response.ok?, "Expected HTTP status code 200, got #{last_response.status} instead")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. It's also better than assert(last_response.ok?)
.
test/test_rack_server.rb Outdated
end | ||
| ||
def test_multibyte_characters | ||
assert_equal([true, "あいうえおかきくけこ"], call('test.add', "あいうえお", "かきくけこ")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert_equal([true, "あいうえおかきくけこ"], call('test.add', "あいうえお", "かきくけこ")) | |
assert_equal([true, "あいうえおかきくけこ"], call("test.add", "あいうえお", "かきくけこ")) |
msg = <<-"MSGEND" | ||
<html> | ||
<head> | ||
<title>#{err}</title> | ||
</head> | ||
<body> | ||
<h1>#{err}</h1> | ||
<p>Unexpected error occurred while processing XML-RPC request!</p> | ||
</body> | ||
</html> | ||
MSGEND |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
msg = <<-"MSGEND" | |
<html> | |
<head> | |
<title>#{err}</title> | |
</head> | |
<body> | |
<h1>#{err}</h1> | |
<p>Unexpected error occurred while processing XML-RPC request!</p> | |
</body> | |
</html> | |
MSGEND | |
msg = <<-HTML | |
<html> | |
<head> | |
<title>#{err}</title> | |
</head> | |
<body> | |
<h1>#{err}</h1> | |
<p>Unexpected error occurred while processing XML-RPC request!</p> | |
</body> | |
</html> | |
HTML |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've got this exact same code snippet two more times in the existing code (CGIServer
and ModRubyServer
). I would prefer to keep this the same for now, and as a future work extract it to some shared code and remove this duplication. It's easier to find all the occurrences if we keep this exactly the same for now.
Once the code has been deduplicated, this improvement can be applied.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. Let's use the approach.
return http_error(400, "Bad Request") unless parse_content_type(env['CONTENT_TYPE']).first == "text/xml" | ||
return http_error(411, "Length Required") unless length > 0 | ||
| ||
req = Rack::Request.new(env) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to require rack
in initialize
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would guess this is already available when you run this as Rack middleware, so that should only be required if you run this rack app without rack. This seems like an unlikely scenario to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. Let's revisit this when we receive a bug report / feature request about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, this is a Rack application not Rack middleware, right?
This is a simple Rack middleware that acts as an XMLRPC server. This can be used in any Rack compatible webserver.
Thanks. |
This is a simple Rack application that acts as an XMLRPC server. This can be used in any Rack compatible webserver.
There are a few gems that provide a Rack-based XMLRPC server (rack-rpc, xmlrpc-rack_server and threez-rack-rpc), but none of these have been updated in the past 10 years.
Implementation has mostly been copied from ModRubyServer, tests have been inspired by the WebrickServer tests