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.
See the generated documentation for more detailed explanations.
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 :
Ewebmachine.Plug.Run
go through the HTTP decision tree and fill theconn
response according to itEwebmachine.Plug.Send
is used to send a conn set withEwebmachine.Plug.Run
Ewebmachine.Plug.Debug
gives you a debugging web UI to see the HTTP decision path taken by each request.Ewebmachine.Plug.ErrorAsException
take a conn with a response set but not send, and throw an exception is the status code is an exceptionEwebmachine.Plug.ErrorAsForward
take a conn with a response set but not send, and forward it changing the request toGET /error/pattern/:status
Ewebmachine.Builder.Handlers
gives you helpers macros and a:add_handler
plug to addhandlers
as defined inEwebmachine.Handlers
to your conn, and set the initial user state.Ewebmachine.Builder.Resources
gives you aresource
macro to define at the same time anEwebmachine.Builder.Handlers
and the matching spec to use it, and a plug:resource_match
to do the match and execute the associated plug. The macroresources_plugs
helps you to define commong plug pipeling
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:
put_resp_header(conn,"Access-Control-Allow-Origin","*")
end
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}
end
end
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>"
end
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)
end
resource "/static/*path" do %{path: Enum.join(path,"/")} after
resource_exists do:
File.regular?(path state.path)
content_types_provided do:
[{state.path|>Plug.MIME.path|>default_plain,:to_content}]
defh to_content, do:
File.stream!(path(state.path),[],300_000_000)
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
end
end
Go to /wm_debug
to see precedent requests and debug there HTTP
decision path. The debug UI can be updated automatically on the
requests.
Create a simple supervision tree with only the Cowboy server adapter spec.
defmodule MyApp do
use Application
def start(_type, _args), do:
Supervisor.start_link([
Plug.Adapters.Cowboy.child_spec(:http,FullApi,[], port: 4000)
], strategy: :one_for_one)
end
And add it as your application entry point in your mix.exs
def application do
[applications: [:logger,:ewebmachine,:cowboy], mod: {MyApp,[]}]
end
defp deps, do:
[{:ewebmachine, "2.0.0"}, {:cowboy, "~> 1.0"}]
Hi, and thank you for wanting to contribute. Please refer to the centralized informations available at: https://github.com/kbrw#contributing