Skip to content
This repository

rpclib-2.6.0 commits #122

Merged
merged 30 commits into from about 2 years ago

1 participant

Burak Arslan
Burak Arslan
Owner

HttpRpc now supports parsing POST Requests, thanks to werkzeug, among many other fixes and small improvements.

and others added some commits January 16, 2012
Burak Arslan latest WS-I test results aa3365c
Burak Arslan add mandatory unsignedinteger type 2e61fb8
Burak Arslan fix backwards-incompatible validator argument in XmlObject c73e047
Burak Arslan utf8 -> UTF-8 8a07943
Burak Arslan not-so-important refactoring 58a282a
Burak Arslan avoid inheritance hierarchies for simpleTypes. 50faf38
Burak Arslan make static files directory that the twisted wrapper publishes dynamic 1ec6af5
Burak Arslan use werkzeug to parse HTTP POST data. 41c7e72
Burak Arslan remove now needless empty input check. 882f358
Burak Arslan ByteArray is now effectively a primitive. e119d7d
Burak Arslan version and changelog update. 34f45ba
Burak Arslan separated call handle and method context generation. 8daa470
Burak Arslan Merge branch 'http-post' d27779f
Burak Arslan changelog update 194b927
Burak Arslan pep8 tweaks 6e7c9d4
Burak Arslan instead of initializing every known instance property as None, Comple…
…xModel default ctor now deletes data from class properties and sets only what it's passed to as **kwargs.
14a66ec
Burak Arslan fix old class definition in sqlalchemy example. 5300b81
Burak Arslan move logic in context dtor to event handler. 875baab
Burak Arslan add method_request_string to XmlObject logger.debug line. 84aab05
Add werkzeug to requirements in README.rst 5c5bceb
Burak Arslan handle missing Content-Type header #119 c013c34
Burak Arslan lowercase encoding name. #119 9371104
Burak Arslan readme update, fix funny typo :) 17a323f
Burak Arslan add RequestNotAllowed error. #119 7b85907
Burak Arslan have rpclib return the relevant HTTP error on RequestNotAllowed excep…
…tion. #119
1f90db8
Burak Arslan handle incorrect soap request for http transport. #119 990f74a
Burak Arslan implement _force_own_namespace 11ce8de
Burak Arslan fix race condition in wsgi server wsdl request. bc983b4
Burak Arslan changelog update. e86ed0c
Burak Arslan readme update 9a0e28e
Burak Arslan plq merged commit 72ebdd9 into from February 12, 2012
Burak Arslan plq closed this February 12, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 30 unique commits by 2 authors.

Jan 16, 2012
Burak Arslan latest WS-I test results aa3365c
Jan 17, 2012
Burak Arslan add mandatory unsignedinteger type 2e61fb8
Jan 24, 2012
Burak Arslan fix backwards-incompatible validator argument in XmlObject c73e047
Jan 25, 2012
Burak Arslan utf8 -> UTF-8 8a07943
Jan 27, 2012
Burak Arslan not-so-important refactoring 58a282a
Jan 28, 2012
Burak Arslan avoid inheritance hierarchies for simpleTypes. 50faf38
Jan 29, 2012
Burak Arslan make static files directory that the twisted wrapper publishes dynamic 1ec6af5
Jan 30, 2012
Burak Arslan use werkzeug to parse HTTP POST data. 41c7e72
Burak Arslan remove now needless empty input check. 882f358
Burak Arslan ByteArray is now effectively a primitive. e119d7d
Burak Arslan version and changelog update. 34f45ba
Burak Arslan separated call handle and method context generation. 8daa470
Burak Arslan Merge branch 'http-post' d27779f
Feb 12, 2012
Burak Arslan changelog update 194b927
Burak Arslan pep8 tweaks 6e7c9d4
Burak Arslan instead of initializing every known instance property as None, Comple…
…xModel default ctor now deletes data from class properties and sets only what it's passed to as **kwargs.
14a66ec
Burak Arslan fix old class definition in sqlalchemy example. 5300b81
Burak Arslan move logic in context dtor to event handler. 875baab
Burak Arslan add method_request_string to XmlObject logger.debug line. 84aab05
Add werkzeug to requirements in README.rst 5c5bceb
Burak Arslan handle missing Content-Type header #119 c013c34
Burak Arslan lowercase encoding name. #119 9371104
Burak Arslan readme update, fix funny typo :) 17a323f
Burak Arslan add RequestNotAllowed error. #119 7b85907
Burak Arslan have rpclib return the relevant HTTP error on RequestNotAllowed excep…
…tion. #119
1f90db8
Burak Arslan handle incorrect soap request for http transport. #119 990f74a
Burak Arslan implement _force_own_namespace 11ce8de
Burak Arslan fix race condition in wsgi server wsdl request. bc983b4
Burak Arslan changelog update. e86ed0c
Burak Arslan readme update 9a0e28e
This page is out of date. Refresh to see the latest.
9  CHANGELOG.rst
Source Rendered
@@ -2,6 +2,15 @@
2 2
 Changelog
3 3
 =========
4 4
 
  5
+rpclib-2.6.0-beta
  6
+-----------------
  7
+ * HttpRpc now parses POST/PUT/PATCH bodies, can accept file uploads.
  8
+   Uses werkzeug to do that, which is now a soft dependency.
  9
+ * ByteArray now child of SimpleModel. It's now possible to customize it simply
  10
+   by calling it.
  11
+ * Fix race condition in wsgi server wsdl request.
  12
+ * Full change log: https://github.com/arskom/rpclib/pull/122
  13
+
5 14
 rpclib-2.5.2-beta
6 15
 -----------------
7 16
  * Misc. fixes.
5  README.rst
Source Rendered
@@ -57,7 +57,10 @@ that Rpclib supports:
57 57
   :class:`rpclib.client.zeromq.ZeroMQClient` and
58 58
   :class:`rpclib.server.zeromq.ZeroMQServer`.
59 59
 * A Wsgi server of your choice to wrap :class:`rpclib.server.wsgi.WsgiApplication`.
60  
-* `Werkzeug <http://werkzeug.pocoo.org/>` is needed for :class:`rpclib.protocol.http.HttpSoap`.
  60
+* `Werkzeug <http://werkzeug.pocoo.org/>` is needed for :class:`rpclib.protocol.http.HttpRpc`.
  61
