msz*_*rlo 2 elixir phoenix-framework
我正在 Elixir/Phoenix 中实现后端 API。出于安全原因,我们决定在 URL 上显示尽可能少的内容,以便将要执行的操作嵌入到 POST 请求的 JSON 负载中。例如,我们将使用以下有效负载https://my.server.com/api/get_user/42发出 POST ,而不是使用类似 REST 的请求:https://my.server.com/api/
{
"action" : "get_user",
"params" : {
"id" : 42
}
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,我的路由器看起来像这样:
scope "/api", AlaaarmWeb do
pipe_through :api
post "/", ApiController, :process
match :*, "/*path", ApiController, :error_404
end
Run Code Online (Sandbox Code Playgroud)
我有一堆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
Run Code Online (Sandbox Code Playgroud)
它工作正常,但代码不是很清楚:一个大文件,使用相同的控制器, ApiController而有一个UserApiController用于管理用户,一个ProductApiController用于管理产品等会更清晰。
所以,我想知道是否有一种方法可以根据有效负载的内容而不仅仅是 URL 来选择要调用的模块和函数。
If you have defined structure as "action" and "params" key-value pair coming through payload and have dozens of requests that you want to filter and delegate to different controllers based on the path then you should be able to have a plug like this defined in endpoint. ex before plug YourApp.Router call
plug Plug.Session, @session_options
plug UrlFromPayloadAction, []
plug StackoverflowApiWeb.Router
Run Code Online (Sandbox Code Playgroud)
This plug would mutate path info so our modified url would be parsed by router and we can have defined controller like post "/get_user/:id", ApiUserController, :process and others based on action defined.
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
Run Code Online (Sandbox Code Playgroud)
这更多的是解决这个问题的可变方式,这可能违背像长生不老药这样的功能框架的一般哲学