How to configure the Plug.Static without Phoenix

纵然是瞬间 提交于 2019-12-20 14:10:52

问题


I am trying to figure out how to configure Plug.Static without any other framework (Phoenix, Sugar, etc); just Cowboy, Plug and Elixir. I just don't know how to put things together in the Router.

  plug :match
  plug Plug.Static, at: "/pub", from: :cerber
  plug :dispatch

  get "/" do
    Logger.info "GET /"
    send_resp(conn, 200, "Hello world\n")
  end
  1. Is the declaration of Plug.Static at the right place ? Shouldn't it be after plug :dispatch ?
  2. Do I need to define an additional route
  3. With this declaration:
    1. what is the URL to reach, say index.html?
    2. where on the file system index.html should be located

I'm just lost.


回答1:


Take a look at Plug.Router docs for how :match and :dispatch works. :match will try to find a matching route and :dispatch is going to invoke it. This means Plug.Static in your setup will only be invoked if you have a matching route in your router, which doesn't make sense. You want plug Plug.Static before everything. Remember plugs are just functions that are invoked in the order they are declared.

Other than that, your Plug.Static setup seems ok. Your current configuration will serve assets at "/pub", meaning "/pub/index.html" will look for "priv/static/index.html" in your app. More info here: http://hexdocs.pm/plug/Plug.Static.html




回答2:


Everything that José Valim said. And here's a most simple example to add to it:

defmodule Server do
  use Plug.Builder
  plug Plug.Logger
  plug Plug.Static, at: "/", from: "/path/to/static"
end

This will serve all static files in "/path/to/static" at the "/" endpoint.

Have a look at the docs for more options and a deeper explanation.




回答3:


This is the answer I was looking for.

In the application start method use the Plug.Router with Cowboy:

defmodule HttpServer.Application do
  require Logger
  use Application

  def start(_type, _args) do
    children = [
      {Plug.Adapters.Cowboy2, scheme: :http, plug: HttpServer.Router, options: [port: 4002]}
    ]

    opts = [strategy: :one_for_one, name: HttpServer.Supervisor]

    Supervisor.start_link(children, opts)
  end
end

The router module looks like this:

defmodule HttpServer.Router do
  use Plug.Router

  plug(Plug.Logger)
  plug(:redirect_index)
  plug(:match)
  plug(:dispatch)

  forward("/static", to: HttpServer.StaticResources)

  get "/sse" do
    # some other stuff...
    conn
  end

  match _ do
    send_resp(conn, 404, "not found")
  end

  def redirect_index(%Plug.Conn{path_info: path} = conn, _opts) do
    case path do
      [] ->
        %{conn | path_info: ["static", "index.html"]}

      ["favicon.ico"] ->
        %{conn | path_info: ["static", "favicon.ico"]}

      _ ->
        conn
    end
  end
end

Here requests to "/static" are forwarded to the HttpServer.StaticResources module, but first, the request path is modified for "/" and "/favicon.ico" with plug(:redirect_index). All static files (*.html, *.ico, *.css, *.js etc.) are placed in the default location (project_dir/priv/static).

Finally, the StaticResource module:

defmodule HttpServer.StaticResources do
  use Plug.Builder

  plug(
    Plug.Static,
    at: "/",
    from: :http_server
  )

  plug(:not_found)

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


来源:https://stackoverflow.com/questions/32543265/how-to-configure-the-plug-static-without-phoenix

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!