+
  62
+You are advised to add these as requirements to your own projects, as these are
  63
+only "soft" dependencies of rpclib, thus not handled in its setup script.
61 64
 
62 65
 Installing
63 66
 ==========
8  examples/user_manager/server_sqlalchemy.py
@@ -76,7 +76,7 @@ class User(TableModel, DeclarativeBase):
76 76
 
77 77
 # this is the same as the above user object. Use this method of declaring
78 78
 # objects for tables that have to be defined elsewhere.
79  
-class AlternativeUser(TableSerializer, DeclarativeBase):
  79
+class AlternativeUser(TableModel, DeclarativeBase):
80 80
     __namespace__ = 'rpclib.examples.user_manager'
81 81
     __table__ = User.__table__
82 82
 
@@ -108,16 +108,12 @@ class UserDefinedContext(object):
108 108
     def __init__(self):
109 109
         self.session = Session()
110 110
 
111  
-    def __del__(self):
112  
-        self.session.close()
113  
-
114 111
 def _on_method_call(ctx):
115 112
     ctx.udc = UserDefinedContext()
116 113
 
117 114
 def _on_method_return_object(ctx):
118  
-    # we don't do this in UserDefinedContext.__del__ simply to be able to alert
119  
-    # the client in case the commit fails.
120 115
     ctx.udc.session.commit()
  116
+    ctx.udc.session.close()
121 117
 
122 118
 application = Application([UserManagerService], 'rpclib.examples.user_manager',
123 119
             interface=Wsdl11(), in_protocol=Soap11(), out_protocol=Soap11())
2  src/rpclib/__init__.py
@@ -17,7 +17,7 @@
17 17
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
18 18
 #
19 19
 
20  
-__version__ = '2.5.2-beta'
  20
+__version__ = '2.6.0-beta'
21 21
 
22 22
 from rpclib._base import TransportContext
23 23
 from rpclib._base import EventContext
6  src/rpclib/decorator.py
@@ -158,11 +158,13 @@ def explain_method(*args, **kwargs):
158 158
             _no_ctx = kparams.get('_no_ctx', True)
159 159
             _udp = kparams.get('_udp', None)
160 160
 
  161
+            _faults = None
161 162
             if ('_faults' in kparams) and ('_throws' in kparams):
162 163
                 raise ValueError("only one of '_throws ' and '_faults' arguments"
163 164
                                  "should be given, as they're synonyms.")
164  
-            _faults = kparams.get('_faults', None)
165  
-            if _faults is None:
  165
+            elif '_faults' in kparams:
  166
+                _faults = kparams.get('_faults', None)
  167
+            elif '_throws' in kparams:
166 168
                 _faults = kparams.get('_throws', None)
167 169
 
168 170
             _in_message_name = kparams.get('_in_message_name', function_name)
9  src/rpclib/error.py
@@ -8,12 +8,17 @@ def __init__(self, faultstring="Requested resource not found"):
8 8
 
9 9
 class RequestTooLongError(Fault):
10 10
     """Raised when the request is too long."""
11  
-    def __init__(self, faultstring):
  11
+    def __init__(self, faultstring=""):
12 12
         Fault.__init__(self, 'Client.RequestTooLong', faultstring)
13 13
 
  14
+class RequestNotAllowed(Fault):
  15
+    """Raised when the request is incomplete."""
  16
+    def __init__(self, faultstring=""):
  17
+        Fault.__init__(self, 'Client.RequestNotAllowed', faultstring)
  18
+
14 19
 class ArgumentError(Fault):
15 20
     """Raised when there is a general problem with input data."""
16  
-    def __init__(self, faultstring):
  21
+    def __init__(self, faultstring=""):
17 22
         Fault.__init__(self, 'Client.ArgumentError', faultstring)
18 23
 
19 24
 class ValidationError(Fault):
4  src/rpclib/interface/_base.py
@@ -145,7 +145,9 @@ def populate_interface(self, types=None):
145 145
 
146 146
         # populate types
147 147
         for s in self.services:
148  
-            logger.debug("populating '%s.%s (%s) ' types..." % (s.__module__, s.__name__, s.get_service_key()))
  148
+            logger.debug("populating '%s.%s (%s) ' types..." % (s.__module__,
  149
+                                                s.__name__, s.get_service_key()))
  150
+
149 151
             for method in s.public_methods.values():
150 152
                 if method.in_header is None:
151 153
                     method.in_header = s.__in_header__
3  src/rpclib/interface/xml_schema/model/_base.py
@@ -33,8 +33,7 @@ def simple_get_restriction_tag(interface, cls):
33 33
     restriction.set('base', cls.__base_type__.get_type_name_ns(interface))
34 34
 
35 35
     for v in cls.Attributes.values:
36  
-        enumeration = etree.SubElement(restriction,
37  
-                                                '{%s}enumeration' % _ns_xsd)
  36
+        enumeration = etree.SubElement(restriction, '{%s}enumeration' % _ns_xsd)
38 37
         enumeration.set('value', str(v))
39 38
 
40 39
     return restriction
14  src/rpclib/model/_base.py
@@ -95,6 +95,8 @@ class Annotations(object):
95 95
     class Empty(object):
96 96
         pass
97 97
 
  98
+    _force_own_namespace = set()
  99
+
98 100
     @staticmethod
99 101
     def is_default(cls):
100 102
         return True
@@ -136,6 +138,9 @@ def resolve_namespace(cls, default_ns):
136 138
         if cls.__namespace__ is None:
137 139
             cls.__namespace__ = cls.__module__
138 140
 
  141
+        for c in cls._force_own_namespace:
  142
+            c.__namespace__ = cls.__namespace__
  143
+
139 144
     @classmethod
140 145
     def get_type_name(cls):
141 146
         """Returns the class name unless the __type_name__ attribute is defined.
@@ -234,6 +239,7 @@ def validate_native(cls, value):
234 239
         """Override this method to do your own input validation on the native
235 240
         value. This is called after converting the incoming string to the
