defmodule Plug.Static.IndexHtml do
@behaviour Plug
@moduledoc """
Serves `index.html` pages for requests to paths without a filename in Plug applications.
"""
@doc ~S"""
Initialize plug options
- at: The request path to reach for static assets, defaults to "/"
- default_file: Filename to serve when request path is a directory, defaults to "index.html"
## Example
iex> Plug.Static.IndexHtml.init(at: "/doc")
[matcher: ~r|/doc/(.*/)?|, default_file: "index.html"]
"""
def init([]), do: init(at: "/")
def init(at: path), do: init(at: path, default_file: "index.html")
def init(at: path, default_file: filename) do
path_no_slash = String.trim_trailing path, "/"
[matcher: ~r|#{path_no_slash}/(.*/)?|, default_file: filename]
end
@doc """
Invokes the plug, adding default_file to request_path and path_info for directory paths
## Example
iex> opts = Plug.Static.IndexHtml.init(at: "/doc")
iex> conn = %Plug.Conn{request_path: "/doc/a/", path_info: ["doc", "a"]}
iex> Plug.Static.IndexHtml.call(conn, opts) |> Map.take([:request_path, :path_info])
%{path_info: ["doc", "a", "index.html"], request_path: "/doc/a/index.html"}
"""
def call(conn, matcher: pattern, default_file: filename) do
if String.match? conn.request_path, pattern do
%{conn |
request_path: "#{conn.request_path}#{filename}",
path_info: conn.path_info ++ [filename]
}
else
conn
end
end
end