Skip to content

Commit

Permalink
first pass of web service scaffolding. add ability to quickly generat…
Browse files Browse the repository at this point in the history
…e an

action pack request for a protocol, add missing log_error when we fail to parse
protocol messages. add RDoc for scaffolding and functional testing.


git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1037 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information
leonbreedt committed Mar 29, 2005
1 parent 715715a commit b94bd32
Show file tree
Hide file tree
Showing 19 changed files with 451 additions and 28 deletions.
4 changes: 4 additions & 0 deletions actionwebservice/CHANGELOG
Original file line number Original file line Diff line number Diff line change
@@ -1,7 +1,11 @@
*0.7.0* (Unreleased) *0.7.0* (Unreleased)


* Add scaffolding via ActionController::Base.web_service_scaffold for quick testing using a web browser

* Generalize casting code to be used by both SOAP and XML-RPC (previously, it was only XML-RPC) * Generalize casting code to be used by both SOAP and XML-RPC (previously, it was only XML-RPC)


* Include backtraces in 500 error responses for failed request parsing, and remove "rescue nil" statements obscuring real errors for XML-RPC



*0.6.2* (27th March, 2005) *0.6.2* (27th March, 2005)


Expand Down
45 changes: 45 additions & 0 deletions actionwebservice/README
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -197,6 +197,51 @@ For this example, a remote call for a method with a name like
method on the <tt>:mt</tt> service. method on the <tt>:mt</tt> service.




== 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 == Using the client support


Action Web Service includes client classes that can use the same API Action Web Service includes client classes that can use the same API
Expand Down
6 changes: 5 additions & 1 deletion actionwebservice/TODO
Original file line number Original file line Diff line number Diff line change
@@ -1,6 +1,10 @@
= 0.7.0 = 0.7.0
- WS Dynamic Scaffolding - WS Dynamic Scaffolding
- WS Scaffolding Generators * add protocol selection ability
* test with XML-RPC (namespaced method name support)
* support structured types as input parameters with the input field helper

- update manual for scaffolding and functional testing


= 0.8.0 = 0.8.0
- Consumption of WSDL services - Consumption of WSDL services
Expand Down
2 changes: 2 additions & 0 deletions actionwebservice/lib/action_web_service.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
require 'action_web_service/protocol' require 'action_web_service/protocol'
require 'action_web_service/struct' require 'action_web_service/struct'
require 'action_web_service/dispatcher' require 'action_web_service/dispatcher'
require 'action_web_service/scaffolding'


ActionWebService::Base.class_eval do ActionWebService::Base.class_eval do
include ActionWebService::Container::Direct include ActionWebService::Container::Direct
Expand All @@ -61,4 +62,5 @@
include ActionWebService::Container::ActionController include ActionWebService::Container::ActionController
include ActionWebService::Dispatcher include ActionWebService::Dispatcher
include ActionWebService::Dispatcher::ActionController include ActionWebService::Dispatcher::ActionController
include ActionWebService::Scaffolding
end end
21 changes: 21 additions & 0 deletions actionwebservice/lib/action_web_service/api/base.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -284,10 +284,31 @@ def cast_returns(marshaler, return_value)
marshaler.cast_inbound_recursive(return_value, @returns[0]) marshaler.cast_inbound_recursive(return_value, @returns[0])
end end


# String representation of this method
def to_s
fqn = ""
fqn << (@returns ? (friendly_param(@returns[0], nil) + " ") : "void ")
fqn << "#{@public_name}("
if @expects
i = 0
fqn << @expects.map{ |p| friendly_param(p, i+= 1) }.join(", ")
end
fqn << ")"
fqn
end

private private
def response_name(encoder) def response_name(encoder)
encoder.is_a?(WS::Encoding::SoapRpcEncoding) ? (@public_name + "Response") : @public_name encoder.is_a?(WS::Encoding::SoapRpcEncoding) ? (@public_name + "Response") : @public_name
end end

def friendly_param(spec, i)
name = param_name(spec, i)
type = param_type(spec)
spec = spec.values.first if spec.is_a?(Hash)
type = spec.is_a?(Array) ? (type.to_s + "[]") : type.to_s
i ? (type + " " + name) : type
end
end end
end end
end end
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def dispatch_web_service_request
end end
else else
exception ||= DispatcherError.new("Malformed SOAP or XML-RPC protocol message") exception ||= DispatcherError.new("Malformed SOAP or XML-RPC protocol message")
log_error(exception) unless logger.nil?
send_web_service_error_response(request, exception) send_web_service_error_response(request, exception)
end end
rescue Exception => e rescue Exception => e
Expand Down
54 changes: 54 additions & 0 deletions actionwebservice/lib/action_web_service/protocol/abstract.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -7,10 +7,64 @@ class AbstractProtocol
attr :marshaler attr :marshaler
attr :encoder attr :encoder


def unmarshal_request(ap_request)
end

def marshal_response(method, return_value) def marshal_response(method, return_value)
body = method.encode_rpc_response(marshaler, encoder, return_value) body = method.encode_rpc_response(marshaler, encoder, return_value)
Response.new(body, 'text/xml') Response.new(body, 'text/xml')
end end

def protocol_client(api, protocol_name, endpoint_uri, options)
end

def create_action_pack_request(service_name, public_method_name, raw_body, options={})
klass = options[:request_class] || SimpleActionPackRequest
request = klass.new
request.request_parameters['action'] = service_name.to_s
request.env['RAW_POST_DATA'] = raw_body
request.env['REQUEST_METHOD'] = 'POST'
request.env['HTTP_CONTENT_TYPE'] = 'text/xml'
request
end
end

class SimpleActionPackRequest < ActionController::AbstractRequest
def initialize
@env = {}
@qparams = {}
@rparams = {}
@cookies = {}
reset_session
end

def query_parameters
@qparams
end

def request_parameters
@rparams
end

def env
@env
end

def host
''
end

def cookies
@cookies
end

def session
@session
end

def reset_session
@session = {}
end
end end


class Request # :nodoc: class Request # :nodoc:
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -20,11 +20,17 @@ def unmarshal_request(ap_request)
Request.new(self, method_name, params, service_name) Request.new(self, method_name, params, service_name)
end end


def protocol_client(api, protocol_name, endpoint_uri, options) def protocol_client(api, protocol_name, endpoint_uri, options={})
return nil unless protocol_name == :soap return nil unless protocol_name == :soap
ActionWebService::Client::Soap.new(api, endpoint_uri, options) ActionWebService::Client::Soap.new(api, endpoint_uri, options)
end end


def create_action_pack_request(service_name, public_method_name, raw_body, options={})
request = super
request.env['HTTP_SOAPACTION'] = '/soap/%s/%s' % [service_name, public_method_name]
request
end

private private
def has_valid_soap_action?(request) def has_valid_soap_action?(request)
return nil unless request.method == :post return nil unless request.method == :post
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def unmarshal_request(ap_request)
Request.new(self, method_name, params, service_name) Request.new(self, method_name, params, service_name)
end end


def protocol_client(api, protocol_name, endpoint_uri, options) def protocol_client(api, protocol_name, endpoint_uri, options={})
return nil unless protocol_name == :xmlrpc return nil unless protocol_name == :xmlrpc
ActionWebService::Client::XmlRpc.new(api, endpoint_uri, options) ActionWebService::Client::XmlRpc.new(api, endpoint_uri, options)
end end
Expand Down
Loading

0 comments on commit b94bd32

Please sign in to comment.