236 241
         native python value."""
  242
+
237 243
         return True
238 244
 
239 245
 class Null(ModelBase):
@@ -267,7 +273,11 @@ def __new__(cls, **kwargs):
267 273
         retval = cls.customize( ** kwargs)
268 274
 
269 275
         if not retval.is_default(retval):
270  
-            retval.__base_type__ = cls
  276
+            if hasattr(cls, '_is_clone_of'):
  277
+                retval.__base_type__ = cls._is_clone_of
  278
+            else:
  279
+                retval.__base_type__ = cls
  280
+
271 281
             retval.__type_name__ = kwargs.get("type_name", ModelBase.Empty)
272 282
 
273 283
         return retval
@@ -278,7 +288,7 @@ def is_default(cls):
278 288
 
279 289
     @staticmethod
280 290
     def validate_string(cls, value):
281  
-        return (    ModelBase.validate_string(cls, value)
  291
+        return (     ModelBase.validate_string(cls, value)
282 292
                 and (len(cls.Attributes.values) == 0 or
283 293
                                                 value in cls.Attributes.values)
284 294
             )
3  src/rpclib/model/binary.py
@@ -29,9 +29,10 @@
29 29
 from rpclib.model import nillable_string
30 30
 from rpclib.model import nillable_iterable
31 31
 from rpclib.model import ModelBase
  32
+from rpclib.model import SimpleModel
32 33
 
33 34
 
34  
-class ByteArray(ModelBase):
  35
+class ByteArray(SimpleModel):
35 36
     """Handles anything other than ascii or unicode-encoded data. Every protocol
36 37
     has a different way to handle arbitrary data. E.g. xml-based protocols
37 38
     encode this as base64, while HttpRpc just hands it over.
10  src/rpclib/model/complex.py
@@ -151,11 +151,17 @@ class ComplexModelBase(ModelBase):
151 151
     from.
152 152
     """
153 153
 
154  
-    def __init__(self, ** kwargs):
  154
+    def __init__(self, **kwargs):
155 155
         super(ComplexModelBase, self).__init__()
156 156
 
157 157
         for k in self.get_flat_type_info(self.__class__).keys():
158  
-            setattr(self, k, kwargs.get(k, None))
  158
+            try:
  159
+                delattr(self, k)
  160
+            except:
  161
+                pass
  162
+
  163
+        for k,v in kwargs.items():
  164
+            setattr(self, k, v)
159 165
 
160 166
     def __len__(self):
161 167
         return len(self._type_info)
1  src/rpclib/model/primitive.py
@@ -554,3 +554,4 @@ class Mandatory(object):
554 554
 
555 555
     String = String(type_name="mandatory_string", min_occurs=1, nillable=False, min_len=1)
556 556
     Integer = Integer(type_name="mandatory_integer", min_occurs=1, nillable=False)
  557
+    UnsignedInteger = UnsignedInteger(type_name="mandatory_unsigned_integer", min_occurs=1, nillable=False)
33  src/rpclib/protocol/_base.py
@@ -34,11 +34,13 @@
34 34
 
35 35
 from rpclib.const.http import HTTP_400
36 36
 from rpclib.const.http import HTTP_404
  37
+from rpclib.const.http import HTTP_405
37 38
 from rpclib.const.http import HTTP_413
38 39
 from rpclib.const.http import HTTP_500
39 40
 
40 41
 from rpclib.error import ResourceNotFoundError
41 42
 from rpclib.error import RequestTooLongError
  43
+from rpclib.error import RequestNotAllowed
42 44
 from rpclib.error import Fault
43 45
 
44 46
 class ProtocolBase(object):
@@ -142,19 +144,9 @@ def set_method_descriptor(self, ctx):
142 144
             raise ResourceNotFoundError('Method %r not found.' % name)
143 145
 
144 146
     def generate_method_contexts(self, ctx):
145  
-        """Method to be overriden to perform any sort of custom matching between
146  
-        the method_request_string and the methods. Returns a list of contexts.
147  
-        Can return multiple contexts if a method_request_string matches more
148  
-        than one function. (This is called the fanout mode.)
149  
-        """
150  
-
151  
-        name = ctx.method_request_string
152  
-        if not name.startswith("{"):
153  
-            name = '{%s}%s' % (self.app.interface.get_tns(), name)
154  
-
155  
-        call_handles = self.app.interface.service_method_map.get(name, [])
  147
+        call_handles = self.get_call_handles(ctx)
156 148
         if len(call_handles) == 0:
157  
-            raise ResourceNotFoundError('Method %r not found.' % name)
  149
+            raise ResourceNotFoundError('Method %r not found.' % ctx.method_request_string)
158 150
 
159 151
         retval = []
160 152
         for sc, d in call_handles:
@@ -169,11 +161,28 @@ def generate_method_contexts(self, ctx):
169 161
 
170 162
         return retval
171 163
 
  164
+    def get_call_handles(self, ctx):
  165
+        """Method to be overriden to perform any sort of custom method mapping
  166
+        using any data in the method context. Returns a list of contexts.
  167
+        Can return multiple contexts if a method_request_string matches more
  168
+        than one function. (This is called the fanout mode.)
  169
