代码之家  ›  专栏  ›  技术社区  ›  Flame_Phoenix

如何用长生不老药堵住管道?

  •  0
  • Flame_Phoenix  · 技术社区  · 6 年前

    背景

    我有一个应用程序,它是一个带有牛仔和使用插件的Web服务器。由于这个应用程序是继承的,使用凤凰城是不可能的,除非我们重新制作整个事情,这是不会发生的。

    我的目标是不要把所有东西都放在一个大文件里,而是要有几个插头,通过管道连接起来。

    代码

    假设我有一个主路由器插头,如下所示:

    defmodule MyApp.Web.Router do
      use Plug.Router
    
      plug(:match)
    
      forward "/check", to: MyApp.Route.Check
      forward "/dispatch", to: MyApp.Plug.Dispatch      
    end
    

    所以这里我有两件事。终结点的路由 /check ,如下所示:

    defmodule MyApp.Route.Check do
      use Plug.Router
    
      plug(:dispatch)
    
      get "/", do: send_resp(conn, 200, "ok")
    end
    

    以及用于 /dispatch 看起来是这样的:

    defmodule MyApp.Plug.Dispatch do
      use Plug.Builder
    
      plug(Plug.Parsers, parsers: [:urlencoded])   #parses parameters
      plug(MyApp.Plug.Metrics)                     #exposes /metrics path
      plug(Cipher.ValidatePlug)                    #typical URL validation
      plug(MyApp.Route.Dispatch)                   #forwards to dispatch Route 
    end
    

    此管道分析参数,通知度量服务,验证请求,然后将其发送到正确的路由器,如下所示:

    defmodule MyApp.Route.Dispatch do
      use Plug.Router
    
      plug(:dispatch)
    
      get "/", do: send_resp(conn, 200, "Info dispatched")
    end
    

    问题

    这里的问题是什么都不起作用。实际上,如果我启动应用程序并尝试访问dummest端点( 检查 )代码出错:

    17:44:03.330 [error] #PID<0.402.0> running MyApp.Web.Router (connection #PID<0.401.0>, stream id 1) terminated
    Server: localhost:4003 (http)
    Request: GET /check
    ** (exit) an exception was raised:
        ** (Plug.Conn.NotSentError) a response was neither set nor sent from the connection
            (plug_cowboy) lib/plug/cowboy/handler.ex:37: Plug.Cowboy.Handler.maybe_send/2
            (plug_cowboy) lib/plug/cowboy/handler.ex:13: Plug.Cowboy.Handler.init/2
            (...)
    

    我现在已经花了一整天的时间阅读文档,这是我所得到的。这个应用程序非常简单,几乎就是插头的Hello World:

    https://elixirschool.com/en/lessons/specifics/plug/

    但是有 MyApp.Web.Router 而不是他们用的那个。

    这里可以看到一个mwe:

    https://github.com/Fl4m3Ph03n1x/plug-pipeline-problem

    我做错什么了?

    1 回复  |  直到 6 年前
        1
  •  3
  •   Marcos Tapajós    6 年前

    上的路由不匹配 Example.Route.Dispatch Example.Route.Check .要修复此问题,需要进行两次更改:

    defmodule Example.Route.Dispatch do
      use Plug.Router
    
      plug(:dispatch)
    
      get "/*glob", do: send_resp(conn, 200, "Info dispatched")
    end
    

    defmodule Example.Route.Check do
      use Plug.Router
    
      plug :match
      plug :dispatch
    
      get "/*glob" do
        send_resp(conn, 200, "ok")
      end
    end
    

    或者,您可以这样做: https://github.com/Fl4m3Ph03n1x/plug-pipeline-problem/pull/1

    要进一步了解它为什么不匹配,可以使用 Plug.Router.match_path/1 在“全力以赴”的比赛中。