如何使用 rebar3 配置 httpc 配置文件?

How to configure httpc profiles with rebar3?

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

这是唯一的 example 通过 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, []}
 ]}.

请求

这是我试图从钢筋 shell 提出的请求:

$ ./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"},...

我在文档中找不到任何内容表明 rebar.config 可以包含您想要的应用程序配置。

相反,应用程序配置通常保存在应用程序的配置目录中,就像您给出的示例所说的那样,启动时必须使用 -config 标志 erl 指向配置文件。

如果您将 rebar3 用于 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

对于我们的软件,我们通常只有一个 config/sys.config 文件。结构与您提供的配置示例相同。请注意,配置文件可以包含许多不同服务的设置。例如,将 inets 与我们的一个混合:

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

我们与 erl -config config/sys.config 一起发布。 这样,如果我们需要设置服务配置,我们可以简单地更新我们的配置文件,其中还包含特定于此应用程序的配置。

据我所知,这是正确的使用方法。我找不到支持任何其他方式的文档。

rebar3 本身使用 inets http 客户端,因此当它在 shell 中启动您的应用程序时,inets 已经启动并配置。一种解决方法是在您的应用程序启动之前停止 inets,as It's suggested by rebar3 developer(在下面复制)。另一个是在控制台模式下启动您的版本:

./_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 上加载 Inets shell 启动

这是来自 rebar3 邮件列表的 full answer 作者 Fred Hebert 的副本:

We do need inets for package fetching and will likely not turn it off automatically for all use cases as this could compromise general usage of the rebar3 agent in case where the user application does not use inets, but still asks to fetch packages in a subsequent run. The workaround I would suggest would be to use a hook script for it. Hook scripts run before we boot user applications and are regular escripts:

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

You can then hook the script in with:

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

in rebar3.config, or with

rebar3 shell --script_file test/check_env.escript