3

使用 rebar3 时如何为httpc的配置文件设置配置选项?

这是通过看起来像这样的唯一示例:erl -config inets.config

[{inets, 
[{services,[{httpc,[{profile, server1}]},
            {httpc, [{profile, server2}]}]}]
}].

我尝试将它应用到我的 rebar3 项目结构中。

代码

项目是使用 rebar3 创建的,具有标准的 OTP 布局:

rebar3 new release myapp

这是我的myapp/config/sys.config

[
  { myapp, []},
  {inets, [{services, [{httpc, [{profile, myapp}]}]}]}
].

rebar.config

{erl_opts, [debug_info]}.
{deps, []}.

{relx, [{release, { myapp, "0.1.0" },
         [myapp,
          sasl]},

        {sys_config, "./config/sys.config"},
        {vm_args, "./config/vm.args"},

        {dev_mode, true},
        {include_erts, false},

        {extended_start_script, true}]
}.

{profiles, [{prod, [{relx, [{dev_mode, false},
                            {include_erts, true}]}]
            }]
}.

这是我myapp.app.src的完整性文件:

{application, myapp,
 [{description, "An OTP application"},
  {vsn, "0.1.0"},
  {registered, []},
  {mod, { myapp_app, []}},
  {applications,
   [kernel,
    stdlib
   ]},
  {env,[]},
  {modules, []},

  {maintainers, []},
  {licenses, []},
  {links, []}
 ]}.

要求

这是我试图从 rebar 的外壳发出的请求:

$ ./rebar3 shell
1> ===> Booted myapp
1> ===> Booted sasl
...
1> httpc:request( "http://reddit.com", myapp).
** exception exit: {noproc,
                    {gen_server,call,
                     [httpc_myapp,
                      {request,
                       {request,undefined,<0.88.0>,0,http,
                        {"reddit.com",80},
                        "/",[],get,
                        {http_request_h,undefined,"keep-alive",undefined,
                         undefined,undefined,undefined,undefined,undefined,
                         undefined,...},
                        {[],[]},
                        {http_options,"HTTP/1.1",infinity,true,
                         {essl,[]},
                         undefined,false,infinity,...},
                        "http://reddit.com",[],none,[],1478280329839,
                        undefined,undefined,false}},
                      infinity]}}
     in function  gen_server:call/3 (gen_server.erl, line 212)
     in call from httpc:handle_request/9 (httpc.erl, line 574)

这是没有配置文件的请求,用于检查 inets 是否确实有效:

2> httpc:request( "http://reddit.com").

=PROGRESS REPORT==== 4-Nov-2016::13:25:51 ===
          supervisor: {local,inet_gethost_native_sup}
             started: [{pid,<0.107.0>},{mfa,{inet_gethost_native,init,[[]]}}]

=PROGRESS REPORT==== 4-Nov-2016::13:25:51 ===
          supervisor: {local,kernel_safe_sup}
             started: [{pid,<0.106.0>},
                       {id,inet_gethost_native_sup},
                       {mfargs,{inet_gethost_native,start_link,[]}},
                       {restart_type,temporary},
                       {shutdown,1000},
                       {child_type,worker}]
{ok,{{"HTTP/1.1",200,"OK"},...
4

2 回答 2

5

rebar3 本身使用 inets http 客户端,因此当它在 shell 中启动您的应用程序时,inets 已经启动和配置。一种解决方法是在您的应用程序启动之前停止 inets,正如 rebar3 开发人员建议的那样(复制如下)。另一种是在控制台模式下启动您的版本:

./_build/default/rel/myapp/bin/myapp console

除此之外,您的项目还有另一个问题。您还没有告诉过您希望为您启动 inets。你应该有这一行myapp.src

{applications, [kernel, stdlib, inets]}

或者您可以在rebar.config发布部分列出 inets,告诉 relx 这个应用程序应该包含在发布中并在启动时启动。

{relx, [{release, { myapp, "0.1.0" }, [inets, myapp, sasl]} ]}

在 rebar3 shell 启动时停止加载 Inets

这是rebar3 邮件列表中 Fred Hebert的完整答案的副本:

我们确实需要 inets 来获取包,并且可能不会在所有用例中自动关闭它,因为如果用户应用程序不使用 inets,但仍要求在后续运行中获取包,这可能会影响 rebar3 代理的一般使用. 我建议的解决方法是使用钩子脚本。钩子脚本在我们启动用户应用程序之前运行并且是常规的 escripts:

#!/usr/bin/env escript 
main(_) -> application:stop(inets). 

然后,您可以使用以下方法挂钩脚本:

{shell, [{script_file, "path/to/file"}]} 

在 rebar3.config 中,或使用

rebar3 shell --script_file test/check_env.escript
于 2016-11-05T07:00:28.760 回答
0

I can't find anything in the documentation to suggest that rebar.config can contain the application configuration you want.

Instead, application configuration is often kept in a configuration directory in your application, and like the example you gave says, you must use the -config flag when launching erl to point to the configuration file.

If you use rebar3 for making release and start your service by script made with relx (from _build/default/rel/<release_name>/bin/<release_name> by default) the application configuration file is passed to erl for you. If config file exist in your application directory, by default in config/sys.config, It will be regarded as application configuration, otherwise an empty configuration will be made. You can customize Its path by relax' release option sys_config.

For our software, we typically had a single config/sys.config file. The structure is the same as the config sample you have provided. Note that the configuration file can contain settings for many different services. For example, mixing inets with one of ours:

[{inets, [
     {services,[{httpc,[{profile, server1}]},
     {httpc, [{profile, server2}]}]}
 ]},
 {my_app, [
     {my_setting, "my value"}
 ]}
].

We launch with erl -config config/sys.config. This way if we need to set service configuration we can simply update our configuration file, which also houses the configuration specific to this application.

As far as I'm aware, this is the correct method to use. I have not been able to find documentation supporting any other way of doing this.

于 2016-11-03T02:55:46.053 回答