default to using UTF-8 as response encoding for SOAP if none is

supplied, but if an encoding is supplied by caller, use that for the
response instead (NAKAMURA Hiroshi)


git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1245 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
Leon Breedt 2005-04-28 17:55:34 +00:00
parent 896fea505b
commit 8694a79bb2
8 changed files with 51 additions and 14 deletions

@ -2,7 +2,7 @@
* Fix that generated WSDL was not using relative_url_root for base URI #1210 [Shugo Maeda]
* Use UTF-8 encoding for SOAP responses #1211 [Shugo Maeda]
* Use UTF-8 encoding by default for SOAP responses, but if an encoding is supplied by caller, use that for the response #1211 [Shugo Maeda, NAKAMURA Hiroshi]
* If the WSDL was retrieved over HTTPS, use HTTPS URLs in the WSDL too

@ -32,7 +32,7 @@ def web_service_direct_invoke(invocation)
else
return_value = self.__send__(invocation.api_method.name)
end
web_service_create_response(invocation.protocol, invocation.api, invocation.api_method, return_value)
web_service_create_response(invocation.protocol, invocation.protocol_options, invocation.api, invocation.api_method, return_value)
end
def web_service_delegated_invoke(invocation)
@ -43,13 +43,14 @@ def web_service_delegated_invoke(invocation)
if cancellation_reason
raise(DispatcherError, "request canceled: #{cancellation_reason}")
end
web_service_create_response(invocation.protocol, invocation.api, invocation.api_method, return_value)
web_service_create_response(invocation.protocol, invocation.protocol_options, invocation.api, invocation.api_method, return_value)
end
def web_service_invocation(request)
public_method_name = request.method_name
invocation = Invocation.new
invocation.protocol = request.protocol
invocation.protocol_options = request.protocol_options
invocation.service_name = request.service_name
if web_service_dispatching_mode == :layered
case invocation.protocol
@ -109,18 +110,19 @@ def web_service_invocation(request)
invocation
end
def web_service_create_response(protocol, api, api_method, return_value)
def web_service_create_response(protocol, protocol_options, api, api_method, return_value)
if api.has_api_method?(api_method.name)
return_type = api_method.returns ? api_method.returns[0] : nil
return_value = api_method.cast_returns(return_value)
else
return_type = ActionWebService::SignatureTypes.canonical_signature_entry(return_value.class, 0)
end
protocol.encode_response(api_method.public_name + 'Response', return_value, return_type)
protocol.encode_response(api_method.public_name + 'Response', return_value, return_type, protocol_options)
end
class Invocation # :nodoc:
attr_accessor :protocol
attr_accessor :protocol_options
attr_accessor :service_name
attr_accessor :api
attr_accessor :api_method

@ -85,7 +85,7 @@ def send_web_service_error_response(request, exception)
api_method = request.api_method
public_method_name = api_method ? api_method.public_name : request.method_name
return_type = ActionWebService::SignatureTypes.canonical_signature_entry(Exception, 0)
response = request.protocol.encode_response(public_method_name + 'Response', exception, return_type)
response = request.protocol.encode_response(public_method_name + 'Response', exception, return_type, request.protocol_options)
send_web_service_response(response)
else
if self.class.web_service_exception_reporting

