2016-07-08 38 views
0

我正在考慮跳過Phoenix,因爲我只是打算爲其狀態使用一些API路由的React應用程序構建一個演示。看起來像是一個熟悉底層技術的機會。如何正確地將任意路徑重新路由到Plug.Static文件的文件?

我想出了以下內容,但感覺非常「硬編碼」,我很好奇是否有一個更優雅的解決方案來實現相同的事情。

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兩次,或者這是要走的路?我也可以看到我的API路線後來碰到了這個問題,我不確定我會如何解決這個問題。

任何輸入將不勝感激。謝謝!

回答

3

爲此,我會使用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任何文件都將回落至路由器之前送達,就像鳳凰一樣。

這些文件在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 
+0

謝謝,這正是我一直在尋找!我檢查了'Plug.Router'文檔,並且在OP中使用了構建的管道,但完全忘記了我也擁有了所有的'Plug.Conn'方法。非常感激。 – MildlySerious

+1

這種方法的一個問題是'send_file'沒有'Plug.Static'的所有功能,比如設置像'ETag'這樣的緩存頭文件。有沒有辦法重寫conn的路徑並將修改後的請求轉發給'Plug.Static'? – denisw

相關問題