diff options
Diffstat (limited to 'actionwebservice')
8 files changed, 51 insertions, 14 deletions
diff --git a/actionwebservice/CHANGELOG b/actionwebservice/CHANGELOG index 9468d47488..277bdb4eaf 100644 --- a/actionwebservice/CHANGELOG +++ b/actionwebservice/CHANGELOG @@ -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 diff --git a/actionwebservice/lib/action_web_service/dispatcher/abstract.rb b/actionwebservice/lib/action_web_service/dispatcher/abstract.rb index bec38d8c1c..e60f30a05b 100644 --- a/actionwebservice/lib/action_web_service/dispatcher/abstract.rb +++ b/actionwebservice/lib/action_web_service/dispatcher/abstract.rb @@ -32,7 +32,7 @@ module ActionWebService # :nodoc: 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 @@ module ActionWebService # :nodoc: 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 @@ module ActionWebService # :nodoc: 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 diff --git a/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb b/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb index bce3f4e944..55f0e96600 100644 --- a/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +++ b/actionwebservice/lib/action_web_service/dispatcher/action_controller_dispatcher.rb @@ -85,7 +85,7 @@ module ActionWebService # :nodoc: 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 diff --git a/actionwebservice/lib/action_web_service/protocol/abstract.rb b/actionwebservice/lib/action_web_service/protocol/abstract.rb index d8830968d0..3819aa2ade 100644 --- a/actionwebservice/lib/action_web_service/protocol/abstract.rb +++ b/actionwebservice/lib/action_web_service/protocol/abstract.rb @@ -17,7 +17,7 @@ module ActionWebService # :nodoc: 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 @@ module ActionWebService # :nodoc: 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) diff --git a/actionwebservice/lib/action_web_service/protocol/soap_protocol.rb b/actionwebservice/lib/action_web_service/protocol/soap_protocol.rb index b3f1be2ae4..3e5bad0086 100644 --- a/actionwebservice/lib/action_web_service/protocol/soap_protocol.rb +++ b/actionwebservice/lib/action_web_service/protocol/soap_protocol.rb @@ -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 @@ module ActionWebService # :nodoc: end class SoapProtocol < AbstractProtocol # :nodoc: + DefaultEncoding = 'utf-8' + def marshaler @marshaler ||= SoapMarshaler.new end @@ -16,7 +19,11 @@ module ActionWebService # :nodoc: 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 @@ module ActionWebService # :nodoc: 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 @@ module ActionWebService # :nodoc: [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 @@ module ActionWebService # :nodoc: 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 @@ module ActionWebService # :nodoc: 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) diff --git a/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb b/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb index af3c1a49f6..d20fe05726 100644 --- a/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb +++ b/actionwebservice/lib/action_web_service/protocol/xmlrpc_protocol.rb @@ -34,7 +34,7 @@ module ActionWebService # :nodoc: [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) diff --git a/actionwebservice/test/abstract_dispatcher.rb b/actionwebservice/test/abstract_dispatcher.rb index 0fe7525c48..70ad04d745 100644 --- a/actionwebservice/test/abstract_dispatcher.rb +++ b/actionwebservice/test/abstract_dispatcher.rb @@ -379,6 +379,12 @@ module DispatcherCommonTests 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 @@ module DispatcherCommonTests # 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) diff --git a/actionwebservice/test/dispatcher_action_controller_soap_test.rb b/actionwebservice/test/dispatcher_action_controller_soap_test.rb index 731185f398..4451c23f3c 100644 --- a/actionwebservice/test/dispatcher_action_controller_soap_test.rb +++ b/actionwebservice/test/dispatcher_action_controller_soap_test.rb @@ -68,6 +68,15 @@ class TC_DispatcherActionControllerSoap < Test::Unit::TestCase 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 |