I embedded YAWS in my application at production environment, and I use the function yaws:start_embedded/4
to start YAWS.
Below is my code:
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).
I'd like to add another appmod, e.g: {"/upload", mod_upload, []}
Is it possible to add appmods at runtime without restarting YAWS?
You can add appmods at runtime by first retrieving the current configuration, using it to create a new configuration containing your new appmods, and then setting the new configuration.
yaws_api:getconf/0
to get a 3-tuple {ok, GlobalConf, ServerConfs}
where GlobalConf
is the global Yaws configuration and ServerConfs
is a list of lists of Yaws server configurations. The global conf is a record type named gconf
, and the server conf is a record type named sconf
; both of these record types are defined in the yaws.hrl
header file.sconf
, create a new sconf
instance from it by adding your new appmod to its current list of appmods. Each element of the appmod list is a tuple consisting of a URL path for the appmod and the name of the appmod module. An appmod tuple can also optionally contain a third field consisting of a list of paths under the first path to be excluded; see the description of exclude_paths
in the Yaws appmod documentation for more details.sconf
value in ServerConfs
with your new value.yaws_api:setconf/2
to set the new configuration, passing the existing GlobalConf
as the first argument and the new ServerConfs
containing your new sconf
as the second argument.The am_extend
module below shows how to do this. It exports an add/1
function that takes a function that can identify and augment the appmods in the particular server you care about.
-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).
An example of using this code is to pass the function below as the AppmodAdder
argument for am_extend:add/1
. For this example, we're looking for a server that has an appmod path "/sse"
so we can add another appmod to that server for the path "/sse2"
. Any server conf we don't care about is just returned unchanged.
-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.
Note that our add_sse2/1
function must be compiled with yaws.hrl
included so it has the definition for the sconf
record available.