Как настроить Plug.Static без Phoenix

Я пытаюсь выяснить, как настроить Plug.Static без каких-либо других фреймворков (Phoenix, Sugar и т.д.); просто ковбой, плагин и эликсир. Я просто не знаю, как собрать все вместе в роутере.

  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. Объявление Plug.Static в правильном месте? Не должно ли быть после plug :dispatch?
  2. Нужно ли определять дополнительный маршрут
  3. С этой декларацией:
    1. какой URL-адрес, скажем, index.html?
    2. где в файловой системе должен быть расположен index.html

Я просто потерян.

Ответ 1

Посмотрите Документы Plug.Router для работы :match и :dispatch. :match попытается найти соответствующий маршрут, и :dispatch собирается его вызывать. Это означает, что Plug.Static в вашей настройке будет вызываться, только если у вас есть соответствующий маршрут в вашем маршрутизаторе, что не имеет смысла. Вы хотите plug Plug.Static перед всем. Помните, что plugs - это просто функции, которые вызывают в том порядке, в котором они объявлены.

Кроме того, ваша настройка Plug.Static выглядит нормально. Ваша текущая конфигурация будет обслуживать активы в "/pub", то есть "/pub/index.html" будет искать "priv/static/index.html" в вашем приложении. Подробнее здесь: http://hexdocs.pm/plug/Plug.Static.html

Ответ 2

Все, что сказал Хосе Валим. И вот самый простой пример:

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

Это будет обслуживать все статические файлы в "/path/to/static" в конечной точке "/".

Посмотрите на документы для получения дополнительных опций и более глубоких объяснений.

Ответ 3

Это тот ответ, который я искал.

В методе запуска приложения используйте Plug.Router с 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

Модуль маршрутизатора выглядит так:

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

Здесь запросы к "/static" пересылаются в модуль HttpServer.StaticResources, но сначала путь запроса изменяется для "/" и "/favicon.ico" с помощью plug (: redirect_index). Все статические файлы (*.html, *.ico, *.css, *.js и т.д.) Помещаются в местоположение по умолчанию (project_dir/priv/static).

Наконец, модуль StaticResource:

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