Permalink
Browse files

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
  • Loading branch information...
1 parent 896fea5 commit 8694a79bb2d543a46867454b743c38ce85380e4e @leonbreedt leonbreedt committed Apr 28, 2005
@@ -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,14 +10,20 @@ def self.included(base)
end
class SoapProtocol < AbstractProtocol # :nodoc:
+ DefaultEncoding = 'utf-8'
+
def marshaler
@marshaler ||= SoapMarshaler.new
end
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

0 comments on commit 8694a79

Please sign in to comment.