[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fVftuNcKcFq0pRbzPMQIN0yyLy-Cbgg9Zm8_tVBVVkkg":3},{"slug":4,"title":5,"summary":6,"category":7,"author":10,"image_url":16,"image_thumb_url":16,"published_at":17,"updated_at":18,"body_html":19,"keywords":20,"reading_time_minutes":21,"related_articles":22,"related_course":58,"related_specialty":78},"conoce-phoenix-el-poderoso-framework-de-elixir","Conoce Phoenix el poderoso framework de elixir","Phoenix es un framework de desarrollo web escrito en Elixir, patrón MVC. Muchos de sus componentes y conceptos le resultará familiar a los que tenemos experiencia en otros framework como Ruby on Rails o Django. Phoenix ofrece lo mejor de ambos mundos - alta productividad en ambitos de desarrollo y un alto rendimiento de la aplicación.",{"slug":8,"name":9},"programacion","Programación",{"username":11,"name":12,"avatar_url":13,"headline":14,"aboutme":15},"Felipe","Felipe Barrios","https:\u002F\u002Fapi.backtrackacademy.com\u002Frails\u002Factive_storage\u002Fblobs\u002Fredirect\u002FeyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBdm9TIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--e9583ea31e7a62df75d5e76630fd7f81299e3521\u002Ffelipeb.png","CEO at Backtrack Academy","I&#39;m Felipe Barrios CEO of Backtrack Academy ethical hacking community | Software Engineer building AI-powered SaaS: LLM agents &amp;amp; RAG | Ruby on Rails · Python · Vue.js · Docker · AWS | AppSec","https:\u002F\u002Fapi.backtrackacademy.com\u002Frails\u002Factive_storage\u002Fblobs\u002Fredirect\u002FeyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBaWdPIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--cc851bee290507a0ef2cddf52744e419376d5811\u002Fshutterstock_776546518.jpg","2017-04-06T22:44:54-03:00","2026-10-26T12:16:02-03:00","\u003Ch3>Introducción\u003C\u002Fh3>\r\n\u003Cp>Phoenix es un framework de desarrollo web escrito en Elixir, patrón MVC. Muchos de sus componentes y conceptos le resultará familiar a los que tenemos experiencia en otros framework como Ruby on Rails o Django. Phoenix ofrece lo mejor de ambos mundos - alta productividad en ambitos de desarrollo y un alto rendimiento de la aplicación.\u003C\u002Fp>\r\n\u003Cp>Pero antes de seguir vamos a definir algunos conceptos:\u003C\u002Fp>\r\n\u003Ch3>¿ Qué es Erlang ?\u003C\u002Fh3>\r\n\u003Cp>Erlang es un lenguaje funcional y tiene una historia aún más larga con manejo de concurrencia. Erlang fue creado en Ericsson en la década de 1980 para permitir un mejor desarrollo de aplicaciones de telefonía. Acualmente WhatsApp tiene cientos de millones de usuarios. con más de diez mil conexiones simultáneas en una sola máquina, lo cual se ve como un gran reto , pero Whatsapp tener servidores individuales con más de 2 millones de conexiones simultáneas. 2 millones de conexiones en un solo servidor, manejados por Erlang.\u003C\u002Fp>\r\n\u003Cp>Erlang también es popular para los servidores del juego. Millones de usuarios juegan con la infraestructura Erlang tález como Call of Duty y Juego de la Guerra.\u003C\u002Fp>\r\n\u003Ch3>¿Qué es Elixir?\u003C\u002Fh3>\r\n\u003Cp>Elixir creado por José Valim, comenta: “Me gustó todo lo que vi en Erlang, pero odiaba las cosas que no vi”. Elixir tiene su propio sistema de gestión de paquetes -&gt; hex.pm.\u003C\u002Fp>\r\n\u003Cp>Elixir es un lenguaje que se ejecuta en la máquina virtual de Erlang. Por lo que tiene todas las ventajas, probado en batalla y puede usar las bibliotecas existentes Erlang sin penalización en el rendimiento. Elixir y añade un montón de sutilezas. Uno de ellos es ```pipe operator``.\u003C\u002Fp>\r\n\u003Cp>La diferencia entre Erlang y elixir no es sólo la sintaxis. Sin embargo, la sintaxis es importante, y especialmente para desarrolladores de Ruby la sintaxis Elixir será muy familiar.\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Ch3>Inmutabilidad y la programación funcional\u003C\u002Fh3>\r\n\u003Cp>Elixir es un lenguaje funcional con la inmutabilidad. La programación funcional es un paradigma de programación declarativa basado en el uso de funciones matemáticas, en contraste con la programación imperativa, que enfatiza los cambios de estado mediante la mutación de variables. La programación funcional tiene sus raíces en el cálculo lambda, un sistema formal desarrollado en los años 1930 para investigar la definición de función, la aplicación de las funciones y la recursión. Muchos lenguajes de programación funcionales pueden ser vistos como elaboraciones del cálculo lambda.\u003C\u002Fp>\r\n\u003Cp>Me he dado cuenta de lo beneficioso que es. Incluso para la programación de un solo subproceso, mutabilidad trae una incertidumbre acerca de cómo va a ejecutar un programa. Y que no se pierda la mutabilidad en absoluto. La programación funcional y la inmutabilidad ayuda a aclarar las cosas y hace que sea más fácil de razonar sobre el código.\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Ch3>Concurrencia\u003C\u002Fh3>\r\n\u003Cp>Otro punto fuerte para Elixir es la simultaneidad. Concurrencia está aquí para quedarse, por varias razones. Para mencionar algunos: La tendencia en hardware es cada vez más núcleos de CPU. Los fabricantes de CPU no van a mejorar el rendimiento de un solo núcleo a la misma velocidad que antes. En su lugar, son la adición de más núcleos. También el mundo es concurrente y no desea que los usuarios finales u otros servicios de software que esperen innecesariamente una respuesta.\u003C\u002Fp>\r\n\u003Cp>En la mayoría de los idiomas de concurrencia es un poco de dolor. No sólo es peligroso y difícil de hacer la sincronización. Con el estado mutable y bifurcación de procesos nativos también es a menudo lento y utiliza una gran cantidad de memoria.\u003C\u002Fp>\r\n\u003Cp>Haciendo concurrencia en Erlang o Elixir otros idiomas es un poco como hacer ramas en Git contra la subversión . En la subversión era muy complicado de hacer - y nunca lo hice. En Git es mucho más fácil y lo hago todo el tiempo.\u003C\u002Fp>\r\n\u003Cp>Bien mucho blabla y ahora un poco de acción ,para continuar vamos a necesitar instalar:\u003C\u002Fp>\r\n\u003Cp>Elixir: Phoenix está escrito en Elixir, y nuestro código de la aplicación también será escrito en Elixir. No vamos a entrar ahora en una aplicación de Phoenix sin él!\u003C\u002Fp>\r\n\u003Cp>Erlang: Elixir se compila a código de bytes de Erlang para ejecutar en la máquina virtual de Erlang. Sin Erlang, Elixir tiene ninguna máquina virtual para ejecutar en, por lo que necesitamos para instalar Erlang también.\u003C\u002Fp>\r\n\u003Cp>\u003Cspan>* Phoenix\u003C\u002Fspan>\u003C\u002Fp>\r\n\u003Cp>\u003Cspan>*\u003C\u002Fspan>\u003Cspan> \u003C\u002Fspan>Plug, Cowboy, and Ecto\u003C\u002Fp>\r\n\u003Cp>\u003Cspan>*\u003C\u002Fspan>\u003Cspan> \u003C\u002Fspan>node.js (&gt;= 5.0.0)\u003C\u002Fp>\r\n\u003Cp>\u003Cspan>*\u003C\u002Fspan>\u003Cspan> \u003C\u002Fspan>PostgreSQL\u003C\u002Fp>\r\n\u003Cp>Ahora vamos a montar nuestro entorno de desarrollo para poder trabajar con este hermoso framework que mucho promete, lo primero sera instalar elixir:\u003C\u002Fp>\r\n\u003Cp>Para instalar elixir en Mac OS X lo vamos hacer mediante Homebrew\u003C\u002Fp>\r\n\u003Cp>Lo primero sera hacer un update a nuestro homebrew para tener la ultima version:\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>\u003Ccode>~ brew update\u003C\u002Fcode>\u003C\u002Fpre>\r\n\u003Cp>Para instalar elixir\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>\u003Ccode>~ brew install elixir\u003C\u002Fcode>\u003C\u002Fpre>\r\n\u003Cp>lo siguiente sera instalar erlang\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre> ~ brew install erlang\u003C\u002Fpre>\r\n\u003Cp>Comprobamos la versión de elixir\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>\u003Cspan>~ elixir -v\u003C\u002Fspan>\u003Cbr>Erlang\u002FOTP 18 [erts-7.3] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]\r\n\r\nElixir 1.2.5\u003C\u002Fpre>\r\n\u003Cp>Gestor de paquetes Hex para poder levantar phoenix.\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>~ mix local.hex\r\nAre you sure you want to install archive \"http:\u002F\u002Fs3.amazonaws.com\u002Fs3.hex.pm\u002Finstalls\u002F1.2.0\u002Fhex-0.11.5.ez\"? [Yn] Y\r\n* creating .mix\u002Farchives\u002Fhex-0.11.5.ez\u003Cbr>\u003Cbr>~ mix archive.install https:\u002F\u002Fgithub.com\u002Fphoenixframework\u002Farchives\u002Fraw\u002Fmaster\u002Fphoenix_new.ez\u003C\u002Fpre>\r\n\u003Cp>Y vuala hasta acá ya tenemos todo listo para poder desarrollar, ahora vamos a crear nuestro primer proyecto: asi que ejecutamos ```mix phoenix.new hello_phoenix```.\u003Cbr>\u003Cbr>\u003C\u002Fp>\r\n\u003Cpre>~ mix phoenix.new hello_phoenix\r\n* creating hello_phoenix\u002Fconfig\u002Fconfig.exs\r\n* creating hello_phoenix\u002Fconfig\u002Fdev.exs\r\n* creating hello_phoenix\u002Fconfig\u002Fprod.exs\r\n* creating hello_phoenix\u002Fconfig\u002Fprod.secret.exs\r\n* creating hello_phoenix\u002Fconfig\u002Ftest.exs\r\n* creating hello_phoenix\u002Flib\u002Fhello_phoenix.ex\r\n* creating hello_phoenix\u002Flib\u002Fhello_phoenix\u002Fendpoint.ex\r\n* creating hello_phoenix\u002Ftest\u002Fviews\u002Ferror_view_test.exs\r\n* creating hello_phoenix\u002Ftest\u002Fsupport\u002Fconn_case.ex\r\n* creating hello_phoenix\u002Ftest\u002Fsupport\u002Fchannel_case.ex\r\n* creating hello_phoenix\u002Ftest\u002Ftest_helper.exs\r\n* creating hello_phoenix\u002Fweb\u002Fchannels\u002Fuser_socket.ex\r\n* creating hello_phoenix\u002Fweb\u002Frouter.ex\r\n* creating hello_phoenix\u002Fweb\u002Fviews\u002Ferror_view.ex\r\n* creating hello_phoenix\u002Fweb\u002Fweb.ex\r\n* creating hello_phoenix\u002Fmix.exs\r\n* creating hello_phoenix\u002FREADME.md\r\n* creating hello_phoenix\u002Fweb\u002Fgettext.ex\r\n* creating hello_phoenix\u002Fpriv\u002Fgettext\u002Ferrors.pot\r\n* creating hello_phoenix\u002Fpriv\u002Fgettext\u002Fen\u002FLC_MESSAGES\u002Ferrors.po\r\n* creating hello_phoenix\u002Fweb\u002Fviews\u002Ferror_helpers.ex\r\n* creating hello_phoenix\u002Flib\u002Fhello_phoenix\u002Frepo.ex\r\n* creating hello_phoenix\u002Ftest\u002Fsupport\u002Fmodel_case.ex\r\n* creating hello_phoenix\u002Fpriv\u002Frepo\u002Fseeds.exs\r\n* creating hello_phoenix\u002F.gitignore\r\n* creating hello_phoenix\u002Fbrunch-config.js\r\n* creating hello_phoenix\u002Fpackage.json\r\n* creating hello_phoenix\u002Fweb\u002Fstatic\u002Fcss\u002Fapp.css\r\n* creating hello_phoenix\u002Fweb\u002Fstatic\u002Fjs\u002Fapp.js\r\n* creating hello_phoenix\u002Fweb\u002Fstatic\u002Fjs\u002Fsocket.js\r\n* creating hello_phoenix\u002Fweb\u002Fstatic\u002Fassets\u002Frobots.txt\r\n* creating hello_phoenix\u002Fweb\u002Fstatic\u002Fassets\u002Fimages\u002Fphoenix.png\r\n* creating hello_phoenix\u002Fweb\u002Fstatic\u002Fassets\u002Ffavicon.ico\r\n* creating hello_phoenix\u002Ftest\u002Fcontrollers\u002Fpage_controller_test.exs\r\n* creating hello_phoenix\u002Ftest\u002Fviews\u002Flayout_view_test.exs\r\n* creating hello_phoenix\u002Ftest\u002Fviews\u002Fpage_view_test.exs\r\n* creating hello_phoenix\u002Fweb\u002Fcontrollers\u002Fpage_controller.ex\r\n* creating hello_phoenix\u002Fweb\u002Ftemplates\u002Flayout\u002Fapp.html.eex\r\n* creating hello_phoenix\u002Fweb\u002Ftemplates\u002Fpage\u002Findex.html.eex\r\n* creating hello_phoenix\u002Fweb\u002Fviews\u002Flayout_view.ex\r\n* creating hello_phoenix\u002Fweb\u002Fviews\u002Fpage_view.ex\r\n\r\nFetch and install dependencies? [Yn]\r\n\r\nFetch and install dependencies? [Yn] Y\r\n* running mix deps.get\r\n* running npm install &amp;&amp; node node_modules\u002Fbrunch\u002Fbin\u002Fbrunch build\r\n\r\nWe are all set! Run your Phoenix application:\r\n\r\n    $ cd hello_phoenix\r\n    $ mix phoenix.server\r\n\r\nYou can also run your app inside IEx (Interactive Elixir) as:\r\n\r\n    $ iex -S mix phoenix.server\r\n\r\nBefore moving on, configure your database in config\u002Fdev.exs and run:\r\n\r\n    $ mix ecto.create\u003Cbr>\u003Cbr>\u003Cbr>\u003C\u002Fpre>\r\n\u003Cpre>$ mix local.rebar\u003Cbr>* creating \u002FUsers\u002Ffbarrios\u002F.mix\u002Frebar\r\n* creating \u002FUsers\u002Ffbarrios\u002F.mix\u002Frebar3\u003C\u002Fpre>\r\n\u003Cp>Up server\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>mix phoenix.server\u003C\u002Fpre>\r\n\u003Cp>En caso de que de error y no carguen los CSS\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cp>\u003Cem>Couldn't find preset \"\u002FUsers\u002Ffbarrios\u002FDocuments\u002Fphoenix\u002Fhello_test\u002Fnode_modules\u002Fbabel-preset-es2015\u003C\u002Fem>\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cp>Instalamos \u003Cem>babel-preset-es2015\u003C\u002Fem>\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>npm install --save-dev babel-preset-es2015\u003C\u002Fpre>\r\n\u003Cp>Estructura de nuestra aplicación:\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>├── channels\r\n├── controllers\r\n│   └── page_controller.ex\r\n├── models\r\n├── static\r\n├── router.ex\r\n├── templates\r\n│   ├── layout\r\n│   │   └── app.html.eex\r\n│   └── page\r\n│       └── index.html.eex\r\n└── views\r\n|   ├── error_view.ex\r\n|   ├── layout_view.ex\r\n|   └── page_view.ex\r\n└── web.ex\u003C\u002Fpre>\r\n\u003Cp>First Resource\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>\u003Cspan>$ mix help | grep -i phoenix\u003C\u002Fspan>\u003Cbr>$ mix phoenix.digest      # Digests and compress static files\r\n$ mix phoenix.gen.channel # Generates a Phoenix channel\r\n$ mix phoenix.gen.html    # Generates controller, model and views for an HTML based resource\r\n$ mix phoenix.gen.json    # Generates a controller and model for a JSON based resource\r\n$ mix phoenix.gen.model   # Generates an Ecto model\r\n$ mix phoenix.gen.secret  # Generates a secret\r\n$ mix phoenix.new         # Create a new Phoenix v1.1.2 application\r\n$ mix phoenix.routes      # Prints all routes\r\n$ mix phoenix.server      # Starts applications and their server\u003C\u002Fpre>\r\n\u003Cp>Ejemplo tipo scaffold en ruby on rails:\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>mix phoenix.gen.html Post posts title:string body:text\u003C\u002Fpre>\r\n\u003Cpre>* creating web\u002Fcontrollers\u002Fpost_controller.ex\u003Cbr>* creating web\u002Ftemplates\u002Fpost\u002Fedit.html.eex\r\n* creating web\u002Ftemplates\u002Fpost\u002Fform.html.eex\r\n* creating web\u002Ftemplates\u002Fpost\u002Findex.html.eex\r\n* creating web\u002Ftemplates\u002Fpost\u002Fnew.html.eex\r\n* creating web\u002Ftemplates\u002Fpost\u002Fshow.html.eex\r\n* creating web\u002Fviews\u002Fpost_view.ex\r\n* creating test\u002Fcontrollers\u002Fpost_controller_test.exs\r\n* creating priv\u002Frepo\u002Fmigrations\u002F20160516033253_create_post.exs\r\n* creating web\u002Fmodels\u002Fpost.ex\r\n* creating test\u002Fmodels\u002Fpost_test.exs\r\n\r\nAdd the resource to your browser scope in web\u002Frouter.ex:\r\n\r\n    resources \"\u002Fposts\", PostController\r\n\r\nRemember to update your repository by running migrations:\r\n\r\n    $ mix ecto.migrate\u003C\u002Fpre>\r\n\u003Cp>Ejecutamos\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>$ mix ecto.migrate\u003C\u002Fpre>\r\n\u003Cpre>mix ecto.migrate\u003Cbr>\u003Cbr>00:48:33.841 [info]  == Running HelloPhoenix.Repo.Migrations.CreatePost.change\u002F0 forward\r\n\r\n00:48:33.841 [info]  create table posts\r\n\r\n00:48:34.216 [info]  == Migrated in 3.7s\u003C\u002Fpre>\r\n\u003Ch3>Channel\u003C\u002Fh3>\r\n\u003Cpre>mix phoenix.gen.channel Room rooms\u003C\u002Fpre>\r\n\u003Cp>El primer argumento es el nombre del módulo para el canal. El segundo argumento es el plural.\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>a channel in web\u002Fchannels\r\na channel_test in test\u002Fchannels\u003C\u002Fpre>\r\n\u003Ch3>Routes\u003C\u002Fh3>\r\n\u003Cp>El archivo de router que genera Phoenix, web\u002Frouter.ex , tendrá un aspecto como éste:\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>def module HelloPhoenix.Router do\r\n  use HelloPhoenix.Web, :router\r\n\r\n  pipeline :browser do\r\n    plug :accepts, [\"html\"]\r\n    plug :fetch_session\r\n    plug :fetch_flash\r\n    plug :protect_from_forgery\r\n    plug :put_secure_browser_headers\r\n  end\r\n\r\n  pipeline :api do\r\n    plug :accepts, [\"json\"]\r\n  end\r\n\r\n  scope \"\u002F\", HelloPhoenix do\r\n    pipe_through :browser # Use the default browser stack\r\n\r\n    get \"\u002F\", PageController, :index\r\n  end\r\n\r\n  # Other scopes may use custom stacks.\r\n  # scope \"\u002Fapi\", HelloPhoenix do\r\n  #   pipe_through :api\r\n  # end\r\nend\u003C\u002Fpre>\r\n\u003Cp>HelloPhoenix corresponde al nombre de la aplicación, tanto para modelo, controlador o router.\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cp>HTTP get, post, y put. y no menos importante resources.\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>mix phoenix.routes\u003C\u002Fpre>\r\n\u003Cp>Hemos recorrido un largo camino en esta guía sin hablar de una de las primeras líneas que vimos en el router\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>pipe_through :browser\u003Cbr>pipeline :browser do\r\n    plug :accepts, [\"html\"] Define el formato que sera aceptado.\r\n    plug :fetch_session Va a buscar los datos de la sesión y lo pone a disposición de la conexión.\r\n    plug :fetch_flash Que recupera los mensajes de flash que pueden haber sido establecidas\r\n    plug :protect_from_forgery Seguridad pu master anti  Cross-Site Request Forgery (CSRF)\r\n    plug :put_secure_browser_headers\r\n  end\u003C\u002Fpre>\r\n\u003Cp>De esta manera cargamos :browser y utilizamos la basura\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>  scope \"\u002F\", HelloPhoenix do\r\n    pipe_through :browser # Use the default browser stack\r\n    resources \"\u002Fposts\", PostController\r\n    get \"\u002F\", PageController, :index\r\n  end\u003C\u002Fpre>\r\n\u003Ch3>Pero qué es plug…\u003C\u002Fh3>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cp>Plug permite la comunicacion entre diferentes maquinas Erlang.\u003C\u002Fp>\r\n\u003Cp>* Una especificación de módulos componibles entre las aplicaciones web.\u003C\u002Fp>\r\n\u003Cp>* Adaptadores de conexión para diferentes servidores web en Erlang VM.\u003C\u002Fp>\r\n\u003Cp>Se puede pensar plug es un framgento de código que recibe una estructura de datos, hace algún tipo de transformación, y devuelve esta misma estructura de datos, ligeramente modificada. Esta estructura de datos que Plug recibe y vuelve por lo general se llama conexión, y representa todo lo que hay que saber acerca de una solicitud.\u003C\u002Fp>\r\n\u003Cp>\u003Cspan>Como siempre plug reciben y devuelven una conexión, pueden ser fácilmente componibles, formando lo que se llama una Plug pipeline.\u003C\u002Fspan>\u003C\u002Fp>\r\n\u003Cp>Tenemos dos tipos de plug:\u003C\u002Fp>\r\n\u003Cp>* Function plugs.\u003C\u002Fp>\r\n\u003Cp>* Module plugs.\u003C\u002Fp>\r\n\u003Cp>Function plug es una función que recibe connection (%Plug.Conn{}) y un conjunto de opciones, y devuelve una connection. Aquí está un ejemplo sencillo de Plug:\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>def my_plug(conn, opts) do\u003Cbr>\u003Cbr>  conn\u003Cbr>\u003Cbr>\u003Cbr>end\u003C\u002Fpre>\r\n\u003Cp>Es cualquier módulo que implementa dos funciones: init\u002F1 y call\u002F2, como el siguiente ejemplo:\u003C\u002Fp>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cpre>module MyPlug do\r\n  def init(opts) do\r\n    opts\r\n  end\r\n\r\n  def call(conn, opts) do\r\n    conn\r\n  end\r\nend\u003C\u002Fpre>\r\n\u003Cp> \u003C\u002Fp>\r\n\u003Cp>Una característica interesante de module plug es que init \u002F 1 se ejecuta en tiempo de compilación, mientras que la llamada call \u002F 2 ocurre en tiempo de ejecución.\u003C\u002Fp>","elixir, phoenix, erlang",9,[23,35,46],{"slug":24,"title":25,"summary":26,"category":27,"author":28,"image_url":32,"image_thumb_url":32,"published_at":33,"updated_at":34},"automatizacion-de-seguridad-en-api-s-con-astra","Automatización de seguridad en API's con Astra  ","Las pruebas de penetración API REST son complejas debido a los continuos cambios en las API existentes y las API recién agregadas. Astra puede ser utilizado por ingenieros o desarrolladores de seguridad como parte integral de su proceso, para que puedan detectar y parchear vulnerabilidades al principio del ciclo de desarrollo. Astra puede detectar y probar automáticamente el inicio de sesión y el cierre de sesión (API de autenticación), por lo que es fácil para cualquiera integrar esto en la tubería de CICD. Astra puede tomar la recopilación de API como entrada, por lo que también se puede usar para probar apis en modo independiente.",{"slug":8,"name":9},{"username":29,"name":30,"avatar_url":31},"Omar_veliz","Omar Jacobo Muñoz Veliz","https:\u002F\u002Fapi.backtrackacademy.com\u002Frails\u002Factive_storage\u002Fblobs\u002Fredirect\u002FeyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBdmdGIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--de6eb458d07377fb9d25e6ed92e1917f274c8cdb\u002Fprofile.jpg","https:\u002F\u002Fapi.backtrackacademy.com\u002Frails\u002Factive_storage\u002Fblobs\u002Fredirect\u002FeyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBcmdSIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--6d9bb60adcd1a2b6c7ca82f28058ca158ada375d\u002Fshutterstock_356278754.jpg","2021-08-10T15:58:52-04:00","2026-10-26T05:54:17-03:00",{"slug":36,"title":37,"summary":38,"category":39,"author":40,"image_url":43,"image_thumb_url":43,"published_at":44,"updated_at":45},"red-team-y-penetration-testing","Red Team y Penetration Testing","Una evaluación en Red Team y Penetration Testing son similares en varias formas pero Red Team es más dirigido a un objetivo que a buscar vulnerabilidades. Un Equipo de Red Team tratara de probar las defensas de una organización para ver su tiempo de detección y su tiempo a responder a las detecciones.",{"slug":8,"name":9},{"username":41,"name":41,"avatar_url":42},"user-1609041409","https:\u002F\u002Fapi.backtrackacademy.com\u002Frails\u002Factive_storage\u002Fblobs\u002Fredirect\u002FeyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBaklNIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--536c91898c7c42c0a3008d37ec317309cb9805cc\u002F9178eae767eec8ff5750bd9a1cfdfe3b.png","https:\u002F\u002Fapi.backtrackacademy.com\u002Frails\u002Factive_storage\u002Fblobs\u002Fredirect\u002FeyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZ2dQIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--e97d64f24ebdecfd5b56c54a45a4dbf69eec59a0\u002Fshutterstock_1382663051.jpg","2021-01-06T12:09:22-03:00","2026-10-26T12:25:47-03:00",{"slug":47,"title":48,"summary":49,"category":50,"author":51,"image_url":55,"image_thumb_url":55,"published_at":56,"updated_at":57},"printer-exploitation-toolkit","Printer Exploitation Toolkit","Han pasado casi 3 años desde que el hacker conocido como @0xGiraffe revoluciona las redes con sus mensajes en apoyo del famoso youtuber PewDiePie y aún a pesar de ello al realizar una simple búsqueda en shodan encontramos expuestos aproximadamente 26,000 impresoras expuestas, sin ningún tipo de autenticación o seguridad alguna.",{"slug":8,"name":9},{"username":52,"name":53,"avatar_url":54},"user-1582119990","José Moreno","https:\u002F\u002Fapi.backtrackacademy.com\u002Frails\u002Factive_storage\u002Fblobs\u002Fredirect\u002FeyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBczhMIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--695dbd13093235a9632272a6a98b0c9ef21a0319\u002FJoseMoreno-300x180.jpg","https:\u002F\u002Fapi.backtrackacademy.com\u002Frails\u002Factive_storage\u002Fblobs\u002Fredirect\u002FeyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZ0VQIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--b136a1170fa84bb7c1a5c7a04fea60dc81a51d39\u002Fshutterstock_1417250795.jpg","2020-11-03T19:00:06-03:00","2026-10-26T15:45:39-03:00",{"slug":59,"title":60,"summary":61,"level":62,"specialty":63,"category":66,"instructor":67,"image_url":71,"image_thumb_url":71,"duration_seconds":72,"lessons_count":73,"students_count":74,"is_free":75,"coming_soon":75,"timer":76,"updated_at":77},"programacion-scripting-python","Programación Scripting Python","Ven y aprende Python desde lo más básico de python hasta desarrollo de Exploit.","Intermedios",{"slug":64,"name":65},"scripting-expert-training-set","Scripting Expert Training",{"slug":8,"name":9},{"username":68,"name":69,"avatar_url":70},"Rodolfo","Rodolfo Cecena","https:\u002F\u002Fapi.backtrackacademy.com\u002Frails\u002Factive_storage\u002Fblobs\u002Fredirect\u002FeyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBanNGIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--2097f10306a2b3955ed91f935c2c204cee999900\u002Frodolfo.jpg","https:\u002F\u002Fapi.backtrackacademy.com\u002Frails\u002Factive_storage\u002Fblobs\u002Fredirect\u002FeyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZzROIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--a0d6d542049120c86ce6a5d8bd28356cd8a6032b\u002FPhyton1.png",17449,23,5482,false,"2018-08-29T09:25:00-03:00","2025-02-15T00:31:57-03:00",null]