2016-04-19 11 views
1

Ich habe mehrere Stunden damit verbracht, dieses Problem mithilfe der Yaws-Dokumentation und Websuchen zu beheben. Die vorhandenen Threads hier haben mir nicht geholfen.Wie starte ich das Gieren im Embedded-Modus?

Ich bin neu zu Erlang und ich versuche, Gieren im Embedded-Modus mit dem Beispielcode http://yaws.hyber.org/embed.yaws. Ich vermisse etwas, weil ich es nicht zur Arbeit bringen kann. Ich habe vier Dateien:

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()}. 

Als ich es (erfolgreich) zusammenstellen und versuchen, die Anwendung zu starten, ich einen Rückgabewert erhalten:

{error,{not_loaded,yaws}} 

Wenn ich versuche, die kompilierte ybed.erl zu laufen, ybed: run(), erhalte ich:

Wenn ich giere vor dem Start der Anwendung, es funktioniert immer noch nicht.

Ich versuche nicht, Releases noch zu erstellen, nur kompilieren und testen im integrierten Modus. Kann mir jemand sagen, was ich vermisse?

Vielen Dank im Voraus

Antwort

0

Wenn Sie erhalten Fehler

** exception error: undefined function yaws_api:embedded_start_conf/4 
    in function ybed:run/0 (src/ybed.erl, line 16) 

Sie eindeutig nicht aus yaws_api.beam in Ihrem code server Suchpfad. Starten Sie Ihre erl mit ordnungsgemäßem -pa Argument oder rufen Sie code:add_patha/1 in Ihrer Anwendungsinitialisierung, wenn Sie nicht planen, Embedded-Modus zu verwenden.

BTW gibt es eine nette Möglichkeit, wie yaws unter Ihrem eigenen Supervisor beschrieben in yaws Dokumentation, aber ohne vollständigen Code, so hier gehen wir in einem Modul und mit sauberen Debugging-Ressource und Vorbereitung für REST-Service.

-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 
        )} 
     ]} 
     ]} 
    }. 

Beachten Sie die Art und Weise, wie yaws in OTP-konformen transienten Prozess initialisiert wird, aber ohne gen_server.

Fügen Sie {yaws, [{embedded, true}]} zu Ihrer .config Datei hinzu, um yaws Anwendung gemeinsame Dienste von Anfang an zu behalten. Es funktioniert auch ohne es, aber es wird nicht vollständig eingebettet sein.

+0

Danke! Es sind die kleinen Dinge für Noobs wie mich, wie alle Strahlengänge in die VM- oder Anwendungskonfiguration einzuschließen. Das hat mein Problem gelöst. – Will