plug 0.11.1

A specification and conveniences for composable modules in between web applications

Platform: Hex

Language: Elixir

License: Apache-2.0

Repository: https://github.com/elixir-lang/plug

View on registry: https://hex.pm/packages/plug/

Documentation: http://hexdocs.pm/plug/0.11.1


Plug

Build Status Inline docs

Plug is:

  1. A specification for composable modules in between web applications
  2. Connection adapters for different web servers in the Erlang VM

Documentation for Plug is available online.

Hello world

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

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:

$ iex -S mix
iex> c "path/to/file.ex"
[MyPlug]
iex> {:ok, _} = Plug.Adapters.Cowboy.http MyPlug, []
{:ok, #PID<...>}

Access "http://localhost:4000/" and we are done!

Installation

You can use plug in your projects in two steps:

  1. Add plug and your webserver of choice (currently cowboy) to your mix.exs dependencies:

    def deps do
     [{:cowboy, "~> 1.0.0"},
     {:plug, "~> 0.11.0"}]
    end
  2. List both :cowboy and :plug as your application dependencies:

    def application do
     [applications: [:cowboy, :plug]]
    end

The Plug.Conn

In the hello world example, we defined our first plug. What is a plug after all?

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 init/1 function to initialize options and implement the call/2 function, receiving the connection and the initialized options, and returning the connection.

As per the specification above, a connection is represented by the Plug.Conn struct:

%Plug.Conn{host: "www.example.com",
 path_info: ["bar", "baz"],
 ...}

Data can be read directly from the connection and also pattern matched on. Manipulating the connection often happens with the use of the functions defined in the Plug.Conn module. In our example, both put_resp_content_type/2 and send_resp/3 are defined in Plug.Conn.

Remember that, as everything else in Elixir, a connection is immutable, so every manipulation returns a new copy of the connection:

conn = put_resp_content_type(conn, "text/plain")
conn = send_resp(conn, 200, "ok")
conn

Finally, keep in mind that a connection is a direct interface to the underlying web server. When you call send_resp/3 above, it will immediately send the given status and body back to the client. This makes features like streaming a breeze to work with.

The Plug Router

In practice, developers rarely write their own plugs. For example, Plug ships with a router that allows developers to quickly match on incoming requests and perform some action:

defmodule AppRouter do
 use Plug.Router
 plug :match
 plug :dispatch
 get "/hello" do
 send_resp(conn, 200, "world")
 end
 forward "/users", to: UsersRouter
 match _ do
 send_resp(conn, 404, "oops")
 end
end

The router is a plug and, not only that, it contains its own plug pipeline too. The example above says that when the router is invoked, it will invoke the :match plug, represented by a local match/2 function, and then call the :dispatch plug which will execute the matched code.

Plug ships with many plugs that you can add to the router plug pipeline, allowing you to plug something before a route matches or before a route is dispatched to. For example, if you want to add logging to the router, just do:

plug Plug.Logger
plug :match
plug :dispatch

Note Plug.Router 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!

This also means that a catch all match 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).

Each route needs to return the connection as per the Plug specification. See Plug.Router docs for more information.

Testing plugs

Plug ships with a Plug.Test module that makes testing your plugs easy. Here is how we can test the router from above (or any other plug):

defmodule MyPlugTest do
 use ExUnit.Case, async: true
 use Plug.Test
 @opts AppRouter.init([])
 test "returns hello world" do
 # Create a test connection
 conn = conn(:get, "/")
 # Invoke the plug
 conn = AppRouter.call(conn, @opts)
 # Assert the response and status
 assert conn.state == :sent
 assert conn.status == 200
 assert conn.resp_body == "Hello world"
 end
end

Available Plugs

This project aims to ship with different plugs that can be re-used across applications:

  • Plug.CSRFProtection - adds Cross-Site Request Forgery protection to your application. Typically required if you are using Plug.Session;
  • Plug.Head - converts HEAD requests to GET requests;
  • Plug.Logger - logs requests;
  • Plug.MethodOverride - overrides a request method with one specified in headers;
  • Plug.Parsers - responsible for parsing the request body given its content-type;
  • Plug.Session - handles session management and storage;
  • Plug.Static - serves static files;

You can go into more details about each of them in our docs.

Helper modules

Modules that can be used after you use Plug.Router or Plug.Builder to help development:

  • Plug.Debugger - shows a helpful debugging page every time there is a failure in a request;
  • Plug.ErrorHandler - allows developers to customize error pages in case of crashes instead of sending a blank one;

License

Plug source code is released under Apache 2 License. Check LICENSE file for more information.

веселые картинки развлекательные гифки интресные факты смешные видео смешные истории из соцсетей

GitHub Repository

elixir-lang/plug elixir-lang/plug

A specification and conveniences for composable modules in between web applications

Language: Elixir

Created: November 15, 2013 10:30

Last updated: March 30, 2015 02:02

Last pushed: March 29, 2015 02:40

Size: 2.71 MB

Stars: 277

Forks: 77

Watchers: 56

Open issues: 5

Top Contributors

José Valim Andrea Leopardi Sonny Scroggin Eric Meadows-Jönsson Gabriel Jaldon Chris McCord Aleksei Magusev Chris Constantin Martin Schürrer Udo Kramer Jason S. Yurii Rashkovskii T. Mjoen Myles Steinhauser Akash Manohar James Fish Michael Shapiro Wojciech Kaczmarek Drew Olson Devin Torres

Releases

  • 0.11.1 - March 06, 2015 16:12
  • 0.11.0 - February 24, 2015 20:26
  • 0.10.0 - January 18, 2015 12:42
  • 0.9.0 - December 10, 2014 10:09
  • 0.8.4 - November 30, 2014 09:58
  • 0.8.3 - November 28, 2014 16:53
  • 0.8.2 - October 29, 2014 14:23
  • 0.8.1 - October 06, 2014 09:22
  • 0.8.0 - September 21, 2014 18:51
  • 0.7.0 - August 30, 2014 17:48
See all 19 releases

Related Projects

ecto 0.10.1
Ecto is a domain specific language for writing queries and interacting with databases in Elixir.
Hex - Elixir - Apache-2.0 - Updated 7 days ago - 629 stars
mailibex 0.0.1
Mailibex is an email library in Elixir : currently implements DKIM, SPF, DMARC, MimeMail (using i...
Hex - Elixir - MIT - Published 4 months ago - 7 stars
mock 0.1.0
A mocking libary for the Elixir language. We use the Erlang meck library to provide module mocki...
Hex - Elixir - MIT - Published 4 months ago - 40 stars
phoenix 0.10.0
Elixir Web Framework targeting full-featured, fault tolerant applications with realtime functiona...
Hex - Elixir - MIT - Updated 24 days ago - 2,151 stars
plugs 0.0.2
A collection of Plug middleware for web applications
Hex - Elixir - MIT - Published 3 months ago - 6 stars
веселые картинки развлекательные гифки интресные факты смешные видео смешные истории из соцсетей