Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fake a soap response in Python?

I am trying to test a function in company product. Our software will make a SOAP request like this:

Request Header

POST /testfunction.php HTTP/1.1
Accept: application/soap+xml, application/xml, text/xml
SOAPAction: "http://www.abc.com/testfunction#test"
Host: soap.abc.com
Content-Length: 461
Connection: Keep-Alive

Request Content

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.abc.com/testfunction">
<SOAP-ENV:Body>
<ns1:test>
<productID>3</productID>
<productSubID>1</productSubID>
<version>1.0.1</version>
<serialNumber/>
<language>EN</language>
<daysLicensed>0</daysLicensed>
<daysLeft>0</daysLeft>
</ns1:test>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

And the SOAP service should respond:

Response Header

HTTP/1.1 200 OK
Server: nginx/0.7.67
Date: Mon, 02 May 2011 13:43:46 GMT
Content-Type: text/xml; charset=utf-8
Connection: keep-alive
X-Powered-By: PHP/5.3.3-1ubuntu9.3
Content-Length: 304
Content-encoding: gzip

Response Content

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.abc.com/testfunction"><SOAP-ENV:Body><ns1:testResponse><result>1000</result></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>

In the beginning I thought I could just make a web service in web.py and returns the same response whenever someone make a POST request on http://www.abc.com/testfunction.

import web                                                                                                                                                                                                                                                                                                                                                                                                                    
url = (                                                                                                                                                                                                                                                                                                                                                                                       
    '/testfunction', 'testfunction',                                                                                                                                                             
)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

class testfunction:                                                                                                                                                                                             
    def POST(self):                                                                                                                                                                                            
        web.header('Content-Type',  'text/xml; charset=utf-8')                                                                                                                                                 
        return """<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.abc.com/testfunction"><SOAP-ENV:Body><ns1:testResponse><result>1000</result></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>               
                """                                                                                                                                                                                            

app = web.application(url, globals())                                                                                                                                                                          

if __name__== "__main__":                                                                                                                                                                                      
    app.run()  

But it didn't work. I think that maybe something to do with the header. Then I tried with SimpleXMLRPCServer.

from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
import xmlrpclib

class MyRequestHandler(SimpleXMLRPCRequestHandler):
    rpc_paths = ('/',)
    def do_POST(self):
        return SimpleXMLRPCRequestHandler.do_POST(self)

def test():
    return "hello, world"

server = SimpleXMLRPCServer(
        ("0.0.0.0", 80),
        requestHandler = MyRequestHandler,
        )   
server.register_function(test, 'test')
server.serve_forever()

but problem is I don't know how to deal with SOAPAction in the header and the client is not using the test function here. Can anyone help me? Thanks a lot!!

Update:

Finally did it, using the following code:

from wsgiref.simple_server import WSGIServer, WSGIRequestHandler

def echo(environ, start_response):
    status = "200 OK"
    headers = [("Content-type", "text/xml")]
    start_response(status, headers)

    return ["""<?xml version="1.0" encoding="UTF-8"?>
    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.abc.com/testfunction"><SOAP-ENV:Body><ns1:testResponse><result>1000</result></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>"""]

httpd = WSGIServer(('0.0.0.0', 80), WSGIRequestHandler)
httpd.set_app(echo)
httpd.serve_forever()

It should work the same with the web.py code, however the web.py one doesn't. From the captured package in wireshark I found some garbled code ("3bc" and "0) before and after the xml content, something to do with the encoding?

like image 459
Zhe Li Avatar asked Feb 24 '23 08:02

Zhe Li


1 Answers

You could use soaplib to create a real SOAP service which implements your interface and returns dummy data. This should be a bit easier to maintain then creating handwritten static responses, and the code shouldn't be much longer than your web.py-based example.

Here's a Hello World example.

like image 107
samplebias Avatar answered Feb 26 '23 20:02

samplebias