+        """
  170
+
  171
+        name = ctx.method_request_string
  172
+        if not name.startswith("{"):
  173
+            name = '{%s}%s' % (self.app.interface.get_tns(), name)
  174
+
  175
+        call_handles = self.app.interface.service_method_map.get(name, [])
  176
+
  177
+        return call_handles
  178
+
172 179
     def fault_to_http_response_code(self, fault):
173 180
         if isinstance(fault, RequestTooLongError):
174 181
             return HTTP_413
175 182
         if isinstance(fault, ResourceNotFoundError):
176 183
             return HTTP_404
  184
+        if isinstance(fault, RequestNotAllowed):
  185
+            return HTTP_405
177 186
         if isinstance(fault, Fault) and (fault.faultcode.startswith('Client.')
178 187
                                                 or fault.faultcode == 'Client'):
179 188
             return HTTP_400
76  src/rpclib/protocol/http.py
@@ -30,10 +30,20 @@
30 30
     from urllib.parse import parse_qs
31 31
 
32 32
 from rpclib.error import ValidationError
33  
-from rpclib.model.complex import Array
  33
+from rpclib.model.binary import ByteArray
34 34
 from rpclib.model.fault import Fault
35 35
 from rpclib.protocol import ProtocolBase
36 36
 
  37
+from werkzeug.formparser import parse_form_data
  38
+
  39
+STREAM_READ_BLOCK_SIZE = 16384
  40
+
  41
+def yield_stream(istr):
  42
+    data = istr.read(STREAM_READ_BLOCK_SIZE)
  43
+    while len(data) > 0:
  44
+        yield data
  45
+        data = istr.read(STREAM_READ_BLOCK_SIZE)
  46
+
37 47
 def _get_http_headers(req_env):
38 48
     retval = {}
39 49
 
@@ -68,11 +78,36 @@ def create_in_document(self, ctx, in_string_encoding=None):
68 78
     def decompose_incoming_envelope(self, ctx):
69 79
         ctx.method_request_string = '{%s}%s' % (self.app.interface.get_tns(),
70 80
                               ctx.in_document['PATH_INFO'].split('/')[-1])
  81
+
71 82
         logger.debug("\033[92mMethod name: %r\033[0m" % ctx.method_request_string)
72 83
 
73 84
         ctx.in_header_doc = _get_http_headers(ctx.in_document)
74 85
         ctx.in_body_doc = parse_qs(ctx.in_document['QUERY_STRING'])
75 86
 
  87
+        if ctx.transport.req_env['REQUEST_METHOD'].lower() in ('post', 'put', 'patch'):
  88
+            stream, form, files = parse_form_data(ctx.transport.req_env)
  89
+
  90
+            for k, v in form.lists():
  91
+                val = ctx.in_body_doc.get(k, [])
  92
+                val.extend(v)
  93
+                ctx.in_body_doc[k] = val
  94
+
  95
+            for k, v in files.items():
  96
+                val = ctx.in_body_doc.get(k, [])
  97
+                val.append(yield_stream(v.stream))
  98
+                ctx.in_body_doc[k] = val
  99
+
  100
+                # FIXME: some proper variable matching is needed here.
  101
+                k2 = k + "_name"
  102
+                val = ctx.in_body_doc.get(k2, [])
  103
+                val.append(v.filename)
  104
+                ctx.in_body_doc[k2] = val
  105
+
  106
+                k2 = k + "_type"
  107
+                val = ctx.in_body_doc.get(k2, [])
  108
+                val.append(v.headers.get('Content-Type','application/octet-stream'))
  109
+                ctx.in_body_doc[k2] = val
  110
+
76 111
         logger.debug('\theader : %r' % (ctx.in_header_doc))
77 112
         logger.debug('\tbody   : %r' % (ctx.in_body_doc))
78 113
 
@@ -101,7 +136,16 @@ def dict_to_object(self, doc, inst_class):
101 136
                 if (self.validator is self.SOFT_VALIDATION and not
102 137
                             member.type.validate_string(member.type, v2)):
103 138
                     raise ValidationError(v2)
104  
-                native_v2 = member.type.from_string(v2)
  139
+
  140
+                if member.type is ByteArray or \
  141
+                        getattr(member.type, '_is_clone_of', None) is ByteArray:
  142
+                    if isinstance(v2, str) or isinstance(v2, unicode):
  143
+                        native_v2 = member.type.from_string(v2)
  144
+                    else:
  145
+                        native_v2 = v2
  146
+                else:
  147
+                    native_v2 = member.type.from_string(v2)
  148
+
105 149
                 if (self.validator is self.SOFT_VALIDATION and not
106 150
                             member.type.validate_native(member.type, native_v2)):
107 151
                     raise ValidationError(v2)
@@ -148,11 +192,6 @@ def dict_to_object(self, doc, inst_class):
148 192
                 logger.debug("\tset default %r(%r) = %r" %
149 193
                                                     (member.path, pkey, value))
150 194
 
151  
-        try:
152  
-            print inst.qo.vehicles
153  
-        except Exception,e:
154  
-            print e
155  
-
156 195
         if self.validator is self.SOFT_VALIDATION:
157 196
             sti = simple_type_info.values()
158 197
             sti.sort(key=lambda x: (len(x.path), x.path))
@@ -199,21 +238,10 @@ def deserialize(self, ctx, message):
199 238
 
200 239
         self.event_manager.fire_event('before_deserialize', ctx)
201 240
 
202  
-        if len(ctx.in_header_doc) > 0:
203  
-            ctx.in_header = self.dict_to_object(ctx.in_header_doc,
  241
+        ctx.in_header = self.dict_to_object(ctx.in_header_doc,
204 242
                                                     ctx.descriptor.in_header)
205  
-        else:
206  
-            ctx.in_header = [None] * len(
207  
-                        ctx.descriptor.in_header.get_flat_type_info(
208  
-                                                    ctx.descriptor.in_message))
209  
-
210  
-        if ctx.in_body_doc is not None:
211  
-            ctx.in_object = self.dict_to_object(ctx.in_body_doc,
  243
+        ctx.in_object = self.dict_to_object(ctx.in_body_doc,
212 244
                                                     ctx.descriptor.in_message)
213  
-        else:
214  
-            ctx.in_object = [None] * len(
215  
-                        ctx.descriptor.in_message.get_flat_type_info(
216  
-                                                    ctx.descriptor.in_message))
217 245
 
218 246
         self.event_manager.fire_event('after_deserialize', ctx)
219 247
 
@@ -244,3 +272,11 @@ def serialize(self, ctx, message):
244 272
 
245 273
     def create_out_string(self, ctx, out_string_encoding='utf8'):
246 274
         ctx.out_string = ctx.out_document
  275
+
  276
+    def get_call_handles(self, ctx):
  277
+        retval = super(HttpRpc, self).get_call_handles(ctx)
  278
+
  279
+        if len(retval) == 0:
  280
+            pass
  281
+
  282
+        return retval
23  src/rpclib/protocol/soap/soap11.py
@@ -27,19 +27,20 @@
27 27
 import cgi
28 28
 
29 29
 import rpclib.const.xml_ns as ns
30  
-from rpclib.const.ansi_color import LIGHT_GREEN
31  
-from rpclib.const.ansi_color import LIGHT_RED
32  
-from rpclib.const.ansi_color import END_COLOR
33 30
 
34 31
 from lxml import etree
35 32
 from lxml.etree import XMLSyntaxError
36 33
 
  34
+from rpclib.const.http import HTTP_405
37 35
 from rpclib.const.http import HTTP_500
  36
+from rpclib.const.ansi_color import LIGHT_GREEN
  37
+from rpclib.const.ansi_color import LIGHT_RED
  38
+from rpclib.const.ansi_color import END_COLOR
  39
+from rpclib.error import RequestNotAllowed
  40
+from rpclib.model.fault import Fault
38 41
 from rpclib.protocol.xml import XmlObject
39 42
 from rpclib.protocol.soap.mime import collapse_swa
40 43
 
41  
-from rpclib.model.fault import Fault
42  
-
43 44
 def _from_soap(in_envelope_xml, xmlids=None):
44 45
     '''Parses the xml string into the header and payload.'''
45 46
 
@@ -145,7 +146,17 @@ def wrapped(self):
145 146
 
146 147
     def create_in_document(self, ctx, charset=None):
147 148
         if ctx.transport.type == 'wsgi':
148  
-            content_type = cgi.parse_header(ctx.transport.req_env.get("CONTENT_TYPE"))
  149
+            # according to the soap via http standard, soap requests must only
  150
+            # work with proper POST requests.
  151
+            content_type = ctx.transport.req_env.get("CONTENT_TYPE")
  152
+            http_verb = ctx.transport.req_env['REQUEST_METHOD'].upper()
  153
+            if content_type is None or http_verb != "POST":
  154
+                ctx.transport.resp_code = HTTP_405
  155
+                raise RequestNotAllowed(
  156
+                        "You must issue a POST request with the Content-Type "
  157
+                        "header properly set.")
  158
+
  159
+            content_type = cgi.parse_header(content_type)
149 160
             collapse_swa(content_type, ctx.in_string)
150 161
 
151 162
         ctx.in_document = _parse_xml_string(ctx.in_string, charset)
9  src/rpclib/protocol/xml/_base.py
@@ -114,8 +114,7 @@ def set_validator(self, validator):
114 114
             self.validate_document = self.__validate_lxml
115 115
             self.validator = self.SCHEMA_VALIDATION
116 116
 
117  
-        elif validator is self.SOFT_VALIDATION or \
118  
-                                    validator is ProtocolBase.SOFT_VALIDATION:
  117
+        elif validator == 'soft' or validator is self.SOFT_VALIDATION:
119 118
             self.validator = self.SOFT_VALIDATION
120 119
 
121 120
         elif validator is None:
@@ -149,8 +148,8 @@ def validate_body(self, ctx, message):
149 148
                 line_header = LIGHT_RED + "Response:" + END_COLOR
150 149
         finally:
151 150
             if self.log_messages:
152  
-                logger.debug("%s %s" % (line_header,
153  
-                            etree.tostring(ctx.in_document, pretty_print=True)))
  151
+                logger.debug("%s %s" % (line_header, ctx.method_request_string))
  152
+                logger.debug(etree.tostring(ctx.in_document, pretty_print=True))
154 153
 
155 154
     def create_in_document(self, ctx, charset=None):
156 155
         """Uses the iterable of string fragments in ``ctx.in_string`` to set
