I need to convert some legacy Java code that implements a SOAP server - I need to convert it from java to python 3.x and I need to deploy the SOAP webservices on AWS Lambda. There is plenty of documentation on how to create REST web services on AWS Lambda in python, but I'm finding it really hard to find any information on writing a SOAP service. There are some client libraries for python SOAP, but I can't seem to find any server-side libraries or examples of how one would do this on AWS Lambda. I found zeep, which is meant to be a client library, and pysimplesoap, but in neither case is it clear how to use these on AWS Lambda. Any suggestions?
UPDATE: So I discovered that SOAP over HTTP is simply a call to HTTP POST which passes the SOAP request message as the HTTP body. (Of course there are headers in the HTTP request too that indicate that the body is a soap/xml message). So, to deploy to AWS Lambda, I basically need to deploy an HTTP PSOT webservice, which is easy enough using Zappa and Flask (or Django). The only tricky part is inside the post() function. Inside that function I would have to:
Get the request.body (SOAP/XML)
Use some python library to extract the items of interest from the SOAP message, perhaps parsing the entire message using a python XML parser
Execute the business logic code that creates a result, say a dictionary
Use some python library to convert that result dictionary to a SOAP response and let AWS Lambda send that SOAP response back
It is parts 2 and 4 that I am not quite sure how to do. I can use xml.etree.ElementTree to parse the XML, but I suspect there might be a better/faster/simpler way. For the output, is there a way I can use something like zeep to take a dictionary of inputs and create a SOAP response message? The zeep library is meant to read the WSDL document and create request SOAP messages, not response SOAP messages, so I'm not exactly sure how to create a SOAP response message using zeep. Has anyone else done this or know of a better way to do it?
Related
i need a guide to establish a connection to a public web service, send request to it and get response back. for example this web service:
http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso?WSDL
i've tried to test this API with SoapUI application. this API has a bunch of methods such as sending you a country's capital by getting it's ISO name (send IR as request and get Tehran as respond). now somehow i want to do this through Python. i want to have access to all it's methods and send requests. only by connecting to API's address or any other way (maybe by loading each method's XML code and running it in Python? idk). is it possible? any guide?
I'd recommend checking out this library:
https://requests.readthedocs.io/en/latest/
You can send HTTP requests to URL endpoints, parse out data, etc. Hope this helps!
I have successfully used suds and SOAPpy in the past. I see people recommend Zeep nowadays but I haven't used it.
Background
I've been using Robot Framework and RequestsLibrary to write automated tests against RESTful endpoints I expose via AWS API Gateway. So I'm writing tests that look roughly like this:
*** Settings ***
Library Collections
Library RequestsLibrary
*** Test Cases ***
Get Requests
Create Session Sess https://<api-gateway-url>
${resp}= Get Request Sess /path/to/my/api?param=value
Should Be Equal As Strings ${resp.status_code} 200
Dictionary Should Contain Value ${resp.json()} someValueIwantToVerify
Now, I'm getting around to securing those API Gateway endpoints with IAM. Therefore requests need to be sig4 signed.
The application that consumes these services is written in javascript, and uses aws-api-gateway-client to sign requests. Testing (manually) in Postman is also easy enough, using AWS Signature Authorization type. However, I'm struggling with figuring out a strategy for Robot Framework.
Question(s)
In the broadest sense, I'm wondering if anyone else is using Robot Framework to test IAM secured API Gateway endpoints. If so, how did you pull it off?
More specifically:
Is there an existing Robot Framework library that addresses this use case?
If not, is writing my own library my only option?
If I am stuck writing a library (this looks promising), what sorts of keywords would I define, and how would I use them?
I don't know of an RF library that does what you want, but my first instinct would be to use Amazon's own AWS SDK for Python (boto3), and write a thin keyword wrapper library around it. I've done that for test cases that used AWS S3, but boto3 also supports API Gateway: http://boto3.readthedocs.io/en/latest/reference/services/apigateway.html
The requests library accepts an auth parameter, which is expected to be a subclass of AuthBase.
It turns out that modifying RequestsLibrary to leverage this existing functionality was a grand total of two lines of code (not counting comments, tests, and whitespace for readability):
def create_custom_session(self, alias, url, auth, headers={}, cookies=None, timeout=None, proxies=None, verify=False, debug=0, max_retries=3, backoff_factor=0.10, disable_warnings=0):
return self._create_session(alias, url, headers, cookies, auth, timeout, max_retries, backoff_factor, proxies, verify, debug, disable_warnings)
Sometimes the answer is just to issue your own pull request.
The new Create Custom Session keyword will accept any arbitrary auth object, including the one produced by the library I'm using (which I highly recommend).
The original issue now contains the details of how aws-requests-auth and RequestsLibrary work together with the new keyword.
#the_mero mentioned boto3 which is almost certainly what you want to use to actually marshal up the credentials. You don't want to hard code them in your test like the simple examples in the issue/pull request do.
Is there any method to return the SOAP Request XML before triggering a call to SOAP method in Suds library?
The client.last_sent() returns request XML after triggered the call. But I want to see before triggering the call.
Yes this is possible and seems to be used in different "fixer" implementations to take care of buggy servers. Basically you should write a MessagePlugin and implement the sending method.
Working on a side project in python that both initiates http requests and has a small web server. It got me thinking - it seems like every python microframework has its own model for accessing properties of the http request (e.g. the underlying request object that you can use to get at the querystring parameters, headers, etc. and the underlying response object for setting the status code, response headers, etc). They all allow you access to the same data and they've all kind of re-invented the wheel.
Are there any microframeworks that use the Request and Response objects from the popular requests library instead of having their own implementation? It seems like the requests library is becoming the canonical way to do http requests in python, so this would make a framework especially minimal. It would also be cool when making apps that essentially glue other services together because forwarding/wrapping requests would be trivial. You could just change the .url attribute on the incoming request and call .prepare() to forward the request (yes, for simple forwarding doing it at the webserver level makes more sense, but you get the idea).
Or if there aren't any frameworks that do this in particular, are there any with similar benefits i.e. the incoming http request object also works as an http client?
Edit: Wanted to point out that this is how the http Request object works in Go, that's partly what inspired my question. From the net/http library "A Request represents an HTTP request received by a server or to be sent by a client."
Flask is based on Werkzeug. Werkzeug itself is using Request which itself is using BaseRequest. But this is not the Requests library.
Note that there was a plan to create an httpcore library using both Requests and Werkzeug, but that seems to have stopped. That said both projects are kicking.
Some people have modified Flask in their apps using Requests
I have a question regarding the different ways inheritance are represented between WCF and SUDS (Python). I have a C++/CLI WCF server (.NET 3.5 SP1) and I'm trying to communicate with it. I've used a C# (WCF also) client and it work fine, but there are problems when using a SUDS client (Python 2.6.4, SUDS 0.3.8). It's mostly fine, but for inherited types, and the difference seems to be in the way the two represent inheritance in the SOAP XML. When I look at the messages that the server logs, I get results similar to the following:
C# Client:
<ns:DerivedType>
...
</ns:DerivedType>
Python Client:
<ns:BaseType xsi:type="ns:DerivedType">
...
</ns:BaseType>
Is it possible to change the WCF server to accept the Python style? Or to change the Python SUDS client to send the WCF style? Which one is correct?
Don't know about the python side but there are couple of options on the WCF side. The more straight foward option is to create a message inspector to detect and convert the python generated soap to something more palatable to the WCF service.
The more difficult but "purer" option is to determine how to shape the WSDL generated by the WCF service so it allows the python client to produce the aforementioned palatable soap. Once you find the required tweaks, you would use the MessageContract classes in place of the DataContract to make the service produce the tweaked WSDL. The .NET clients should handle this tweaked WSDL without complaint.
You could use the data contract serializer to control how the xml is created and read. See: http://msdn.microsoft.com/en-us/library/ms731073.aspx