RESTful 4 allDiego Sapriza
[email protected]@AV4TAr
Como diseñar una API RESTful sin morir en el intento.
Hi!Diego SaprizaI’M
@AV4TAr
PHP.meetup.uy
DevOps.meetup.uy
..uy
“El mundo evoluciona constantemente”
Restful api
versionamiento
recursos
status codes
autenticación mensajes
paginación documentación!
hypermedia (HATEOAS)
verbos tools
Quiénes hacen mayoritariamente
Web dev?
REpresentational State transfer
no es un estándar
Acuerdo
https://www.flickr.com/photos/124247024@N07/
Roy Fielding escalabilidad
:(
restricciones escalabilidadClient-Server
Stateless
Cache
Uniform Interfaces Layered System
Code on demand (opcional)
Richardson Maturity Modelhttp://bit.ly/api-rmm
0: The Swamp of POX
RPC SOBRE HTTP
JSON XML html images
0: The Swamp of POX
GET http://srv.com/addin/auto-‐harvest/end-‐job/:id/
errors/:errors_messages
http://srv.com/addin/auto-‐harvest/start-‐job/:id
Richardson Maturity Modelhttp://bit.ly/api-rmm
Uniform Interfaces
• Identificación recursos.
• Manipulación de recursos a través de su representación.
• Mensajes auto-descriptivos.
• Hypermedia como motor del estado de la aplicación (HATEOAS).
1: RECURSOS
tienen una URI
mapean entidad/es
sustantivos
uri
scheme:hierarchical part[?query][#fragment]
telnet://192.168.1.1
urn:isbn:978-1-449-3150-9
mailto:[email protected]
https://api.twilio.com/2010-‐04-‐01
identificación
/recurso/:id
/recurso/:id/:acción
!
/?r=recurso&id=:id
/?r=recurso&id=:id&a=:acción
colecciones
/recursos
/recursos/:id
/recursos/:id?pagina=:n&limite=100
Richardson Maturity Model
Uniform Interfaces
• Identificación recursos.
• Manipulación de recursos a través de su representación.!
• Mensajes auto-descriptivos.
• Hypermedia como motor del estado de la aplicación (HATEOAS).
Representación
HTTP verbsGet Post Put Delete
Patch Options Head Trace Connect
http://bit.ly/http-‐request-‐methods
crud http
CREATE POST
READ GET
UPDATE PUT
DELETE DELETE
método seguro idempotente cachable
GET
HEAD
POST
PUT
DELETE
GET /personas Obtener lista de personas
POST /personas Agregar una persona
DELETE /personas/:id Eliminar una persona
GET /personas/:id Obtener una persona
PUT /personas/:id Actualizar una persona
GET /personas/:id/contactos Obtener los contactos de una persona
POST /personas/:id/contactos Agregar un contacto a una persona
POST /personas/subirImagen Subir una imagen
y ahora… ¿qué hacemos con estos msjs?
Richardson Maturity Model
Documentar…
Uniform Interfaces
• Identificación recursos.
• Manipulación de recursos a través de su representación.
• Mensajes auto-descriptivos.!
• Hypermedia como motor del estado de la aplicación (HATEOAS).
auto-descriptivos
¿Cómo procesar el mensaje?
¿qué parser utilizar?
¿Caching?
ahora… ¿cómo son los mensajes?
HAL Collection JSON Siren
HTTP/1.1 200 OK!Content-Type: application/json!{! "status":"ok",! "message":"Data retrieved OK!",! "data" : [! !{! !! "id": 90, ! !! "modelId": 81, ! !! "path": "Somewhere over the rainbow.rvt"! !},! !{! !! "id": 91, ! !! "modelId": 13, ! !! "path": "Blue birds fly.rvt”! }]!}!
GET http://server/addin/auto-‐harvest/get-‐jobs/ o_O
HTTP/1.1 200 OK!Content-Type: application/json!{! "status":"error",! "message":"Page not found”,! "data" : []!}!
o_O
status codes
2xx - Success
3xx - Redirection
4xx - Client Error
5xx - Server Error
Error messages api-problem
HTTP/1.1 401 Unauthorized!Content-Type: application/problem+json!{!! "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html",!! "title": "Unauthorized",!! "status": 401,!! "detail": "Unauthorized",!! "authentication_uri": "/oauth"!}!
Uniform Interfaces
• Identificación recursos.
• Manipulación de recursos a través de su representación.
• Mensajes auto-descriptivos.
• Hypermedia como motor del estado de la aplicación (HATEOAS).
HATEOASClients make state transitions only through
actions that are dynamically identified within hypermedia by the server. !
Except for simple fixed entry points to the application, a client does not assume that any particular action is available for any
particular resources beyond those described in representations previously
received from the server.
clase.php
public class Customer!{!! ! public $Id;!! ! public $Name;!}!
clase.c#
public class Customer!{!! public int Id { get; set; }!! public string Name { get; set; }!}!
json
{ ! "id" : "1"! "name" : "Diego"!}!
HAL
http://bit.ly/hal-spec
{! "id": "diego",! "name": "Diego Sapriza”,!! "_links": {! "self": {! "href": "http://web.org/api/user/diego"! },! "website": {! "href": "http://web.org/api/locations/diego"! }! }!} !
HAL{! .. *snip* ..! "_embedded": {! "website": {! "_links": {! "self": {! "href": “http://web.org/api/locations/diego"! }! },! "id": "diego",! "url": "http://diego.uy"! }! }!}!
HAL - colecciones
{! "_links": {! "self" :{ "href": "http://web.org/api/user?page=3" },! "first":{ "href": "http://web.org/api/user" },! "prev" :{ "href": "http://web.org/api/user?page=2" },! "next" :{ "href": "http://web.org/api/user?page=4" },! "last" :{ "href": "http://web.org/api/user?page=133" }! },! "count": 3,! "total": 498,! ...!}
https://api.github.com
{! "current_user_url": "https://api.github.com/user",! "authorizations_url": "https://api.github.com/authorizations",! "emails_url": "https://api.github.com/user/emails",! "emojis_url": "https://api.github.com/emojis",! "events_url": "https://api.github.com/events",! "feeds_url": "https://api.github.com/feeds",! "following_url": "https://api.github.com/user/following{/target}",! "gists_url": "https://api.github.com/gists{/gist_id}",! "hub_url": "https://api.github.com/hub",! "issues_url": "https://api.github.com/issues",! "keys_url": "https://api.github.com/user/keys",! "notifications_url": "https://api.github.com/notifications",! "organization_url": "https://api.github.com/orgs/{org}",! "public_gists_url": "https://api.github.com/gists/public",! "rate_limit_url": "https://api.github.com/rate_limit",! "repository_url": "https://api.github.com/repos/{owner}/{repo}",! "starred_url": "https://api.github.com/user/starred{/owner}{/repo}",! "starred_gists_url": "https://api.github.com/gists/starred",! "team_url": "https://api.github.com/teams",! "user_url": "https://api.github.com/users/{user}",! "user_organizations_url": "https://api.github.com/user/orgs",! ...!}!
Richardson Maturity Modelhttp://bit.ly/api-rmm
Sigamos links
Restful api
versionamiento!recursos
status codes
autenticación!mensajes
paginación
documentación!hypermedia (HATEOAS)
verbos tools
Versiona tu API
HTTP GET https://web.com/api/v1/users/diego
HTTP GET https://web.com/api/users/diego api-‐version: 2
HTTP GET https://web.com/api/users/diego Accept: application/vnd.myapi.v2+json
HTTP GET https://web.com/api/users/diego
por defecto última versión Headers para versiones anteriores
autenticación
crea tu propio método
HTTP Basic Auth !
HTTP Digest !
OAuth2
tools
Postman
Runscope
jsonmate.com
Restful api
versionamiento
recursos
status codes
autenticación
mensajes
paginación
documentación!hypermedia (HATEOAS)
verbos tools
@AV4TAr http://AV4TAr.com
https://speakerdeck.com/av4tar/restful-para-todos
• http://www.troyhunt.com/2014/02/your-api-versioning-is-wrong-which-is.html
• http://martinfowler.com/articles/richardsonMaturityModel.html
• http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
• http://spf13.com/post/soap-vs-rest
• https://leanpub.com/build-apis-you-wont-hate
• https://speakerdeck.com/caseysoftware/on-the-edge-of-hypermedia-midwest-dot-io
Top Related