Diferència entre revisions de la pàgina «JsonXat»
(Hi ha 14 revisions intermèdies del mateix usuari que no es mostren) | |||
Línia 2: | Línia 2: | ||
Per permetre una màxima eficiencia i bon disseny utilitzarem serveis web. Et caldrà haver llegit els següents articles: | Per permetre una màxima eficiencia i bon disseny utilitzarem serveis web. Et caldrà haver llegit els següents articles: | ||
+ | * [[Web Services]] | ||
* [[Web Services amb Pyramid i Cornice]] | * [[Web Services amb Pyramid i Cornice]] | ||
* [[Android]] | * [[Android]] | ||
Línia 29: | Línia 30: | ||
#* http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/renderers.html#jsonp-renderer | #* http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/renderers.html#jsonp-renderer | ||
#* Test amb curl | #* Test amb curl | ||
+ | #* Teniu el codi per aquest projecte íntegre (versió Pyramid, utilitzant sistema d'arxius, sense DB): | ||
+ | #*: https://github.com/lacetans/jsonxat_ws | ||
# Costat client: exemple JavaScript | # Costat client: exemple JavaScript | ||
#* http://enricus.tk/jsonxat.html | #* http://enricus.tk/jsonxat.html | ||
#* Instal·leu l'exemple al vostre domini | #* Instal·leu l'exemple al vostre domini | ||
# Aplicació mòbil: | # Aplicació mòbil: | ||
− | #* [[Android]] | + | #* [[JsonXat#App_mòbil_Android]] (en aquest article, més avall) |
+ | #* [[Android]]: per introduir-se a la programació Android | ||
<br> | <br> | ||
== Definint la nostra API dels serveis JSON == | == Definint la nostra API dels serveis JSON == | ||
+ | Aquesta part és important. Si estem fent un projecte que requereix comunicació entre diversos mòduls caldrà que realitzem un document com aquesta secció, indicant: | ||
+ | # quins serveis oferim | ||
+ | # com s'han de demanar (valors d'entrada) | ||
+ | # què ens retornen | ||
+ | |||
Necessitem una interfície per parlar amb el servidor. Ens permetrà definir el '''protocol per enviar i rebre missatges independentment de la implementació que tinguem al servidor'''. És a dir que podem tenir el servei muntat sobre el filesystem o sobre una base de dades i que el client no noti la diferència, ja que la interfície és comuna. | Necessitem una interfície per parlar amb el servidor. Ens permetrà definir el '''protocol per enviar i rebre missatges independentment de la implementació que tinguem al servidor'''. És a dir que podem tenir el servei muntat sobre el filesystem o sobre una base de dades i que el client no noti la diferència, ja que la interfície és comuna. | ||
Bàsicament volem enviar i rebre missatges. El nostre protocol tindrà, doncs: | Bàsicament volem enviar i rebre missatges. El nostre protocol tindrà, doncs: | ||
− | * Demanar llista de canals: '''xat_get_canals_ws''' | + | * Demanar llista de canals: '''xat_get_canals_ws'''. Prova amb: <pre>$ curl http://enricus.tk/serveis/xat_get_canals_ws</pre> |
* Demanar missatges per un canal: '''xat_get_canal_ws/<canal>''' | * Demanar missatges per un canal: '''xat_get_canal_ws/<canal>''' | ||
* Enviar missatge per un canal: '''xat_set_missatge_ws''' | * Enviar missatge per un canal: '''xat_set_missatge_ws''' | ||
+ | |||
+ | Detalls a continuació... | ||
+ | <br> | ||
=== xat_get_canal_ws === | === xat_get_canal_ws === | ||
Línia 61: | Línia 73: | ||
{| border="1" class="wikitable" style="border-collapse:collapse;" | {| border="1" class="wikitable" style="border-collapse:collapse;" | ||
− | |+ xat_get_canal_ws (sortida) | + | |+ xat_get_canal_ws (sortida) |
! atribut | ! atribut | ||
! valor | ! valor | ||
! comentari | ! comentari | ||
|- | |- | ||
− | | | + | | status |
− | | | + | | true/false |
− | | | + | | ens informa si tot ha anat bé |
+ | |- | ||
+ | | missatges | ||
+ | | [ {"remitent":"pere","missatge":"hola!"} , {} , {} ] | ||
+ | | llista de missatges del canal | ||
|- | |- | ||
| missatge | | missatge | ||
− | | " | + | | "canal inexistent"<br>"error intern" |
− | | | + | | detalls del status de la comanda |
|} | |} | ||
− | + | Test (versió JSON amb POST): | |
− | $ curl http://enricus.tk/serveis/xat_get_canal_ws | + | $ curl http://enricus.tk/serveis/xat_get_canal_ws -d '{"canal":"principal"}' |
+ | |||
+ | Test (simulant JSONP amb GET): | ||
+ | $ curl http://enricus.tk/serveis/xat_get_canal_ws?canal=principal | ||
+ | |||
+ | Prova d'introduir-hi errors per veure el resultat que ens ofereix. | ||
=== xat_set_missatge_ws === | === xat_set_missatge_ws === | ||
Línia 129: | Línia 150: | ||
Per testejar el GET amb JSONP utilitzeu la web: (provoca error si canvies el canal per un d'inexistent) | Per testejar el GET amb JSONP utilitzeu la web: (provoca error si canvies el canal per un d'inexistent) | ||
http://enricus.tk/jsonxat.html | http://enricus.tk/jsonxat.html | ||
+ | |||
+ | <br> | ||
== Directiva de seguretat de browsers i JSONP == | == Directiva de seguretat de browsers i JSONP == | ||
Línia 150: | Línia 173: | ||
== App mòbil Android == | == App mòbil Android == | ||
− | + | Utilitzeu l'article [[Android]] per iniciar-vos amb les aplicacions pel SO de Google. | |
Volem realitzar una app que ens faci la mateixa funció que la web d'exemple anterior. És a dir, que carregui i envii missatges a un servidor seguint el protocol marcat per la nostra API. | Volem realitzar una app que ens faci la mateixa funció que la web d'exemple anterior. És a dir, que carregui i envii missatges a un servidor seguint el protocol marcat per la nostra API. | ||
+ | |||
+ | Exemples de tractament de dades JSON amb Android: | ||
+ | * Robust: teniu codi en la carpeta "android" | ||
+ | * [http://stackoverflow.com/questions/2793150/how-to-use-java-net-urlconnection-to-fire-and-handle-http-requests StackOverflow java i http]. | ||
+ | |||
+ | |||
+ | Procediment recomanat: | ||
+ | |||
+ | # Utilitzar llibreria estàndard de HTTP per descarregar-nos el "string" del servidor. | ||
+ | #* Us trobareu que el ''main thread'' no permet executar requests HTTP i llança l'excepció '''NetworkOnMainThreadException'''. Això ho fa per evitar que el ''main thread'' es quedi "penjat" esperant alguna cosa d'internet. | ||
+ | #*: Solució: utilitzar un thread apart. | ||
+ | #*: [http://uf.ctrl-alt-d.net/material/mostra/147/threads-en-java Threads en Java]. '''Feu els exercicis de threads abans de continuar'''. | ||
+ | # Mostrar el ''string'' a un textView. | ||
+ | #* S'ha de fer des del GUI (main) thread. Per tant el nou thread que hem creat no pot fer un simple setText. Llegiu la resposta aquí (utiltizar ''view.post''): | ||
+ | #*: http://stackoverflow.com/questions/9884246/how-to-set-text-of-text-view-in-another-thread | ||
+ | #* Ull quan actualitzeu una View (com el TextView). Perquè s'actualitzi (equival a un REPAINT de Qt): | ||
+ | #** Utilitzeu .invalidate() si esteu al ''main thread''. | ||
+ | #** Utiltizeu .postInvalidate() si esteu a qualsevol altre ''thread''. | ||
+ | # "Parsejar" el string obtingut i descodificar les dades dins d'estructures del nostre llenguatge (arrays, diccionaris, etc.). Utilitzar JSONObject | ||
+ | # Enviar missatges al xat a través del ''web service'' xat_set_missatge_ws |
Revisió de 15:06, 22 maig 2014
Realitzarem una aplicació de xat a través del mòbil i de la web.
Per permetre una màxima eficiencia i bon disseny utilitzarem serveis web. Et caldrà haver llegit els següents articles:
Contingut
Introducció[modifica]
Objectius:
- Treballar web services.
- Treballar JSON com a format estàndard de comunicació.
- Establir una API de referència independent de l'implementació.
- Treballar aplicacions mòbils.
Recursos:
- Links articles anteriors.
- curl: (Call URL) utilitat per línia de comandes Unix per testejar serveis web (i d'altres).
- Pàgina web de test i exemple amb JavaScript:
Passes recomanades[modifica]
- Costat servidor: serveis web
- Es pot realitzar amb el llenguatge/framework de la vostra elecció (en principi Pyramid o PHP).
- Web Services amb Pyramid i Cornice
- JSONP en Pyramid: ens resulta més convenient ja que podem cridar la llibreria entre servidors (problema de seguretat dels browsers i la política de "mateix domini" en les crides JSON).
- http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/renderers.html#jsonp-renderer
- Test amb curl
- Teniu el codi per aquest projecte íntegre (versió Pyramid, utilitzant sistema d'arxius, sense DB):
- Costat client: exemple JavaScript
- http://enricus.tk/jsonxat.html
- Instal·leu l'exemple al vostre domini
- Aplicació mòbil:
- JsonXat#App_mòbil_Android (en aquest article, més avall)
- Android: per introduir-se a la programació Android
Definint la nostra API dels serveis JSON[modifica]
Aquesta part és important. Si estem fent un projecte que requereix comunicació entre diversos mòduls caldrà que realitzem un document com aquesta secció, indicant:
- quins serveis oferim
- com s'han de demanar (valors d'entrada)
- què ens retornen
Necessitem una interfície per parlar amb el servidor. Ens permetrà definir el protocol per enviar i rebre missatges independentment de la implementació que tinguem al servidor. És a dir que podem tenir el servei muntat sobre el filesystem o sobre una base de dades i que el client no noti la diferència, ja que la interfície és comuna.
Bàsicament volem enviar i rebre missatges. El nostre protocol tindrà, doncs:
- Demanar llista de canals: xat_get_canals_ws. Prova amb:
$ curl http://enricus.tk/serveis/xat_get_canals_ws
- Demanar missatges per un canal: xat_get_canal_ws/<canal>
- Enviar missatge per un canal: xat_set_missatge_ws
Detalls a continuació...
xat_get_canal_ws[modifica]
atribut | valor (exemple) | comentari |
---|---|---|
canal | principal | canal de xat del què volem rebre els missatges |
atribut | valor | comentari |
---|---|---|
status | true/false | ens informa si tot ha anat bé |
missatges | [ {"remitent":"pere","missatge":"hola!"} , {} , {} ] | llista de missatges del canal |
missatge | "canal inexistent" "error intern" |
detalls del status de la comanda |
Test (versió JSON amb POST):
$ curl http://enricus.tk/serveis/xat_get_canal_ws -d '{"canal":"principal"}'
Test (simulant JSONP amb GET):
$ curl http://enricus.tk/serveis/xat_get_canal_ws?canal=principal
Prova d'introduir-hi errors per veure el resultat que ens ofereix.
xat_set_missatge_ws[modifica]
atribut | valor (exemple) | comentari |
---|---|---|
canal | principal | canal de xat al què volem enviar el missatge |
missatge | "hola, com anem per aquí?" | cos dels missatge a enviar |
Cal tenir en compte que potser no us cal tota la informació que el servei ens dóna:
atribut | valor | comentari |
---|---|---|
servei | "xat" | nom del servei que estem utilitzant (sempre serà "xat") |
canal | "principal" | canal de xat al què hem volgut enviar el missatge |
status | true/false | si la petició s'ha resolt OK (gravar missatge) |
missatge | "ERROR: JSON incorrecte" "missatge enregistrat correctament" |
missatge amb detalls de l'execució |
Tingueu en compte que les dades es poden enviar per GET (cas del JSONP) o per POST (JSON normal). El servei implementa els dos casos, però si ho feu vosaltres penseu en què us cal comprovar les dades de les 2 fonts (GET i JSON).
Podeu testejar el POST amb: (prova també de variar la clau remitent o missatge per provocar que et retorni error)
$ curl http://enricus.tk/serveis/xat_set_missatge_ws -d '{"remitent":"nuria","missatge":"prova aviam"}'
Per testejar el GET amb JSONP utilitzeu la web: (provoca error si canvies el canal per un d'inexistent)
http://enricus.tk/jsonxat.html
Directiva de seguretat de browsers i JSONP[modifica]
En aquesta pràctica ens convé utiltizar JSONP (wikipedia) enlloc del JSON habitual per solventar un "problema" de seguretat. Bé, no és un problema, sinó una directiva amb molt de sentit:
SOP o Same-Origin Policy: simplement, els navegadors o browsers impedeixen crides a serveis en servidors que no son el què apareix a la URL en curs.
És lògic i convenient, perquè si no, ens poden "robar la cartera" quan naveguem.
Pel desenvolupament, però, ens provocarà certes molèsties. Les alternatives son:
- Treballem sempre amb el mateix servidor+port amb JSON (important el port, diferents ports el navegador els considera diferents sites).
- Col·locar un proxy en el nostre servidor perquè ens redirigeixi certes crides al 2n servidor (apache2 mod_proxy).
- Utiltizar un "truc" anomenat JSONP. Ens permetrà cridar serveis en un altre servidor però només ens funciona a través de GET.
Teniu un exemple de tot plegat (particularment de la part JavaScript) a:
http://enricus.tk/jsonxat.html
Cal implementar JSONP al servidor i al client. La part negativa de tot plegat és que si després volem fer els serveis amb JSON haurem de duplicar codi o bé passar-lo de JSONP a JSON (seria convenient per seguretat).
App mòbil Android[modifica]
Utilitzeu l'article Android per iniciar-vos amb les aplicacions pel SO de Google.
Volem realitzar una app que ens faci la mateixa funció que la web d'exemple anterior. És a dir, que carregui i envii missatges a un servidor seguint el protocol marcat per la nostra API.
Exemples de tractament de dades JSON amb Android:
- Robust: teniu codi en la carpeta "android"
- StackOverflow java i http.
Procediment recomanat:
- Utilitzar llibreria estàndard de HTTP per descarregar-nos el "string" del servidor.
- Us trobareu que el main thread no permet executar requests HTTP i llança l'excepció NetworkOnMainThreadException. Això ho fa per evitar que el main thread es quedi "penjat" esperant alguna cosa d'internet.
- Solució: utilitzar un thread apart.
- Threads en Java. Feu els exercicis de threads abans de continuar.
- Us trobareu que el main thread no permet executar requests HTTP i llança l'excepció NetworkOnMainThreadException. Això ho fa per evitar que el main thread es quedi "penjat" esperant alguna cosa d'internet.
- Mostrar el string a un textView.
- S'ha de fer des del GUI (main) thread. Per tant el nou thread que hem creat no pot fer un simple setText. Llegiu la resposta aquí (utiltizar view.post):
- Ull quan actualitzeu una View (com el TextView). Perquè s'actualitzi (equival a un REPAINT de Qt):
- Utilitzeu .invalidate() si esteu al main thread.
- Utiltizeu .postInvalidate() si esteu a qualsevol altre thread.
- "Parsejar" el string obtingut i descodificar les dades dins d'estructures del nostre llenguatge (arrays, diccionaris, etc.). Utilitzar JSONObject
- Enviar missatges al xat a través del web service xat_set_missatge_ws