我正在开发一个使用 Phoenix 框架实现的 API 服务器。 JSON API 由 /api/<version>
提供网址。服务器还需要提供静态.html
(以及其他, .css
、 .js
等)来自 /
的文件:它实际上是用另一种语言开发的一个小 SPA,并编译为 HTML5、JS 和 CSS。行为应该是:
-
/
应该服务于index.html
文件; -
/some/file.html
应该服务于file.html
文件来自some
路径存在则返回 404,如果不存在则返回 404; - 类似
/some/
的网址应发回 403 或 404 以防止目录列出 /api
下的所有内容由专用 Controller 管理。
该项目是用 mix phx.new --no-ecto --no-html --no-gettext --no-webpack static
生成的摆脱.css
, .js
文件和模板。我还创建了一个priv/static
静态资源目录。
我必须删除only: ~w(css fonts images js favicon.ico robots.txt)
来自plug Plug.Static
的参数列表在endpoint.ex
让根 URL 处的文件得到服务。除了错误之外,一切正常:
- 关于
/
的请求显示 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 回复。
这是我尝试过的两种配置:
session 一
# 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)
...
session 二
我从 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
最佳答案
我遇到了同样的问题,我试图提供使用 create-react-app 创建的 SPA,并将所有生成的文件放在 priv/static
文件夹中。
我发现从根路径提供静态index.html 文件的唯一方法如下:
- 我必须像您一样从端点.ex 文件中的
Static.Plug
中删除only:
选项。 - 按照这个答案:https://stackoverflow.com/a/37568770/8620481 ,我采取了不同的策略。我没有尝试直接提供静态文件,而是将其内容作为字符串读取,然后从 Controller 提供它。
特别是,在 router.ex
文件中的 "/"
范围下,我定义了以下路由:
get "/", PageController, :index
在PageController中,我实现了index方法,如下:
def index(conn, _params) do
file = File.read!("priv/static/index.html")
html(conn, file)
end
我不知道静态插头背后的机制到底是什么,但我发现这个解决方法对于我的用例来说是可以接受的。
希望这也能帮到你。
关于phoenix-framework - 从 Phoenix 框架/在 Phoenix 框架中提供静态 html(和其他),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63378017/