Bookmark and Share
Document Actions

Utilizzare tipi complessi, WSDL e conclusioni
difficile

I metodi possono prendere in input e restituire tipi più complessi di interi, stringhe e liste. Vediamo come è possibile scambiare binari e tipi composti. Inoltre vediamo come estrarre il WSDL necessario per l`interoperabilità.

Passaggio di binari

Il protocollo http non prevede lo scambio di valori binari. Qualsiasi cosa venga trasmessa deve quindi essere trasformata con una codifica chiamata Base64 che trasforma un flusso binario in un flusso ascii. Fortunatamente il passaggio di dati binari viene gestito automaticamente attraverso il tipo Attachment.
L'oggetto attachment è dotato di una serie di metodi appositi per la gestione di file.
Vediamo due esempi dalladocumentazione

class DocumentArchiver(SimpleWSGISoapApp):

    @soapmethod(Attachment,_returns=String)
    def archive_document(self,document):
        '''
        This method accepts an Attachment object, and returns the filename of the
        archived file
        '''
        fd,fname = mkstemp()
        os.close(fd)
        document.fileName = fname
        document.save_to_file()
        return fname
    @soapmethod(String,_returns=Attachment)
    def get_archived_document(self,file_path):
        '''
        This method loads a document from the specified file path
        and returns it.  If the path isn't found, an exception is
        raised.
        '''
        if not os.path.exists(file_path):
            raise Exception("File [%s] not found"%file_path)
        document = Attachment(fileName=file_path)
        # the service automatically loads the data from the file.
        # alternatively, The data could be manually loaded into memory
        # and loaded into the Attachment like:
        #   document = Attachment(data=data_from_file)
        return document

Questo oggetto contiene due metodi:
Il primo "archive_document" prende in input un file, lo salva in una cartella temporanea e restituisce il nome del file.
Il secondo "get_archived_document" prende in input il nome di un file e restituisce il file.

Il client può sfruttare il server in questo modo:

# client è la nostra istanza
remotefilename=client.archive_document(Attachment(fileName="mydata")

mydata è il nome del mio file locale e remotefilename è il nome del file sul sistema remoto.

Posso anche passare al costruttore direttamente una stringa di dati binari.

remotefilename=client.archive_document(Attachment(data=open("binaryfile").read()

Posso recuperare il mio file con

myfile=client.get_archived_document(remotefilename)
# myfile è un oggetto di tipo Attachment
myfile.save_to_file("mydata"

Utilizzare dei tipi composti


E' possibile definire dei tipi composti. Per farlo è necessario che la nostra classe estenda ClassSerializer (from soaplib.serializers.clazz) e definisca una sottoclasse di nome types con un elenco di attributi (semplici o, a loro volta, composti).
Ad esempio:

class Permission(ClassSerializer):
    class types:
        application = String
        feature = String
class User(ClassSerializer):
    class types:
        userid = Integer
        username = String
        firstname = String
        lastname = String
        permissions = Array(Permission)

Questi nuovi tipi potranno essere usati nei nostri decoratori soapmethod:

  @soapmethod(User)

o

  @soapmethod(_returns=Array(User))

Queste classi speciali funzionano come classi normali:

u=User()
u.username="Pippo"
u.userid=3

Gli attributi non inizializzati saranno però valorizzati None.

Generare WSDL

I wsdl sono dei file xml che contengono la descrizione dell'oggetto: i metodi esposti, la quantità e il tipo degli argomenti e dei valori di ritorno. Tramite questi file su Eclipse, utilizzando Java ad esempio, è possibile farsi costruire automaticamente la classe client.
Soaplib dispone di due modi di generare il wsdl: il primo direttamente dal server aggiungendo "wsdl" all'indirizzo della nostra risorsa. Tornando al nostro primo esempio:

>>> client = make_service_client('http://localhost:7789/',HelloWorldService())
>>> print client.say_hello("Dave",5)

Visitando l'indirizzo http://localhost:7789/wsdl ci verrà restituito il file wsdl.

Il secondo modo per ottenere il wsdl e tramite la funzione

client.server.wsdl('')

In questo modo il wsdl viene generato lato client.

Conclusioni


Direi che abbiamo affrontato tutti i punti relativi all'interfacciamento di un applicazione python tramite web service.
- come usare un web server wsgi (in questo caso cherrypy)
- come scrivere un`interfaccia web (a basso livello con WSGI)
- come esporre degli oggetti tramite il protocollo soap (usando soaplib)

Approfondimenti

Per approfondire l'argomento dei web service può essere interessante esplorare altri tipi di web service, ad esempio xmlrpc (librerie xmlrpc e pyro) o altre implementazioni di soap per python (suds, zsi, twisted ).

 
by Maurizio Lupo last modified 2009-04-03 12:46