Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support 'forward' from Plug.Router #83

Closed
jalcine opened this issue Oct 24, 2017 · 4 comments
Closed

Support 'forward' from Plug.Router #83

jalcine opened this issue Oct 24, 2017 · 4 comments

Comments

@jalcine
Copy link
Contributor

jalcine commented Oct 24, 2017

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
Copy link
Member

falood commented Oct 25, 2017

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

@jalcine
Copy link
Contributor Author

jalcine commented Oct 26, 2017

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
Copy link
Member

falood commented Oct 27, 2017

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
Copy link
Contributor Author

jalcine commented Oct 28, 2017

Solid. This works for me!

@jalcine jalcine closed this as completed Oct 28, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants