Adds a branch for unlimited project hierarchy.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/work@2148 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
@@ -0,0 +1,364 @@
|
||||
= Action Web Service -- Serving APIs on rails
|
||||
|
||||
Action Web Service provides a way to publish interoperable web service APIs with
|
||||
Rails without spending a lot of time delving into protocol details.
|
||||
|
||||
|
||||
== Features
|
||||
|
||||
* SOAP RPC protocol support
|
||||
* Dynamic WSDL generation for APIs
|
||||
* XML-RPC protocol support
|
||||
* Clients that use the same API definitions as the server for
|
||||
easy interoperability with other Action Web Service based applications
|
||||
* Type signature hints to improve interoperability with static languages
|
||||
* Active Record model class support in signatures
|
||||
|
||||
|
||||
== Defining your APIs
|
||||
|
||||
You specify the methods you want to make available as API methods in an
|
||||
ActionWebService::API::Base derivative, and then specify this API
|
||||
definition class wherever you want to use that API.
|
||||
|
||||
The implementation of the methods is done separately from the API
|
||||
specification.
|
||||
|
||||
|
||||
==== Method name inflection
|
||||
|
||||
Action Web Service will camelcase the method names according to Rails Inflector
|
||||
rules for the API visible to public callers. What this means, for example,
|
||||
is that the method names in generated WSDL will be camelcased, and callers will
|
||||
have to supply the camelcased name in their requests for the request to
|
||||
succeed.
|
||||
|
||||
If you do not desire this behaviour, you can turn it off with the
|
||||
ActionWebService::API::Base +inflect_names+ option.
|
||||
|
||||
|
||||
==== Inflection examples
|
||||
|
||||
:add => Add
|
||||
:find_all => FindAll
|
||||
|
||||
|
||||
==== Disabling inflection
|
||||
|
||||
class PersonAPI < ActionWebService::API::Base
|
||||
inflect_names false
|
||||
end
|
||||
|
||||
|
||||
==== API definition example
|
||||
|
||||
class PersonAPI < ActionWebService::API::Base
|
||||
api_method :add, :expects => [:string, :string, :bool], :returns => [:int]
|
||||
api_method :remove, :expects => [:int], :returns => [:bool]
|
||||
end
|
||||
|
||||
==== API usage example
|
||||
|
||||
class PersonController < ActionController::Base
|
||||
web_service_api PersonAPI
|
||||
|
||||
def add
|
||||
end
|
||||
|
||||
def remove
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
== Publishing your APIs
|
||||
|
||||
Action Web Service uses Action Pack to process protocol requests. There are two
|
||||
modes of dispatching protocol requests, _Direct_, and _Delegated_.
|
||||
|
||||
|
||||
=== Direct dispatching
|
||||
|
||||
This is the default mode. In this mode, public controller instance methods
|
||||
implement the API methods, and parameters are passed through to the methods in
|
||||
accordance with the API specification.
|
||||
|
||||
The return value of the method is sent back as the return value to the
|
||||
caller.
|
||||
|
||||
In this mode, a special <tt>api</tt> action is generated in the target
|
||||
controller to unwrap the protocol request, forward it on to the relevant method
|
||||
and send back the wrapped return value. <em>This action must not be
|
||||
overridden.</em>
|
||||
|
||||
==== Direct dispatching example
|
||||
|
||||
class PersonController < ApplicationController
|
||||
web_service_api PersonAPI
|
||||
|
||||
def add
|
||||
end
|
||||
|
||||
def remove
|
||||
end
|
||||
end
|
||||
|
||||
class PersonAPI < ActionWebService::API::Base
|
||||
...
|
||||
end
|
||||
|
||||
|
||||
For this example, protocol requests for +Add+ and +Remove+ methods sent to
|
||||
<tt>/person/api</tt> will be routed to the controller methods +add+ and +remove+.
|
||||
|
||||
|
||||
=== Delegated dispatching
|
||||
|
||||
This mode can be turned on by setting the +web_service_dispatching_mode+ option
|
||||
in a controller to <tt>:delegated</tt>.
|
||||
|
||||
In this mode, the controller contains one or more web service objects (objects
|
||||
that implement an ActionWebService::API::Base definition). These web service
|
||||
objects are each mapped onto one controller action only.
|
||||
|
||||
==== Delegated dispatching example
|
||||
|
||||
class ApiController < ApplicationController
|
||||
web_service_dispatching_mode :delegated
|
||||
|
||||
web_service :person, PersonService.new
|
||||
end
|
||||
|
||||
class PersonService < ActionWebService::Base
|
||||
web_service_api PersonAPI
|
||||
|
||||
def add
|
||||
end
|
||||
|
||||
def remove
|
||||
end
|
||||
end
|
||||
|
||||
class PersonAPI < ActionWebService::API::Base
|
||||
...
|
||||
end
|
||||
|
||||
|
||||
For this example, all protocol requests for +PersonService+ are
|
||||
sent to the <tt>/api/person</tt> action.
|
||||
|
||||
The <tt>/api/person</tt> action is generated when the +web_service+
|
||||
method is called. <em>This action must not be overridden.</em>
|
||||
|
||||
Other controller actions (actions that aren't the target of a +web_service+ call)
|
||||
are ignored for ActionWebService purposes, and can do normal action tasks.
|
||||
|
||||
|
||||
=== Layered dispatching
|
||||
|
||||
This mode can be turned on by setting the +web_service_dispatching_mode+ option
|
||||
in a controller to <tt>:layered</tt>.
|
||||
|
||||
This mode is similar to _delegated_ mode, in that multiple web service objects
|
||||
can be attached to one controller, however, all protocol requests are sent to a
|
||||
single endpoint.
|
||||
|
||||
Use this mode when you want to share code between XML-RPC and SOAP clients,
|
||||
for APIs where the XML-RPC method names have prefixes. An example of such
|
||||
a method name would be <tt>blogger.newPost</tt>.
|
||||
|
||||
|
||||
==== Layered dispatching example
|
||||
|
||||
|
||||
class ApiController < ApplicationController
|
||||
web_service_dispatching_mode :layered
|
||||
|
||||
web_service :mt, MovableTypeService.new
|
||||
web_service :blogger, BloggerService.new
|
||||
web_service :metaWeblog, MetaWeblogService.new
|
||||
end
|
||||
|
||||
class MovableTypeService < ActionWebService::Base
|
||||
...
|
||||
end
|
||||
|
||||
class BloggerService < ActionWebService::Base
|
||||
...
|
||||
end
|
||||
|
||||
class MetaWeblogService < ActionWebService::API::Base
|
||||
...
|
||||
end
|
||||
|
||||
|
||||
For this example, an XML-RPC call for a method with a name like
|
||||
<tt>mt.getCategories</tt> will be sent to the <tt>getCategories</tt>
|
||||
method on the <tt>:mt</tt> service.
|
||||
|
||||
|
||||
== Customizing WSDL generation
|
||||
|
||||
You can customize the names used for the SOAP bindings in the generated
|
||||
WSDL by using the wsdl_service_name option in a controller:
|
||||
|
||||
class WsController < ApplicationController
|
||||
wsdl_service_name 'MyApp'
|
||||
end
|
||||
|
||||
You can also customize the namespace used in the generated WSDL for
|
||||
custom types and message definition types:
|
||||
|
||||
class WsController < ApplicationController
|
||||
wsdl_namespace 'http://my.company.com/app/wsapi'
|
||||
end
|
||||
|
||||
The default namespace used is 'urn:ActionWebService', if you don't supply
|
||||
one.
|
||||
|
||||
|
||||
== ActionWebService and UTF-8
|
||||
|
||||
If you're going to be sending back strings containing non-ASCII UTF-8
|
||||
characters using the <tt>:string</tt> data type, you need to make sure that
|
||||
Ruby is using UTF-8 as the default encoding for its strings.
|
||||
|
||||
The default in Ruby is to use US-ASCII encoding for strings, which causes a string
|
||||
validation check in the Ruby SOAP library to fail and your string to be sent
|
||||
back as a Base-64 value, which may confuse clients that expected strings
|
||||
because of the WSDL.
|
||||
|
||||
Two ways of setting the default string encoding are:
|
||||
|
||||
* Start Ruby using the <tt>-Ku</tt> command-line option to the Ruby executable
|
||||
* Set the <tt>$KCODE</tt> flag in <tt>config/environment.rb</tt> to the
|
||||
string <tt>'UTF8'</tt>
|
||||
|
||||
|
||||
== Testing your APIs
|
||||
|
||||
|
||||
=== Functional testing
|
||||
|
||||
You can perform testing of your APIs by creating a functional test for the
|
||||
controller dispatching the API, and calling #invoke in the test case to
|
||||
perform the invocation.
|
||||
|
||||
Example:
|
||||
|
||||
class PersonApiControllerTest < Test::Unit::TestCase
|
||||
def setup
|
||||
@controller = PersonController.new
|
||||
@request = ActionController::TestRequest.new
|
||||
@response = ActionController::TestResponse.new
|
||||
end
|
||||
|
||||
def test_add
|
||||
result = invoke :remove, 1
|
||||
assert_equal true, result
|
||||
end
|
||||
end
|
||||
|
||||
This example invokes the API method <tt>test</tt>, defined on
|
||||
the PersonController, and returns the result.
|
||||
|
||||
|
||||
=== Scaffolding
|
||||
|
||||
You can also test your APIs with a web browser by attaching scaffolding
|
||||
to the controller.
|
||||
|
||||
Example:
|
||||
|
||||
class PersonController
|
||||
web_service_scaffold :invocation
|
||||
end
|
||||
|
||||
This creates an action named <tt>invocation</tt> on the PersonController.
|
||||
|
||||
Navigating to this action lets you select the method to invoke, supply the parameters,
|
||||
and view the result of the invocation.
|
||||
|
||||
|
||||
== Using the client support
|
||||
|
||||
Action Web Service includes client classes that can use the same API
|
||||
definition as the server. The advantage of this approach is that your client
|
||||
will have the same support for Active Record and structured types as the
|
||||
server, and can just use them directly, and rely on the marshaling to Do The
|
||||
Right Thing.
|
||||
|
||||
*Note*: The client support is intended for communication between Ruby on Rails
|
||||
applications that both use Action Web Service. It may work with other servers, but
|
||||
that is not its intended use, and interoperability can't be guaranteed, especially
|
||||
not for .NET web services.
|
||||
|
||||
Web services protocol specifications are complex, and Action Web Service client
|
||||
support can only be guaranteed to work with a subset.
|
||||
|
||||
|
||||
==== Factory created client example
|
||||
|
||||
class BlogManagerController < ApplicationController
|
||||
web_client_api :blogger, :xmlrpc, 'http://url/to/blog/api/RPC2', :handler_name => 'blogger'
|
||||
end
|
||||
|
||||
class SearchingController < ApplicationController
|
||||
web_client_api :google, :soap, 'http://url/to/blog/api/beta', :service_name => 'GoogleSearch'
|
||||
end
|
||||
|
||||
See ActionWebService::API::ActionController::ClassMethods for more details.
|
||||
|
||||
==== Manually created client example
|
||||
|
||||
class PersonAPI < ActionWebService::API::Base
|
||||
api_method :find_all, :returns => [[Person]]
|
||||
end
|
||||
|
||||
soap_client = ActionWebService::Client::Soap.new(PersonAPI, "http://...")
|
||||
persons = soap_client.find_all
|
||||
|
||||
class BloggerAPI < ActionWebService::API::Base
|
||||
inflect_names false
|
||||
api_method :getRecentPosts, :returns => [[Blog::Post]]
|
||||
end
|
||||
|
||||
blog = ActionWebService::Client::XmlRpc.new(BloggerAPI, "http://.../xmlrpc", :handler_name => "blogger")
|
||||
posts = blog.getRecentPosts
|
||||
|
||||
|
||||
See ActionWebService::Client::Soap and ActionWebService::Client::XmlRpc for more details.
|
||||
|
||||
== Dependencies
|
||||
|
||||
Action Web Service requires that the Action Pack and Active Record are either
|
||||
available to be required immediately or are accessible as GEMs.
|
||||
|
||||
It also requires a version of Ruby that includes SOAP support in the standard
|
||||
library. At least version 1.8.2 final (2004-12-25) of Ruby is recommended; this
|
||||
is the version tested against.
|
||||
|
||||
|
||||
== Download
|
||||
|
||||
The latest Action Web Service version can be downloaded from
|
||||
http://rubyforge.org/projects/actionservice
|
||||
|
||||
|
||||
== Installation
|
||||
|
||||
You can install Action Web Service with the following command.
|
||||
|
||||
% [sudo] ruby setup.rb
|
||||
|
||||
|
||||
== License
|
||||
|
||||
Action Web Service is released under the MIT license.
|
||||
|
||||
|
||||
== Support
|
||||
|
||||
The Ruby on Rails mailing list
|
||||
|
||||
Or, to contact the author, send mail to bitserf@gmail.com
|
||||
|
||||
Reference in New Issue
Block a user