@ -17,7 +17,7 @@ def encode_action_pack_request(service_name, public_method_name, raw_body, optio
request
end
def decode_request(raw_request, service_name, protocol_options=nil)
def decode_request(raw_request, service_name, protocol_options={})
end
def encode_request(method_name, params, param_types)
@ -26,7 +26,7 @@ def encode_request(method_name, params, param_types)
def decode_response(raw_response)
end
def encode_response(method_name, return_value, return_type)
def encode_response(method_name, return_value, return_type, protocol_options={})
end
def protocol_client(api, protocol_name, endpoint_uri, options)

@ -1,4 +1,5 @@
require 'action_web_service/protocol/soap_protocol/marshaler'
require 'soap/streamHandler'
module ActionWebService # :nodoc:
module Protocol # :nodoc:
@ -9,6 +10,8 @@ def self.included(base)
end
class SoapProtocol < AbstractProtocol # :nodoc:
DefaultEncoding = 'utf-8'
def marshaler
@marshaler ||= SoapMarshaler.new
end
@ -16,7 +19,11 @@ def marshaler
def decode_action_pack_request(action_pack_request)
return nil unless soap_action = has_valid_soap_action?(action_pack_request)
service_name = action_pack_request.parameters['action']
protocol_options = { :soap_action => soap_action }
charset = parse_charset(action_pack_request.env['HTTP_CONTENT_TYPE'])
protocol_options = {
:soap_action => soap_action,
:charset => charset
}
decode_request(action_pack_request.raw_post, service_name, protocol_options)
end
@ -26,8 +33,9 @@ def encode_action_pack_request(service_name, public_method_name, raw_body, optio
request
end
def decode_request(raw_request, service_name, protocol_options=nil)
envelope = SOAP::Processor.unmarshal(raw_request)
def decode_request(raw_request, service_name, protocol_options={})
charset = protocol_options[:charset] || DefaultEncoding
envelope = SOAP::Processor.unmarshal(raw_request, :charset => charset)
unless envelope
raise ProtocolError, "Failed to parse SOAP request message"
end
@ -66,7 +74,7 @@ def decode_response(raw_response)
[method_name, return_value]
end
def encode_response(method_name, return_value, return_type)
def encode_response(method_name, return_value, return_type, protocol_options={})
if return_type
return_binding = marshaler.register_type(return_type)
marshaler.annotate_arrays(return_binding, return_value)
@ -93,7 +101,8 @@ def encode_response(method_name, return_value, return_type)
end
end
envelope = create_soap_envelope(response)
Response.new(SOAP::Processor.marshal(envelope), 'text/xml; charset=utf-8', return_value)
charset = protocol_options[:charset] || DefaultEncoding
Response.new(SOAP::Processor.marshal(envelope, :charset => charset), "text/xml; charset=#{charset}", return_value)
end
def protocol_client(api, protocol_name, endpoint_uri, options={})
@ -121,6 +130,15 @@ def has_valid_soap_action?(request)
soap_action
end
def parse_charset(content_type)
return DefaultEncoding if content_type.nil?
if /^text\/xml(?:\s*;\s*charset=([^"]+|"[^"]+"))$/i =~ content_type
$1
else
DefaultEncoding
end
end
def create_soap_envelope(body)
header = SOAP::SOAPHeader.new
body = SOAP::SOAPBody.new(body)

@ -34,7 +34,7 @@ def decode_response(raw_response)
[nil, XMLRPC::Marshal.load_response(raw_response)]
end
def encode_response(method_name, return_value, return_type)
def encode_response(method_name, return_value, return_type, protocol_options={})
return_value = true if return_value.nil?
if return_type
return_value = value_to_xmlrpc_wire_format(return_value, return_type)

@ -379,6 +379,12 @@ def is_exception?(obj)
raise NotImplementedError
end
def update_request(ap_request)
end
def check_response(ap_response)
end
def do_method_call(container, public_method_name, *params)
request_env = {}
mode = container.web_service_dispatching_mode
@ -416,9 +422,11 @@ def do_method_call(container, public_method_name, *params)
# puts body
ap_request = @protocol.encode_action_pack_request(service_name, public_method_name, body, :request_class => ActionController::TestRequest)
ap_request.env.update(request_env)
update_request(ap_request)
ap_response = ActionController::TestResponse.new
container.process(ap_request, ap_response)
# puts ap_response.body
check_response(ap_response)
public_method_name, return_value = @protocol.decode_response(ap_response.body)
unless is_exception?(return_value) || virtual
return_value = method.cast_returns(return_value)

@ -68,6 +68,15 @@ def test_layered_dispatching
end
protected
def update_request(ap_request)
ap_request.env.update('HTTP_CONTENT_TYPE' => 'text/xml; charset=us-ascii')
end
def check_response(ap_response)
assert_equal 'text/xml; charset=us-ascii', ap_response.headers['Content-Type']
assert_match /xml.*?encoding="us-ascii"/, ap_response.body
end
def exception_message(soap_fault_exception)
soap_fault_exception.detail.cause.message
end