Ewebmachine (ewebmachine v2.3.0) View Source

Ewebmachine is a full rewrite with clean DSL and plug integration based on Webmachine from basho. This version is not backward compatible with the previous one that was only a thin wrapper around webmachine, use the branch 1.0-legacy to use the old one.

The principle is to go through the HTTP decision tree and make decisions according to response of some callbacks called "handlers".

To do that, the library gives you 5 plugs and 2 plug pipeline builders :

Example usage

defmodule MyJSONApi do 
  use Ewebmachine.Builder.Handlers
  plug :cors
  plug :add_handlers, init: %{}

  content_types_provided do: ["application/json": :to_json]
  defh to_json, do: Poison.encode!(state[:json_obj])

  defp cors(conn,_), do: 

defmodule ErrorRoutes do
  use Ewebmachine.Builder.Resources ; resources_plugs
  resource "/error/:status" do %{s: elem(Integer.parse(status),0)} after 
    content_types_provided do: ['text/html': :to_html, 'application/json': :to_json]
    defh to_html, do: "<h1> Error ! : '#{Ewebmachine.Core.Utils.http_label(state.s)}'</h1>"
    defh to_json, do: ~s/{"error": #{state.s}, "label": "#{Ewebmachine.Core.Utils.http_label(state.s)}"}/
    finish_request do: {:halt,state.s}

defmodule FullApi do
  use Ewebmachine.Builder.Resources
  if Mix.env == :dev, do: plug Ewebmachine.Plug.Debug
  resources_plugs error_forwarding: "/error/:status", nomatch_404: true
  plug ErrorRoutes

  resource "/hello/:name" do %{name: name} after 
    content_types_provided do: ['application/xml': :to_xml]
    defh to_xml, do: "<Person><name>#{state.name}</name>"

  resource "/hello/json/:name" do %{name: name} after 
    plug MyJSONApi #this is also a plug pipeline
    allowed_methods do: ["GET","DELETE"]
    resource_exists do: pass((user=DB.get(state.name)) !== nil, json_obj: user)
    delete_resource do: DB.delete(state.name)

  resource "/static/*path" do %{path: Enum.join(path,"/")} after
    resource_exists do:
      File.regular?(path state.path)
    content_types_provided do:
    defh to_content, do:
    defp path(relative), do: "#{:code.priv_dir :ewebmachine_example}/web/#{relative}"
    defp default_plain("application/octet-stream"), do: "text/plain"
    defp default_plain(type), do: type

Debug UI

Go to /wm_debug to see precedent requests and debug there HTTP decision path. The debug UI can be updated automatically on the requests.

Debug UI example

Use Cowboy to serve the plug

Create a simple supervision tree with only the Cowboy server adapter spec.

defmodule MyApp do
  use Application
  def start(_type, _args), do:
        Plug.Adapters.Cowboy.child_spec(:http,FullApi,[], port: 4000)
      ], strategy: :one_for_one)

And add it as your application entry point in your mix.exs

def application do
  [applications: [:logger,:ewebmachine,:cowboy], mod: {MyApp,[]}]
defp deps, do:
  [{:ewebmachine, "2.0.0"}, {:cowboy, "~> 1.0"}]

Link to this section Summary


Set :resp_redirect to true

Fetch request body

Returns request body from request (requires fetching body first)

Link to this section Functions


do_redirect(Plug.Conn.t()) :: Plug.Conn.t()

Set :resp_redirect to true

Link to this function

fetch_req_body(conn, opts)

View Source


fetch_req_body(Plug.Conn.t(), Enumerable.t()) :: Plug.Conn.t()

Fetch request body


  • max_length: maximum bytes to fetch (default: 1_000_000)


req_body(Plug.Conn.t()) :: binary()

Returns request body from request (requires fetching body first)