Elixir Plug.Conn.resp/3中没有匹配的函数子句

Elixir Plug.Conn.resp/3中没有匹配的函数子句,elixir,phoenix-framework,guardian,Elixir,Phoenix Framework,Guardian,在使用Guardian对JWT令牌验证GET请求后,我尝试使用JSON进行响应 我的测试: describe "Show user if authenticated" do setup %{conn: conn} do {:ok, %User{} = user} = Riders.create_user(@create_attrs) {:ok, jwt, claims} = Bikefit.Guardian.encode_and_sign(user)

在使用Guardian对JWT令牌验证GET请求后,我尝试使用JSON进行响应

我的测试:

  describe "Show user if authenticated" do
    setup %{conn: conn} do
      {:ok, %User{} = user} = Riders.create_user(@create_attrs)
      {:ok, jwt, claims} = Bikefit.Guardian.encode_and_sign(user)
      IO.inspect claims
      conn = put_req_header(conn, "authorization", "Bearer #{jwt}")
      {:ok, conn: conn, user: user}
    end

    test  "and return user if token is valid", %{conn: conn, user: user} do
      email = user.email
      conn = get conn, current_user_path(conn, :current)
      response = json_response(conn, 200)
      IO.puts "---------- test response--------"
      IO.inspect response
      assert %{"email" => email} = response
    end
  end
我的控制器:

defmodule BikefitWeb.UserController do
  use BikefitWeb, :controller

  alias Bikefit.Riders
  alias Bikefit.Riders.User

  plug Guardian.Plug.EnsureAuthenticated, handler: BikefitWeb.AuthController

  action_fallback BikefitWeb.FallbackController

  def current(conn, _params) do
    user = conn |> Guardian.Plug.current_resource

    conn
    |> render(BikefitWeb.UserView, "show.json-api", user: user)
  end
end
我的看法是:

defmodule BikefitWeb.UserView do
  use BikefitWeb, :view
  alias BikefitWeb.UserView

  def render("show.json-api", %{user: user}) do
    %{data: render_one(user, UserView, "user.json")}
  end

  def render("user.json",  %{user: user}) do
    %{id: user.id,
      email: user.email,
      auth_provider: user.auth_provider}
  end
end
我的路由器:

defmodule BikefitWeb.Router do
  use BikefitWeb, :router

  pipeline :api do
    plug :accepts, ["json", "json-api"]
    plug JaSerializer.Deserializer
  end

  pipeline :api_auth do
    plug :accepts, ["json", "json-api"]
    plug Guardian.Plug.Pipeline, 
          module: Bikefit.Guardian, 
          error_handler: BikefitWeb.AuthErrorHandler
    plug Guardian.Plug.VerifyHeader, realm: "Bearer"
    plug Guardian.Plug.LoadResource
    plug JaSerializer.Deserializer
  end

  scope "/api/v1", BikefitWeb do
    pipe_through :api_auth

    resources "/users", UserController, except: [:new, :edit]
    get "/user/current", UserController, :current, as: :current_user
    delete "/logout", UserController, :delete
  end
