Ono*_*cci 2 elixir elixir-framework
所以我试图在URL中传递多个参数来插件.这是我用于测试的URL:
http://localhost:4000/uid=ToddFlanders&pwd=MyTestPword
这是代码:
defmodule Sci do
    @userid "uid"
    @password "pwd"
    import Plug.Conn
    import Plug.Conn.Utils
    use Plug.Router
    plug :match
    plug :dispatch
    get "/:args" do
        %{@userid => usr} = params(args)
        %{@password => pass} = params(args)
        send_resp(conn, 200, "Hello #{usr}. Your password is #{pass}")
    end
    match _ do
        send_resp(conn, 404, "oops")
  end
  def start do
    Plug.Adapters.Cowboy.http Sci, [], port: 4000
  end
  def stop do
    Plug.Adapters.Cowboy.shutdown Sci.HTTP
  end
end
如果我只传递一个参数(uid或pwd),它匹配正常.如果我删除?查询字符串前面的它失败 - 抛出异常.
我也试过这个:
get "/:args" do
  %{@userid => usr, @password => pass} = params(args)
也没工作.所以有两个问题:
1.)这是在URL中传递多个参数的正确方法吗?
2.)是否有一些技巧可以让插头看到这两个参数?
任何想法或见解都会受到欢迎 - 甚至建议更好的方法来做到这一点.
Elixir v0.15.1和Plug v0.5.1
编辑:
根据Jose的评论添加堆栈跟踪:
iex(2)> 07:46:56.499 [error] Error in process <0.232.0> with exit value: {[{reason,{badmatch,#{}}},{mfa,{'Elixir.Plug.Adapters.Cowboy.Handler',init,3}},{stacktrace,[{'Elixir.Sci','-do_match/2-fun-0-',2,[{file,"lib/sci.ex"},{line,18}]},{'Eli
xir.Sci',call,2,[{file,"lib/sci.ex"},{line,1}]},{'Elixir.Plug.Adapters.Cowboy.Handler'...                                                                                                                                                       
iex(2)> 07:46:56.510 [error] Ranch listener Sci.HTTP had connection process started with :cowboy_protocol:start_link/4 at #PID<0.232.0> exit with reason: {[reason: {:badmatch, %{}}, mfa: {Plug.Adapters.Cowboy.Handler, :init, 3}, stacktrace:
 [{Sci, :"-do_match/2-fun-0-", 2, [file: 'lib/sci.ex', line: 18]}, {Sci, :call, 2, [file: 'lib/sci.ex', line: 1]}, {Plug.Adapters.Cowboy.Handler, :init, 3, [file: 'lib/plug/adapters/cowboy/handler.ex', line: 7]}, {:cowboy_handler, :handler_
init, 4, [file: 'src/cowboy_handler.erl', line: 64]}, {:cowboy_protocol, :execute, 4, [file: 'src/cowboy_protocol.erl', line: 435]}], req: [socket: #Port<0.5168>, transport: :ranch_tcp, connection: :keepalive, pid: #PID<0.232.0>, method: "G
ET", version: :"HTTP/1.1", peer: {{127, 0, 0, 1}, 63880}, host: "localhost", host_info: :undefined, port: 4000, path: "/uid=ToddFlanders&pwd=MyTestPassword", path_info: :undefined, qs: "", qs_vals: :undefined, bindings: [], headers: [{"host
", "localhost:4000"}, {"connection", "keep-alive"}, {"cache-control", "max-age=0"}, {"accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"}, {"user-agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/53
7.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36"}, {"accept-encoding", "gzip,deflate,sdch"}, {"accept-language", "en-US,en;q=0.8"}], p_headers: [{"connection", ["keep-alive"]}], cookies: :undefined, meta: [], body_state: :waitin
g, buffer: "", multipart: :undefined, resp_compress: false, resp_state: :waiting, resp_headers: [], resp_body: "", onresponse: :undefined], opts: {Sci, []}], [{:cowboy_protocol, :execute, 4, [file: 'src/cowboy_protocol.erl', line: 435]}]}  
iex(2)> 07:46:56.969 [error] Error in process <0.233.0> with exit value: {[{reason,{badmatch,#{}}},{mfa,{'Elixir.Plug.Adapters.Cowboy.Handler',init,3}},{stacktrace,[{'Elixir.Sci','-do_match/2-fun-0-',2,[{file,"lib/sci.ex"},{line,18}]},{'Eli
xir.Sci',call,2,[{file,"lib/sci.ex"},{line,1}]},{'Elixir.Plug.Adapters.Cowboy.Handler'...                                                                                                                                                       
iex(2)> 07:46:56.971 [error] Ranch listener Sci.HTTP had connection process started with :cowboy_protocol:start_link/4 at #PID<0.233.0> exit with reason: {[reason: {:badmatch, %{}}, mfa: {Plug.Adapters.Cowboy.Handler, :init, 3}, stacktrace:
 [{Sci, :"-do_match/2-fun-0-", 2, [file: 'lib/sci.ex', line: 18]}, {Sci, :call, 2, [file: 'lib/sci.ex', line: 1]}, {Plug.Adapters.Cowboy.Handler, :init, 3, [file: 'lib/plug/adapters/cowboy/handler.ex', line: 7]}, {:cowboy_handler, :handler_
init, 4, [file: 'src/cowboy_handler.erl', line: 64]}, {:cowboy_protocol, :execute, 4, [file: 'src/cowboy_protocol.erl', line: 435]}], req: [socket: #Port<0.5174>, transport: :ranch_tcp, connection: :keepalive, pid: #PID<0.233.0>, method: "G
ET", version: :"HTTP/1.1", peer: {{127, 0, 0, 1}, 63881}, host: "localhost", host_info: :undefined, port: 4000, path: "/favicon.ico", path_info: :undefined, qs: "", qs_vals: :undefined, bindings: [], headers: [{"host", "localhost:4000"}, {"
connection", "keep-alive"}, {"accept", "*/*"}, {"user-agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36"}, {"accept-encoding", "gzip,deflate,sdch"}, {"accept-language", "e
n-US,en;q=0.8"}], p_headers: [{"connection", ["keep-alive"]}], cookies: :undefined, meta: [], body_state: :waiting, buffer: "", multipart: :undefined, resp_compress: false, resp_state: :waiting, resp_headers: [], resp_body: "", onresponse: 
:undefined], opts: {Sci, []}], [{:cowboy_protocol, :execute, 4, [file: 'src/cowboy_protocol.erl', line: 435]}]}                                                                                                                                 
编辑2:我记下了错误的URL; 现在已经纠正了.另外要添加问题,如果我将URL http://localhost:4000/?uid=ToddFlanders&pwd=MyTestPword设为:,则代码跳转到该match _ do子句
您要使用的URL结构不是很好.因此,您的问题与框架无关,因为几乎所有框架/库都存在以预期方式解析URL的问题.
/uid=ToddFlanders&pwd=MyTestPword 被视为没有任何查询参数的路径.
PATH: /uid=ToddFlanders&pwd=MyTestPword
QUERY STRING: (empty/unset)
QUERY PARAMS: [ ]
我想你真的想拥有类似的东西/?uid=ToddFlanders&pwd=MyTestPword.
PATH: /
QUERY STRING: uid=ToddFlanders&pwd=MyTestPword
QUERY PARAMS: [ uid: "ToddFlanders", pwd: "MyTestPword" ]
此外Plug.Conn.Utils.params/1,旨在解析标头参数.使用Plug.Conn.Query.decode/1查询参数来代替.
因此,在您的示例中,我建议调整应用程序代码如下:
defmodule Sci do
  import Plug.Conn
  use Plug.Router
  @userid   "uid"
  @password "pwd"
  plug :match
  plug :dispatch
  get "/" do
    conn = fetch_params(conn) # populates conn.params
    %{ @userid => usr, @password => pass } = conn.params
    send_resp(conn, 200, "Hello #{usr}. Your password is #{pass}")
  end
  match _ do
    send_resp(conn, 404, "oops")
  end
  def start do
    Plug.Adapters.Cowboy.http Sci, [], port: 4000
  end
  def stop do
    Plug.Adapters.Cowboy.shutdown Sci.HTTP
  end
end
然后你就可以成功试试http://localhost:4000/?uid=ToddFlanders&pwd=MyTestPword.
(此外,它不应该触及该match(_)功能,因为/如果您正确地对此路径发出请求,则应始终匹配.
我不是通用插件,但是对于演示代码,我使用了fetch_params/1然后conn.params["foo"],conn.params["bar"]依此类推,这绝对有效.
更新:自插件0.12.0起,应使用fetch_query_params/2