Este post nace a raíz de las horas que he "perdido" en el curro intentando desplegar un servidor de webservices en Python, partiendo del descriptor (fichero WSDL). La causa de esas horas "perdidas" es el uso de tipos de datos complejos, es decir, no un simple String por ejemplo, sino una secuencia de éstos (vector de Strings) y el uso de la herramienta wsdl2py para generar la base de lo que será nuestro servidor. La librería que usaremos es ZSI, que es actualmente la que tiene un desarrollo más activo y parece ser que se impone como la de referencia para desarrollar webservices usando Python. Por contra, la documentación disponible es escasa.
Entremos en materia. Tenemos el siguiente descriptor que define el servicio que queremos ofrecer y las operaciones que tiene disponibles. Digamos que el servicio tiene que devolver una lista de pares (peso,Variable) para una petición de un String. Caso práctico: le pedimos al webservice la última lista de la compra que hizo Juan (el String "Juan" sería el input del servicio) en la frutería, nos devolverá una lista de parejas (kilos, fruta), por ejemplo :) Veamos la parte relevante: `
El primer paso será generar la base de código Python que luego extenderemos para crear nuestro servicio. Para ello usamos el script pythonwsdl2pyy su compañero de viajewsdl2dispatch. **Atención** como hacemos uso de tipos de dato complejos (complexType), necesitamos pasarle awsdl2pyel argumento--complexType(o-b), sino, tendremos errores en la serialización de los objetos python y del [XML][5] cuando os habléis con vuestro servicio. Aquí me tiré yo horas por no hacer un--help:)$ wsdl2py --complexType --file Servicio.wsdl
$ wsdl2dispatch --file Servicio.wsdl
Estos dos comandos nos crearán 3 ficheros .py:
*Servicio_services.py*Servicio_services_server.py*Servicio_services_types.py` Para crear nuestro servidor, extenderemos Servicio_services_server en una nueva clase (myServer, por ejemplo).
`from ZSI import * class MyServicio(ServicioService): _wsdl = "".join(open("Servicio.wsdl").readlines()) # para devolver el WSDL a cliente que lo solicite
def soap_getPares(self, ps, **kw):
response = ServicioService.soap_getPares(self, ps, **kw)
request = self.request
return self.getPares(request)
def getPares(self, req):
db = DB.connect()
pares = db.getListaCompra(req.get_element_input())
return pares
...
y ahora un poco de OptionParser antes de ponerlo en marcha
op = OptionParser(usage="%prog [options]") op.add_option("-l", "--loglevel", help="loglevel (DEBUG, WARN)", metavar="LOGLEVEL") op.add_option("-p", "--port", help="HTTP port", metavar="PORT", default=8080, type="int") options, args = op.parse_args()
if options.loglevel: loglevel = eval(options.loglevel, logging.dict) logger = logging.getLogger("") logger.setLevel(loglevel)
Ejecutamos el servidor
AsServer(port=options.port, services=[MyServicio(),]) ` Ahora ya sólo faltaría el cliente (y la base de datos, que lo puse ahí vilmente :) ). También, ya habréis visto, los tabuladores del código se los ha pasado el wordpress por el forro, así que no hagáis copypaste ;-) El cliente, lo dejo como ejercicio al ávido lector (siempre lo había querido decir esto xDD), os dejo un enlace una buena guía por si os quedáis atascados.
If you liked this post, you can donate using Bitcoin 12jVrWkk5S6x5hEizThZwgTx59KxaDdK4C