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
lib/ewebmachine/core.dsl.ex
defmodule Ewebmachine.Core.DSL do
## Macros and helpers defining the DSL for the Ewebmachine decision
## core : for legacy reasons, the module is called 'DSL' while they are
## are mostly helper functions.
##
## Changes:
## Macros hiding `conn` and `user_state` variables have been removed
## as they can produce unsafe use of these variables if used in
## structures like if/cond/... which is deprecated in elixir 1.3
## Usage :
## decision mydecision(conn, user_state, args...) do # def mydecision(conn, user_state, arg...)
## ...debug_decision
## ...exec body
## end
@moduledoc false
alias Plug.Conn
defmacro __using__(_opts) do quote do
import Ewebmachine.Core.DSL
import Ewebmachine.Core.Utils
end end
def sig_to_sigwhen({:when, _, [{name,_,params}, guard]}), do: {name, params, guard}
def sig_to_sigwhen({name, _, params}) when is_list(params), do: {name, params, true}
def sig_to_sigwhen({name, _, _}), do: {name, [], true}
defmacro decision(sig, do: body) do
{name, [conn, state], guard} = sig_to_sigwhen(sig)
quote do
def unquote(name)(unquote(conn), unquote(state)) when unquote(guard) do
var!(conn) = Ewebmachine.Log.debug_decision(unquote(conn), unquote(name))
unquote(body)
end
end
end
def resource_call(conn, state, fun) do
handler = conn.private[:resource_handlers][fun] || Ewebmachine.Handlers
{reply, conn, state} = term = apply(handler, fun, [conn, state])
conn = Ewebmachine.Log.debug_call(conn, handler, fun, [conn, state], term)
case reply do
{:halt, code} ->
throw {:halt, set_response_code(conn, code)}
_ ->
{reply, conn, state}
end
end
def method(conn), do: conn.method
def resp_redirect(conn), do: conn.private[:resp_redirect]
def get_resp_header(conn, name), do: first_or_nil(Conn.get_resp_header(conn, name))
def path(conn), do: conn.request_path
def get_header_val(conn, name), do: first_or_nil(Conn.get_req_header(conn, name))
def set_response_code(conn, code) do
conn = conn # halt machine when set response code, on respond
|> Conn.put_status(code)
|> Ewebmachine.Log.debug_enddecision
conn = if !conn.resp_body, do: %{conn | resp_body: ""}, else: conn
%{conn | state: :set}
end
def set_resp_header(conn, k, v), do: Conn.put_resp_header(conn, k, v)
def set_resp_headers(conn, kvs) do
Enum.reduce(kvs, conn,
fn {k,v}, acc ->
Conn.put_resp_header(acc, k, v)
end)
end
def remove_resp_header(conn, k) do
Conn.delete_resp_header(conn, k)
end
def set_disp_path(conn, path), do: %{conn | script_name: String.split("#{path}","/")}
def resp_body(conn), do: conn.private[:machine_body_stream] || conn.resp_body
def set_resp_body(conn, body) when is_binary(body) or is_list(body) do
%{conn | resp_body: body}
end
def set_resp_body(conn, body) do #if not an IO List, then it should be an enumerable
Conn.put_private(conn, :machine_body_stream, body)
end
def has_resp_body(conn) do
(!is_nil(conn.resp_body) or !is_nil(conn.private[:machine_body_stream]))
end
def get_metadata(conn, key), do: conn.private[key]
def set_metadata(conn, k, v), do: Conn.put_private(conn, k, v)
def compute_body_md5(conn) do
conn = Ewebmachine.fetch_req_body(conn, [])
:crypto.hash(:md5, Ewebmachine.req_body(conn))
end
def first_or_nil([v|_]), do: v
def first_or_nil(_), do: nil
end