如何正确地将任意路径重新路由到Plug.Static文件的文件?

Mil*_*ous 1 elixir phoenix-framework

我正在考虑跳过凤凰城,因为我只打算为React应用程序构建一个演示程序,该应用程序使用一些API路由作为其状态.似乎是一个熟悉底层技术的机会.

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

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
Run Code Online (Sandbox Code Playgroud)

这个想法是让/服务index.html没有重定向,并在找不到某些东西时提供错误文件的内容,而不是最小的响应"404 file not found"字符串.

有没有办法实现这一点,而无需插入Plug.Static两次,或者这是要走的路?我:default_404后面也可以看到catchall 与我的API路径发生冲突,我不知道如何解决这个问题.

任何输入都将非常感激.谢谢!

Dog*_*ert 6

我会用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
Run Code Online (Sandbox Code Playgroud)

当插入:match:dispatch插入之后Plug.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
Run Code Online (Sandbox Code Playgroud)

以下是此代码的工作原理:

? 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
Run Code Online (Sandbox Code Playgroud)

  • 这种方法的一个问题是`send_file`没有`Plug.Static`的所有功能,比如设置像`ETag`这样的缓存头.有没有办法只重写conn的路径并将修改后的请求转发给`Plug.Static`? (2认同)