【问题标题】:Phoenix routing based on the payload基于payload的Phoenix路由
【发布时间】:2020-08-02 07:17:40
【问题描述】:

我正在 Elixir/Phoenix 中实现一个后端 API。出于安全原因,决定在 URL 上尽可能少地显示,以便将要执行的操作嵌入到 POST 请求的 JSON 有效负载中。例如,我们将在https://my.server.com/api/ 上使用以下有效负载发出一个 POST,而不是类似 REST 的请求 https://my.server.com/api/get_user/42

{
    "action" : "get_user",
    "params" : {
        "id" : 42
    }
}

到目前为止,我的路由器是这样的:

  scope "/api", AlaaarmWeb do
     pipe_through :api

     post "/", ApiController, :process
     match :*, "/*path", ApiController, :error_404
   end

我有一堆process 函数在params 映射上匹配:

  def process(conn, params = %{"action" => "get_user"}) do
    # ... get the user from the DB in resp, and sed back
    json(conn, resp)
  end

它工作正常,但代码不是很清楚:一个大文件,使用相同的控制器,ApiController,而使用UserApiController 管理用户会更清晰,ProductApiController 用于管理产品等等。

所以,我想知道是否有一种方法可以根据有效负载的内容而不仅仅是根据 URL 来选择要调用的模块和函数。

【问题讨论】:

    标签: elixir phoenix-framework


    【解决方案1】:

    如果您将结构定义为“action”和“params”键值对,通过有效负载传递,并且有数十个请求要根据路径过滤并委托给不同的控制器,那么您应该能够拥有一个像这样在端点中定义的插件。前插上YourApp.Router调用

      plug Plug.Session, @session_options
      plug UrlFromPayloadAction, []
      plug StackoverflowApiWeb.Router
    

    这个插件会改变路径信息,因此我们修改后的 url 将被路由器解析,我们可以定义控制器,如 post "/get_user/:id", ApiUserController, :process 和其他基于定义的操作。

    defmodule UrlFromPayloadAction do
            import Plug.Conn
    
            def init(default), do: default
    
            def call(%Plug.Conn{params: %{"action" => action,
                                             "params" => %{ "id" => id }
                                         }} = conn, _default) do
                  conn = conn
                         |> assign(:original_path_info, conn.path_info)
                         |> assign(:original_request_path, conn.request_path)
                   
                  %Plug.Conn{conn | path_info: conn.path_info ++ [ "#{action}", "#{id}" ] , request_path: conn.request_path <> "/#{action}/#{id}" }
            end
            def call(conn, _default), do: conn
    end
    

    这更像是解决这个问题的一种可变方式,这可能违反像长生不老药这样的功能框架的一般哲学

    【讨论】:

    • 聪明!工作正常。谢谢。
    【解决方案2】:

    不,我不认为 Phoenix.Router 可以基于有效负载进行路由。这必须在控制器中完成。

    但您仍然可以按照您的描述制作单独的控制器文件/模块,只需 use 将它们全部放在“主”ApiController 中。

    【讨论】:

      猜你喜欢
      • 2018-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-07
      • 2021-04-18
      • 2018-01-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多