end
测试的输出:

   ** (FunctionClauseError) no function clause matching in Plug.Conn.resp/3

     The following arguments were given to Plug.Conn.resp/3:

         # 1
         %Plug.Conn{adapter: {Plug.Adapters.Test.Conn, :...}, 
  assigns: %{layout: false, user: %Bikefit.Riders.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
  auth_provider: "some auth_provider", email: "some email", id: 272, inserted_at: ~N[2018-02-24 06:28:20.876426], 
  password: nil, password_hash: nil, updated_at: ~N[2018-02-24 06:28:20.876442]}}, 
  before_send: [#Function<1.42514850/1 in Plug.Logger.call/2>], body_params: %{}, 
  cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false, host: "www.example.com", method: "GET", owner: #PID<0.418.0>, 
  params: %{}, path_info: ["api", "v1", "user", "current"], path_params: %{}, peer: {{127, 0, 0, 1}, 111317}, 
  port: 80, private: %{BikefitWeb.Router => {[], %{}}, 
  :guardian_default_claims => %{"aud" => "Bikefit", "exp" => 1522045700, "iat" => 1519453700, "iss" => "Bikefit", "jti" => "5f8312a9-8f49-4f0a-9654-968882cd3f90", "nbf" => 1519453699, "sub" => "some email", "typ" => "access"}, 
  :guardian_default_resource => %Bikefit.Riders.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, auth_provider: "some auth_provider", email: "some email", id: 272, inserted_at: ~N[2018-02-24 06:28:20.876426], password: nil, password_hash: nil, updated_at: ~N[2018-02-24 06:28:20.876442]}, 
  :guardian_default_token => "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJCaWtlZml0IiwiZXhwIjoxNTIyMDQ1NzAwLCJpYXQiOjE1MTk0NTM3MDAsImlzcyI6IkJpa2VmaXQiLCJqdGkiOiI1ZjgzMTJhOS04ZjQ5LTRmMGEtOTY1NC05Njg4ODJjZDNmOTAiLCJuYmYiOjE1MTk0NTM2OTksInN1YiI6InNvbWUgZW1hac3MifQ.gt7B7itXs8HFWEzFwQxa5LJaDzSKkF1b2C4BDxw28nP3Q4_cHDi-PexZQDh8BbjD363qFKK9p9jvoQqqe9yx8A", :guardian_error_handler => BikefitWeb.AuthErrorHandler, 
 :guardian_module => Bikefit.Guardian, :phoenix_action => :current, 
 :phoenix_controller => BikefitWeb.UserController, :phoenix_endpoint => BikefitWeb.Endpoint, 
 :phoenix_format => "json", :phoenix_layout => {BikefitWeb.LayoutView, :app}, :phoenix_pipelines => [:api_auth], 
 :phoenix_recycled => true, :phoenix_router => BikefitWeb.Router, :phoenix_template => "show.json-api", 
 :phoenix_view => BikefitWeb.UserView, :plug_session_fetch => #Function<1.45862765/1 in Plug.Session.fetch_session/1>, 
 :plug_skip_csrf_protection => true}, query_params: %{}, query_string: "", remote_ip: {127, 0, 0, 1}, 
 req_cookies: %Plug.Conn.Unfetched{aspect: :cookies}, req_headers: [{"accept", "application/json"}, 
 {"authorization", "Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJCaWtlZml0IiwiZXhwIjoxNTIyMDQ1NzAwLCJpYXQiOjE1MTk0NTM3MDAsImlzcyI6IkJpa2VmaXQRmMGEtOTY1NC05Njg4ODJjZDNmOTAiLCJuYmYiOjE1MTk0NTM2OTksInN1YiI6InNvbWUgZW1haWwiLCJ0eXAiOiJhY2Nlc3MifQ.gt7B7itXs8HFWEzFwQxa5LJaDzSKkF1b2C4BDxw28nP3Q4_cHDi-PexZQDh8BbjD363qFKK9p9jvoQqqe9yx8A"}], 
 request_path: "/api/v1/user/current", resp_body: nil, resp_cookies: %{}, 
 resp_headers: [{"content-type", "application/vnd.api+json; charset=utf-8"}, 
 {"cache-control", "max-age=0, private, must-revalidate"}, {"x-request-id", "44e2jir0js16jn0pe2pf8qgbksc9346s"}], 
 scheme: :http, script_name: [], secret_key_base: "UD4qdbi6YOBRbCrf", 
 state: :unset, status: nil}

         # 2
         200

         # 3
         %{data: %{auth_provider: "some auth_provider", email: "some email", id: 272}}

     Attempted function clauses (showing 3 out of 3):

         def resp(%Plug.Conn{state: state}, status, _body) when not(state === :set or (state === :set_chunked or (state === :set_file or state === :unset)))
         def resp(%Plug.Conn{}, _status, nil)
         def resp(%Plug.Conn{} = conn, status, body) when is_binary(body) or is_list(body)

     code: conn = get conn, current_user_path(conn, :current)
     stacktrace:
       (plug) lib/plug/conn.ex:505: Plug.Conn.resp/3
       (plug) lib/plug/conn.ex:495: Plug.Conn.send_resp/3
       (bikefit) lib/bikefit_web/controllers/user_controller.ex:1: BikefitWeb.UserController.action/2
       (bikefit) lib/bikefit_web/controllers/user_controller.ex:1: BikefitWeb.UserController.phoenix_controller_pipeline/2
       (bikefit) lib/bikefit_web/endpoint.ex:1: BikefitWeb.Endpoint.instrument/4
       (phoenix) lib/phoenix/router.ex:278: Phoenix.Router.__call__/1
       (bikefit) lib/bikefit_web/endpoint.ex:1: BikefitWeb.Endpoint.plug_builder_call/2
       (bikefit) lib/bikefit_web/endpoint.ex:1: BikefitWeb.Endpoint.call/2
       (phoenix) lib/phoenix/test/conn_test.ex:224: Phoenix.ConnTest.dispatch/5
       test/bikefit_web/controllers/user_controller_test.exs:63: (test)
