2

我正在使用 Phoenix 框架实现的 API 服务器。JSON API 由/api/<version>URL 提供。服务器还需要提供来自 的静态.html (和其他,,.css.js)文件/:它实际上是一个用另一种语言开发并编译成 HTML5、JS 和 CSS 的小型 SPA。行为应该是:

  • /应该送达index.html文件;
  • /some/file.html如果路径存在,则应该file.htmlsome目录中提供文件,如果不存在,则为 404;
  • 像这样的 URL/some/应该发回 403 或 404 以防止目录列表
  • 下面的一切/api都由专用控制器管理。

生成项目mix phx.new --no-ecto --no-html --no-gettext --no-webpack static 以摆脱.css.js文件和模板。我还priv/static为静态资产创建了一个目录。

我必须从 in 的参数列表中删除,only: ~w(css fonts images js favicon.ico robots.txt)才能在根 URL 处提供文件。除错误外,一切正常:plug Plug.Staticendpoint.ex

  • 上的请求/显示带有日志的 Phoenix 错误页面[debug] ** (Phoenix.Router.NoRouteError) no route found for GET / (StaticWeb.Router)。我添加了 {:plug_static_index_html, "~> 1.0"}所以我摆脱了这个问题,但调用会/subdir发回 Phoenix 错误页面。我只是不知道在哪里以及如何告诉 Phoenix 发回 403 或 404(除了/)。
  • 在非退出文件上调用 URL 不会返回 404,而是返回 Phoenix 错误页面。我试图在其中创建一个static管道,router.ex但似乎流程没有到达那里。文档指出:如果找不到静态资产,Plug.Static只需将连接转发到管道的其余部分。我看不到将 404 回复放在哪里

这是我尝试的两种配置:

配置我

# endpoint.ex
...
  # Serve at "/" the static files from "priv/static" directory.
  plug Plug.Static.IndexHtml, at: "/"
  plug Plug.Static,
    at: "/",
    from: :static,
    gzip: false
    # only: ~w(css fonts images js favicon.ico robots.txt)
...

会议二

我删除了所有关于静态内容的东西,endpoint.ex并在其中添加了一个static管道router.ex

# router.ex
...
  pipeline :static do
    plug :put_secure_browser_headers
    plug Plug.Static,
      at: "/",
      from: :static,
      gzip: false # ,
      # only: ~w(css fonts images js favicon.ico robots.txt)
    plug :not_found
  end
  
  scope "/", staticWeb do
    pipe_through :static
  end

  def not_found(conn, _) do
    send_resp(conn, 404, "not found")
  end
...

任何提示都会有所帮助。

2020 年 8 月 13 日更新

"/"在末尾添加了一条关于范围的全部规则router.ex,至少对于任何错误请求我都会收到 404。我只是想知道这一切有多干净......

# router.ex
...
  scope "/", AlaaarmWeb do
    match :*, "/*path", DefController, :error_404
  end
4

1 回答 1

2

我遇到了同样的问题,我试图提供使用 create-react-app 创建的 SPA,并将所有生成的文件放在priv/static文件夹中。

我发现从根路径提供静态 index.html 文件的唯一方法如下:

  • 我必须像您一样从 endpoint.ex 文件中删除only:选项Static.Plug
  • 按照这个答案:https ://stackoverflow.com/a/37568770/8620481 ,我采用了不同的策略。我没有尝试直接提供静态文件,而是将其内容作为字符串读取,然后从控制器提供。

特别是,在router.ex文件中,在"/"范围内,我定义了以下路线:

get "/", PageController, :index

在PageController中,我实现了index方法如下:

def index(conn, _params) do
  file = File.read!("priv/static/index.html")
  html(conn, file)
end

我不知道静态插头背后的机制是什么,但我发现这种解决方法对我的用例来说是可以接受的。

我希望这也能帮助你。

于 2021-05-01T19:44:19.443 回答