如何在Phoenix框架中运行响应后的中间件功能? [英] How do you run middleware functions post response in Phoenix framework?
问题描述
我正在与Phoenix一起在Elixir中开发一个简单的网站.我想添加一些自定义中间件,该中间件在生成响应后 即可运行.例如,为了记录每个响应中的字节总数,我想要一个这样的插件
I'm developing a simple website in Elixir with Phoenix. I'd like to add some custom middleware that runs after a response has been generated. For example, in order to log the total number of bytes in each response I'd like to have a Plug like this
defmodule HelloWeb.Plugs.ByteLogger do
import Plug.Conn
require Logger
def init(default), do: default
def call(conn, default) do
log("bytes sent: #{String.length(conn.resp_body)}")
end
end
尽管尝试在路由器的Phoenix管道之一中使用此插件无法正常工作,但它们都已在呈现响应之前运行.相反,它会导致 FunctionClauseError
,因为 conn.resp_body
为 nil
.我不确定如何使用此插件,以便在响应呈现后即可运行.
Trying to use this plug in one of the Phoenix pipelines in the router won't work though, they are all run before the response is rendered. Instead it causes a FunctionClauseError
since conn.resp_body
is nil
. I'm not sure how to use this plug so it can run after the response is rendered.
推荐答案
我认为您正在寻找 register_before_send/2 .
这允许注册在 resp_body
设置为nil之前将被调用的回调,例如
This allows to register callbacks that will be called before resp_body
gets set to nil as explained here.
应该像这样:
defmodule HelloWeb.Plugs.ByteLogger do
import Plug.Conn
require Logger
def init(default), do: default
def call(conn, default) do
register_before_send(conn, fn conn ->
log("bytes sent: #{String.length(conn.resp_body)}")
conn
end)
end
end
我不认为您应该使用 String.length
作为字节大小:
I don't think you should be using String.length
for the byte size:
-
resp_body
不一定是字符串,可以是I/O列表 -
byte_size/1
用于计数字节,String.length/1
返回UTF-8字素计数
resp_body
is not necessarily a string, can be an I/O-listbyte_size/1
should be used to count bytes,String.length/1
returns UTF-8 grapheme count
以下方法可以完成这项工作,但是由于需要连接身体,因此会对性能产生重大影响:
The following could do the job, but with a significant performance impact due to the need of concatenating the body:
conn.resp_body |> to_string() |> byte_size()
:erlang.iolist_size/1 似乎运行良好,我认为在性能方面要好得多.
:erlang.iolist_size/1 seems to work well and I suppose is much better performance-wise.
这篇关于如何在Phoenix框架中运行响应后的中间件功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!