elixir-maru / maru

Elixir RESTful Framework
https://maru.readme.io
BSD 3-Clause "New" or "Revised" License
1.32k stars 84 forks source link

Support 'forward' from Plug.Router #83

Closed jalcine closed 6 years ago

jalcine commented 6 years ago

When attempting to mount a plug to another location, I've conventionally used forward to do so. Adding support for forward would make Maru.Router a bit more compliant of the whole Plug.Router interface.

falood commented 6 years ago

Thank you, I also this it's useful, will be add with next release 🙂

jalcine commented 6 years ago

Thank you! What kind of steps are required for that in terms of difficultly? That could help with having people submit PRs for things like this.

falood commented 6 years ago

as mentioned #84 , I just focus on other things, if you're urgent for this feature, try this 🙂

defmodule MyForwardPlug do
  @moduledoc """
  A plug for forwarding request to another plug.
  When use within Maru.Router, should make sure use this plug in `before` block.

  ## Examples

      plug MyForwardPlug,
        path: "/graphiql",
        to: Absinthe.Plug.GraphQL,
        init_opts: [schema: MyApp.Schema]

  """

  @spec init(Keyword.t()) :: Map.t()
  def init(options) do
    %{
      path: options |> Keyword.fetch!(:path) |> Maru.Builder.Path.split(),
      to: Keyword.fetch!(options, :to),
      init_opts: Keyword.get(options, :init_opts, [])
    }
  end

  @spec call(Plug.Conn.t(), Map.t()) :: Plug.Conn.t()
  def call(%Plug.Conn{path_info: path_info} = conn, options) do
    case get_new_path(options[:path], path_info) do
      :not_matched ->
        conn

      {:ok, new_path} ->
        conn = %Plug.Conn{conn | path_info: new_path}
        options[:to].call(conn, options[:to].init(options[:init_opts]))
    end
  end

  defp get_new_path([], new_path), do: {:ok, new_path}
  defp get_new_path([h | t1], [h | t2]), do: get_new_path(t1, t2)
  defp get_new_path([h | t1], [_ | t2]) when is_atom(h), do: get_new_path(t1, t2)
  defp get_new_path(_, _), do: :not_matched
end
jalcine commented 6 years ago

Solid. This works for me!