API, REST, RESTful

Conceitos e exemplo prático
Voltar

API

Application Programming Interface tem função de intermediar comunicação universal entre diferentes sistemas, assim como do banco de dados com o próprio sistema (interno ou externo), utilizando protocolo de comunicação HTTP (XML/JSON), requisitados via URL específica, independente da tecnologia do sistema que irá consumí-la (acessá-la).

  • URL: http://www.sistema.com
  • URL + URI: http://www.sistema.com/api/produtos
  • Endpoint coleção: /api/produtos
  • Endpoint individual: /api/produtos/2

Estrutura de URL



REST

Representational State Transfer. Técnica que consiste em princípios que, quando seguidos, permitem a criação de projetos (web services) com interfaces/arquitetura bem definidas (padrão REST), utilizando novos métodos/verbos REST HTTP:

  • PUT: Create
    • /api/produtos
    • /api/produtos/42 (requer body(XML-JSON) no header request)

  • GET: Read
    • /api/produtos
    • /api/produtos/42

  • POST: Update
    • /api/produtos (requer body(XML-JSON) no header request)
    • /api/produtos/42

  • DELETE: Delete
    • /api/produtos
    • /api/produtos/42

Nativamente, o HTTP é Stateless (Não guarda estado). Com o uso de REST, permitirá que as requisições HTTP armazenem dados (estados). Os Web services que estão em conformidade com o estilo arquitetural REST são denominados Web services RESTful. Um sistema é considerado RESTful quando segue corretamente o padrão REST.


HTTP Request e Response


Request:

Requisição HTTP do dispositivo ao servidor web. Incluem dados de pares chave/valor na URI (query string).
Ex: /api/produtos?order=desc&limit=5

Header da request:
  • Accept: Especifica formato do arquivo desejado pelo requester
    • Accept: application/xml
    • Accept: application/json
    • Accept: application/pdf
  • Accept-Language: Idioma do conteúdo
  • Cache-Control: Conteúdo pode ser consumido do cache e o tempo em que o cache é atualizado

Versão da API: /api/v1/produtos


Response:

Resposta HTTP do servidor web ao dispositivo, sob sua requisição.

  • Na requisição existe query string?
  • Qual foi o verbo HTTP que realizou a ação?
  • Quais os dados do header?
  • Qual o formato requisitado?
  • Quais dados da coleção ou indivíduo do recurso solicitado precisam ser enviados?
Header da response:
  • Content-Type: text/javascript (Formato de dado conforme requisitado)
  • Last-Modified: Tue, 15 Jan 2023 12:45:26 GMT
  • Expires: Thu, 22 Jan 2023 16:00:00 GTM
  • Status: 200 OK (Código de status HTTP)

HTTP Status Codes:
  • 1XX: Informational (100 a 199)
  • 2XX: Success
    • 200: Consulta encontrada no server
    • 201/202: Criação de novo recurso com sucesso
  • 3XX: Redirection
    • 300: Requisição HTTP foi entendida, mas o recurso encontra-se em outra URI
  • 4XX: Client Error
    • 404: URI informada incorretamente (Not Found)
    • 405 e 403: URI pode ser requisitada apenas com verbo GET/POST
  • 5XX: Server Error
    • 500: Requisição realizada, mas houve erro no lado do servidor (Server Error)

Segurança em APIs

  • Uso de cache para requests: Cliente faz requisição ao servidor, que enviará a resposta e a armazenará em memória. As próximas requisições similares consultarão diretamente o cache, dispensando acesso ao servidor todas as vezes. O Redis é um exemplo de ferramenta que constrói tal estrutura.
  • Limitar quantidade de requests no servidor para evitar queda do mesmo.
  • Promover autenticação e autorização de acesso, aderindo Tokens, via Public Key enviada no Header da Request para autenticação e acesso ao servidor.
    • Authorization: What you can do
    • Authentication: Who are you


Exemplo prático

Aplicação Front-end envia requisição HTTP com métodos REST para Back-end, que, de acordo com a URL, realizará determinadas rotinas e gerará um JSON de resposta com os resultados da requisição. Essa requisição, geralmente, será reenviada ao Front-end, que o 'consumirá' em um layout interativo ao usuário.

Exemplo consultar dados de cliente: Usuário clica em Consultar Cliente, que enviará URL requisitando dados do cliente ao Back-end. Conforme parâmetros na URI requisitada (ID do usuário, URL via método GET) (Request), dinâmica e denominada endpoint, com isso, o Back-end, por meio da API REST (Métodos e padrões de código) com Laravel, consultará BD e criará JSON com resultado dos dados do cliente solicitado e o enviará de volta ao Front-end (Response), que lerá o JSON (Consumir API REST) com React, mostrando os dados do cliente em interface gráfica agradável para o usuário.


Pré-instalações

  1. Instalar Laravel: Instruções
  2. Instalar Postman: Instruções
  3. Criar BD: Iniciar Apache e MySQL XAMPP e, no Phpmyadmin, criar BD: 'CREATE DATABASE artigos;'
  4. Criar projeto Laravel: 'composer create-project --prefer-dist laravel/laravel laravelApiRest'
  5. Configurar BD em .env: 'DB_DATABASE=artigos'

