class BlogRPC::RackApp
An embeddable Rack handler for RPC servers
Attributes
blog_url[RW]
The root URL of the blog
handlers[RW]
All the XML-RPC handlers that can respond to the request, if it so happens that you have more than one
rpc_endpoint_url[RW]
The URL of the blog API endpoint (like /backend.rpc)
Public Class Methods
new(blog_handler)
click to toggle source
# File lib/blogrpc/rack_app.rb, line 15 def initialize(blog_handler) @handlers = [blog_handler] end
Public Instance Methods
call(env)
click to toggle source
# File lib/blogrpc/rack_app.rb, line 19 def call(env) @env = env req = Rack::Request.new(env) # If the request is a GET return the autodiscovery RSD fragment if req.get? return endpoint_xml else return post_request end end
Private Instance Methods
all_supported_method_names()
click to toggle source
# File lib/blogrpc/rack_app.rb, line 32 def all_supported_method_names method_names = [] @handlers.map do |h| methods_of_handler = h.get_methods(nil, nil) methods_of_handler.each do | m | method_names << m[0] end end method_names end
endpoint_xml()
click to toggle source
Returns the endpoint information that smart blogging clients can use to detect which APIs you support.
# File lib/blogrpc/rack_app.rb, line 57 def endpoint_xml b = Builder::XmlMarkup.new b.rsd :version => '1.0', :xmlns => "http://archipelago.phrasewise.com/rsd" do; b.service do b.engineName "MovableType" # It's better to pose as MT b.homePageLink(blog_url) b.apis do b.api( :name=>"MovableType", :preferred => "true", :apiLink => rpc_endpoint_url, :blogID => 1) if supports_mt? b.api( :name=>"MetaWeblog", :apiLink => rpc_endpoint_url, :blogID => 1) if supports_metaweblog? b.api( :name=>"WordPress", :apiLink => rpc_endpoint_url, :blogID => 1) if supports_wordpress? end end;end [200, {"Content-Length"=> Rack::Utils.bytesize(b.target!), "Content-Type" => 'application/rsd+xml'}, b.target!] end
format_exception(e)
click to toggle source
# File lib/blogrpc/rack_app.rb, line 107 def format_exception(e) first_line = [e.class.to_s, e.message].join(' : ') ([first_line] + e.backtrace.to_a).join("\n") end
post_request()
click to toggle source
# File lib/blogrpc/rack_app.rb, line 71 def post_request body = begin # Ruby's XMLRPC does not love rack.input wrappers, # it wants a bona-fide IO. Also, different rack input # wrappers work differently (some are better than others), # so to protect us from extra grief we will rebuffer everything # in a Tempfile @temp = Tempfile.new("rxrpc") @env['rack.input'].each(&@temp.method(:write)) @temp.rewind s = XMLRPC::BasicServer.new(self) # Here we initialize the handlers @handlers.each do |handler| # Inject the Rack environment into the handler handler.env = @env s.add_handler(handler) end # AND PROZESSS! s.process(@temp) rescue Exception => e # Transform all errors, even LoadError, into a properly formatted XML-RPC fault struct # Supports captivity logger by default @env["captivity.logger"].fatal([e.message, e.backtrace].join("\n")) if @env['captivity.logger'] b = Builder::XmlMarkup.new b.methodResponse do |b|; b.fault do; b.value do; b.struct do b.member { b.name("faultCode"); b.value { b.int 1 } } b.member { b.name("faultString"); b.value { b.string(format_exception(e)) }} end;end;end;end b.target! ensure @temp.close! end [200, {"Content-Length"=> Rack::Utils.bytesize(body), "Content-Type" => 'text/xml; charset=utf-8'}, body] end
supports_metaweblog?()
click to toggle source
# File lib/blogrpc/rack_app.rb, line 47 def supports_metaweblog? all_supported_method_names.grep(/^metaWeblog\./).any? end
supports_mt?()
click to toggle source
# File lib/blogrpc/rack_app.rb, line 43 def supports_mt? all_supported_method_names.grep(/^mt\./).any? end
supports_wordpress?()
click to toggle source
# File lib/blogrpc/rack_app.rb, line 51 def supports_wordpress? all_supported_method_names.grep(/^wp\./).any? end