在一个新的Phoenix应用程序中,默认情况下存在Plug.Head
插件,我对它的重要性很感兴趣。
我知道"HEAD 方法与 GET 相同,只是服务器不得在响应中发送消息正文"。
我认为凤凰城官方指南是一流的,但这让我在路由指南中大吃一惊:
Plug.Head - 将 HEAD 请求转换为 GET 请求并剥离响应正文
如果 HEAD 请求没有正文,那么为什么需要这样做?我想也许可以控制格式错误的请求,但看看 Plug.Head 实现,它只是将 HEAD 方法切换到 GET。
def call(%Conn{method: "HEAD"} = conn, []), do: %{conn | method: "GET"}
def call(conn, []), do: conn
end
在这个主题上,我能找到的最接近的东西是关于ServerFault的问题,但它与NGINX和一个有缺陷的应用程序逻辑有关,其中HEAD请求需要转换为GET并将相应的GET响应转换回HEAD。
由于 Phoenix 在很大程度上受到 Rails 的启发,因此您可以放心地打赌Plug.Head
灵感来自 Rack::Head
。
HEAD 请求返回与 GET 相同的响应,但仅包含标头。因此,为了生成正确的标头,它们被路由到 Phoenix 应用中的 GET 操作。
但是,要生成正确的(空)正文,必须剥离响应的正文。因为Rack::Head
是中间件,所以它在获得控制器的响应后才能这样做。
相比之下,Plug的架构更像是一个管道,Plug.Head
修改方法并传递conn
,但再也看不到它。
如果你看到cdegroot的答案,剥离响应主体的责任将传递给要实现的Plug.Conn.Adapter
(即Web服务器)。
AFAICT,这个想法是Plug.Head
只是确保请求作为GET
处理;实现HEAD
的第二部分,即不发送主体,由插头连接适配器完成。大多数回调的文档(如 send_resp)指定"如果请求具有方法 "HEAD"
,适配器不应将响应发送到客户端。