Diferència entre revisions de la pàgina «Serveis web amb Laravel»

De Cacauet Wiki
Salta a la navegació Salta a la cerca
 
(Hi ha 21 revisions intermèdies del mateix usuari que no es mostren)
Línia 2: Línia 2:
  
  
== Perquè Laravel per a serveis web? ==
+
== Introducció ==
 +
Articles previs:
 +
* [[Serveis Web]]
 +
* [[Laravel]]
 +
 
 +
Articles següents:
 +
* [[Serveis Web amb Opendata]]
 +
 
 +
=== Perquè Laravel per a serveis web? ===
 
No és imprescindible utilitzar [[Laravel]] per implementar un servei web. Ens és convenient pels següents motius:
 
No és imprescindible utilitzar [[Laravel]] per implementar un servei web. Ens és convenient pels següents motius:
 
# En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.
 
# En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.
Línia 11: Línia 19:
  
 
== Primera prova de la API ==
 
== Primera prova de la API ==
 +
Anem a implementar una primera prova de API en un projecte [[Laravel]] nou. Si et cal, crea'n un.
 +
 
Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:
 
Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:
 
  routes/api.php
 
  routes/api.php
Línia 37: Línia 47:
 
  $ curl -i localhost:8000/api/ping
 
  $ curl -i localhost:8000/api/ping
  
Obtindrem:
+
Obtindrem algo com:
 
  HTTP/1.1 200 OK
 
  HTTP/1.1 200 OK
 
  Host: localhost:8000
 
  Host: localhost:8000
 +
Date: Wed, 17 Mar 2021 15:13:14 GMT
 
  Connection: close
 
  Connection: close
  X-Powered-By: PHP/7.0.15-0ubuntu0.16.04.4
+
  X-Powered-By: PHP/7.4.9
Cache-Control: no-cache
 
 
  Content-Type: text/html; charset=UTF-8
 
  Content-Type: text/html; charset=UTF-8
 +
Cache-Control: no-cache, private
 +
Date: Wed, 17 Mar 2021 15:13:14 GMT
 
  X-RateLimit-Limit: 60
 
  X-RateLimit-Limit: 60
 
  X-RateLimit-Remaining: 59
 
  X-RateLimit-Remaining: 59
  Date: Thu, 09 Mar 2017 17:25:32 GMT
+
  Access-Control-Allow-Origin: *
 +
 +
pong! :)super@HPi5-07:~/dev/laraveltest1$
 +
 
 +
<br>
  
pong! :)super@HPi5-07:~/dev/laraveltest1$  
+
== Autenticació API amb Laravel Sanctum ==
 +
Des de fa algunes versions Laravel ha incorporat diversos mètodes d'autenticació, entre ells Breeze (bàsic), Fortify (avançat) i Sanctum (API). Aquest darrer és el què ens interessa.
 +
 
 +
Sanctum té diversos mecanismes, depenent de qui utilitzarà la API (app mòbil, una web externa, etc.). Agafarem l'exemple de la APP MÒBIL.
 +
 
 +
Consulta aquí la [https://laravel.com/docs/8.x/sanctum documentació de Laravel Sanctum].
 +
 
 +
En definitiva, les diferents passes que cal seguir son:
 +
# Crear projecte Laravel i afegir algun usuari (via Breeze o via Tinker).
 +
# '''Instal·lació''' de Sanctum (install, publish, migrate).
 +
# Anem a la [https://laravel.com/docs/8.x/sanctum#issuing-mobile-api-tokens secció per a generar tokens per a mòbils].
 +
#* Implementem el '''mètode d'autenticació''' mitjançant email i password a l'arxiu '''api.php'''. També cal passar-li el ''device_name'' que quedarà anotat junt al token.
 +
# Anem a la secció [https://laravel.com/docs/8.x/sanctum#issuing-api-tokens generate API tokens] i veiem que cal afegir el TRAIT <code>HasApiTokens</code> al model User.
 +
#: <syntaxhighlight lang="php">class User extends Authenticatable {
 +
    use HasApiTokens, HasFactory, Notifiable;
 +
 
 +
    // ...
 +
}
 +
</syntaxhighlight>
 +
# Protegim rutes amb '''->middleware("auth:sanctum")''' , per exemple:
 +
#: <syntaxhighlight lang="php">Route::middleware('auth:sanctum')->get("/ping", function(Request $request) {
 +
    // ...
 +
}
 +
</syntaxhighlight>
 +
# Ara simularem la crida per '''demanar el token''' (la que posteriorment faríem des d'un mòbil)
 +
#: <pre>curl localhost:8000/api/sanctum/token -X POST -d '[email protected]&password=enric123&device_name=LolaPhone55'</pre>
 +
#: Prendre nota del TOKEN que se'ns retorna.
 +
# Crida URL per '''accedir a la API amb el Header Bearer''' necessari :
 +
#: <pre>curl localhost:8000/api/ping -H 'Authorization: Bearer lL0a21yHy4MzU4FdV5Cm0xZzd35AJ97acOOnW83t'</pre>
 +
