Packages
Ewebmachine contains macros and plugs to allow you to compose HTTP decision handlers and run the HTTP decision tree to get your HTTP response. This project is a rewrite for Elixir and Plug of basho webmachine.
Current section
Files
Jump to
Current section
Files
examples/hello/lib/hello.ex
defmodule Hello do
defmodule App do
use Application
def start(_type, _args) do
Supervisor.start_link([
Plug.Adapters.Cowboy2.child_spec(scheme: :http, plug: Hello.Api, options: [port: 4000]),
Supervisor.Spec.worker(Hello.Db, [])
], strategy: :one_for_one)
end
end
defmodule Db do
def start_link, do: Agent.start_link(&Map.new/0, name: __MODULE__)
def get(id), do: Agent.get(__MODULE__, &(Map.get(&1, id, nil)))
def put(id, val), do: Agent.update(__MODULE__, &(Map.put(&1, id, val)))
def delete(id), do: Agent.update(__MODULE__, &(Map.delete(&1, id)))
end
defmodule ApiCommon do
use Ewebmachine.Builder.Handlers
plug :cors
plug :add_handlers
content_types_provided do: ["application/json": :to_json]
defh to_json(conn, state), do: {Poison.encode!(state[:json_obj]), conn, state}
defp cors(conn, _) do
put_resp_header(conn, "Access-Control-Allow-Origin", "*")
end
end
defmodule Api do
use Ewebmachine.Builder.Resources
plug Ewebmachine.Plug.Debug
resources_plugs nomatch_404: true
resource "/hello/:name" do %{name: name} after
content_types_provided do: ['application/xml': :to_xml]
defh to_xml(conn, state), do: {"<Person><name>#{state.name}</name>", conn, state}
end
resource "/hello/json/:name" do %{name: name} after
plug ApiCommon # this is also a plug pipeline
allowed_methods do: ["GET", "PUT", "DELETE"]
content_types_accepted do: ['application/json': :from_json]
defh resource_exists(conn, state) do
case Hello.Db.get(state.name) do
nil -> {false, conn, state}
user -> {true, conn, Map.put(state, :json_obj, user)}
end
end
defh delete_resource(conn, state), do: {Hello.Db.delete(state.name), conn, state}
defh from_json(conn, state) do
value = conn |> Ewebmachine.fetch_req_body([]) |> Ewebmachine.req_body |> Poison.decode!
_ = Hello.Db.put(state.name, value)
{true, conn, state}
end
end
resource "/new" do %{} after
plug ApiCommon #this is also a plug pipeline
allowed_methods do: ["POST"]
content_types_accepted do: ['application/json': :from_json]
post_is_create do: true
defh create_path(conn, state), do: {state.newpath, conn, state}
defh from_json(conn, state) do
value = conn |> Ewebmachine.fetch_req_body([]) |> Ewebmachine.req_body() |> Poison.decode!()
newpath = "#{:io_lib.format("~9..0b", [:rand.uniform(999999999)])}"
_ = Hello.Db.put(value["id"], value)
{true, conn, Map.put(state, :newpath, newpath)}
end
end
resource "/new_with_redirect" do %{} after
plug ApiCommon #this is also a plug pipeline
allowed_methods do: ["POST"]
content_types_accepted do: ['application/json': :from_json]
post_is_create do: true
defh create_path(conn, state), do: {state.newpath, conn, state}
defh from_json(conn, state) do
value = conn |> Ewebmachine.fetch_req_body([]) |> Ewebmachine.req_body() |> Poison.decode!()
newpath = "#{:io_lib.format("~9..0b", [:rand.uniform(999999999)])}"
_ = Hello.Db.put(value["id"], value)
conn = Plug.Conn.put_private(conn, :resp_redirect, true)
{true, conn, Map.put(state, :newpath, newpath)}
end
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(conn, state) do
body = File.stream!( path(state.path), [], 300_000_000)
{body, conn, state}
end
defp path(relative), do: "#{:code.priv_dir(:ewebmachine)}/static/#{relative}"
defp default_plain("application/octet-stream"), do: "text/plain"
defp default_plain(type), do: type
end
end
end