Current section
6 Versions
Jump to
Current section
6 Versions
Compare versions
6
files changed
+97
additions
-162
deletions
| @@ -1,9 +1,8 @@ | |
| 1 1 | {<<"app">>,<<"placid">>}. |
| 2 2 | {<<"build_tools">>,[<<"mix">>]}. |
| 3 | - {<<"contributors">>,[<<"Shane Logsdon">>]}. |
| 4 3 | {<<"description">>, |
| 5 | - <<"A REST toolkit for building highly-scalable and fault-tolerant HTTP APIs with Elixir\n">>}. |
| 6 | - {<<"elixir">>,<<">= 1.0.0-rc1">>}. |
| 4 | + <<"A REST toolkit for building highly-scalable and fault-tolerant HTTP APIs with Elixir">>}. |
| 5 | + {<<"elixir">>,<<">= 1.0.0">>}. |
| 7 6 | {<<"files">>, |
| 8 7 | [<<"lib/mix/placid/serve.ex">>,<<"lib/placid.ex">>, |
| 9 8 | <<"lib/placid/config.ex">>,<<"lib/placid/handler.ex">>, |
| @@ -15,22 +14,34 @@ | |
| 15 14 | <<"lib/placid/response/rendering/engines/json.ex">>, |
| 16 15 | <<"lib/placid/response/rendering/engines/xml.ex">>, |
| 17 16 | <<"lib/placid/response/status_code.ex">>,<<"lib/placid/router.ex">>, |
| 18 | - <<"lib/placid/router/util.ex">>,<<"mix.exs">>,<<"README.md">>, |
| 19 | - <<"LICENSE">>]}. |
| 17 | + <<"mix.exs">>,<<"README.md">>,<<"LICENSE">>]}. |
| 20 18 | {<<"licenses">>,[<<"MIT">>]}. |
| 21 | - {<<"links">>,#{<<"GitHub">> => <<"https://github.com/slogsdon/placid">>}}. |
| 19 | + {<<"links">>,[{<<"GitHub">>,<<"https://github.com/slogsdon/placid">>}]}. |
| 20 | + {<<"maintainers">>,[<<"Shane Logsdon">>]}. |
| 22 21 | {<<"name">>,<<"placid">>}. |
| 23 22 | {<<"requirements">>, |
| 24 | - #{<<"cowboy">> => #{<<"app">> => <<"cowboy">>,<<"optional">> => nil,<<"requirement">> => <<"~> 1.0.0">>}, |
| 25 | - <<"http_router">> => #{<<"app">> => <<"http_router">>, |
| 26 | - <<"optional">> => nil, |
| 27 | - <<"requirement">> => <<"~> 0.0.3">>}, |
| 28 | - <<"linguist">> => #{<<"app">> => <<"linguist">>, |
| 29 | - <<"optional">> => nil, |
| 30 | - <<"requirement">> => <<"~> 0.1.2">>}, |
| 31 | - <<"plug">> => #{<<"app">> => <<"plug">>,<<"optional">> => nil,<<"requirement">> => <<"~> 0.9.0">>}, |
| 32 | - <<"poison">> => #{<<"app">> => <<"poison">>,<<"optional">> => nil,<<"requirement">> => <<"~> 1.2.0">>}, |
| 33 | - <<"xml_builder">> => #{<<"app">> => <<"xml_builder">>, |
| 34 | - <<"optional">> => nil, |
| 35 | - <<"requirement">> => <<"~> 0.0.5">>}}}. |
| 36 | - {<<"version">>,<<"0.1.3">>}. |
| 23 | + [[{<<"app">>,<<"cowboy">>}, |
| 24 | + {<<"name">>,<<"cowboy">>}, |
| 25 | + {<<"optional">>,false}, |
| 26 | + {<<"requirement">>,<<"~> 1.0">>}], |
| 27 | + [{<<"app">>,<<"plug">>}, |
| 28 | + {<<"name">>,<<"plug">>}, |
| 29 | + {<<"optional">>,false}, |
| 30 | + {<<"requirement">>,<<"~> 1.0">>}], |
| 31 | + [{<<"app">>,<<"http_router">>}, |
| 32 | + {<<"name">>,<<"http_router">>}, |
| 33 | + {<<"optional">>,false}, |
| 34 | + {<<"requirement">>,<<"~> 0.0">>}], |
| 35 | + [{<<"app">>,<<"linguist">>}, |
| 36 | + {<<"name">>,<<"linguist">>}, |
| 37 | + {<<"optional">>,false}, |
| 38 | + {<<"requirement">>,<<"~> 0.1">>}], |
| 39 | + [{<<"app">>,<<"poison">>}, |
| 40 | + {<<"name">>,<<"poison">>}, |
| 41 | + {<<"optional">>,false}, |
| 42 | + {<<"requirement">>,<<"~> 3.0">>}], |
| 43 | + [{<<"app">>,<<"xml_builder">>}, |
| 44 | + {<<"name">>,<<"xml_builder">>}, |
| 45 | + {<<"optional">>,false}, |
| 46 | + {<<"requirement">>,<<"~> 0.0">>}]]}. |
| 47 | + {<<"version">>,<<"0.2.0">>}. |
| @@ -2,12 +2,12 @@ defmodule Placid.Handler do | |
| 2 2 | @moduledoc """ |
| 3 3 | Handlers facilitate some separation of concerns for your application's logic. |
| 4 4 | |
| 5 | - All handler actions should have an arrity of 2, with the first argument being |
| 6 | - a `Plug.Conn` representing the current connection and the second argument |
| 5 | + All handler actions should have an arrity of 2, with the first argument being |
| 6 | + a `Plug.Conn` representing the current connection and the second argument |
| 7 7 | being a `Keyword` list of any parameters captured in the route path. |
| 8 8 | |
| 9 9 | `Placid.Handler` imports `Plug.Conn`, the `plug/1` and `plug/2` macros from |
| 10 | - `Plug.Builder`, `Placid.Handler`, and `Placid.Response.Helpers` for |
| 10 | + `Plug.Builder`, `Placid.Handler`, and `Placid.Response.Helpers` for |
| 11 11 | convenience when creating handlers for your applications |
| 12 12 | |
| 13 13 | ## Example |
| @@ -25,7 +25,7 @@ defmodule Placid.Handler do | |
| 25 25 | @doc false |
| 26 26 | def show(conn, args) do |
| 27 27 | result = case Integer.parse args["page_id"] do |
| 28 | - :error -> |
| 28 | + :error -> |
| 29 29 | %Error{ id: "no_page_id", |
| 30 30 | message: "A valid page_id is required." } |
| 31 31 | {i, _} -> |
| @@ -43,7 +43,7 @@ defmodule Placid.Handler do | |
| 43 43 | @doc false |
| 44 44 | def update(conn, args) do |
| 45 45 | result = case Integer.parse args["page_id"] do |
| 46 | - :error -> |
| 46 | + :error -> |
| 47 47 | %Error{ id: "no_page_id", |
| 48 48 | message: "A valid page_id is requried." } |
| 49 49 | {i, _} -> |
| @@ -75,7 +75,7 @@ defmodule Placid.Handler do | |
| 75 75 | { plug, Keyword.put_new(opts, :run, :before), guard } |
| 76 76 | end) |
| 77 77 | |
| 78 | - plug_stacks = build_plug_stacks plugs |
| 78 | + plug_stacks = build_plug_stacks env, plugs |
| 79 79 | |
| 80 80 | quote do |
| 81 81 | def init(opts) do |
| @@ -94,17 +94,17 @@ defmodule Placid.Handler do | |
| 94 94 | end |
| 95 95 | end |
| 96 96 | |
| 97 | - defp build_plug_stacks(plugs) do |
| 97 | + defp build_plug_stacks(env, plugs) do |
| 98 98 | only_actions = get_only_actions plugs |
| 99 99 | |
| 100 100 | Enum.map only_actions ++ [nil], fn action -> |
| 101 | - build_plug_stacks_for action, plugs |
| 101 | + build_plug_stacks_for action, env, plugs |
| 102 102 | end |
| 103 103 | end |
| 104 104 | |
| 105 | - defp build_plug_stacks_for(action, plugs) do |
| 106 | - before_body = build_calls_for(:before, action, plugs) |
| 107 | - after_body = build_calls_for(:after, action, plugs) |
| 105 | + defp build_plug_stacks_for(action, env, plugs) do |
| 106 | + before_body = build_calls_for(:before, action, env, plugs) |
| 107 | + after_body = build_calls_for(:after, action, env, plugs) |
| 108 108 | |
| 109 109 | quote do |
| 110 110 | unquote(before_body) |
| @@ -112,15 +112,15 @@ defmodule Placid.Handler do | |
| 112 112 | end |
| 113 113 | end |
| 114 114 | |
| 115 | - defp build_calls_for(before_or_after, nil, plugs) do |
| 116 | - { conn, body } = plugs |
| 117 | - |> Enum.filter(fn { _, opts, _ } -> |
| 118 | - opts[:only] === nil |
| 119 | - end) |
| 120 | - |> Enum.filter(fn { _, opts, _ } -> |
| 121 | - opts[:run] === before_or_after |
| 122 | - end) |
| 123 | - |> Plug.Builder.compile |
| 115 | + defp build_calls_for(before_or_after, nil, env, plugs) do |
| 116 | + plugs = plugs |
| 117 | + |> Enum.filter(fn { _, opts, _ } -> |
| 118 | + opts[:only] === nil |
| 119 | + end) |
| 120 | + |> Enum.filter(fn { _, opts, _ } -> |
| 121 | + opts[:run] === before_or_after |
| 122 | + end) |
| 123 | + { conn, body } = env |> Plug.Builder.compile(plugs, []) |
| 124 124 | |
| 125 125 | quote do |
| 126 126 | defp do_call(unquote(conn), unquote(before_or_after), _) do |
| @@ -128,17 +128,17 @@ defmodule Placid.Handler do | |
| 128 128 | end |
| 129 129 | end |
| 130 130 | end |
| 131 | - defp build_calls_for(before_or_after, action, plugs) do |
| 132 | - { conn, body } = plugs |
| 133 | - |> Enum.filter(fn { _, opts, _ } -> |
| 134 | - opts[:only] === nil || |
| 135 | - action === opts[:only] || |
| 136 | - action in opts[:only] |
| 137 | - end) |
| 138 | - |> Enum.filter(fn { _, opts, _ } -> |
| 139 | - opts[:run] === before_or_after |
| 140 | - end) |
| 141 | - |> Plug.Builder.compile |
| 131 | + defp build_calls_for(before_or_after, action, env, plugs) do |
| 132 | + plugs = plugs |
| 133 | + |> Enum.filter(fn { _, opts, _ } -> |
| 134 | + opts[:only] === nil || |
| 135 | + action === opts[:only] || |
| 136 | + action in opts[:only] |
| 137 | + end) |
| 138 | + |> Enum.filter(fn { _, opts, _ } -> |
| 139 | + opts[:run] === before_or_after |
| 140 | + end) |
| 141 | + { conn, body } = env |> Plug.Builder.compile(plugs, []) |
| 142 142 | |
| 143 143 | quote do |
| 144 144 | defp do_call(unquote(conn), unquote(before_or_after), unquote(action)) do |
| @@ -157,4 +157,4 @@ defmodule Placid.Handler do | |
| 157 157 | end) |
| 158 158 | |> Enum.uniq |
| 159 159 | end |
| 160 | - end |
| \ No newline at end of file | |
| 160 | + end |
| @@ -1,6 +1,6 @@ | |
| 1 1 | defmodule Placid.Response.Helpers do |
| 2 2 | @moduledoc """ |
| 3 | - Placid bundles these response helpers with handlers to |
| 3 | + Placid bundles these response helpers with handlers to |
| 4 4 | assist in sending a response. |
| 5 5 | |
| 6 6 | #### Example |
| @@ -47,7 +47,7 @@ defmodule Placid.Response.Helpers do | |
| 47 47 | def status(conn, status_code) when is_integer(status_code) |
| 48 48 | when is_atom(status_code) do |
| 49 49 | %StatusCode{ code: code } = status_code |> StatusCode.find |
| 50 | - %Plug.Conn{ conn | status: code, |
| 50 | + %Plug.Conn{ conn | status: code, |
| 51 51 | state: :set } |
| 52 52 | end |
| 53 53 | |
| @@ -65,7 +65,7 @@ defmodule Placid.Response.Helpers do | |
| 65 65 | """ |
| 66 66 | @spec headers(Plug.Conn.t, Plug.Conn.headers) :: Plug.Conn.t |
| 67 67 | def headers(conn, headers) do |
| 68 | - %Plug.Conn{ conn | resp_headers: headers, |
| 68 | + %Plug.Conn{ conn | resp_headers: headers, |
| 69 69 | state: :set } |
| 70 70 | end |
| 71 71 | |
| @@ -130,7 +130,7 @@ defmodule Placid.Response.Helpers do | |
| 130 130 | """ |
| 131 131 | @spec halt!(Plug.Conn.t, Keyword.t) :: Plug.Conn.t |
| 132 132 | def halt!(conn, opts \\ []) do |
| 133 | - opts = [ status: 401] |> Keyword.merge opts |
| 133 | + opts = [ status: 401] |> Keyword.merge(opts) |
| 134 134 | %StatusCode{ code: code, reason: reason } = opts[:status] |> StatusCode.find |
| 135 135 | conn |
| 136 136 | |> send_resp_if_not_sent(code, reason) |
| @@ -187,10 +187,10 @@ defmodule Placid.Response.Helpers do | |
| 187 187 | """ |
| 188 188 | @spec redirect(Plug.Conn.t, binary, Keyword.t) :: Plug.Conn.t |
| 189 189 | def redirect(conn, location, opts \\ []) do |
| 190 | - opts = [ status: 302 ] |> Keyword.merge opts |
| 191 | - %StatusCode{code: code, reason: reason} = opts[:status] |> StatusCode.find |
| 190 | + opts = [ status: 302 ] |> Keyword.merge(opts) |
| 191 | + %StatusCode{code: code, reason: reason} = opts[:status] |> StatusCode.find |
| 192 192 | conn |
| 193 | - |> put_resp_header_if_not_sent("Location", location) |
| 193 | + |> put_resp_header_if_not_sent("location", location) |
| 194 194 | |> send_resp_if_not_sent(code, reason) |
| 195 195 | end |
| @@ -4,6 +4,19 @@ defmodule Placid.Router do | |
| 4 4 | quote do |
| 5 5 | use HttpRouter, |
| 6 6 | default_content_type: "application/json; charset=utf-8" |
| 7 | + |
| 8 | + def run(opts \\ nil) do |
| 9 | + adapter = Placid.Config.get(:placid, :plug_adapter, Plug.Adapters.Cowboy) |
| 10 | + opts = opts || Placid.Config.get(__MODULE__) |
| 11 | + |
| 12 | + adapter.https __MODULE__, [], opts[:https] |
| 13 | + if opts[:https_only] do |
| 14 | + # Sends `403 Forbidden` to all HTTP requests |
| 15 | + adapter.http Placid.Request.HttpsOnly, [], opts[:http] |
| 16 | + else |
| 17 | + adapter.http __MODULE__, [], opts[:http] |
| 18 | + end |
| 19 | + end |
| 7 20 | end |
| 8 21 | end |
| 9 22 | end |
| @@ -1,90 +0,0 @@ | |
| 1 | - defmodule Placid.Router.Util do |
| 2 | - |
| 3 | - defmodule InvalidSpecError do |
| 4 | - defexception message: "invalid route specification" |
| 5 | - end |
| 6 | - |
| 7 | - def normalize_method(method) do |
| 8 | - method |> to_string |> String.upcase |
| 9 | - end |
| 10 | - |
| 11 | - def split(bin) do |
| 12 | - for segment <- String.split(bin, "/"), segment != "", do: segment |
| 13 | - end |
| 14 | - |
| 15 | - def build_spec(spec, context \\ nil) |
| 16 | - def build_spec(spec, context) when is_binary(spec) do |
| 17 | - build_spec split(spec), context, [], [] |
| 18 | - end |
| 19 | - def build_spec(spec, _context) do |
| 20 | - {[], spec} |
| 21 | - end |
| 22 | - defp build_spec([h|t], context, vars, acc) do |
| 23 | - handle_segment_match segment_match(h, "", context), t, context, vars, acc |
| 24 | - end |
| 25 | - defp build_spec([], _context, vars, acc) do |
| 26 | - {vars |> Enum.uniq |> Enum.reverse, Enum.reverse(acc)} |
| 27 | - end |
| 28 | - |
| 29 | - defp handle_segment_match({:literal, literal}, t, context, vars, acc) do |
| 30 | - build_spec t, context, vars, [literal|acc] |
| 31 | - end |
| 32 | - defp handle_segment_match({:identifier, identifier, expr}, t, context, vars, acc) do |
| 33 | - build_spec t, context, [identifier|vars], [expr|acc] |
| 34 | - end |
| 35 | - defp handle_segment_match({:glob, identifier, expr}, t, context, vars, acc) do |
| 36 | - if t != [] do |
| 37 | - raise InvalidSpecError, message: "cannot have a *glob followed by other segments" |
| 38 | - end |
| 39 | - |
| 40 | - case acc do |
| 41 | - [hs|ts] -> |
| 42 | - acc = [{:|, [], [hs, expr]} | ts] |
| 43 | - build_spec([], context, [identifier|vars], acc) |
| 44 | - _ -> |
| 45 | - {vars, expr} = build_spec([], context, [identifier|vars], [expr]) |
| 46 | - {vars, hd(expr)} |
| 47 | - end |
| 48 | - end |
| 49 | - |
| 50 | - defp segment_match(":" <> argument, buffer, context) do |
| 51 | - identifier = binary_to_identifier(":", argument) |
| 52 | - expr = quote_if_buffer identifier, buffer, context, fn var -> |
| 53 | - quote do: unquote(buffer) <> unquote(var) |
| 54 | - end |
| 55 | - {:identifier, identifier, expr} |
| 56 | - end |
| 57 | - defp segment_match("*" <> argument, buffer, context) do |
| 58 | - underscore = {:_, [], context} |
| 59 | - identifier = binary_to_identifier("*", argument) |
| 60 | - expr = quote_if_buffer identifier, buffer, context, fn var -> |
| 61 | - quote do: [unquote(buffer) <> unquote(underscore)|unquote(underscore)] = unquote(var) |
| 62 | - end |
| 63 | - {:glob, identifier, expr} |
| 64 | - end |
| 65 | - defp segment_match(<<h, t::binary>>, buffer, context) do |
| 66 | - segment_match t, buffer <> <<h>>, context |
| 67 | - end |
| 68 | - defp segment_match(<<>>, buffer, _context) do |
| 69 | - {:literal, buffer} |
| 70 | - end |
| 71 | - |
| 72 | - defp quote_if_buffer(identifier, "", context, _fun) do |
| 73 | - {identifier, [], context} |
| 74 | - end |
| 75 | - defp quote_if_buffer(identifier, _buffer, context, fun) do |
| 76 | - fun.({identifier, [], context}) |
| 77 | - end |
| 78 | - |
| 79 | - defp binary_to_identifier(prefix, <<letter, _::binary>> = binary) when letter in ?a..?z |
| 80 | - or letter == ?_ do |
| 81 | - if binary =~ ~r/^\w+$/ do |
| 82 | - String.to_atom(binary) |
| 83 | - else |
| 84 | - raise InvalidSpecError, message: "#{prefix}identifier in routes must be made of letters, numbers and underscore" |
| 85 | - end |
| 86 | - end |
| 87 | - defp binary_to_identifier(prefix, _) do |
| 88 | - raise InvalidSpecError, message: "#{prefix} in routes must be followed by lowercase letters" |
| 89 | - end |
| 90 | - end |
| \ No newline at end of file |
Loading more files…