plug
Directory actions
More options
Directory actions
More options
plug
Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
parent directory.. | ||||
<!DOCTYPE html>
<html>
<head>
<title>README</title>
<meta charset="utf-8">
<link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
<script type="text/javascript" charset="utf-8">
relpath = '';
if (relpath != '') relpath += '/';
</script>
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
</head>
<body>
<script type="text/javascript" charset="utf-8">
if (window.top.frames.main) document.body.className = 'frames';
</script>
<div id="content">
<div class="breadcrumbs">plug v0.5.1 → <a href="readme.html">README</a></div>
<h1 id="plug">Plug</h1>
<p><a href="https://travis-ci.org/elixir-lang/plug"><embed src="https://travis-ci.org/elixir-lang/plug.png?branch=master" /></a></p>
<p>Plug is:</p>
<ol style="list-style-type: decimal">
<li>A specification for composable modules in between web applications</li>
<li>Connection adapters for different web servers in the Erlang VM</li>
</ol>
<p><a href="http://elixir-lang.org/docs/plug/">Documentation for Plug is available online</a>.</p>
<h2 id="hello-world">Hello world</h2>
<pre class="elixir"><code>defmodule MyPlug do
import Plug.Conn
def init(options) do
# initialize options
options
end
def call(conn, _opts) do
conn
|> put_resp_content_type("text/plain")
|> send_resp(200, "Hello world")
end
end
IO.puts "Running MyPlug with Cowboy on http://localhost:4000"
Plug.Adapters.Cowboy.http MyPlug, []</code></pre>
<p>The snippet above shows a very simple example on how to use Plug. Save that snippet to a file and run it inside the plug application with:</p>
<pre class="codeblock"><code>mix run --no-halt path/to/file.exs</code></pre>
<p>Access "http://localhost:4000" and we are done!</p>
<h2 id="installation">Installation</h2>
<p>You can use plug in your projects in two steps:</p>
<ol style="list-style-type: decimal">
<li><p>Add plug and your webserver of choice (currently cowboy) to your <code>mix.exs</code> dependencies:</p>
<pre class="elixir"><code>def deps do
[{:cowboy, github: "extend/cowboy"},
{:plug, "~> 0.4.2"}]
end</code></pre></li>
<li><p>List both <code>:cowboy</code> and <code>:plug</code> as your application dependencies:</p>
<pre class="elixir"><code>def application do
[applications: [:cowboy, :plug]]
end</code></pre></li>
</ol>
<p>Note: if you are using Elixir master, please use Plug master (from git) as well.</p>
<h2 id="the-plug.conn">The Plug.Conn</h2>
<p>In the hello world example, we defined our first plug. What is a plug after all?</p>
<p>A plug takes two shapes. It is a function that receives a connection and a set of options as arguments and returns the connection or it is a module that provides an <code>init/1</code> function to initialize options and implement the <code>call/2</code> function, receiving the connection and the initialized options, and returning the connection.</p>
<p>As per the specification above, a connection is represented by the <code>Plug.Conn</code> record (<a href="http://elixir-lang.org/docs/plug/Plug.Conn.html">docs</a>):</p>
<pre class="elixir"><code>%Plug.Conn{host: "www.example.com",
path_info: ["bar", "baz"],
...}</code></pre>
<p>Data can be read directly from the record and also pattern matched on. However, whenever you need to manipulate the record, you must use the functions defined in the <code>Plug.Conn</code> module (<a href="http://elixir-lang.org/docs/plug/Plug.Conn.html">docs</a>). In our example, both <code>put_resp_content_type/2</code> and <code>send_resp/3</code> are defined in <code>Plug.Conn</code>.</p>
<p>Remember that, as everything else in Elixir, <strong>a connection is immutable</strong>, so every manipulation returns a new copy of the connection:</p>
<pre class="elixir"><code>conn = put_resp_content_type(conn, "text/plain")
conn = send_resp(conn, 200, "ok")
conn</code></pre>
<p>Finally, keep in mind that a connection is a <strong>direct interface to the underlying web server</strong>. When you call <code>send_resp/3</code> above, it will immediately send the given status and body back to the client. This makes features like streaming a breeze to work with.</p>
<h2 id="testing-plugs-and-applications">Testing plugs and applications</h2>
<p>Plug ships with a <code>Plug.Test</code> module (<a href="http://elixir-lang.org/docs/plug/Plug.Test.html">docs</a>) that makes testing your plugs easy. Here is how we can test our hello world example:</p>
<pre class="elixir"><code>defmodule MyPlugTest do
use ExUnit.Case, async: true
use Plug.Test
@opts MyPlug.init([])
test "returns hello world" do
# Create a test connection
conn = conn(:get, "/")
# Invoke the plug
conn = MyPlug.call(conn, @opts)
# Assert the response and status
assert conn.state == :sent
assert conn.status == 200
assert conn.resp_body == "Hello world"
end
end</code></pre>
<h2 id="the-plug-router">The Plug Router</h2>
<p>The Plug router allows developers to quickly match on incoming requests and perform some action:</p>
<pre class="elixir"><code>defmodule AppRouter do
import Plug.Conn
use Plug.Router
plug :match
plug :dispatch
get "/hello" do
send_resp(conn, 200, "world")
end
match _ do
send_resp(conn, 404, "oops")
end
end</code></pre>
<p>The router is a plug, which means it can be invoked as:</p>
<pre class="elixir"><code>AppRouter.call(conn, AppRouter.init([]))</code></pre>
<p>Each route needs to return the connection as per the Plug specification.</p>
<p>Note <code>Plug.Router</code> compiles all of your routes into a single function and relies on the Erlang VM to optimize the underlying routes into a tree lookup, instead of a linear lookup that would instead match route-per-route. This means route lookups are extremely fast in Plug!</p>
<p>This also means that a catch all <code>match</code> is recommended to be defined, as in the example above, otherwise routing fails with a function clause error (as it would in any regular Elixir function).</p>
<h3 id="available-plugs">Available Plugs</h3>
<p>This project aims to ship with different plugs that can be re-used accross applications:</p>
<ul>
<li><code>Plug.Head</code> (<a href="http://elixir-lang.org/docs/plug/Plug.Head.html">docs</a>) - converts HEAD requests to GET requests;</li>
<li><code>Plug.MethodOverride</code> (<a href="http://elixir-lang.org/docs/plug/Plug.MethodOverride.html">docs</a>) - overrides a request method with one specified in headers;</li>
<li><code>Plug.Parsers</code> (<a href="http://elixir-lang.org/docs/plug/Plug.Parsers.html">docs</a>) - responsible for parsing the request body given its content-type;</li>
<li><code>Plug.Session</code> (<a href="http://elixir-lang.org/docs/plug/Plug.Session.html">docs</a>) - handles session management and storage;</li>
<li><code>Plug.Static</code> (<a href="http://elixir-lang.org/docs/plug/Plug.Static.html">docs</a>) - serves static files;</li>
</ul>
<h2 id="license">License</h2>
<p>Plug source code is released under Apache 2 License. Check LICENSE file for more information.</p>
</div>
</body>
</html>