问题描述
我正在使用Phoenix框架实现API服务器。 JSON API通过/api/<version>
URL提供。服务器还需要提供来自.html
的静态.css
(以及其他.js
,/
等)文件:它实际上是一个用另一种语言开发并编译的SPA。到HTML5,JS和CSS。该行为应为:
-
/
应该投放index.html
文件; -
/some/file.html
应该提供file.html
目录中的some
文件,前提是该路径存在,如果路径不存在则为404; - 诸如
/some/
之类的网址应发回403或404以阻止目录列表 -
/api
下的所有内容均由专用控制器进行管理。
该项目是使用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错误页面。 我只是不知道告诉凤凰网在什么地方以及如何发送回403或404(/
除外)。 - 在未退出的文件上调用URL不会发送回404,而是会发回Phoenix错误页面。我试图在
static
中创建一个router.ex
管道,但似乎流程没有到达那里。文档指出:如果找不到静态资产,Plug.Static
只会将连接转发到管道的其余部分。,但是我看不到将404答复放在何处。 。
这是我尝试过的两种配置:
Conf I
# 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)
...
Conf II
我从endpoint.ex
中删除了有关静态内容的所有内容,并在static
中添加了router.ex
管道
# router.ex
...
pipeline :static do
plug :put_secure_browser_headers
plug Plug.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 文件的唯一方法如下:
- 我不得不像您一样从 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
我不知道静态插头背后的具体机制是什么,但我发现这种解决方法对于我的用例是可以接受的。
我希望这也能帮到你。