是否可以在运行时添加 YAWS appmods 配置?
Is it possible to add YAWS appmods config at runtime?
我在生产环境的应用程序中嵌入了 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, []}
是否可以在不重启 YAWS 的情况下在运行时添加 appmods?
您可以在运行时添加 appmod,方法是首先检索当前配置,使用它创建包含新 appmod 的新配置,然后设置新配置。
- 调用
yaws_api:getconf/0
获取三元组{ok, GlobalConf, ServerConfs}
,其中GlobalConf
是全局Yaws配置,ServerConfs
是Yaws服务器配置列表。 global conf是一个名为gconf
的记录类型,server conf是一个名为sconf
的记录类型;这两种记录类型都在 yaws.hrl
头文件中定义。
- 通过服务器配置找到包含您要更改的 appmod 的配置。这有点棘手,因为您正在处理列表的列表,并且需要保持整个数据结构的形状不变。
- 找到
sconf
后,通过将新的 appmod 添加到其当前的 appmod 列表,从中创建一个新的 sconf
实例。 appmod 列表的每个元素都是一个元组,由 appmod 的 URL 路径和 appmod 模块的名称组成。 appmod 元组还可以选择包含第三个字段,该字段由要排除的第一个路径下的路径列表组成;有关详细信息,请参阅 the Yaws appmod documentation 中 exclude_paths
的说明。
- 用您的新值替换
ServerConfs
中现有的 sconf
值。
- 调用
yaws_api:setconf/2
设置新配置,将现有 GlobalConf
作为第一个参数传递,将包含新 sconf
的新 ServerConfs
作为第二个参数传递。
下面的 am_extend
模块显示了如何执行此操作。它导出一个 add/1
函数,该函数采用一个函数,该函数可以识别和扩充您关心的特定服务器中的 appmod。
-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).
使用此代码的一个示例是将下面的函数作为 am_extend:add/1
的 AppmodAdder
参数传递。对于此示例,我们正在寻找具有 appmod 路径 "/sse"
的服务器,因此我们可以将另一个 appmod 添加到该服务器的路径 "/sse2"
。我们不关心的任何服务器 conf 都将原封不动地返回。
-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
记录的定义。
我在生产环境的应用程序中嵌入了 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, []}
是否可以在不重启 YAWS 的情况下在运行时添加 appmods?
您可以在运行时添加 appmod,方法是首先检索当前配置,使用它创建包含新 appmod 的新配置,然后设置新配置。
- 调用
yaws_api:getconf/0
获取三元组{ok, GlobalConf, ServerConfs}
,其中GlobalConf
是全局Yaws配置,ServerConfs
是Yaws服务器配置列表。 global conf是一个名为gconf
的记录类型,server conf是一个名为sconf
的记录类型;这两种记录类型都在yaws.hrl
头文件中定义。 - 通过服务器配置找到包含您要更改的 appmod 的配置。这有点棘手,因为您正在处理列表的列表,并且需要保持整个数据结构的形状不变。
- 找到
sconf
后,通过将新的 appmod 添加到其当前的 appmod 列表,从中创建一个新的sconf
实例。 appmod 列表的每个元素都是一个元组,由 appmod 的 URL 路径和 appmod 模块的名称组成。 appmod 元组还可以选择包含第三个字段,该字段由要排除的第一个路径下的路径列表组成;有关详细信息,请参阅 the Yaws appmod documentation 中exclude_paths
的说明。 - 用您的新值替换
ServerConfs
中现有的sconf
值。 - 调用
yaws_api:setconf/2
设置新配置,将现有GlobalConf
作为第一个参数传递,将包含新sconf
的新ServerConfs
作为第二个参数传递。
下面的 am_extend
模块显示了如何执行此操作。它导出一个 add/1
函数,该函数采用一个函数,该函数可以识别和扩充您关心的特定服务器中的 appmod。
-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).
使用此代码的一个示例是将下面的函数作为 am_extend:add/1
的 AppmodAdder
参数传递。对于此示例,我们正在寻找具有 appmod 路径 "/sse"
的服务器,因此我们可以将另一个 appmod 添加到该服务器的路径 "/sse2"
。我们不关心的任何服务器 conf 都将原封不动地返回。
-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
记录的定义。