启动phoenix服务器时,我试图从Mac上将API密钥作为系统环境加载。我怎么了?这些是我的步骤:
在我的Mac终端上:
export API_NOTIFICATION_KEY=1234
在我的config.exs中
config :app, App.Notifications,
notification_api_key: {:system, "API_NOTIFICATION_KEY"}
在我使用它的模块中
@api_notification_key Application.get_env(:app, App.Notifications)[:notification_api_key]
启动我的凤凰服务器
mix phx.server
然后当我尝试进行API调用时,它显示为nil。我缺少要正确加载的步骤吗?
答案 0 :(得分:2)
在编译过程中评估属性,因此:
@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
答案 1 :(得分:0)
当我使用您的配置时,然后尝试使用以下命令访问控制器中的密钥:
Application.get_env(:app, App.Notifications)[:notification_api_key]
我得到:
{:system, "API_NOTIFICATION_KEY"}
因此phoenix没有查找env变量。另一方面,如果我在配置中手动设置密钥,如下所示:
config :app, App.Notifications,
notification_api_key: 1234
然后我在控制器中得到1234
。我读到一些东西说用{:system, "ENV_VAR"}
读取环境变量将在某个时候被弃用,并且我在文档中没有看到关于:system
的任何提及。我正在使用phoenix 1.4.6
。
根据this article,您可以在init/2
中定义一个endpoint.ex
函数,该函数将在运行时(在您的phoenix应用程序启动之前)被调用,这意味着您可以直接在运行时使用System.get_env/1
查找环境变量。 Phoenix.Endpoint docs中描述了init/2
函数:
动态配置
用于动态配置端点,例如从 环境变量或配置文件,Phoenix调用 端点上的init / 2回调,首先传递:supervisor原子 参数,端点配置为第二。
这是我想出的一个例子:
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]
如上在endpoint.ex中定义的和init/2
,以及在我的控制器中的@attr为nil-符合预期。这是因为在编译时尚未调用init/2
,因此尚未设置:notification_api_key
的值。
对我来说,在Application.put_env()
中调用init/2
感觉不对:
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"
所以也可以。