#: Si no posem el token adequadament se'ns redireccionarà a la pàgina principal amb un codi 302
  
 
<br>
 
<br>
Línia 74: Línia 119:
 
És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.
 
És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.
  
En l'exemple del karaoke tenim 3 crides, i les especificarem amb uns quadres tal que aquests:
+
En l'exemple del karaoke tenim 3 crides, i les especificacions les indiquem amb quadres com els que mostrem a continuació:
 +
* /api/'''nvots'''/{tema_id}
 +
* /api/'''vota'''/{tema_id}
 +
* /api/'''fet'''/{tema_id}
 +
 
  
 
=== nvots ===
 
=== nvots ===
 
Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la ''request'':
 
Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la ''request'':
  
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L68 Veure codi del controller]
+
[https://github.com/emieza/laravel-karaoke/blob/master/app/Http/Controllers/TemaController.php#L68 Veure codi del TemaController@nvots]
  
 
{| class="wikitable"
 
{| class="wikitable"
Línia 95: Línia 144:
 
|}
 
|}
  
 +
Aquesta response retorna les dades en format '''JSON''', però podria tenir altres formats (XML, plain text):
 
{| class="wikitable"
 
{| class="wikitable"
!colspan="3"|Response
+
!colspan="3"|Response : JSON
 
|-
 
|-
 
!colspan="3"|GET /api/nvots/{tema_id}
 
!colspan="3"|GET /api/nvots/{tema_id}
Línia 112: Línia 162:
 
| Total de vots per al tema
 
| Total de vots per al tema
 
|-
 
|-
| message
+
| tema_id
| text
+
| integer
| Missatge de text amb la descripció de l'error o acció
+
| ID del tema consultat
 
|}
 
|}
 +
 +
Per exemple, per testejar-la:
 +
$ curl http://localhost:8000/api/nvots/1
 +
{"status":"OK","tema_id":"1","nvots":1}
 +
 +
Per testejar l'exemple en producció, podeu provar (el -k és important perquè no demani els certificats HTTPS):
 +
$ curl https://jolgorio.tk/api/nvots/1 '''-k'''
 +
{"status":"OK","tema_id":"1","nvots":2}
  
 
<br>
 
<br>
Línia 123: Línia 181:
  
 
{| class="wikitable"
 
{| class="wikitable"
!colspan="3"|Request : JSON
+
!colspan="3"|Request
 
|-
 
|-
 
!colspan="3"|GET /api/vota/{tema_id}
 
!colspan="3"|GET /api/vota/{tema_id}
Línia 137: Línia 195:
  
 
{| class="wikitable"
 
{| class="wikitable"
!colspan="3"|Response
+
!colspan="3"|Response : JSON
 
|-
 
|-
 
!colspan="3"|GET /api/vota/{tema_id}
 
!colspan="3"|GET /api/vota/{tema_id}

Revisió de 15:29, 18 març 2021

Per poder seguir amb normalitat aquest article cal haver llegit i treballat Laravel.


Introducció[modifica]

Articles previs:

Articles següents:

Perquè Laravel per a serveis web?[modifica]

No és imprescindible utilitzar Laravel per implementar un servei web. Ens és convenient pels següents motius:

  1. En el curs de M7 de DAW estem treballant amb aquest framework i ens interessa aprofundir el seu coneixement.
  2. Integrarem la part del frontend de la nostra web juntament amb la API que farem.
  3. Laravel facilita l'accés a la base de dades a través del ORM Eloquent, que resulta molt útil.


Primera prova de la API[modifica]

Anem a implementar una primera prova de API en un projecte Laravel nou. Si et cal, crea'n un.

Totes les funcions que vulguem implementar per al nostre sistema hem de començar per indicar-les al arxiu de rutes:

routes/api.php

De fet, les podríem implementar al mateix arxiu. Quan es compliquin, però, convindrà crear un controlador com vam fer al tutorial de Laravel.

Afegiu el següent codi a routes/api.php:

Route::get('/ping', function(Request $request) {
    return "pong! :)";
});

Poseu en marxa el servidor i proveu la funció amb:

$ curl localhost:8000/api/ping
pong! :)super@HPi5-07:~/dev/laraveltest1$ 

Noteu que:

  • Encara que hem definit la ruta "/ping", per poder-la cridar hem de fer "/api/ping". Ve predefinit pel Laravel, tot i que no té perquè ser així.
  • Ens contesta el què hem posat al RETURN final
  • No retorna HTML, retorna un text que pot ser qualsevol cosa
  • No hi ha \n final (s'enganxa amb el prompt de la shell)

Headers en la crida curl[modifica]

Per veure els headers de retorn, podem utilitzar "-i", pot ser molt útil per depurar:

$ curl -i localhost:8000/api/ping

Obtindrem algo com:

HTTP/1.1 200 OK
Host: localhost:8000
Date: Wed, 17 Mar 2021 15:13:14 GMT
Connection: close
X-Powered-By: PHP/7.4.9
Content-Type: text/html; charset=UTF-8
Cache-Control: no-cache, private
Date: Wed, 17 Mar 2021 15:13:14 GMT
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
Access-Control-Allow-Origin: *

pong! :)super@HPi5-07:~/dev/laraveltest1$ 


Autenticació API amb Laravel Sanctum[modifica]

Des de fa algunes versions Laravel ha incorporat diversos mètodes d'autenticació, entre ells Breeze (bàsic), Fortify (avançat) i Sanctum (API). Aquest darrer és el què ens interessa.

Sanctum té diversos mecanismes, depenent de qui utilitzarà la API (app mòbil, una web externa, etc.). Agafarem l'exemple de la APP MÒBIL.

Consulta aquí la documentació de Laravel Sanctum.

En definitiva, les diferents passes que cal seguir son:

  1. Crear projecte Laravel i afegir algun usuari (via Breeze o via Tinker).
  2. Instal·lació de Sanctum (install, publish, migrate).
  3. Anem a la secció per a generar tokens per a mòbils.
    • Implementem el mètode d'autenticació mitjançant email i password a l'arxiu api.php. També cal passar-li el device_name que quedarà anotat junt al token.
  4. Anem a la secció generate API tokens i veiem que cal afegir el TRAIT HasApiTokens al model User.
    class User extends Authenticatable {
        use HasApiTokens, HasFactory, Notifiable;
    
        // ...
    }
    
  5. Protegim rutes amb ->middleware("auth:sanctum") , per exemple:
    Route::middleware('auth:sanctum')->get("/ping", function(Request $request) {
        // ...
    }
    
  6. Ara simularem la crida per demanar el token (la que posteriorment faríem des d'un mòbil)
    curl localhost:8000/api/sanctum/token -X POST -d '[email protected]&password=enric123&device_name=LolaPhone55'
    Prendre nota del TOKEN que se'ns retorna.
  7. Crida URL per accedir a la API amb el Header Bearer necessari :
    curl localhost:8000/api/ping -H 'Authorization: Bearer lL0a21yHy4MzU4FdV5Cm0xZzd35AJ97acOOnW83t'
    Si no posem el token adequadament se'ns redireccionarà a la pàgina principal amb un codi 302


Exemples de API: laravel-karaoke[modifica]

En el projecte karaoke en Laravel, el podeu veure aquí:

Recordem que per crear un controller amb Laravel ho fem amb (per exemple):

$ php artisan make:controller ApiController

Si mireu TemaController pareu atenció que per poder fer crides com TemaController::fet($id) , necessitem que siguin funcions estàtiques (static).

Ara, per poder mirar el nº de vots, a routes/api.php tindrem:

Route::get('/nvots/{id}', function(Request $request, $id) {
    return TemaController::nvots( $id );
});


Especificacions d'una API[modifica]

És molt important especificar adequadament una API per tal que la pugui fer servir molta gent.

En l'exemple del karaoke tenim 3 crides, i les especificacions les indiquem amb quadres com els que mostrem a continuació:

  • /api/nvots/{tema_id}
  • /api/vota/{tema_id}
  • /api/fet/{tema_id}


nvots[modifica]

Al ser una crida GET, els paràmetres han d'anar a la URL. Si fos POST, anirien afegits en el cos de la request:

Veure codi del TemaController@nvots

Request
GET /api/nvots/{tema_id}
Param Values Description
tema_id integer ID del tema del que volem saber el nº de vots que té

Aquesta response retorna les dades en format JSON, però podria tenir altres formats (XML, plain text):

Response : JSON
GET /api/nvots/{tema_id}
Param Values Description
status "OK" / "ERROR" Estat intern de la consulta/acció
nvots integer Total de vots per al tema
tema_id integer ID del tema consultat

Per exemple, per testejar-la:

$ curl http://localhost:8000/api/nvots/1
{"status":"OK","tema_id":"1","nvots":1}

Per testejar l'exemple en producció, podeu provar (el -k és important perquè no demani els certificats HTTPS):

$ curl https://jolgorio.tk/api/nvots/1 -k
{"status":"OK","tema_id":"1","nvots":2}


vota[modifica]

Veure codi de TemaController@vota

Request
GET /api/vota/{tema_id}
Param Values Description
tema_id integer ID del tema del que volem saber el nº de vots que té
Response : JSON
GET /api/vota/{tema_id}
Param Values Description
status "OK" / "ERROR" Estat intern de la consulta/acció
vot true / false Estat actual del nostre vot de la nostra IP
nvots integer Total de vots per al tema
message text Missatge de text amb la descripció de l'error o acció


fet[modifica]

Veure codi de TemaController@fet

Request
GET /api/vota/{tema_id}
Param Values Description
tema_id integer ID del tema del que volem saber el nº de vots que té
Response : JSON
GET /api/vota/{tema_id}
Param Values Description
status "OK" / "ERROR" Estat intern de la consulta/acció
fet true / false Estat actual del tema (fet / no fet)
message text Missatge de text amb la descripció de l'error o acció