@@ -174,7 +173,7 @@ def create_out_string(self, ctx, charset=None):
174 173
         """Sets an iterable of string fragments to ctx.out_string"""
175 174
 
176 175
         if charset is None:
177  
-            charset = 'utf8'
  176
+            charset = 'UTF-8'
178 177
 
179 178
         ctx.out_string = [etree.tostring(ctx.out_document,
180 179
                         xml_declaration=self.xml_declaration, encoding=charset)]
21  src/rpclib/server/wsgi.py
@@ -24,6 +24,8 @@
24 24
 
25 25
 import cgi
26 26
 
  27
+from threading import Lock
  28
+
27 29
 from rpclib import TransportContext
28 30
 from rpclib import MethodContext
29 31
 
@@ -66,14 +68,19 @@ def _wsgi_input_to_iterable(http_env):
66 68
 
67 69
         yield data
68 70
 
  71
+
69 72
 def reconstruct_wsgi_request(http_env):
70 73
     """Reconstruct http payload using information in the http header."""
71 74
 
72 75
     # fyi, here's what the parse_header function returns:
73 76
     # >>> import cgi; cgi.parse_header("text/xml; charset=utf-8")
74 77
     # ('text/xml', {'charset': 'utf-8'})
75  
-    content_type = cgi.parse_header(http_env.get("CONTENT_TYPE"))
76  
-    charset = content_type[1].get('charset', 'utf-8')
  78
+    content_type = http_env.get("CONTENT_TYPE")
  79
+    if content_type is None:
  80
+        charset = 'utf-8'
  81
+    else:
  82
+        content_type = cgi.parse_header(content_type)
  83
+        charset = content_type[1].get('charset', 'utf-8')
77 84
 
78 85
     return _wsgi_input_to_iterable(http_env), charset
79 86
 
@@ -166,6 +173,7 @@ def __init__(self, app):
166 173
             "GET": self.handle_rpc,
167 174
             "POST": self.handle_rpc,
168 175
         }
  176
+        self._mtx_build_interface_document = Lock()
169 177
 
170 178
     def __call__(self, req_env, start_response, wsgi_url=None):
