erlang - How do I start yaws to run in embedded mode? -
i've spent several hours trying troubleshoot issue using yaws documentation , web searches. existing threads here haven't helped me.
i new erlang , trying run yaws in embedded mode using sample code provided on http://yaws.hyber.org/embed.yaws. missing because cannot work. have 4 files:
ybed.app
{application, ybed_app, [ {description, "yaws embedded application test"}, {vsn, "0.1.0"}, {registered, []}, {applications, [kernel, stdlib, yaws]}, {mod, {ybed_app, []}}, {env, []} ]}.
ybed_app.erl
-module(ybed_app). -behaviour(application). %% application callbacks -export([start/2, stop/1]). start(_starttype, _startargs) -> case ybed_sup:start_link() of {ok, pid} -> {ok, pid}; other -> {error, other} end. stop(_state) -> ok.
ybed_sup.erl
-module(ybed_sup). -behaviour(supervisor). %% api -export([start_link/0]). %% supervisor callbacks -export([init/1]). start_link() -> supervisor:start_link({local, ?module}, ?module, []). init([]) -> ybed = {ybed, {ybed,start,[]}, permanent,2000,worker,[ybed]}, {ok,{{one_for_all,0,1}, [ybed]}}.
ybed.erl
-module(ybed). -compile(export_all). start() -> {ok, spawn(?module, run, [])}. run() -> id = "embedded", gconflist = [{id, id}], docroot = "/tmp", sconflist = [{port, 8000}, {servername, "foobar"}, {listen, {127,0,0,1}}, {docroot, docroot}], {ok, sclist, gc, childspecs} = yaws_api:embedded_start_conf(docroot, sconflist, gconflist, id), [supervisor:start_child(ybed_sup, ch) || ch <- childspecs], yaws_api:setconf(gc, sclist), {ok, self()}.
when compile (successfully) , try start application, return value:
{error,{not_loaded,yaws}}
when try run compiled ybed.erl, ybed:run(), get:
** exception error: undefined function yaws_api:embedded_start_conf/4 in function ybed:run/0 (src/ybed.erl, line 16)
if start yaws before start application, still doesn't work.
i not trying build releases yet, compile , test yaws in embedded mode. can tell me i'm missing?
thanks in advance
when error
** exception error: undefined function yaws_api:embedded_start_conf/4 in function ybed:run/0 (src/ybed.erl, line 16)
you don't have yaws_api.beam
in code
server search path. start erl
proper -pa
argument or call code:add_patha/1
in application initialization if not planning use embedded mode.
btw there neat way how start yaws
under own supervisor described in yaws
documentation without complete code here go in 1 module , neat debugging resource , preparation rest servicing.
-module(ybed_yaws). -behaviour(supervisor). -include_lib("yaws/include/yaws_api.hrl"). %% api -export([start_link/0]). %% supervisor callbacks -export([init/1]). %% internal functions export -export([init_yaws/1, out/1]). %%%=================================================================== %%% defaults %%%=================================================================== default_global() -> #{id => "yaws", logdir => "log"}. default_server() -> #{port => 9900, listen => {0,0,0,0}, docroot => "www", appmods => [{"/", ?module}]}. %%%=================================================================== %%% api functions %%%=================================================================== start_link() -> supervisor:start_link(?module, []). %%%=================================================================== %%% supervisor callbacks %%%=================================================================== init([]) -> {ok, {{one_for_all, 0, 1}, [#{id => init_yaws, start => {?module, init_yaws, [self()]}, restart => transient}] }}. %%%=================================================================== %%% internal functions %%%=================================================================== init_yaws(sup) -> {ok, proc_lib:spawn_link(fun() -> config(sup) end)}. ensure_dir(dir) -> {ok, app} = application:get_application(), d = filename:join([code:priv_dir(app), dir]) filelib:ensure_dir(filename:join([d, "foo"])), d. config(supervisor) -> #{id := id} = gcmap = default_global(), #{docroot := dr} = scmap = default_server(), docroot = ensure_dir(dr), {ok, sc, gc, childspecs} = yaws_api:embedded_start_conf( docroot, maps:to_list(scmap#{docroot => docroot}), maps:to_list(gcmap), id), [supervisor:start_child(supervisor, ch) || ch <- childspecs], yaws_api:setconf(gc, sc), ok. -compile({inline, [h/1, f/2]}). h(a) when is_atom(a) -> h(atom_to_binary(a, latin1)); h(s) -> yaws_api:htmlize(s). f(fmt, args) -> yaws_api:f(fmt, args). box(str) -> {'div',[{class,"box"}], {pre, [], h(str)}}. out(a) -> pathstring = case a#arg.pathinfo of undefined -> ""; p -> p end, path = string:tokens(pathstring, "/"), method = a#arg.req#http_request.method, out(a, method, path). out(a, method, path) -> {ehtml, {html, [], [{head}, {body, [], [ {h5, [], "paths:"}, {hr}, box(f("method = ~p~n" "path = ~p~n" "a#arg.querydata = ~p~n", [method, path, a#arg.querydata])), {h5, [], "headers:"}, {hr}, {ol, [], yaws_api:reformat_header( a#arg.headers, fun(h, v)-> {li, [], [h(h), ": ", {code, [], h(v)}]} end )} ]} ]} }.
note way how yaws
initialised in otp compliant transient process without gen_server
.
add {yaws, [{embedded, true}]}
.config
file keep yaws
application common services starting. work without not embedded.
Comments
Post a Comment