如何在 Elixir 中插入管道?
How to do Plug pipelines in Elixir?
背景
我有一个应用程序,它是一个带有 cowboy 并使用插件的网络服务器。由于此应用程序是继承而来的,除非我们重新制作整个东西,否则使用 Phoenix 是不可能的,但这并没有发生。
我的 objective 不是将所有内容都放在一个巨大的文件中,而是要有多个插头并通过管道连接它们。
代码
假设我有一个主路由器插头,看起来像这样:
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
的 Plug 管道如下所示:
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
问题
这里的问题是没有任何效果。毫不夸张地说,如果我启动应用程序并尝试访问最愚蠢的端点 ( /check
),代码就会出错:
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
我做错了什么?
路线在 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
要了解有关不匹配原因的更多信息,您可以在 "catch all" 匹配项上使用 Plug.Router.match_path/1。
背景
我有一个应用程序,它是一个带有 cowboy 并使用插件的网络服务器。由于此应用程序是继承而来的,除非我们重新制作整个东西,否则使用 Phoenix 是不可能的,但这并没有发生。
我的 objective 不是将所有内容都放在一个巨大的文件中,而是要有多个插头并通过管道连接它们。
代码
假设我有一个主路由器插头,看起来像这样:
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
的 Plug 管道如下所示:
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
问题
这里的问题是没有任何效果。毫不夸张地说,如果我启动应用程序并尝试访问最愚蠢的端点 ( /check
),代码就会出错:
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
我做错了什么?
路线在 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
要了解有关不匹配原因的更多信息,您可以在 "catch all" 匹配项上使用 Plug.Router.match_path/1。