171 179
         '''This method conforms to the WSGI spec for callable wsgi applications
@@ -210,8 +218,13 @@ def __handle_wsdl_request(self, req_env, start_response, url):
210 218
         try:
211 219
             ctx.transport.wsdl = self.app.interface.get_interface_document()
212 220
             if ctx.transport.wsdl is None:
213  
-                self.app.interface.build_interface_document(url)
214  
-                ctx.transport.wsdl = self.app.interface.get_interface_document()
  221
+                self._mtx_build_interface_document.acquire()
  222
+
  223
+                if ctx.transport.wsdl is None:
  224
+                    self.app.interface.build_interface_document(url)
  225
+                    ctx.transport.wsdl = self.app.interface.get_interface_document()
  226
+
  227
+                self._mtx_build_interface_document.release()
215 228
 
216 229
             assert ctx.transport.wsdl != None
217 230
 
192  src/rpclib/test/interop/wsi-report-rpclib.xml
... ...
@@ -1,6 +1,6 @@
1 1
 <?xml version="1.0" encoding="UTF-8"?>
2 2
 <?xml-stylesheet href="wsi-test-tools/common/xsl/report.xsl" type="text/xsl" ?>
3  
-<report name="WS-I Basic Profile Conformance Report."    timestamp="2011-12-10T14:06:06.639"
  3
+<report name="WS-I Basic Profile Conformance Report."    timestamp="2012-01-16T00:24:35.343"
4 4
     xmlns="http://www.ws-i.org/testing/2004/07/report/"
5 5
     xmlns:wsi-report="http://www.ws-i.org/testing/2004/07/report/"
6 6
     xmlns:wsi-log="http://www.ws-i.org/testing/2003/03/log/"
@@ -141,37 +141,37 @@
141 141
       <assertionResult id="SSBP2403" result="passed">
142 142
       </assertionResult>
143 143
     </entry>
144  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_in_complex_headerInHeaderMsg">
  144
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_in_complex_headerOutHeaderMsg">
145 145
       <assertionResult id="BP2115" result="passed">
146 146
       </assertionResult>
147 147
       <assertionResult id="BP2116" result="passed">
148 148
       </assertionResult>
149 149
     </entry>
150  
-    <entry type="message" referenceID="{rpclib.test.interop.server}OutHeader">
  150
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_in_complex_headerInHeaderMsg">
151 151
       <assertionResult id="BP2115" result="passed">
152 152
       </assertionResult>
153 153
       <assertionResult id="BP2116" result="passed">
154 154
       </assertionResult>
155 155
     </entry>
156  
-    <entry type="message" referenceID="{rpclib.test.interop.server}send_out_complex_headerOutHeaderMsg">
  156
+    <entry type="message" referenceID="{rpclib.test.interop.server}OutHeader">
157 157
       <assertionResult id="BP2115" result="passed">
158 158
       </assertionResult>
159 159
       <assertionResult id="BP2116" result="passed">
160 160
       </assertionResult>
161 161
     </entry>
162  
-    <entry type="message" referenceID="{rpclib.test.interop.server}send_out_complex_headerInHeaderMsg">
  162
+    <entry type="message" referenceID="{rpclib.test.interop.server}InHeader">
163 163
       <assertionResult id="BP2115" result="passed">
164 164
       </assertionResult>
165 165
       <assertionResult id="BP2116" result="passed">
166 166
       </assertionResult>
167 167
     </entry>
168  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_in_complex_headerOutHeaderMsg">
  168
+    <entry type="message" referenceID="{rpclib.test.interop.server}send_out_complex_headerOutHeaderMsg">
169 169
       <assertionResult id="BP2115" result="passed">
170 170
       </assertionResult>
171 171
       <assertionResult id="BP2116" result="passed">
172 172
       </assertionResult>
173 173
     </entry>
174  
-    <entry type="message" referenceID="{rpclib.test.interop.server}InHeader">
  174
+    <entry type="message" referenceID="{rpclib.test.interop.server}send_out_complex_headerInHeaderMsg">
175 175
       <assertionResult id="BP2115" result="passed">
176 176
       </assertionResult>
177 177
       <assertionResult id="BP2116" result="passed">
@@ -445,535 +445,535 @@
445 445
       <assertionResult id="BP2014" result="notApplicable">
446 446
       </assertionResult>
447 447
     </entry>
448  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_enum">
  448
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_durationResponse">
449 449
       <assertionResult id="BP2115" result="passed">
450 450
       </assertionResult>
451 451
       <assertionResult id="BP2116" result="passed">
452 452
       </assertionResult>
453 453
     </entry>
454  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_doubleResponse">
  454
+    <entry type="message" referenceID="{rpclib.test.interop.server}documented_exceptionResponse">
455 455
       <assertionResult id="BP2115" result="passed">
456 456
       </assertionResult>
457 457
       <assertionResult id="BP2116" result="passed">
458 458
       </assertionResult>
459 459
     </entry>
460  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_attachment">
  460
+    <entry type="message" referenceID="{rpclib.test.interop.server}return_other_class_arrayResponse">
461 461
       <assertionResult id="BP2115" result="passed">
462 462
       </assertionResult>
463 463
       <assertionResult id="BP2116" result="passed">
464 464
       </assertionResult>
465 465
     </entry>
466  
-    <entry type="message" referenceID="{rpclib.test.interop.server}non_nillable">
  466
+    <entry type="message" referenceID="{rpclib.test.interop.server}python_exceptionResponse">
467 467
       <assertionResult id="BP2115" result="passed">
468 468
       </assertionResult>
469 469
       <assertionResult id="BP2116" result="passed">
470 470
       </assertionResult>
471 471
     </entry>
472  
-    <entry type="message" referenceID="{rpclib.test.interop.server}huge_numberResponse">
  472
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_float">
473 473
       <assertionResult id="BP2115" result="passed">
474 474
       </assertionResult>
475 475
       <assertionResult id="BP2116" result="passed">
476 476
       </assertionResult>
477 477
     </entry>
478  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_in_header">
  478
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_nested_class_arrayResponse">
479 479
       <assertionResult id="BP2115" result="passed">
480 480
       </assertionResult>
481 481
       <assertionResult id="BP2116" result="passed">
482 482
       </assertionResult>
483 483
     </entry>
484  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_any">
  484
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_simple_class">
485 485
       <assertionResult id="BP2115" result="passed">
486 486
       </assertionResult>
487 487
       <assertionResult id="BP2116" result="passed">
488 488
       </assertionResult>
489 489
     </entry>
490  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_string">
  490
+    <entry type="message" referenceID="{rpclib.test.interop.server}python_exception">
491 491
       <assertionResult id="BP2115" result="passed">
492 492
       </assertionResult>
493 493
       <assertionResult id="BP2116" result="passed">
494 494
       </assertionResult>
495 495
     </entry>
496  
-    <entry type="message" referenceID="{rpclib.test.interop.server}huge_number">
  496
+    <entry type="message" referenceID="{rpclib.test.interop.server}do_something_elseResponse">
497 497
       <assertionResult id="BP2115" result="passed">
498 498
       </assertionResult>
499 499
       <assertionResult id="BP2116" result="passed">
500 500
       </assertionResult>
501 501
     </entry>
502  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_anyResponse">
  502
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_date_time_array">
503 503
       <assertionResult id="BP2115" result="passed">
504 504
       </assertionResult>
505 505
       <assertionResult id="BP2116" result="passed">
506 506
       </assertionResult>
507 507
     </entry>
508  
-    <entry type="message" referenceID="{rpclib.test.interop.server}return_binary_data">
  508
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_boolean_arrayResponse">
509 509
       <assertionResult id="BP2115" result="passed">
510 510
       </assertionResult>
511 511
       <assertionResult id="BP2116" result="passed">
512 512
       </assertionResult>
513 513
     </entry>
514  
-    <entry type="message" referenceID="{rpclib.test.interop.server}return_other_class_arrayResponse">
  514
+    <entry type="message" referenceID="{rpclib.test.interop.server}test_emptyResponse">
515 515
       <assertionResult id="BP2115" result="passed">
516 516
       </assertionResult>
517 517
       <assertionResult id="BP2116" result="passed">
518 518
       </assertionResult>
519 519
     </entry>
520  
-    <entry type="message" referenceID="{rpclib.test.interop.server}test_empty">
  520
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_boolean">
521 521
       <assertionResult id="BP2115" result="passed">
522 522
       </assertionResult>
523 523
       <assertionResult id="BP2116" result="passed">
524 524
       </assertionResult>
525 525
     </entry>
526  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_integer">
  526
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_attachmentResponse">
527 527
       <assertionResult id="BP2115" result="passed">
528 528
       </assertionResult>
529 529
       <assertionResult id="BP2116" result="passed">
530 530
       </assertionResult>
531 531
     </entry>
532  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_double_arrayResponse">
  532
+    <entry type="message" referenceID="{rpclib.test.interop.server}return_invalid_dataResponse">
533 533
       <assertionResult id="BP2115" result="passed">
534 534
       </assertionResult>
535 535
       <assertionResult id="BP2116" result="passed">
536 536
       </assertionResult>
537 537
     </entry>
538  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_float_arrayResponse">
  538
+    <entry type="message" referenceID="{rpclib.test.interop.server}long_string">
539 539
       <assertionResult id="BP2115" result="passed">
540 540
       </assertionResult>
541 541
       <assertionResult id="BP2116" result="passed">
542 542
       </assertionResult>
543 543
     </entry>
544  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_datetimeResponse">
  544
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_double_array">
545 545
       <assertionResult id="BP2115" result="passed">
546 546
       </assertionResult>
547 547
       <assertionResult id="BP2116" result="passed">
548 548
       </assertionResult>
549 549
     </entry>
550  
-    <entry type="message" referenceID="{rpclib.test.interop.server}multi_param">
  550
+    <entry type="message" referenceID="{rpclib.test.interop.server}non_nillableResponse">
551 551
       <assertionResult id="BP2115" result="passed">
552 552
       </assertionResult>
553 553
       <assertionResult id="BP2116" result="passed">
554 554
       </assertionResult>
555 555
     </entry>
556  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_boolean">
  556
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_nested_classResponse">
557 557
       <assertionResult id="BP2115" result="passed">
558 558
       </assertionResult>
559 559
       <assertionResult id="BP2116" result="passed">
560 560
       </assertionResult>
561 561
     </entry>
562  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_simple_boolean_arrayResponse">
  562
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_in_complex_headerResponse">
563 563
       <assertionResult id="BP2115" result="passed">
564 564
       </assertionResult>
565 565
       <assertionResult id="BP2116" result="passed">
566 566
       </assertionResult>
567 567
     </entry>
568  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_in_complex_header">
  568
+    <entry type="message" referenceID="{rpclib.test.interop.server}return_binary_data">
569 569
       <assertionResult id="BP2115" result="passed">
570 570
       </assertionResult>
571 571
       <assertionResult id="BP2116" result="passed">
572 572
       </assertionResult>
573 573
     </entry>
574  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_float">
  574
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_nested_class">
575 575
       <assertionResult id="BP2115" result="passed">
576 576
       </assertionResult>
577 577
       <assertionResult id="BP2116" result="passed">
578 578
       </assertionResult>
579 579
     </entry>
580  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_in_complex_headerResponse">
  580
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_simple_boolean_arrayResponse">
581 581
       <assertionResult id="BP2115" result="passed">
582 582
       </assertionResult>
583 583
       <assertionResult id="BP2116" result="passed">
584 584
       </assertionResult>
585 585
     </entry>
586  
-    <entry type="message" referenceID="{rpclib.test.interop.server}python_exceptionResponse">
  586
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_nested_class_array">
587 587
       <assertionResult id="BP2115" result="passed">
588 588
       </assertionResult>
589 589
       <assertionResult id="BP2116" result="passed">
590 590
       </assertionResult>
591 591
     </entry>
592  
-    <entry type="message" referenceID="{rpclib.test.interop.server}long_stringResponse">
  592
+    <entry type="message" referenceID="{rpclib.test.interop.server}return_other_class_array">
593 593
       <assertionResult id="BP2115" result="passed">
594 594
       </assertionResult>
595 595
       <assertionResult id="BP2116" result="passed">
596 596
       </assertionResult>
597 597
     </entry>
598  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_class_with_self_referenceResponse">
  598
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_enum">
599 599
       <assertionResult id="BP2115" result="passed">
600 600
       </assertionResult>
601 601
       <assertionResult id="BP2116" result="passed">
602 602
       </assertionResult>
603 603
     </entry>
604  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_integer_array">
  604
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_double_arrayResponse">
605 605
       <assertionResult id="BP2115" result="passed">
606 606
       </assertionResult>
607 607
       <assertionResult id="BP2116" result="passed">
608 608
       </assertionResult>
609 609
     </entry>
610  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_duration">
  610
+    <entry type="message" referenceID="{rpclib.test.interop.server}non_nillable">
611 611
       <assertionResult id="BP2115" result="passed">
612 612
       </assertionResult>
613 613
       <assertionResult id="BP2116" result="passed">
614 614
       </assertionResult>
615 615
     </entry>
616  
-    <entry type="message" referenceID="{rpclib.test.interop.server}documented_exceptionResponse">
  616
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_simple_class_arrayResponse">
617 617
       <assertionResult id="BP2115" result="passed">
618 618
       </assertionResult>
619 619
       <assertionResult id="BP2116" result="passed">
620 620
       </assertionResult>
621 621
     </entry>
622  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_simple_class_arrayResponse">
  622
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_attachment_arrayResponse">
623 623
       <assertionResult id="BP2115" result="passed">
624 624
       </assertionResult>
625 625
       <assertionResult id="BP2116" result="passed">
626 626
       </assertionResult>
627 627
     </entry>
628  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_enumResponse">
  628
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_doubleResponse">
629 629
       <assertionResult id="BP2115" result="passed">
630 630
       </assertionResult>
631 631
       <assertionResult id="BP2116" result="passed">
632 632
       </assertionResult>
633 633
     </entry>
634  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_in_headerResponse">
  634
+    <entry type="message" referenceID="{rpclib.test.interop.server}multi_paramResponse">
635 635
       <assertionResult id="BP2115" result="passed">
636 636
       </assertionResult>
637 637
       <assertionResult id="BP2116" result="passed">
638 638
       </assertionResult>
639 639
     </entry>
640  
-    <entry type="message" referenceID="{rpclib.test.interop.server}test_emptyResponse">
  640
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_integer_arrayResponse">
641 641
       <assertionResult id="BP2115" result="passed">
642 642
       </assertionResult>
643 643
       <assertionResult id="BP2116" result="passed">
644 644
       </assertionResult>
645 645
     </entry>
646  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_nested_class_array">
  646
+    <entry type="message" referenceID="{rpclib.test.interop.server}send_out_complex_header">
647 647
       <assertionResult id="BP2115" result="passed">
648 648
       </assertionResult>
649 649
       <assertionResult id="BP2116" result="passed">
650 650
       </assertionResult>
651 651
     </entry>
652  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_array_in_arrayResponse">
  652
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_enumResponse">
653 653
       <assertionResult id="BP2115" result="passed">
654 654
       </assertionResult>
655 655
       <assertionResult id="BP2116" result="passed">
656 656
       </assertionResult>
657 657
     </entry>
658  
-    <entry type="message" referenceID="{rpclib.test.interop.server}return_binary_dataResponse">
  658
+    <entry type="message" referenceID="{rpclib.test.interop.server}documented_exception">
659 659
       <assertionResult id="BP2115" result="passed">
660 660
       </assertionResult>
661 661
       <assertionResult id="BP2116" result="passed">
662 662
       </assertionResult>
663 663
     </entry>
664  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_string_arrayResponse">
  664
+    <entry type="message" referenceID="{rpclib.test.interop.server}custom_messages">
665 665
       <assertionResult id="BP2115" result="passed">
666 666
       </assertionResult>
667 667
       <assertionResult id="BP2116" result="passed">
668 668
       </assertionResult>
669 669
     </entry>
670  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_attachment_arrayResponse">
  670
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_anyResponse">
671 671
       <assertionResult id="BP2115" result="passed">
672 672
       </assertionResult>
673 673
       <assertionResult id="BP2116" result="passed">
674 674
       </assertionResult>
675 675
     </entry>
676  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_nested_classResponse">
  676
+    <entry type="message" referenceID="{rpclib.test.interop.server}getCustomMessagesMsgOut">
677 677
       <assertionResult id="BP2115" result="passed">
678 678
       </assertionResult>
679 679
       <assertionResult id="BP2116" result="passed">
680 680
       </assertionResult>
681 681
     </entry>
682  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_any_as_dict">
  682
+    <entry type="message" referenceID="{rpclib.test.interop.server}huge_numberResponse">
683 683
       <assertionResult id="BP2115" result="passed">
684 684
       </assertionResult>
685 685
       <assertionResult id="BP2116" result="passed">
686 686
       </assertionResult>
687 687
     </entry>
688  
-    <entry type="message" referenceID="{rpclib.test.interop.server}multi_paramResponse">
  688
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_stringResponse">
689 689
       <assertionResult id="BP2115" result="passed">
690 690
       </assertionResult>
691 691
       <assertionResult id="BP2116" result="passed">
692 692
       </assertionResult>
693 693
     </entry>
694  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_attachmentResponse">
  694
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_extension_class">
695 695
       <assertionResult id="BP2115" result="passed">
696 696
       </assertionResult>
697 697
       <assertionResult id="BP2116" result="passed">
698 698
       </assertionResult>
699 699
     </entry>
700  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_floatResponse">
  700
+    <entry type="message" referenceID="{rpclib.test.interop.server}long_stringResponse">
701 701
       <assertionResult id="BP2115" result="passed">
702 702
       </assertionResult>
703 703
       <assertionResult id="BP2116" result="passed">
704 704
       </assertionResult>
705 705
     </entry>
706  
-    <entry type="message" referenceID="{rpclib.test.interop.server}getCustomMessagesMsgOut">
  706
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_datetime">
707 707
       <assertionResult id="BP2115" result="passed">
708 708
       </assertionResult>
709 709
       <assertionResult id="BP2116" result="passed">
710 710
       </assertionResult>
711 711
     </entry>
712  
-    <entry type="message" referenceID="{rpclib.test.interop.server}custom_messages">
  712
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_simple_class_array">
713 713
       <assertionResult id="BP2115" result="passed">
714 714
       </assertionResult>
715 715
       <assertionResult id="BP2116" result="passed">
716 716
       </assertionResult>
717 717
     </entry>
718  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_nested_class">
  718
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_array_in_array">
719 719
       <assertionResult id="BP2115" result="passed">
720 720
       </assertionResult>
721 721
       <assertionResult id="BP2116" result="passed">
722 722
       </assertionResult>
723 723
     </entry>
724  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_any_as_dictResponse">
  724
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_date_time_arrayResponse">
725 725
       <assertionResult id="BP2115" result="passed">
726 726
       </assertionResult>
727 727
       <assertionResult id="BP2116" result="passed">
728 728
       </assertionResult>
729 729
     </entry>
730  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_float_array">
  730
+    <entry type="message" referenceID="{rpclib.test.interop.server}soap_exception">
731 731
       <assertionResult id="BP2115" result="passed">
732 732
       </assertionResult>
733 733
       <assertionResult id="BP2116" result="passed">
734 734
       </assertionResult>
735 735
     </entry>
736  
-    <entry type="message" referenceID="{rpclib.test.interop.server}echo_durationResponse">
  736
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_in_complex_header">
737 737
       <assertionResult id="BP2115" result="passed">
738 738
       </assertionResult>
739 739
       <assertionResult id="BP2116" result="passed">
740 740
       </assertionResult>
741 741
     </entry>
742  
-    <entry type="message" referenceID="{rpclib.test.interop.server}documented_exception">
  742
+    <entry type="message" referenceID="{rpclib.test.interop.server}echo_any">
743 743
       <assertionResult id="BP2115" result="passed">
744 744
       </assertionResult>
745 745
       <assertionResult id="BP2116" result="passed">
746 746
       </assertionResult>
747 747 </