Python et les Web Services¶
Les web service permettent un découplage entre les données et leurs utilisations.
Ainsi un client peut être en python et le server qui distribue le web service en java.
Un peu de vocabulaire
Web Service : typiquement, c’est un programme informatique capable de recevoir/transmettre des données entre des applications et systèmes hétérogènes (oui, wikipedia m’a aidé). Pour faire simple et vulgaire, c’est une application qui peut fonctionner à peu près partout et n’importe comment. Exemple : on peut utiliser un web service comme une bibliothèque partagée via réseau intranet/Internet par des programmes écrits dans différents langages.
SOAP : Protocole RPC (Remote Procedure Call), basé sur XML, utilisé pour appeler et retourner le résultat d’une fonction distante.
WSDL (Web Service Description Language): Format XML servant à décrire un web service. En effet, pour pouvoir utiliser un web service, il nous faut connaître sa structure : le nom des fonctions, les paramètres, etc... C’est à ça que sert la description WSDL.
Il existe comme souvent en python un module qui gère ce genre de problématique: soappy.
son installation
pip install soappy
son utilisation: on va faire un serveur et un client soap
server.py
import SOAPpy
def hello():
return "Hello World"
def msg(txt):
return "Your message is %s " % txt
server = SOAPpy.SOAPServer(("localhost", 8085))
server.registerFunction(hello)
server.registerFunction(msg)
server.serve_forever()
client.py
import SOAPpy
server = SOAPpy.SOAPProxy("http://localhost:8085/")
print server.hello()
print server.msg('coucou')
Note
Pour voir les trames transmises et reçues on ajoute
server.config.debug = 1
vous lancez maintenant le serveur puis le client: et voilà tout le monde communique
son installation
python server.py &
python client.py
On peut écrire un client rapide pour é=essayer le serveur (on utilise un message xml directement dans l’appli)
# post xml soap message
import sys, httplib
# a "as lighter as possible" soap message:
SoapMessage= """<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
>
<SOAP-ENV:Body>
<getTemp SOAP-ENC:root="1">
<v1 xsi:type="xsd:int">85500</v1>
</getTemp>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
"""
#construct and send the header
webservice = httplib.HTTP("127.0.0.1:8085")
webservice.putrequest("POST", "/")
webservice.putheader("Host", "127.0.0.1:8085")
webservice.putheader("User-Agent", "Python post")
webservice.putheader("Content-type", "text/xml; charset=\"UTF-8\"")
webservice.putheader("Content-length", "%d" % len(SoapMessage))
webservice.putheader("SOAPAction", "\"\"")
webservice.endheaders()
webservice.send(SoapMessage)
# get the response
statuscode, statusmessage, header = webservice.getreply()
print "Response: ", statuscode, statusmessage
print "headers: ", header
res = webservice.getfile().read()
print res
On peut utiliser le module soappy pour faire de l’instrospection de web service
from SOAPpy import WSDL
wsdlFile = 'http://www.xmethods.net/sd/2001/TemperatureService.wsdl'
server = WSDL.Proxy(wsdlFile)
print server.methods.keys()
callInfo = server.methods['getTemp']
print callInfo.inparams
print callInfo.inparams[0].name
print callInfo.inparams[0].type
# on utilise le web service
print server.getTemp('90210')
Note
le module soappy ne permet pas la génération automatique du fichier wsdl, il faut don l’écrire à la main pour le rendre disponible.
exemple de fichier wsdl
<?xml version="1.0"?>
<definitions name="TemperatureService" targetNamespace="http://www.xmethods.net/sd/TemperatureService.wsdl" xmlns:tns="http://www.xmethods.net/sd/TemperatureService.wsdl" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/">
<message name="getTempRequest">
<part name="zipcode" type="xsd:string"/>
</message>
<message name="getTempResponse">
<part name="return" type="xsd:float"/>
</message>
<portType name="TemperaturePortType">
<operation name="getTemp">
<input message="tns:getTempRequest"/>
<output message="tns:getTempResponse"/>
</operation>
</portType>
<binding name="TemperatureBinding" type="tns:TemperaturePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getTemp">
<soap:operation soapAction=""/>
<input>
<soap:body use="encoded" namespace="urn:xmethods-Temperature" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" namespace="urn:xmethods-Temperature" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="TemperatureService">
<documentation>Returns current temperature in a given U.S. zipcode </documentation>
<port name="TemperaturePort" binding="tns:TemperatureBinding">
<soap:address location="http://services.xmethods.net:80/soap/servlet/rpcrouter"/>
</port>
</service>
</definitions>