【问题标题】:Is it possible to add YAWS appmods config at runtime?是否可以在运行时添加 YAWS appmods 配置?
【发布时间】:2017-03-30 04:00:51
【问题描述】:

我在生产环境的应用程序中嵌入了 YAWS,并使用函数yaws:start_embedded/4 来启动 YAWS。

下面是我的代码:

Id = "my_server",
GconfList = [{logdir, "./log"}, {id, Id}],  
SconfList = [{docroot, Docroot},
  {port, Port},
  {listen, Listen},
  {appmods, [      
    {"/rest", mod_rest, []},
    {"/file", mod_file, []}      
  ]}
],
yaws:start_embedded(Docroot, SconfList, GconfList, Id).

我想添加另一个 appmod,例如:{"/upload", mod_upload, []}

是否可以在运行时添加 appmods 而无需重新启动 YAWS?

【问题讨论】:

    标签: erlang yaws


    【解决方案1】:

    您可以在运行时添加 appmods,方法是首先检索当前配置,使用它来创建包含新 appmods 的新配置,然后设置新配置。

    1. 调用yaws_api:getconf/0得到一个三元组{ok, GlobalConf, ServerConfs},其中GlobalConf是全局Yaws配置,ServerConfs是Yaws服务器配置列表。全局conf是一个名为gconf的记录类型,服务器conf是一个名为sconf的记录类型;这两种记录类型都在yaws.hrl 头文件中定义。
    2. 通过服务器配置找到包含您要更改的应用程序模块的配置。这有点棘手,因为您正在处理一个列表列表,并且您需要保持整个数据结构的形状不变。
    3. 找到sconf 后,通过将新的appmod 添加到其当前的appmod 列表中,从中创建一个新的sconf 实例。 appmod 列表的每个元素都是一个元组,由 appmod 的 URL 路径和 appmod 模块的名称组成。 appmod 元组还可以选择包含第三个字段,该字段由要排除的第一个路径下的路径列表组成;更多详情请参见the Yaws appmod documentation 中exclude_paths 的描述。
    4. 将ServerConfs 中现有的sconf 值替换为您的新值。
    5. 调用yaws_api:setconf/2 设置新配置,将现有GlobalConf 作为第一个参数,将包含新sconf 的新ServerConfs 作为第二个参数。

    下面的am_extend 模块显示了如何执行此操作。它导出一个add/1 函数,该函数采用一个函数,该函数可以识别和增强您关心的特定服务器中的应用程序模块。

    -module(am_extend).
    -export([add/1]).
    
    add(AppmodAdder) ->
        {ok, GlobalConf, ServerConfs} = yaws_api:getconf(),
        NewServerConfs = add_appmod(ServerConfs, AppmodAdder),
        yaws_api:setconf(GlobalConf, NewServerConfs).
    
    add_appmod(ServerConfs, AppmodAdder) ->
        lists:foldl(fun(Val, Acc) ->
                            Acc ++ [AppmodAdder(A) || A <- Val]
                    end, [], ServerConfs).
    

    使用此代码的一个示例是将下面的函数作为AppmodAdder 参数传递给am_extend:add/1。对于此示例,我们正在寻找具有 appmod 路径 "/sse" 的服务器,因此我们可以将另一个 appmod 添加到该服务器的路径 "/sse2"。任何我们不关心的服务器配置都会原封不动地返回。

    -include_lib("yaws/include/yaws.hrl").
    
    add_sse2(#sconf{appmods=AM}=SC) ->
        case lists:keyfind("/sse", 1, AM) of
            false ->
                SC;
            _ ->
                SC#sconf{appmods=[{"/sse2", my_sse_module}|AM]}
        end.
    

    请注意,我们的 add_sse2/1 函数必须在编译时包含 yaws.hrl,以便它具有可用的 sconf 记录的定义。

    【讨论】:

    • 我试过你提供的代码,它可以工作,并且不会影响其他连接,非常感谢!
    猜你喜欢
    • 2016-01-13
    • 2013-08-19
    • 2023-01-20
    • 2012-07-03
    • 2010-10-14
    • 2015-09-21
    • 2020-02-02
    • 1970-01-01
    • 2014-07-28
    相关资源
    最近更新 更多