Conceitos de Aplicações RESTful

Arquitetura REST, RMM e HATEOAS

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/football

HATEOAS

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/user
POST 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/rplansky
POST 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!

Made with Slides.com