【问题标题】:How to correctly reroute arbitrary paths to files for Plug.Static files?如何正确地将任意路径重新路由到 Plug.Static 文件的文件?
【发布时间】:2016-07-08 03:11:28
【问题描述】:

我正在考虑跳过 Phoenix,因为我正计划为一个使用一些 API 路由来表示其状态的 React 应用程序构建一个演示。似乎是一个熟悉底层技术的机会。

我想出了以下内容,但感觉非常“硬编码”,我很好奇是否有更优雅的解决方案来实现相同的目标。

defmodule DemoApp.Plug.ServeStatic do
  use Plug.Builder

  @static_opts [at: "/", from: "priv/static"]

  plug :default_index
  plug Plug.Static, @static_opts
  plug :default_404
  plug Plug.Static, Keyword.put(@static_opts, :only, ["error_404.html"])

  # Rewrite / to "index.html" so Plug.Static finds a match
  def default_index(%{request_path: "/"} = conn, _opts) do
    %{conn | :path_info => ["index.html"]}
  end
  def default_index(conn, _), do: conn

  # Rewrite everything that wasn't found to an existing error file
  def default_404(conn, _opts) do
    %{conn | :path_info => ["error_404.html"]}
  end
end

我们的想法是让/index.html 服务而不重定向,并在找不到任何内容时提供错误文件的内容,而不是最小响应“404 文件未找到”字符串。

有没有办法在不插入 Plug.Static 两次的情况下实现这一点,或者这是要走的路?稍后我还可以看到包罗万象的 :default_404 与我的 API 路由发生冲突,我不确定如何解决。

任何意见将不胜感激。谢谢!

【问题讨论】:

    标签: elixir phoenix-framework


    【解决方案1】:

    我会为此使用Plug.RouterPlug.Conn.send_file/5。这里有一些代码可以做你所做的,但更简洁:

    defmodule M do
      use Plug.Router
    
      plug Plug.Static, at: "/", from: "priv/static"
      plug :match
      plug :dispatch
    
      get "/" do
        send_file(conn, 200, "priv/static/index.html")
      end
    
      match _ do
        send_file(conn, 404, "priv/static/404.html")
      end
    end
    

    由于:match:dispatchPlug.Static 之后插入,priv/static 中的任何文件都将在返回到路由器之前提供服务,就像 Phoenix 一样。

    这些文件在priv/static:

    ➜ cat priv/static/404.html
    404.html
    ➜ cat priv/static/index.html
    index.html
    ➜ cat priv/static/other.html
    other.html
    

    这段代码的工作原理如下:

    ➜ curl http://localhost:4000
    index.html
    ➜ curl http://localhost:4000/
    index.html
    ➜ curl http://localhost:4000/index.html
    index.html
    ➜ curl http://localhost:4000/other.html
    other.html
    ➜ curl http://localhost:4000/foo
    404.html
    ➜ curl http://localhost:4000/foo/bar
    404.html
    ➜ curl http://localhost:4000/404.html
    404.html
    ➜ curl -s -I http://localhost:4000/foo | grep HTTP
    HTTP/1.1 404 Not Found
    ➜ curl -s -I http://localhost:4000/foo/bar | grep HTTP
    HTTP/1.1 404 Not Found
    ➜ curl -s -I http://localhost:4000/404.html | grep HTTP
    HTTP/1.1 200 OK
    

    【讨论】:

    • 谢谢,这正是我想要的!我检查了Plug.Router 文档,我正在使用 OP 中的内置管道,但完全忘记了我也拥有所有 Plug.Conn 方法。非常感谢。
    • 这种方法的一个问题是send_file 没有Plug.Static 的所有功能,例如设置像ETag 这样的缓存头。有没有办法只重写conn的路径并将修改后的请求转发到Plug.Static
    • 您也可以结合 Plug.Router 和 Plug.Static 来启用文件缓存:stackoverflow.com/a/51155884/285691
    猜你喜欢
    • 2016-10-20
    • 1970-01-01
    • 1970-01-01
    • 2014-12-23
    • 2010-11-07
    • 1970-01-01
    • 2015-08-30
    • 1970-01-01
    相关资源
    最近更新 更多