def test_cookie_parse(self): string = 'some_string' class RequestHeader(ComplexModel): some_field = String class SomeService(ServiceBase): __in_header__ = RequestHeader @rpc(String) def some_call(ctx, s): assert ctx.in_header.some_field == string def start_response(code, headers): assert code == HTTP_200 c = SimpleCookie() c['some_field'] = string ''.join(wsgiref_validator(WsgiApplication(Application([SomeService], 'tns', in_protocol=HttpRpc(parse_cookie=True), out_protocol=HttpRpc())))({ 'SCRIPT_NAME': '', 'QUERY_STRING': '', 'PATH_INFO': '/some_call', 'REQUEST_METHOD': 'GET', 'SERVER_NAME': 'localhost', 'SERVER_PORT': "9999", 'HTTP_COOKIE': str(c), 'wsgi.url_scheme': 'http', 'wsgi.version': (1,0), 'wsgi.input': StringIO(), 'wsgi.errors': StringIO(), 'wsgi.multithread': False, 'wsgi.multiprocess': False, 'wsgi.run_once': True, }, start_response))
def test_http_headers(self): d = datetime(year=2013, month=1, day=1) string = ['hey', 'yo'] class ResponseHeader(ComplexModel): _type_info = { 'Set-Cookie': String(max_occurs='unbounded'), 'Expires': DateTime } class SomeService(ServiceBase): __out_header__ = ResponseHeader @rpc(String) def some_call(ctx, s): assert s is not None ctx.out_header = ResponseHeader(**{ 'Set-Cookie': string, 'Expires': d }) def start_response(code, headers): print(headers) assert len([s for s in string if ('Set-Cookie', s) in headers]) == len(string) assert dict(headers)['Expires'] == 'Tue, 01 Jan 2013 00:00:00 GMT' app = Application([SomeService], 'tns', in_protocol=HttpRpc(), out_protocol=HttpRpc()) wsgi_app = WsgiApplication(app) req_dict = { 'SCRIPT_NAME': '', 'QUERY_STRING': '&s=foo', 'PATH_INFO': '/some_call', 'REQUEST_METHOD': 'GET', 'SERVER_NAME': 'localhost', 'SERVER_PORT': "9999", 'wsgi.url_scheme': 'http', 'wsgi.version': (1, 0), 'wsgi.input': StringIO(), 'wsgi.errors': StringIO(), 'wsgi.multithread': False, 'wsgi.multiprocess': False, 'wsgi.run_once': True, } ret = wsgi_app(req_dict, start_response) print(list(ret)) wsgi_app = wsgiref_validator(wsgi_app) ret = wsgi_app(req_dict, start_response) assert list(ret) == [b'']
def from_base64(cls, value): if value is None: return None istream = StringIO(value) ostream = StringIO() base64.decode(istream, ostream) ostream.seek(0) return Attachment(data=ostream.read())
def test_many(self): class SomeComplexModel(ComplexModel): s = Unicode i = Integer v = [ SomeComplexModel(s='a', i=1), SomeComplexModel(s='b', i=2), SomeComplexModel(s='c', i=3), SomeComplexModel(s='d', i=4), SomeComplexModel(s='e', i=5), ] class SomeService(ServiceBase): @rpc(_returns=Array(SomeComplexModel)) def get(ctx): return v desc = SomeService.public_methods['get'] ctx = FakeContext(out_object=[v], descriptor=desc) ostr = ctx.out_stream = StringIO() XmlDocument(Application([SomeService], __name__)) \ .serialize(ctx, XmlDocument.RESPONSE) elt = etree.fromstring(ostr.getvalue()) print(etree.tostring(elt, pretty_print=True)) assert elt.xpath('x:getResult/x:SomeComplexModel/x:i/text()', namespaces={'x': __name__}) == ['1', '2', '3', '4', '5'] assert elt.xpath('x:getResult/x:SomeComplexModel/x:s/text()', namespaces={'x': __name__}) == ['a', 'b', 'c', 'd', 'e']
def test_unicode_chars_in_exception(self): class SomeService(ServiceBase): @srpc(Unicode(pattern=u'x'), _returns=Unicode) def some_call(s): test(never,reaches,here) app = Application([SomeService], "tns", name="test_mandatory_elements", in_protocol=XmlDocument(validator='lxml'), out_protocol=XmlDocument()) server = WsgiApplication(app) req = ( '<some_call xmlns="tns">' '<s>Ğ</s>' '</some_call>' ) resp = server({ 'QUERY_STRING': '', 'PATH_INFO': '/', 'REQUEST_METHOD': 'POST', 'SERVER_NAME': 'localhost', 'SERVER_PORT': '80', 'wsgi.input': StringIO(req), "wsgi.url_scheme": 'http', }, lambda x,y: print(x,y)) assert 'Ğ' in ''.join(resp)
def test_one(self): class SomeComplexModel(ComplexModel): s = Unicode i = Integer v = SomeComplexModel(s='a', i=1), class SomeService(ServiceBase): @rpc(_returns=SomeComplexModel) def get(ctx): return v desc = SomeService.public_methods['get'] ctx = FakeContext(out_object=v, descriptor=desc) ostr = ctx.out_stream = StringIO() XmlDocument(Application([SomeService], __name__)) \ .serialize(ctx, XmlDocument.RESPONSE) elt = etree.fromstring(ostr.getvalue()) print etree.tostring(elt, pretty_print=True) assert elt.xpath('x:getResult/x:i/text()', namespaces={'x': __name__}) == ['1'] assert elt.xpath('x:getResult/x:s/text()', namespaces={'x': __name__}) == ['a']
def serialize(self, ctx, message): """Uses ``ctx.out_object``, ``ctx.out_header`` or ``ctx.out_error`` to set ``ctx.out_body_doc``, ``ctx.out_header_doc`` and ``ctx.out_document`` as an ``lxml.etree._Element instance``. Not meant to be overridden. """ assert message in (self.REQUEST, self.RESPONSE) self.event_manager.fire_event('before_serialize', ctx) if ctx.out_stream is None: ctx.out_stream = StringIO() logger.debug("%r %d", ctx.out_stream, id(ctx.out_stream)) if ctx.out_error is not None: # All errors at this point must be Fault subclasses. inst = ctx.out_error cls = inst.__class__ name = cls.get_type_name() ctx.out_document = E.div() with self.docfile(ctx.out_stream) as xf: # as XmlDocument is not push-ready yet, this is what we do. # this is an ugly hack, bear with me. retval = XmlCloth.HtmlMicroFormat() \ .to_parent(ctx, cls, inst, xf, name) else: assert message is self.RESPONSE result_message_class = ctx.descriptor.out_message name = result_message_class.get_type_name() if ctx.descriptor.body_style == BODY_STYLE_WRAPPED: if self.ignore_wrappers: result_message = ctx.out_object[0] while result_message_class.Attributes._wrapper and \ len(result_message_class._type_info) == 1: result_message_class, = \ result_message_class._type_info.values() else: result_message = result_message_class() for i, attr_name in enumerate( result_message_class._type_info.keys()): setattr(result_message, attr_name, ctx.out_object[i]) else: result_message, = ctx.out_object retval = self.incgen(ctx, result_message_class, result_message, name) self.event_manager.fire_event('after_serialize', ctx) return retval
def to_base64(cls, value): if value is None: return None ostream = StringIO() if not (value.data is None): istream = StringIO(value.data) elif not (value.file_name is None): istream = open(value.file_name, 'rb') else: raise ValueError("Neither data nor a file_name has been specified") base64.encode(istream, ostream) ostream.seek(0) return ostream.read()
def serialize(self, ctx, message): """Uses ``ctx.out_object``, ``ctx.out_header`` or ``ctx.out_error`` to set ``ctx.out_body_doc``, ``ctx.out_header_doc`` and ``ctx.out_document`` as an ``lxml.etree._Element instance``. Not meant to be overridden. """ assert message in (self.REQUEST, self.RESPONSE) self.event_manager.fire_event('before_serialize', ctx) if ctx.out_stream is None: ctx.out_stream = StringIO() if ctx.out_error is not None: # All errors at this point must be Fault subclasses. inst = ctx.out_error cls = inst.__class__ name = cls.get_type_name() ctx.out_document = E.div() from lxml import etree with etree.xmlfile(ctx.out_stream) as xf: retval = HtmlBase.HtmlMicroFormat() \ .to_parent(ctx, cls, inst, xf, name) else: assert message is self.RESPONSE result_message_class = ctx.descriptor.out_message name = result_message_class.get_type_name() if ctx.descriptor.body_style == BODY_STYLE_WRAPPED: if self.ignore_wrappers: ctx.out_object = ctx.out_object[0] result_message = ctx.out_object while result_message_class.Attributes._wrapper: result_message_class = next( iter(result_message_class._type_info.values())) else: result_message = result_message_class() for i, attr_name in enumerate( result_message_class._type_info.keys()): setattr(result_message, attr_name, ctx.out_object[i]) else: result_message = ctx.out_object retval = self.incgen(ctx, result_message_class, result_message, name) self.event_manager.fire_event('after_serialize', ctx) return retval
def test_wsgi(self): retval = ''.join(self.wsgi_app({ 'PATH_INFO': '/', 'QUERY_STRING': 'wsdl', 'SERVER_NAME': 'localhost', 'SERVER_PORT': '7000', 'REQUEST_METHOD': 'GET', 'wsgi.url_scheme': 'http', 'wsgi.input': StringIO(), }, start_response)) from lxml import etree assert etree.fromstring(retval).tag == '{%s}definitions' % NS_WSDL
def test_fault_generation(self): class SoapException(ServiceBase): @srpc() def soap_exception(): raise Fault( "Client.Plausible", "A plausible fault", 'http://faultactor.example.com') app = Application([SoapException], 'tns', in_protocol=Soap12(), out_protocol=Soap12()) req = """ <soap12env:Envelope xmlns:soap12env="http://www.w3.org/2003/05/soap-envelope" xmlns:tns="tns"> <soap12env:Body> <tns:soap_exception/> </soap12env:Body> </soap12env:Envelope> """ server = WsgiApplication(app) response = etree.fromstring(''.join(server({ 'QUERY_STRING': '', 'PATH_INFO': '/call', 'REQUEST_METHOD': 'GET', 'wsgi.input': StringIO(req) }, start_response, "http://null"))) response_str = etree.tostring(response, pretty_print=True) print(response_str) expected = """ <soap12env:Envelope xmlns:soap12env="http://www.w3.org/2003/05/soap-envelope"> <soap12env:Body> <soap12env:Fault> <soap12env:Reason> <soap12env:Text xml:lang="en">A plausible fault</soap12env:Text> </soap12env:Reason> <soap12env:Role>http://faultactor.example.com</soap12env:Role> <soap12env:Code> <soap12env:Value>soap12env:Sender</soap12env:Value> <soap12env:Subcode> <soap12env:Value>Plausible</soap12env:Value> </soap12env:Subcode> </soap12env:Code> </soap12env:Fault> </soap12env:Body> </soap12env:Envelope>""" if not LXMLOutputChecker().check_output(expected, response_str, PARSE_XML): raise Exception("Got: %s but expected: %s" % (response_str, expected))
def test_soap_bare_empty_output(self): class SomeService(ServiceBase): @rpc(String, _body_style='bare') def some_call(ctx, s): assert s == 'abc' app = Application([SomeService], 'tns', in_protocol=Soap11(), out_protocol=Soap11(cleanup_namespaces=True)) req = """ <soap11env:Envelope xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="tns"> <soap11env:Body> <tns:some_call>abc</tns:some_call> </soap11env:Body> </soap11env:Envelope> """ server = WsgiApplication(app) resp = etree.fromstring(''.join( server( { 'QUERY_STRING': '', 'PATH_INFO': '/call', 'REQUEST_METHOD': 'GET', 'SERVER_NAME': 'localhost', 'wsgi.input': StringIO(req) }, start_response, "http://null"))) print(etree.tostring(resp, pretty_print=True)) assert resp[0].tag == '{http://schemas.xmlsoap.org/soap/envelope/}Body' assert len(resp[0]) == 1 assert resp[0][0].tag == '{tns}some_call' + RESPONSE_SUFFIX assert len(resp[0][0]) == 0
def test_soap_bare_wrapped_array_output(self): class SomeService(ServiceBase): @rpc(_body_style='bare', _returns=Array(String)) def some_call(ctx): return ['abc', 'def'] app = Application([SomeService], 'tns', in_protocol=Soap11(), out_protocol=Soap11(cleanup_namespaces=True)) req = """ <soap11env:Envelope xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="tns"> <soap11env:Body> <tns:some_call/> </soap11env:Body> </soap11env:Envelope> """ server = WsgiApplication(app) resp = etree.fromstring(''.join( server( { 'QUERY_STRING': '', 'PATH_INFO': '/call', 'REQUEST_METHOD': 'GET', 'wsgi.input': StringIO(req) }, start_response, "http://null"))) print(etree.tostring(resp, pretty_print=True)) assert resp[0].tag == '{http://schemas.xmlsoap.org/soap/envelope/}Body' assert resp[0][0].tag == '{tns}some_call' + RESPONSE_SUFFIX assert resp[0][0][0].text == 'abc' assert resp[0][0][1].text == 'def'
def test_rpc(self): data = {"a": "b", "c": "d"} class KeyValuePair(ComplexModel): key = Unicode value = Unicode class Service(ServiceBase): @rpc(String(max_occurs='unbounded'), _returns=Array(KeyValuePair), _in_variable_names={'keys': 'key'}) def get_values(ctx, keys): for k in keys: yield KeyValuePair(key=k, value=data[k]) application = Application( [Service], in_protocol=MessagePackRpc(), out_protocol=MessagePackRpc(ignore_wrappers=False), name='Service', tns='tns') server = WsgiApplication(application) input_string = msgpack.packb([0, 0, "get_values", [["a", "c"]]]) input_stream = StringIO(input_string) ret = server( { 'CONTENT_LENGTH': str(len(input_string)), 'CONTENT_TYPE': 'application/x-msgpack', 'HTTP_CONNECTION': 'close', 'HTTP_CONTENT_LENGTH': str(len(input_string)), 'HTTP_CONTENT_TYPE': 'application/x-msgpack', 'PATH_INFO': '/', 'QUERY_STRING': '', 'SERVER_NAME': 'localhost', 'SERVER_PORT': '7000', 'REQUEST_METHOD': 'POST', 'wsgi.url_scheme': 'http', 'wsgi.input': input_stream, }, start_response) ret = ''.join(ret) print(repr(ret)) print(msgpack.unpackb(ret)) s = msgpack.packb([ 1, 0, None, { 'get_valuesResponse': { 'get_valuesResult': [ { "KeyValuePair": { 'value': 'b', 'key': 'a' } }, { "KeyValuePair": { 'value': 'd', 'key': 'c' } }, ] } } ]) print(s) assert ret == s