Rap*_*nah 0 elixir phoenix-framework
我有一个端点check,200如果请求包含有效的则返回响应auth_token,401否则返回。
def check(conn, _) do
if auth_token = get_session(conn, :auth_token) do
send_resp(conn, 200, "")
end
send_resp(conn, 401, "")
end
Run Code Online (Sandbox Code Playgroud)
这在auth_tokenis的情况下工作正常nil,但是,对于定义它的情况,我收到了一个奇怪的错误。
[error] Ranch listener AppWeb.Endpoint.HTTP had connection process started with :cowboy_clear:start_link/4 at #PID<0.6370.0> exit with reason: {:function_clause, [{:cowboy_http, :commands, [{:state, #PID<0.5887.0>, AppWeb.Endpoint.HTTP, #Port<0.1651>, :ranch_tcp, :undefined, %{env: %{dispatch: [{:_, [], [{:_, [], Phoenix.Endpoint.Cowboy2Handler, {AppWeb.Endpoint, []}}]}]}, stream_handlers: [Plug.Cowboy.Stream]}, "", %{}, {{127, 0, 0, 1}, 61063}, {{127, 0, 0, 1}, 4000}, :undefined, #Reference<0.3022468478.150208513.95764>, true, 2, {:ps_request_line, 0}, 65535, 1, :done, 1000, [{:stream, 1, {Plug.Cowboy.Stream, {:state, :undefined, AppWeb.Endpoint.HTTP, #PID<0.6371.0>, :undefined, :undefined, :undefined, :undefined, 0, :nofin, "", 0, :undefined, :normal}}, "GET", :"HTTP/1.1", :undefined, :undefined, 0, []}], [{:child, #PID<0.6371.0>, 1, 5000, :undefined}]}, 1, [{:response, "401 Unauthorized", %{"cache-control" => "max-age=0, private, must-revalidate", "content-length" => "0", "date" => "Sat, 29 Aug 2020 17:32:18 GMT", "server" => "Cowboy", "x-request-id" => "Fi_Nf1nWhRxOi1UAAQPB"}, ""}]], [file: '/Users/raph/Code/App/api/deps/cowboy/src/cowboy_http.erl', line: 954]}, {:cowboy_http, :loop, 1, [file: '/Users/raph/Code/App/api/deps/cowboy/src/cowboy_http.erl', line: 254]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 226]}]}
Run Code Online (Sandbox Code Playgroud)
注意:响应在所有情况下都发送成功,之后出现上述错误。
该错误是什么意思,我该如何避免?
我只是注意到上面的代码似乎试图发送两个响应:
[info] Sent 200 in 41ms
[info] Sent 401 in 41ms
Run Code Online (Sandbox Code Playgroud)
鉴于我的真实代码更接近于:
def check(conn, _) do
if auth_token = get_session(conn, :auth_token) do
if user = Accounts.get_user_by_session_token(auth_token) do
send_resp(conn, 200, Map.get(user, :email))
end
end
send_resp(conn, 401, "")
end
Run Code Online (Sandbox Code Playgroud)
编写上述逻辑以便send_resp仅调用一次的惯用方法是什么?
下面的实现没有错误,但感觉它可以以更惯用的方式重构。
def check(conn, _) do
if auth_token = get_session(conn, :auth_token) do
if user = Accounts.get_user_by_session_token(auth_token) do
send_resp(conn, 200, Map.get(user, :email))
else
send_resp(conn, 401, "")
end
else
send_resp(conn, 401, "")
end
end
Run Code Online (Sandbox Code Playgroud)
假设有一个User结构,我认为这更符合习惯:
def check(conn, _) do
with token when is_binary(token) <- get_session(conn, :auth_token),
%User{} = user <- Accounts.get_user_by_session_token(token) do
send_resp(conn, 200, user.email)
else
_ -> send_resp(conn, 401, "")
end
end
Run Code Online (Sandbox Code Playgroud)