DEV Community

Cover image for Entendendo Plugs em Elixir
Paulo Castro
Paulo Castro

Posted on • Edited on

Entendendo Plugs em Elixir

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, 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

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.

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:

def connection_example(conn, _opts) do
  conn
end
Enter fullscreen mode Exit fullscreen mode

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:

defmodule PlugExample do
  def init(opts) do
    opts
  end

  def call(conn, opts) do
    conn
  end
end
Enter fullscreen mode Exit fullscreen mode

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

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:

pipeline :browser do
  plug :accepts, ["html"]
  plug :fetch_session
  plug :fetch_flash
  plug :protect_from_forgery
  plug :put_secure_browser_headers
end
Enter fullscreen mode Exit fullscreen mode

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!

Top comments (9)

Collapse
 
wlsf profile image
Willian Frantz

Muito massa o texto maninho, parabéns e obrigado por compartilhar o conteúdo!

Uma das coisas que mais admiro no Elixir, é esse princípio de Composability que é muito utilizado, como no exemplo que você deu de aninhar plugs em uma pipeline, que também pode ser usado no Ecto para aninhar queries, ou até mesmo no Elixir com o pipe operator!

Collapse
 
cyytrus profile image
Paulo Castro

Muito obrigado pelo feedback, irmão! e agradeço mais ainda por ter me incentivado a buscar esse conteúdo e trazê-lo em português!

Exatamente! Composability em Elixir é incrível em todas as formas!

Collapse
 
rohlacanna profile image
Rômulo Silva

Ótimo artigo! Parabéns Paulo, ficou realmente muito bom! :')

Collapse
 
cyytrus profile image
Paulo Castro

Agradeço demais pelo feedback, Rômulo! Você é uma inspiração p mim!

Collapse
 
uberlandino profile image
Douglas Alves

Parabéns pelo artigo! Didática impecavel, sempre.

Collapse
 
cyytrus profile image
Paulo Castro

Valeuuuu Douglão, você é o melhor!

Collapse
 
bronen profile image
BRonen

incrivel explicação👌👏

Collapse
 
cyytrus profile image
Paulo Castro

Mt obg!

Collapse
 
jvmartyns profile image
João Vitor Martins Araújo

Muito bom!