**(FunctionClauseError)Plug.Conn.resp/3中没有匹配的函数子句
为Plug.Conn.resp/3提供了以下参数:
# 1
%Plug.Conn{adapter:{Plug.Adapters.Test.Conn,:…},
分配:%{layout:false,用户:%Bikefit.Riders.user{{uuuuu meta}uuuuu:#exto.Schema.Metadata,
认证提供者:“一些认证提供者”,电子邮件:“一些电子邮件”,id:272,插入地址:~N[2018-02-24 06:28:20.876426],
密码:nil,密码\u散列:nil,更新地址:~N[2018-02-24 06:28:20.876442]},
在发送之前:[函数],体参数:%{},
cookies:%Plug.Conn.Unfetched{aspect::cookies},暂停:false,主机:“www.example.com”,方法:“GET”,所有者:#PID,
参数:%{},路径信息:[“api”,“v1”,“用户”,“当前”],路径参数:%{},对等:{127,0,0,1},111317},
端口:80,专用:%{BikefitWeb.Router=>{[],%{},
:guardian\u default\u claims=>%{“aud”=>“Bikefit”,“exp”=>1522045700,“iat”=>1519453700,“iss”=>“Bikefit”,“jti”=>“5f8312a9-8f49-4f0a-9654-968882cd3f90”,“nbf”=>1519453699,“sub”=>“一些电子邮件”,“典型”=>“访问”},
:guardian_default_resource=>%Bikefit.Riders.User{uuuuuu meta_uuu:#exto.Schema.Metadata,身份验证提供者:“一些身份验证提供者”,电子邮件:“一些电子邮件”,id:272,插入地址:~N[2018-02-24 06:28:20.876426],密码:nil,密码哈希:nil,更新地址:~N[2018-02-24 06:28:20.876442],
:监护人\默认\令牌=>“Eyjhbgcioijiuzuxmiiir5cci6IKPxvcj9.Eyjhdwqioijcawtlzml0iiiiijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj“,:guardian\u error\u handler=>BikefitWeb.AuthErrorHandler,
:guardian_module=>Bikefit.guardian,:phoenix_action=>:current,
:phoenix_controller=>BikefitWeb.UserController,:phoenix_endpoint=>BikefitWeb.endpoint,
:phoenix_format=>“json”,:phoenix_layout=>{BikefitWeb.LayoutView,:app},:phoenix_pipelines=>[:api_auth],
:phoenix_recycled=>true,:phoenix_router=>BikefitWeb.router,:phoenix_template=>“show.json api”,
:phoenix_view=>BikefitWeb.UserView,:plug_session_fetch=>,
:plug_skip_csrf_protection=>true},查询参数:%{},查询字符串:,远程ip:{127,0,0,1},
请求cookies:%Plug.Conn.Unfetched{aspect::cookies},请求头:[{“accept”,“application/json”},
{“授权”、“持票人”eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.EYJDWQOIJCAWTLZML0IIWIZHWIJOXNTIYMDQ1NZKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYK0MTKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYKYK,
请求路径:“/api/v1/user/current”,响应主体:nil,响应cookie:%{},
响应头:[{“content-type”,“application/vnd.api+json;charset=utf-8”},
{“缓存控制”,“最大年龄=0,私有,必须重新验证”},{“x-request-id”,“44e2jir0js16jn0pe2pf8qgbksc9346s”},
方案::http,脚本名称:[],密钥库:“UD4QDBI6YOBCRF”,
状态::未设置,状态:nil}
# 2
200
# 3
%{数据:%{auth_提供者:“某些auth_提供者”,电子邮件:“某些电子邮件”,id:272}
尝试的函数子句(显示3个中的3个):
def resp(%Plug.Conn{state:state},status,_body)不在时(state==:set或(state==:set_chunked或(state==:set_file或state==:unset)))
def响应(%Plug.Conn{},_状态,无)
def resp(%Plug.Conn{}=Conn,status,body)何时为二进制(body)或列表(body)
代码:conn=获取conn,当前用户路径(conn,:当前)
堆栈跟踪:
(plug)lib/plug/conn.ex:505:plug.conn.resp/3
(plug)lib/plug/conn.ex:495:plug.conn.send_resp/3
(bikefit)lib/bikefit\u web/controllers/user\u controller.ex:1:BikefitWeb.UserController.action/2
(bikefit)lib/bikefit\u web/controllers/user\u controller.ex:1:BikefitWeb.UserController.phoenix\u controller\u管道/2
(bikefit)lib/bikefit_web/endpoint.ex:1:BikefitWeb.endpoint.instrument/4
(凤凰城)lib/phoenix/router.ex:278:phoenix.router.\uuuuuu呼叫\uuuuu/1
(bikefit)lib/bikefit\u web/endpoint.ex:1:BikefitWeb.endpoint.plug\u builder\u call/2
(bikefit)lib/bikefit_web/endpoint.ex:1:BikefitWeb.endpoint.call/2
(phoenix)lib/phoenix/test/conn_test.ex:224:phoenix.connstest.dispatch/5
test/bikefit\u web/controllers/user\u controller\u test.exs:63:(测试)

我认为问题在于conn的
state::unset
导致函数子句匹配出现问题,但我不确定为什么会发生这种情况,因为我认为我的控制器和视图与教程匹配。有什么想法吗

您需要告诉Phoenix如何通过。默认情况下,它知道如何对
.json
进行编码,但对
.json api
一无所知,这就是为什么它们在默认情况下没有编码


将其重命名为.json或向格式编码器添加一个新条目就足以修复它。

您需要告诉Phoenix如何通过。默认情况下,它知道如何对
.json
进行编码,但对
.json api
一无所知,这就是为什么它们在默认情况下没有编码


重命名它.json或向格式编码器添加新条目就足以修复它。

如果需要json响应,则应使用
json
not
render
render(conn,BikefitWeb.UserView,“show.json api”,user:user)
json(conn,BikefitWeb.UserView,“show.json api”,user:user)
.json\4似乎不存在于Phoenix.Controller模块中。仅json\2,它不调用视图。菲尼克斯控制器测试指南