Entendendo Plugs em Elixir
Tags: elixir, webdev, programming, tutorial
Published: 2022-04-18 14:28:10

# Introdução

A motivação do Artigo veio através de uma dificuldade que tive estudando Plugs em Elixir, o conteúdo não exemplificava e/ou explicava muito bem o funcionamento desse tipo de componente, e após muito estudo consegui uma forma interessante para entender tudo isso, e nada melhor do que compartilhar esse estudo!

Dessa forma, artigo de hoje tem o intuito de explicar o funcionamento dos Plugs em Elixir por meio das seguintes etapas abaixo. No entanto, é de ***SUMA*** importância que você tenha conhecimento do [protocolo HTTP e do ciclo de vida das requisições](https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Overview), pois isso não será abordado no texto abaixo:

1. Middlewares: Um breve resumo
  1. Tipos comuns de middlewares utilizados em Elixir
  
2. Plugs em Elixir!
  1. Elementos e caminhos de um Plug
  
3. Tipos de Plugs em Elixir
  1. Function Plugs
  2. Module Plugs
  
4. Plug Pipelines

## 1 - Middlewares: Um breve resumo

Middleware é um tipo de software que gerencia dados e informações de um determinado tipo de aplicação, seja ela um sistema de mensageria, autenticação, API, dentre outros. Dessa forma, o middleware atua como uma ***"ponte"*** entre os processos do software, possibilitando a criação de aplicações mais legíveis e eficientes, uma vez que o desenvolvedor entenda todos os processos de seu middleware, onde as conexões e dados do usuário final sejam tratadas de forma integral e legível pelo programa.

### 1.1 - Tipos comuns de middlewares utilizados em Elixir

  * ***Integração abrangente:*** Esse middleware possibilita conectar sistemas internos e externos da aplicação, facilitando a tratativa dos dados recebidos, temos como exemplo uma linha de autenticação por token, onde o usuário envia a primeira requisição com seus dados e em seguida ganha um ***"Token"*** para continuar navegando em outras áreas de um determinado site. Em elixir temos libs que disponibilizam plugs para isso.

  * ***API's:*** As nossas boas e velhas APi's também são tipos de middlewares, uma vez que as mesmas também podem ser ferramentas integradas por meio de protocolos, transmitindo e/ou tratando dados para uma aplicação e podendo conectar os produtos e serviços de um software.


![Elixir-plug-example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2xf7tcw15zh8c5gwas3x.png)

## 2 - Plugs em Elixir!

Em Elixir, o Plug é o que possibilita diferentes frameworks se comunicarem com diferentes servidores na VM do Erlang, atuando como um ***Middleware***. Entender os Plugs é algo vital para um bom desenvolvedor Elixir, uma vez que grande parte do ecossistema de uma aplicação e seus frameworks é feita por meio de Plugs. 

Os Plugs vão interagir em todas as etapas de uma aplicação, sejam elas *controllers, endpoints ou routers*, e internamente, todos são plugs.

A intenção principal de um Plug é unificar o conceito de ***"Connection"*** (isso não será traduzido, pois, será tratado como elementos e parâmetros em Elixir, e é uma convenção abreviar tal parâmetro) ou ***"Conn"***. Dessa forma, o Plug difere-se de outros middlewares que utilizam desse mesmo sistema de Connections, pois internamente ele não separa a requisição da resposta.

### 2.1 - Elementos e caminhos de um Plug

É possível pensar em um Plug como um trecho do código que recebe uma estrutura de dados, transforma-a e retorna a mesma estrutura, porém, com algum tipo de transformação. A estrutura principal recebida pelo Plug é a ***"Connection"***, que representa tudo em uma requisição.

Desse modo, ao receber a Connection por meio da estrutura de dados ***%{} - "struct"***, a mesma será transformada progressivamente por meio do que chamamos de ***"Plug pipeline"*** até a resposta final que precisamos.

Essa Connection que utilizaremos sempre é chamada de %Plug.Conn{}, uma struct onde armazenaremos as informações da nossa requisição, você pode consultar a documentação da mesma [aqui](https://hexdocs.pm/plug/Plug.Conn.html).

## 3 - Tipos de Plugs em Elixir

Em seu nível mais simples, os Plugs dividem-se em duas formas: ***Function Plugs e Module Plugs.***

### 3.1 - Function Plugs

Para atuar como um Plug, uma função precisa de duas coisas:

1. Aceitar uma *Connection struct* ( **%Plug.Conn{}** ).

2. Retornar uma Connection struct

Toda função que receber e retornar tais parâmetros pode ser chamada **Function plug.**

Temos como exemplo: 

```Elixir
def connection_example(conn, _opts) do
  conn
end
```

#### Explicando o código:

**Elementos:**

  * conn: struct %Plug.Conn{}.

  * _opts: abreviação para "options", como não será utilizada e, por convenção em elixir, é colocado um *underscore ( _ )* para ignorar os valores.

**Comportamento:**

  * Receberá a connection e as options (que não utilizaremos).

### 3.2 - Module Plugs

É considerado ***Module Plug*** tudo aquilo que implementa as duas funções: ***init/1 e call/2:***

```Elixir
defmodule PlugExample do
  def init(opts) do
    opts
  end

  def call(conn, opts) do
    conn
  end
end
```

#### Explicando o código:

**Elementos:**

  * função *init/1*

  * função *call/2*

**Comportamento:**

  * init receberá um parâmetro (options) e retornará o parâmetro recebido.

  * call receberá dois parâmetros: a connection e as **options** de *init/1*, agilizando muito o processo de execução do programa.

    * Curiosidade: *init/1* é executada enquanto o programa é compilado, enquanto *call/2* acontece enquanto o programa está sendo executado.

### **Um exemplo**

Para não deixar esse artigo gigante, você pode consultar um exemplo funcional de um ***MODULE PLUG*** no meu [github](https://github.com/Cyytrus/plug-article)

## Plug pipelines

Os Plugs começam a tomar sentido quando começamos a utilizar pipelines, que nada mais é do que um jeito de aninhar os Plugs, cada um fazendo uma pequena tarefa, transformando os dados e mandando-os para o próximo Plug de forma ***sequencial***.

Tal coisa é muito utilizada no Phoenix, o framework para aplicações Web do Elixir, de modo que temos a seguinte pipeline como padrão:

```Elixir
pipeline :browser do
  plug :accepts, ["html"]
  plug :fetch_session
  plug :fetch_flash
  plug :protect_from_forgery
  plug :put_secure_browser_headers
end
```

Dessa forma, cada requisição terá como retorno uma Connection modificada, que será passada para outros plugs até chegarmos a uma resposta final.

# Conclusão

Com esse artigo, é possível entender o que é um middleware, Plugs em Elixir, Tipos de Plugs e Plug pipelines, não será possível, nessa ocasião, a construção de um Plug em Phoenix. No entanto, farei um artigo futuramente detalhando passo-a-passo a criação de um Plug desde o `mix phx.new` até o término do código.

No mais, espero que eu tenha conseguido clarear um pouco a ideia dos Plugs, e qualquer dúvida e/ou correções é possível me contatar no [twitter](https://twitter.com/Elixitrus)!