Hey,
is there a way to configure Plug.Static
at runtime (right after boot)?
I have a usecase where the location of the files and the desired request path (:from
and :at
options) is only known after startup.
Hey,
is there a way to configure Plug.Static
at runtime (right after boot)?
I have a usecase where the location of the files and the desired request path (:from
and :at
options) is only known after startup.
This is going to be complicated because Plug.Static
uses pattern matching to only match against particular from
/ at
values. I guess you could write a custom plug that makes its decisions dynamically and eat the performance loss.
Performance is not a big deal here. So I might look into building my own version of Plug.Static
.
EDIT: Seems like it would be enough to create a wrapper plug that calls Plug.Static.call/2
with the conn and the dynamically created options.
Since this post’s title is very descriptive and the first one that comes up when you search about the topic on the forum, I want to document an alternative in case someone ends up here trying to find a solution. The documentation currently states that you can also pass a MFA tuple to Plug.Static
:
:from
- the file system path to read static assets from. It can be either: a string containing a file system path, an atom representing the application name (where assets will be served frompriv/static
), a tuple containing the application name and the directory to serve assets from (besidespriv/static
), or an MFA tuple.
This is also, exactly how Livebook does it (see):
plug Plug.Static,
at: "/",
from: {__MODULE__, :static_from, []},
gzip: true,
only: LivebookWeb.static_paths()
@doc false
def static_from(), do: Path.join(Livebook.Config.priv_path(), "static")
This means you can change static_from
to something like the following and resolve the path properly at runtime as well:
# endpoint.exs
def static_from(), do: Application.get_env(:app, :path)
# runtime.exs
config :app, path: System.get_env("RUNTIME_PATH")
Even where mfas are not explicitly allowed one can always wrap a plug, which does so:
That was my first instinct but interestingly enough, wrapping Plug.Static
and calling it with the exact same options wasn’t serving the files for me (an absolute path outside of the project). I stopped investigating once I read that you can pass an MFA to it.
I’m wondering if you called Plug.Static.init/1
still. The opts for call/2
are not always the same data passed on the plug
call.