José,
Thank you... your solution worked perfectly for the plug.
It does seem that the combination of being compiled + macros makes for some
tricky work arounds. I have another instance in our router.ex with a forward
which
I haven't looked into how to work around. If something is just compiled,
the lookup can happen in a function. But when it's compiled and a macro, it
gets tricky with some APIs. We lucked out that plug :atom exists to invoke
a function, as you recommended. I don't think that would work for forward
(honestly haven't dug into it yet, so maybe?).
I just read the thread "What is the difference between using..." Something
like on_init: {Demo.Web.Endpoint, :load_from_system_env, []} is NOT an
alternative solution to my PlugCanonicalHost question above, right?
I appreciate your help and admit I'm still getting my head around how best
to configure our Phoenix app, especially since we are most comfortable with
the 12-factor app style of configuration, which recommends loading from the
env. Additionally, we're deploying to Heroku and using pipelines to promote
our stage slug (compiled app) to production. Same code, different
configuration.
Cheers,
Christian
On Thursday, March 2, 2017 at 6:16:21 AM UTC-8, José Valim wrote:
>
> In your case, the simplest thing to do is to move the plug initialization
> and execution to runtime:
>
> defmodule HalfDome.Endpoint do
> use Phoenix.Endpoint, otp_app: :half_dome
>
> plug :canonical_host
>
> defp canonical_host(conn, _opts) do
> opts = Plug.CanonicalHost.init(canonical_host:
> System.get_env("CANONICAL_HOST"))
> PlugCanonicalHost.call(conn, opts)
> end
> end
>
>
> Now you will properly read the system environment every time and there is
> no need for {:system, "something"}.
>
> The {:system, _} tuple environment has been a workaround and right now we
> have better solutions to the problem. I have written about how Ecto and
> Phoenix, which provide stateful features, are tackling this problem here:
> https://elixirforum.com/t/what-is-the-difference-between-using-system-port-and-system-get-env-port-in-deployment/1975/12
>
> However, if the other application always reads from Application.get_env,
> then you can simply set the application environment directly with the
> desired above when your app starts:
>
> Application.put_env(:plug_canonical_host, :canonical_host,
> System.get_env("CANONICAL_HOST"))
>
>
> To sum the new approach up: runtime/dynamic configuration needs to be done
> at runtime, and not in the config files.
>
>
>
> *José Valim*
> www.plataformatec.com.br
> Skype: jv.ptec
> Founder and Director of R&D
>
> On Thu, Mar 2, 2017 at 2:26 AM, Christian Nelson <[email protected]
> <javascript:>> wrote:
>
>> The version of this issue I ran into today is with a 3rd party plug,
>> https://github.com/remiprev/plug_canonical_host. I wanted to do
>> something like this:
>>
>> defmodule HalfDome.Endpoint do
>> use Phoenix.Endpoint, otp_app: :half_dome
>>
>> plug PlugCanonicalHost, canonical_host: System.get_env("CANONICAL_HOST"
>> )
>>
>> #...
>> end
>>
>> But, between the compilation of the file and the "plug" macro expansion,
>> System.get_env("CANONICAL_HOST") is resolved at compile time. I'm pretty
>> new to Elixir and I tried 4-5 things to have the lookup be dynamic without
>> any luck.
>>
>> So, I submitted a pull request to that library
>> <https://github.com/remiprev/plug_canonical_host/pull/7> so that it
>> supports the {:system, "CANONICAL_HOST"} syntax. It was easy to do and
>> works. Unfortunately we have other situations where we want to do the same
>> thing and it's not easy to patch every library that's out there.
>>
>> Also, I noticed that in the phoenix code, many instances of {:system,
>> env_var} are flagged for deprecation in 1.4... which makes me think trying
>> to perpetuate this convention could be a bad idea.
>>
>> Is there some elixir-fu that would make it easy(ish) to fetch the
>> CANONICAL_HOST at runtime in the example above?
>>
>> Thanks!
>> Christian
>>
>> On Wednesday, March 1, 2017 at 9:26:01 AM UTC-8, Almas Sapargali wrote:
>>>
>>> Hello, I'd vote for this change too, actually found that and other
>>> discussion, when I was going to make exact same proposal, and just did a
>>> quick search first. Then only notable stopper I've seen is that values
>>> would be strong, whilist user may expect int/bool etc. I think we could
>>> handle this case by passing some typing info in first element, like
>>> {:system_int, "POOL_SIZE"} etc, which would evaluate to nil if env isn't
>>> set or not an integer.
>>>
>>>
>>> On Saturday, December 17, 2016 at 3:17:35 PM UTC+6, José Valim wrote:
>>> > There has been a couple discussions on the topic either here or on the
>>> issues tracker.
>>> >
>>> >
>>> > The consensus is that this problem needs to be solved but we are not
>>> quite sure how. The only way to support {:system, "DATABASE_URL"} in a way
>>> that it would also work for Erlang applications is by hijacking the
>>> application controller using private APIs. We could also try solve this
>>> exclusively for Elixir but then there would be gaps where it wouldn't be
>>> supported.
>>> >
>>> >
>>> > Ecto 2.1 is trying a new approach where the value is configured using
>>> a repository callback, that's what we will try to do when Phoenix 1.3 comes
>>> out and see where it will lead us to.
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> > José Valim
>>> >
>>> > www.plataformatec.com.br
>>> > Skype: jv.ptec
>>> > Founder and Director of R&D
>>> >
>>> >
>>> > On Sat, Dec 17, 2016 at 1:48 AM, Cory ODaniel <[email protected]>
>>> wrote:
>>> >
>>> > I've definitely run into issues where I need to pass an environment
>>> variable at run time, but an application that I use doesn't support the
>>> {:system, "DATABASE_URL"} or {:system, "PORT"} style environment variables
>>> that Ecto and Phoenix support.
>>> >
>>> >
>>> > I'm curious if it would be beneficial to add support in
>>> Application.get_env/2 that when the value that returns matches {:system,
>>> var} then System.get_env(var) would be called under the hood.
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> > --
>>> >
>>> > You received this message because you are subscribed to the Google
>>> Groups "elixir-lang-core" group.
>>> >
>>> > To unsubscribe from this group and stop receiving emails from it, send
>>> an email to [email protected].
>>> >
>>> > To view this discussion on the web visit
>>> https://groups.google.com/d/msgid/elixir-lang-core/9fd6e998-04d2-4d7d-87ee-34abb16ee779%40googlegroups.com.
>>>
>>>
>>> >
>>> > For more options, visit https://groups.google.com/d/optout.
>>>
>>>
>
--
You received this message because you are subscribed to the Google Groups
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/elixir-lang-core/dd63b674-35ed-4afe-833b-4080f197160b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.