Passo a passo

Github projeto
  1. Criar Model, migration e Controller: php artisan make:model Artigo -m php artisan make:controller ArtigoController --resource
  2. Configurar Migration create_artigos_table.php (Após código, realizar comando 'php artisan migrate')
  3. 
    <?php
    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;
    
    class CreateArtigosTable extends Migration {
    
        public function up() {
            Schema::create('artigos', function (Blueprint $table) {
                $table->id();
                $table->string('titulo');
                $table->text('conteudo');
                $table->timestamps();
            });
        }
    
        public function down() {
            Schema::dropIfExists('artigos');
        }
    }
    
  4. Definir Controller ArtigoController
  5. 
    <?php
    namespace App\Http\Controllers;
    use App\Models\Artigo as Artigo;
    use App\Http\Resources\Artigo as ArtigoResource;
    use Illuminate\Http\Request;
    
    class ArtigoController extends Controller {
    
        public function index() {
            $artigos = Artigo::paginate(15);
            return ArtigoResource::collection($artigos);
        }
    
        public function show($id) {
            $artigo = Artigo::findOrFail( $id );
            return new ArtigoResource($artigo);
        }
    
        public function store(Request $request) {
            $artigo = new Artigo;
            $artigo->titulo = $request->input('titulo');
            $artigo->conteudo = $request->input('conteudo');
    
            if($artigo->save()) {
                return new ArtigoResource($artigo);
            }
        }
    
        public function update(Request $request) {
            $artigo = Artigo::findOrFail($request->id);
            $artigo->titulo = $request->input('titulo');
            $artigo->conteudo = $request->input('conteudo');
    
            if(artigo->save()) {
                return new ArtigoResource($artigo);
            }
        } 
    
        public function destroy($id) {
            $artigo = Artigo::findOrFail($id);
            if($artigo->delete()) {
                return new ArtigoResource($artigo);
            }
        }
    }
    
  6. Criar Routes em routes/api.php
  7. 
    <?php
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Route;
    use App\Http\Controllers\ArtigoController;
    
    Route::middleware('auth:api')->get('/user', function (Request $request) {
        return $request->user();
    });
    
    Route::get('artigos',[ArtigoController::class,'index']); //Listar artigos
    Route::get('artigo/{id}',[ArtigoController::class,'show']); //Ver artigo
    Route::post('artigo',[ArtigoController::class,'store']); //Criar artigo
    Route::put('artigo/{id}',[ArtigoController::class,'update']); //Editar artigo
    Route::delete('artigo/{id}',[ArtigoController::class,'destroy']); //Excluir artigo
    
  8. Criar Resource em app/Http/Resources/Artigo.php: 'php artisan make:resource Artigo'
  9. 
    <?php
    namespace App\Http\Resources;
    use Illuminate\Http\Resources\Json\JsonResource;
    
    class Artigo extends JsonResource {
    
        public function toArray($request){
            //return parent::toArray($request);
            return [
                'id' => $this->id,
                'titulo' => $this->titulo,
                'conteudo' => $this->conteudo
            ];
        }
    
        /* public function with( $request ){
            return [
                'version' => '1.0.0',
                'author_url' => url('https://ubsocial.github.io')
            ];
        } */
    }
    
  10. Executar projeto Laravel: 'php artisan serve' (http://localhost:8000)

  11. Testes no Postman
  12. No Postman, testar API para inserir artigo: (Deverá retornar JSON e inserir no BD)
    POST: http://localhost:8000/api/artigo
    (Headers)
    Key: Content-Type
    Value: application/json
    (Body raw) (Enviar 1 bloco de chaves por vez)
  13. 
    {
        "titulo": "Primeiro artigo pelo Postman",
        "conteudo": "Descrição desse artigo de número um."
    }
    
    {
        "titulo": "Segundo artigo pelo Postman",
        "conteudo": "Descrição desse artigo de número dois."
    }
    
    {
        "titulo": "Terceiro artigo pelo Postman",
        "conteudo": "Descrição desse artigo de número três."
    }
    
  14. No Postman, testar API para listar artigos: (Mostrará em data no JSON)
    GET: http://localhost:8000/api/artigos
  15. No Postman, testar API para ver somente o 1º artigo:
    GET: http://localhost:8000/api/artigo/1
  16. No Postman, testar API para editar o artigo 1:
    PUT: http://localhost:8000/api/artigo/1
    (Headers)
    Key: Content-Type
    Value: application/json
    (Body raw)
  17. 
    {
        "titulo": "ATUALIZANDO Primeiro artigo pelo Postman",
        "conteudo": "Descrição desse artigo de número um sendo ATUALIZADO."
    }
    
  18. No Postman, testar API para remover o artigo 1:
    DELETE: http://localhost:8000/api/artigo/1

Elaborado por Mateus Schwede
ubsocial.github.io