jueves, 15 de abril de 2010

Soporte para AMF (RPC) en Trac

Parche de la API multi-protocols para Trac

Otro día histórico. Después que Odd Simon Simonsen me invitara a participar en el desarrollo del muy útil y exitoso plugin TracXmlRpc y añadir soporte para Hessian, le ha tocado el turno a Action Message Format. Este es un protocolo binario diseñado por Macromedia, actualmente absorbido por Adobe Systems. Su objetivo es proporcionar un medio ligero y eficiente para codificar, decodificar y transportar datos entre Flash Player y el Flash Remoting gateway. En otras palabras se puede utilizar Flash Remoting MX con ActionScript para hacer aplicaciones interactivas, en este caso utilizando datos de proyectos administrados por Trac. El nuevo componente que ha sido construido permite tener más elementos de juicio para evaluar la API que se desarrolla actualmente, y que permitirá ejecutar los métodos disponibles a través de múltiples protocolos. Hace solo unos minutos efectué la primera llamada exitosa utilizando AMF desde Python . Los detalles ...

... no quiero adelantar mucho todavía porque la implementación no está estable y muy probablemente se le hagan cambios incompatibles al prototipo de la API que existe hoy. Pero bueno, todo comenzó con un parche ofrecido por thijs para incorporarlo en el plugin plugin TracXmlRpc. En ese momento solo existían implementaciones para dos protocolos muy populares: XML-RPC, JSON-RPC. Hay soporte para el primero en la librería estándar (i.e. xmlrpclib.ServerProxy), mientras que el segundo es accesible si se utilizan otras librerías (e.g. wsgi-jsonrpc). En el caso específico de AMF, el autor del parche ofreció un ejemplo basado en PyAMF que luego modifiqué un poco hasta obtener lo siguiente :

#!/usr/bin/env python

"""
AMF client for the Trac RPC plugin.
"""

import base64
from optparse import OptionParser
from socket import error
import sys

from pyamf.remoting import RemotingError
from pyamf.remoting.client import RemotingService

p = OptionParser()

p.add_option("-U", dest="username",
                  help="Trac USER", metavar="USER")
p.add_option("-P", dest="password", metavar="PASSWORD",
                  help="use PASSWORD to authenticate USER")
p.add_option("-e", dest="env", metavar="URL",
                  help="base URL of target environment")

(opts, args) = p.parse_args()

username = opts.username
password = opts.password
try :
  url = opts.env + '/rpc'
except :
  sys.exit("Missing Trac environment. Use -e option.")

service_name = 'system'

gw = RemotingService(url)
if (username, password) != (None, None):
  auth = base64.encodestring('%s:%s' % (username, password))[:-1]
  gw.addHTTPHeader("Authorization", "Basic %s" % auth)

service = gw.getService(service_name)

try:
    print service.getAPIVersion()
except RemotingError, e:
    print e
except error, e:
    print e[1]

Como se puede ver, si la base del servidor se encuentra, por ejemplo, en http://localhost/trac entonces el protocolo está disponible en http://localhost/trac/rpc. Realmente esta URL debe servir para todos los protocolos disponibles que ya mencioné anteriormente y los que vendrán. El tipo de protocolo se determina considerando el encabezado Content-Type de la petición HTTP, que en este caso es application/x-amf. Esta es la idea fundamental que utilizó Odd para diseñar la API.

El script anterior muestra el número de la versión del protocolo. Para probar, ejecutamos el módulo de la siguiente forma

$ python ./amf-client.py -U username -P mypassword -e http://localhost/trac
[1, 1, 0]

¡Y ya está! . A continuación les muestro otro ejemplo más simplificado utilizando solamente el intérprete de Python.

>>> import base64
>>> from pyamf.remoting import RemotingError
>>> from pyamf.remoting.client import RemotingService
>>> username, password = 'olemis', 'mypassword'
>>> url = 'http://localhost/trac/rpc'
>>> gw = RemotingService(url)
>>> auth = base64.encodestring('%s:%s' % (username, password))[:-1]
>>> gw.addHTTPHeader("Authorization", "Basic %s" % auth)
>>> service = gw.getService('system')
>>> print service.getAPIVersion()
[1, 1, 0]

¡Eso es todo! Todas estas implementaciones serán ofrecidas próximamente por el plugin TracRpcProtocols. Si quiere estar al tanto del desarrollo de esta nueva funcionalidad le invito a seguir los próximos artículos. El soporte de AMF para Trac es solo el segundo capítulo de la primera temporada (gracias osimons y thijs ;o) .

No hay comentarios:

Publicar un comentario