Conceitos de Aplicações RESTful
Arquitetura REST, RMM e HATEOAS
por Ricardo Plansky
Ricardo Plansky - Analista Desenvolvedor @ Leroy Merlin Brasil
- Formado em Análise e Desenvolvimento de Sistemas
- 11 anos de experiência com programação
- 09 anos com PHP OO
- Áreas: Marketing Digital, Business Intelligence, Telecom e, agora, e-commerce varejista.
Quem sou eu
- O que é REST
- Como funciona este modelo
- Quais são as restrições
- O que é RESTful
- Richardson Maturity Model
- Níveis do RMM
- HATEOAS
- JSON Schema
- Considerações finais
Agenda
o que é REST?
REpresentational
State
Transfer
Modelo de Arquitetura criado por Roy Fielding em meados de 2000 em sua tese de Doutorado
Como funciona este modelo?
Entendendo as regras de arquitetura REST para aplicações
1
Client-Server
- Evolução independente dos ambientes
- Separação de responsabilidades
- Recursos divididos
Client-Server
2
Stateless
-
Toda requisição deve ser independente
-
Os servidores não devem guardar estados dos seus clientes
-
O client deve mandar toda informação necessária para o servidor entender e processar a requisição
Stateless
3
Cacheable
-
Evitar processamento desnecessário
-
Ganho de performance
-
Tempo de resposta para os clients
-
Menor uso de recursos do servidor
Cacheable
4
Uniform Interface
-
Contrato de comunicação entre client e server
-
Coesão em endpoints e respostas
-
Estrutura clara de organização
-
RMM
-
HATEOAS
Uniform Interface
5
Layered System
Clientes não se comunicam diretamente com servidores
Camada de abstração
Load Balancer
Escalabilidade
Layered System
6
Code on Demand
opcional
-
Execução de código do lado do cliente
-
Necessidades variantes de acordo com o cliente
-
JavaScript, Applets, Flash, etc.
Code on Demand
O que é
RESTful?
1) Seguir estritamente as regras do modelo de arquitetura REST
2) Possuir um certo nível de coesão e maturidade
Richardson
Maturity
Model
-
Um modelo simples que define o nível de 'maturidade' RESTful da sua app.
-
Possui 3 níveis (mais o nível zero)
-
Aplicado basicamente na quarta regra do REST (Uniform Interface)
Exemplo
Um webservice simples para
gerenciamento de usuaŕios e seus respectivos hobbies
É a ausência de qualquer regra.
- Basicamente usar o HTTP como transporte de informações
- Possui apenas um endpoint e um verbo HTTP
- Comum em SOAP
Nível Zero
POST http://api.meetuplaravelsp.com/call{
"action": "createUser",
"parameters": {
"username": "rplansky",
"password": "letmein",
"hobbies": [
"football",
"drawing",
"skating"
]
}
}criar usuário
POST http://api.meetuplaravelsp.com/call{
"action": "deleteUser",
"parameters": {
"username": "rplansky"
}
}deletar usuário
POST http://api.meetuplaravelsp.com/call{
"action": "removeHobbie",
"parameters": {
"username": "rplansky",
"hobbie": "football"
}
}deletar hobbie
<?php
class MagicController
{
public function call($action, array $parameters = array())
{
switch ($action) {
case 'createUser':
// Some code
break;
case 'deleteUser':
// Some code
break;
case 'removeHobbie':
// Some code
break;
...
}
}
}Código
Aplicação de resources
-
São criados diversos endpoints para representar os resources
-
Melhor estruturação
Nível Um
POST http://api.meetuplaravelsp.com/user/create{
"username": "rplansky",
"password": "letmein",
"hobbies": [
"football",
"drawing",
"skating"
]
}POST http://api.meetuplaravelsp.com/user/delete{
"username": "rplansky"
}POST http://api.meetuplaravelsp.com/user/rplansky/hobbie/remove{
"hobbie": "football"
}Código
class UserController
{
public function create($parameters)
{
// Some code
}
public function delete($username)
{
// Some code
}
}class HobbieController
{
public function delete($username, $hobbie)
{
// Some code
}
}Nível Dois
Aplicação de verbos HTTP
- Além dos endpoints criados no nível 1, agora há coesão entre verbos e ações executadas
POST http://api.meetuplaravelsp.com/user{
"username": "rplansky",
"password": "letmein",
"hobbies": [
"football",
"drawing",
"skating"
]
}{}DELETE http://api.meetuplaravelsp.com/user/rplansky{}DELETE http://api.meetuplaravelsp.com/user/rplansky/hobbie/footballHATEOAS
Hypermedia As The Engine Of Application State
Nível Três
HATEOAS
É prover uma maneira do cliente interagir com o serviço inteiramente por hipermídia.
Deixar claro como é feita a comunicação com os seus recursos e fornecer as informações necessárias para isso
GET http://api.meetuplaravelsp.com/{
"name": "Meetup Laravel SP API",
"version": "1.4-beta",
"_links": [
{
"rel": "user",
"_links": [
{"rel": "create", "href": "/user", "method": "POST"},
{"rel": "delete", "href": "/user", "method": "DELETE"},
{"rel": "list", "href": "/user", "method": "GET"},
{"rel": "hobbie", "_links": [
...
]}
]
}
}
}{
"user": {
"username": "rplansky",
"password": "letmein",
"hobbies": ["football", "drawing", "skating"]
},
"_links": [
{"rel": "self", "href": "/user/rplansky", "method": "GET"},
{"rel": "delete", "href": "/user/rplansky", "method": "DELETE"},
{"rel": "addHobbie", "href": "/user/rplansky/hobbie", "method": "POST"}
{"rel": "hobbies", "href": "/user/rplansky/hobbie", "method": "GET"}
]
}POST http://api.meetuplaravelsp.com/user{
"username": "rplansky",
"password": "letmein",
"hobbies": ["football", "drawing", "skating"]
}request
response
POST http://api.meetuplaravelsp.com/userPOST HTTP/1.1 201 Created
content-type: application/json; charset=UTF-8
date: Wed, 01 Apr 2015 18:06:36 GMT
status: 201 Created
version: HTTP/1.1
Location: http://api.meetuplaravelsp.com/user/rplanskyPOST http://api.meetuplaravelsp.com/user/rplansky/hobbie{
"user": {
"username": "rplansky",
"password": "letmein",
"hobbies": ["football", "drawing", "skating", "new-hobbie"]
},
"_links": [
{"rel": "self", "href": "/user/rplansky/hobbie/new-hobbie", "method": "GET"},
{"rel": "parent", "href": "/user/rplansky", "method": "GET"},
{"rel": "delete", "href": "/user/rplansky/hobbie/new-hobbie", "method": "DELETE"},
{"rel": "add", "href": "/user/rplansky/hobbie", "method": "POST"},
{"rel": "list", "href": "/user/rplansky/hobbie", "method": "GET"}
]
}{
"hobbie": "new-hobbie"
}request
response
Exemplo
Paginação de usuários nesse nosso webservice
GET http://api.meetuplaravelsp.com/user/page/2{
"page": 2,
"limit": 10,
"users": [
{
"username": "rplansky",
"password": "letmein",
"hobbies": [
"football",
"drawing",
"skating",
"new-hobbie"
]
},
{...}
]
"_links": [
{"rel": "add", "href": "/user", "method": "POST"},
{"rel": "next", "href": "/user/page/3"},
{"rel": "prev", "href": "/user/page/1"},
]
}JSON
Schema
{
"title": "User Example Schema",
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0
}
},
"required": ["firstName", "lastName"]
}Pequenas
Considerações
Sempre que possível, e fizer sentido, utilizem os headers das suas requisições e respostas.
Evite colocar informações que não dizem respeito ao resource no corpo da requisição
Headers
Sempre retorne um status code que faça sentido para a resposta.
Fuja do padrão de retornar apenas: 200, 400, 404 ou 500
Status Code
Analise as respostas dos seus serviços. É coeso? Tem todas as informações necessárias para interação?
Analise suas respostas
Perguntas?
Obrigado!
Conceitos de Aplicações RESTful
By Ricardo Plansky Jr.
Conceitos de Aplicações RESTful
Slides da apresentação feita no Segundo Meetup de Laravel de SP, onde falo um pouco sobre o modelo de arquitetura REST e como construir uma aplicação RESTful apresentando os conceitos de Richardson Maturity Model e HATEOAS
- 329