Elixir Phoenix在运行时未加载Env变量



我在启动Phoenix服务器时试图从Mac中加载API密钥作为系统ENV。我出了什么问题?这些是我的步骤:

  1. 在我的Mac终端上:

    export API_NOTIFICATION_KEY=1234
    
  2. 在我的config.exs

    config :app, App.Notifications,
    notification_api_key: {:system, "API_NOTIFICATION_KEY"}
    
  3. 在我使用的模块中

    @api_notification_key Application.get_env(:app, App.Notifications)[:notification_api_key]
    
  4. 启动我的凤凰服务器

    mix phx.server
    

然后,当我尝试使API调用时,它显示为零。我是否缺少一个步骤来正确加载它?

属性在汇编过程中评估,因此:

@api_notification_key Application.get_env(:app, App.Notifications)[:notification_api_key]

将在编译时设置其值。我认为这不是您想要的,因此最好使用功能:

defp api_notification_key() do
  case Application.get_env(:test, App.Notifications)[:notification_api_key] do
    {:system, var_name} -> System.get_env(var_name)
    value -> value
  end
end

当我使用您的配置时,请尝试使用以下方式访问控制器中的密钥

Application.get_env(:app, App.Notifications)[:notification_api_key]

我得到:

{:system, "API_NOTIFICATION_KEY"}

因此,凤凰城没有查找Env变量。另一方面,如果我手动在配置中设置键,则是这样的:

config :app, App.Notifications,
    notification_api_key: 1234

然后我在控制器中获得1234。我读了一些内容,这些内容在某个时候会弃用{:system, "ENV_VAR"}的阅读环境变量,并且在文档中没有提及:system。我正在使用phoenix 1.4.6

根据本文,您可以在endpoint.ex中定义init/2函数,该功能将在运行时称为 - 仅在Phoenix应用程序开始之前,这意味着您可以在运行时间直接查找环境变量,该变量在运行时使用System.get_env/1。phoenix.endpoint文档中描述了init/2功能:

动态配置

用于动态配置端点,例如从 环境变量或配置文件,Phoenix调用 端点上的init/2回调,通过A:主管原子作为第一个 参数和端点配置为第二。

这是我想到的一个例子:

  def init(:supervisor, config) do
    #IO.inspect config, label: "config"
    #IO.inspect Application.get_all_env(:app1), label: "all"
    Application.put_env(:app1, :notification_api_key, 
        System.get_env("API_NOTIFICATION_KEY"),
        persistent: true
    )
    {:ok, config}
  end

然后在我的控制器中:

key = Application.get_env(
        :app1, App1.Notifications 
      )[:notification_api_key]
IO.inspect key, label: "key" 

,在服务器窗口中我看到:

key: 1234

您还应该意识到设置模块属性发生在编译时间,因此该行:

@api_notification_key Application.get_env(:app, App.Notifications)[:notification_api_key]

检索编译应用程序的系统的ENV变量。

我还尝试在控制器中设置模块属性:

@attr Application.get_env(
        :app1, App1.Notifications 
      )[:notification_api_key]

init/2在endpoint.ex中定义为上述,在我的控制器@ATTR中,nil nil nil nil nil nil nil nil nil。这是因为在编译时,尚未调用init/2,因此尚未设置:notification_api_key的值。

对我来说,在init/2中打电话给Application.put_env()不正确:

  def init(:supervisor, config) do
    Application.put_env(:app1, :notification_api_key, 
        System.get_env("API_NOTIFICATION_KEY"),
        persistent: true
    )
    {:ok, config}
  end

我认为我应该对config做些事情。这是另一个例子:

  def init(:supervisor, config) do
    IO.inspect config, label: "config"
    key = System.get_env("API_NOTIFICATION_KEY")
    new_config = Keyword.put_new(config, :notification_api_key, key)
    IO.inspect new_config, label: "inside init/2: new_config"
    {:ok, new_config}
  end

然后在我的控制器中:

IO.inspect(
  App1Web.Endpoint.config(:notification_api_key, :not_set), 
  label: "config"
)

在我的服务器窗口中,我看到:

config: "1234"

也有效。

最新更新