API di Genropy

Genropy mette a disposizione un sistema di comunicazione per ricevere informazioni dall’esterno tramite chiamate REST. Le API di Genropy possono essere utilizzate per modificare inserire, modificare o eliminare record, per esempio per disiscrivere un utente da una mailing list, o aggiungere un indirizzo e-mail alla lista dei contatti, o ancora modificare le quantità di un prodotto a magazzino, innescare script, ecc.

Le API di Genropy prevedono innanzitutto la definizione, in una webpage, di un webhook, ovvero un metodo che, una volta «attivato» da chiamate POST/GET da un service esterno, permetterà di eseguire le azioni desiderate.

Il primo passo è quindi la definizione all’interno di un package di una webpage con il metodo desiderato:

from gnr.core.gnrdecorator import public_method

  class GnrCustomWebPage(object):
    py_requires = 'gnrcomponents/externalcall:BaseRpc'

    @public_method
    def metodo_webhook(self, **kwargs):
        pass

Il metodo_webhook non dovrà necessariamente chiamarsi così ma potrà essere nominato a piacimento. Si noti che il nome del metodo webhook determinerà l’URL da chiamare, ad esempio:

https://dominiogenropy.it/nome_package/nome_webpage/metodo_webhook

Si noti che il metodo deve prevedere l’utilizzo del decoratore @public_method. I parametri possono essere passati in modo esplicito (es: contatto_id=None), oppure nei ** kwargs.

Il webhook invocato elaborerà un oggetto self.request e un oggetto self.response. È infatti possibile fornire risposte di tipo differente, o innescare azioni diverse a seconda del tipo di chiamata GET o POST, ad esempio:

if self.request.method == 'GET':
     if kwargs['verify_token'] == token:
           return kwargs['challenge']
     else:
           self.response.status_code = 403
           return 'Access forbidden'
elif request.method == 'POST':
       incoming_message = json.loads(request.data.decode('utf-8'))
       self.recordFromMessage(incoming_message=incoming_message)

Nell’esempio distinguiamo innanzitutto se la chiamata che abbiamo ricevuto (self.request.method) è di tipo GET o di tipo POST. Se è di tipo GET, controlliamo che contenga un token corrispondente a una variabile token che avremo definito in altra sede: se corrisponde, restituiamo un ulteriore parametro challenge che ci sarà stato fornito nella chiamata, alternativamente restituiamo un codice di errore 403. Se invece è di tipo POST, elaboriamo il messaggio in ingresso e lanciamo un altro metodo recordFromMessage.

Suggerimento

Si noti che di default lo status_code della risposta sarà sempre 200 OK salvo diversamente specificato.

Si consiglia sempre di inviare un token prima di effettuare modifiche al database. Nel caso precedente abbiamo inviato il token come semplice parametro (verify_token), sfruttando poi il codice della risposta per «bloccare» la procedura, ma in alternativa possiamo fare lo stesso tipo di controllo nell”header della chiamata, interrompendo il flusso se l’autorizzazione non viene correttamente verificata:

app_token = self.site.getPreference('subscription_token', pkg='dem')
received_token = self.request.headers.get('Authorization')
if f'Bearer {app_token}' != received_token:
    raise GnrBasicAuthenticationError('Wrong Authorization Login')

Autore della sezione: Davide Paci