Diferència entre revisions de la pàgina «Web Services»

De Cacauet Wiki
Salta a la navegació Salta a la cerca
Línia 85: Línia 85:
  
 
== Exemple en Python i Pyramid ==
 
== Exemple en Python i Pyramid ==
 +
Teniu el codi íntegre a: https://github.com/lacetans/jsonxat_ws
 +
 
Fixa't en què en aquest cas:
 
Fixa't en què en aquest cas:
* El ''framwork'' ja ens parseja l'entrada:<pre>dades = request.json_body</pre>
+
* El ''framework'' ja ens parseja l'entrada:<pre>dades = request.json_body</pre>
 
*: O sigui, no cal fer un json.loads
 
*: O sigui, no cal fer un json.loads
 
* També el propi ''framwork'' ens parseja la sortida, fent un return d'un diccionari Python que es tradueix automàticament a JSON.
 
* També el propi ''framwork'' ens parseja la sortida, fent un return d'un diccionari Python que es tradueix automàticament a JSON.

Revisió del 15:07, 22 maig 2014

Introducció

Un servei web o web service ve a ser un servei més del sistema informàtic (o sigui, un sistema d'intercanvi d'informació), però amb algunes peculiaritats:

  • Utilitza el protocol HTTP per intercanviar les dades.
    • Utilitza els mètodes HTTP: GET, POST, PUT, DELETE (inspirat en el CRUD de les BBDD).
    • Pot tenir altres mètodes (arbitraris) però no és tan usual.
  • Sol aplicar-se a sistemes navegables (enllaços/hipervincles).
  • Sol estar al port 80
  • Sol utiltizar una arquitectura REST o REpresentational State Transfer.
    • Arquitectura client-servidor
    • Sense estat
    • Cachejable
    • Per capes
    • Codi "on demand": compartit (al client, p.ex. javascript)
    • Interfície uniforme

Avantatges:

  • Estandarització
  • ...


Exemple en Python i CherryPy

En Python solem utiltizar la llibreria json o bé simplejson.

Els mètodes més importants son:

  • json.loads
  • json.dumps

En moltes ocasions, els propis "renderers" del nostre framework ens faran aquesta feina, tot i que estan utilitzant aquesta llibreria.

# http://www.cherrypy.org/
# http://docs.cherrypy.org/en/latest/tutorial/REST.html

import cherrypy, json

class Xat:
    exposed = True
    
    # llistar missatges
    def GET(self,*args,**kwargs):
        # processem parametres
        canal = kwargs.get("canal")
        # preparem resposta
        resposta = {}
        resposta["status"] = False
        resposta["missatge"] = "Servei no implementat (encara). Canal=" + str(canal)
        return json.dumps( resposta )
        
    # enviar missatges
    @cherrypy.tools.json_in()
    def POST(self,*args,**kwargs):
        dades = cherrypy.request.json
        # "dades" conte elements JSON deserialitzats amb dicts, llista, etc.
        resposta = {}
        resposta["status"] = True
        resposta["missatge"] = "Missatge llegit correctament: " + str(dades)
        return json.dumps( resposta )

if __name__ == '__main__':
    cherrypy.tree.mount(
        Xat(), '/api/xat',
        {'/':
            {'request.dispatch': cherrypy.dispatch.MethodDispatcher()}
        }
    )
    cherrypy.engine.start()
    cherrypy.engine.block()

Utilitza la següent crida cURL per testejar:

$ curl http://localhost:8080/api/xat -d '"hola"' -H "Content-Type: application/json" -X POST

El -X POST és opcional ja que sempre que li posem un "-d" (dades) ja s'assumeix que és POST.

Fixeu-vos en què:

  • Les dades d'entrada ens les parseja el framework:
    dades = cherrypy.request.json
  • Les dades de sortida les hem de transformar a JSON
    return json.dumps
    El framwork s'encarrega de posar headers.


Exemple en Python i Pyramid

Teniu el codi íntegre a: https://github.com/lacetans/jsonxat_ws

Fixa't en què en aquest cas:

  • El framework ja ens parseja l'entrada:
    dades = request.json_body
    O sigui, no cal fer un json.loads
  • També el propi framwork ens parseja la sortida, fent un return d'un diccionari Python que es tradueix automàticament a JSON.
    El punt clau per realitzar això és el renderer:
    @view_config(route_name='xat_set_missatge_ws', renderer='jsonp')
@view_config(route_name='xat_set_missatge_ws', renderer='jsonp')
def xat_set_missatge_ws(request):
    try:
        # ho intentem per GET (JSONP)
        remitent = request.GET.get("remitent")
        missatge = request.GET.get("missatge")
        if remitent and missatge:
            if remitent.strip() and missatge.strip():
                linia = remitent + "\t" + missatge 
        else:
            # ho intentm per POST (JSON)
            dades = request.json_body
            linia = dades["remitent"] + "\t" + dades["missatge"] 
        if "<" in linia or "\n" in linia:
            return {
                "servei":"xat",
                "canal":"principal",
                "status":False,
                "missatge":"ERROR: caracters ilegals"
            }
        file = open(STORAGE_FILENAME,"a+")
        file.write(linia+"\n");
        file.close()
            
    except ValueError:
        return {"servei":"xat",
		"canal":"principal",
		"status":False,
		"missatge":"ERROR: JSON incorrecte"
        }
    except Exception as e:
        print type(e).__name__
        print e.args
        return {"servei":"xat",
		"canal":"principal",
		"status":False,
		"missatge":"ERROR desonegut: " + type(e).__name__
        }
    
    return {	"servei":"xat",
		"canal":"principal",
		"status":True,
		"missatge":"missatge enregistrat correctament"
    }