Permalink
Browse files

improved embedded support

Add yaws_api:embedded_start_conf functions that take the same
arguments as yaws:start_embedded but instead of starting the yaws
application, return the gconf, sconf, and supervisor child specs
corresponding to the supplied arguments. When the application doing
the embedding is ready to start yaws, it can use the child specs to
start yaws under its own supervisors, and can then pass the gconf and
sconf to yaws_api:setconf to configure yaws. This approach gives the
application more control over how yaws is started and supervised.

Reimplement yaws:start_embedded in terms of the new
yaws_api:embedded_start_conf, maintaining backward compatibility.

Change www/embed.yaws and its example ybed code to describe the new
yaws_api:embedded_start_conf functions.

Updated web documentation and the yaws.tex file.
  • Loading branch information...
1 parent 968de1b commit 6b26557b73c44706b2d51ad1e332fde60b3292d0 @vinoski vinoski committed Apr 10, 2010
Showing with 431 additions and 264 deletions.
  1. +90 −12 doc/yaws.tex
  2. +4 −11 src/yaws.erl
  3. +34 −6 src/yaws_api.erl
  4. +16 −9 src/yaws_config.erl
  5. +16 −10 src/yaws_sup.erl
  6. +241 −195 www/embed.yaws
  7. +14 −21 www/ybed.erl
  8. +16 −0 www/ybed_sup.erl
View
102 doc/yaws.tex
@@ -1918,14 +1918,16 @@ \section{WWW-Authenticate}
into another - larger - application. The \Yaws\ source tree must be
integrated into the larger applications build environment. \Yaws\ is
then simply started by \verb+application:start()+ from the larger
-applications boot script.
+applications boot script, or the \Yaws\ components needed for the
+larger application can be started individually under the application's
+supervisor(s).
-By default \Yaws\ reads its configuration data from a config file, the
-default is "/etc/yaws.conf". If \Yaws\ is integrated into a larger
-application that application typically has its configuration data kept
-at some other centralized place. Sometimes we may not even have a file
-system to read the configuration from if we run a small embedded
-system.
+By default \Yaws\ reads its configuration data from a config file, the
+default is "/etc/yaws.conf". If \Yaws\ is integrated into a larger
+application, however, that application typically has its configuration
+data kept at some other centralized place. Sometimes we may not even
+have a file system to read the configuration from if we run a small
+embedded system.
\Yaws\ reads its application environment. If the environment key
\verb+embedded+ is set to t\verb+true+, \Yaws\ starts in embedded mode.
@@ -1936,17 +1938,93 @@ \section{WWW-Authenticate}
It is possible to call \verb+setconf/2+ several times to force \Yaws\ to
reread the configuration.
+\section{Creating Global and Server Configurations}
+The \verb+yaws_api:setconf/2+ function mentioned in the previous
+section takes two arguments:
+\begin{itemize}
+
+\item a \verb+#gconf+ record instance, specifying global
+ \Yaws\ configuration
+
+\item a list of lists of \verb+#sconf+ record instances, each
+ specifying configuration for a particular server instance
+
+\end{itemize}
+
+These record types are specified in \verb+yaws.hrl+, which is not
+normally intended for inclusion by applications. Instead,
+\Yaws\ provides the \verb+yaws_api:embedded_start_conf/1,2,3,4+
+functions that allow embedded mode applications to specify
+configuration data using property lists (lists of
+\verb+\{key, value\}+ pairs).
+
+The \verb+yaws_api:embedded_start_conf+ functions all return a tuple
+containing the following four items:
+
+\begin{itemize}
+
+\item the atom \verb+ok+.
+
+\item a list of lists of \verb+#sconf+ record instances. This variable
+ is intended to be passed directly to\\* \verb+yaws_api:setconf/2+ as
+ its second argument.
+
+\item a \verb+#gconf+ record instance. This variable is intended to
+ be passed directly to \verb+yaws_api:setconf/2+ as its first
+ argument.
+
+\item a list of supervisor child specification for the
+ \Yaws\ components the embedded mode application's configuration
+ specified should be started. This allows embedded mode applications
+ to start \Yaws\ under its own supervisors.
+
+\end{itemize}
+
+Note that \verb+yaws_api:embedded_start_conf+ does not actually start
+any servers, but rather it only returns the configuration information
+and child specifications needed for the embedded mode application to
+start and configure \Yaws\ itself.
+
+\section{Starting Yaws in Embedded Mode}
+
+An embedded mode application can start \Yaws\ in one of two ways:
+
+\begin{itemize}
+
+\item It can call \verb+yaws_api:embedded_start_conf+ to obtain
+ configuration and \Yaws\ startup information as described in the
+ previous section, start \Yaws\ under its own supervisors, and then
+ pass the global and server configuration settings to
+ \verb+yaws_api:setconf/2+.
+
+\item It can call \verb+yaws:start_embedded/1,2,3,4+, each of which
+ takes exactly the same arguments as the corresponding
+ \verb+yaws_api:embedded_start_conf/1,2,3,4+ function. Instead of just
+ returning start and configuration information, however,
+ \verb+yaws:start_embedded+ also starts and configures \Yaws\ , which
+ can be more convenient but does not allow the embedded mode
+ application any supervision control over \Yaws\ .
+
+\end{itemize}
+
+Both of these functions take care of setting the environment key
+\verb+embedded+ to \verb+true+. Neither approach requires any special
+settings in the embedded mode application's \verb+.app+ file nor any
+special command-line switches to the \Erlang\ runtime.
+
+For an example of how to use \verb+yaws_api:embedded_start_conf+ along
+with \verb+yaws_api:setconf+, please see the files
+\verb+www/ybed_sup.erl+ and \verb+www/ybed.erl+ in the
+\Yaws\ distribution.
\chapter{The config file - yaws.conf}
In this section we provide a complete listing of all possible
-configuration file options.
-The
- configuration contains two distinct parts a global part
- which affects all the virtual hosts and a server part
- where options for each virtual host is supplied.
+configuration file options. The configuration contains two distinct
+parts: a global part which affects all the virtual hosts and a server
+part where options for each virtual host is supplied.
\section{Global Part}
View
15 src/yaws.erl
@@ -128,19 +128,12 @@ start_embedded(DocRoot, SL) when is_list(DocRoot),is_list(SL) ->
start_embedded(DocRoot, SL, GL) when is_list(DocRoot),is_list(SL),is_list(GL) ->
start_embedded(DocRoot, SL, GL, "default").
-start_embedded(DocRoot, SL, GL, Id) when is_list(DocRoot),is_list(SL),is_list(GL) ->
- case application:load(yaws) of
- ok -> ok;
- {error, {already_loaded,yaws}} -> ok;
- _ -> exit("Can not load yaws")
- end,
- ok = application:set_env(yaws, embedded, true),
- ok = application:set_env(yaws, id, Id),
+start_embedded(DocRoot, SL, GL, Id)
+ when is_list(DocRoot), is_list(SL), is_list(GL) ->
+ {ok, SCList, GC, _} = yaws_api:embedded_start_conf(DocRoot, SL, GL, Id),
application:start(yaws),
- GC = create_gconf(GL, Id),
- SC = create_sconf(DocRoot, SL),
yaws_config:add_yaws_soap_srv(GC),
- yaws_api:setconf(GC, [[SC]]).
+ yaws_api:setconf(GC, SCList).
add_server(DocRoot, SL) when is_list(DocRoot),is_list(SL) ->
SC = create_sconf(DocRoot, SL),
View
40 src/yaws_api.erl
@@ -44,7 +44,9 @@
replace_cookie_session/2, delete_cookie_session/1]).
-export([getconf/0,
- setconf/2]).
+ setconf/2,
+ embedded_start_conf/1, embedded_start_conf/2,
+ embedded_start_conf/3, embedded_start_conf/4]).
-export([set_status_code/1, reformat_header/1,
reformat_request/1, reformat_response/1, reformat_url/1]).
@@ -1922,7 +1924,37 @@ getconf() ->
gen_server:call(yaws_server, getconf, infinity).
-%% Function which invokeable typically from an index.yaws file
+embedded_start_conf(DocRoot) when is_list(DocRoot) ->
+ embedded_start_conf(DocRoot, []).
+embedded_start_conf(DocRoot, SL) when is_list(DocRoot), is_list(SL) ->
+ embedded_start_conf(DocRoot, SL, []).
+embedded_start_conf(DocRoot, SL, GL)
+ when is_list(DocRoot), is_list(SL), is_list(GL) ->
+ embedded_start_conf(DocRoot, SL, GL, "default").
+embedded_start_conf(DocRoot, SL, GL, Id)
+ when is_list(DocRoot), is_list(SL), is_list(GL) ->
+ case application:load(yaws) of
+ ok -> ok;
+ {error, {already_loaded,yaws}} -> ok;
+ _ -> exit("cannot load yaws")
+ end,
+ ok = application:set_env(yaws, embedded, true),
+ ok = application:set_env(yaws, id, Id),
+ ChildSpecs = yaws_sup:child_specs(),
+ GC = yaws:create_gconf(GL, Id),
+ SCList = case SL of
+ [] ->
+ [[]];
+ [Cnf|_] when is_tuple(Cnf) ->
+ [[yaws:create_sconf(DocRoot, SL)]];
+ [Cnf|_] when is_list(Cnf) ->
+ [[yaws:create_sconf(DocRoot, SLItem)] || SLItem <- SL]
+ end,
+ SoapChild = yaws_config:add_yaws_soap_srv(GC, false),
+ {ok, SCList, GC, ChildSpecs ++ SoapChild}.
+
+
+%% Function which is invoked typically from an index.yaws file
dir_listing(Arg) ->
dir_listing(Arg, ".").
dir_listing(Arg, RelDir) ->
@@ -1982,7 +2014,3 @@ redirect_self(A) ->
scheme_str = SchemeStr,
port = Port,
port_str = PortStr}.
-
-
-
-
View
25 src/yaws_config.erl
@@ -20,7 +20,7 @@
make_default_gconf/2, make_default_sconf/0,
add_sconf/1,
add_yaws_auth/1,
- add_yaws_soap_srv/1,
+ add_yaws_soap_srv/1, add_yaws_soap_srv/2,
search_sconf/2, search_group/2,
update_sconf/2, delete_sconf/2,
eq_sconfs/2, soft_setconf/4, hard_setconf/2,
@@ -80,16 +80,23 @@ load(E) ->
add_yaws_soap_srv(GC) when GC#gconf.enable_soap == true ->
- SoapStarted = (whereis(yaws_soap_srv) /= undefined),
- if (SoapStarted == false) ->
- Spec = {yaws_soap_srv, {yaws_soap_srv, start_link, [GC#gconf.soap_srv_mods] },
- permanent, 5000, worker, [yaws_soap_srv]},
- spawn(fun() -> supervisor:start_child(yaws_sup, Spec) end);
+ add_yaws_soap_srv(GC, true);
+add_yaws_soap_srv(_GC) ->
+ [].
+add_yaws_soap_srv(GC, false) when GC#gconf.enable_soap == true ->
+ [{yaws_soap_srv, {yaws_soap_srv, start_link, [GC#gconf.soap_srv_mods]},
+ permanent, 5000, worker, [yaws_soap_srv]}];
+add_yaws_soap_srv(GC, true) when GC#gconf.enable_soap == true ->
+ Spec = add_yaws_soap_srv(GC, false),
+ case whereis(yaws_soap_srv) of
+ undefined ->
+ spawn(fun() -> supervisor:start_child(yaws_sup, hd(Spec)) end);
true ->
ok
- end;
-add_yaws_soap_srv(_GC) ->
- ok.
+ end,
+ Spec;
+add_yaws_soap_srv(_GC, _Start) ->
+ [].
add_yaws_auth(SCs) ->
View
26 src/yaws_sup.erl
@@ -16,7 +16,7 @@
%% supervisor callbacks
-export([init/1]).
--export([get_app_args/0]).
+-export([get_app_args/0, child_specs/0]).
-import(lists, [member/2]).
@@ -34,26 +34,32 @@ start_link() ->
%%----------------------------------------------------------------------
init([]) ->
+ ChildSpecs = child_specs(),
+
+ %% The idea behind this is if we're running in an embedded env,
+ %% typically the supervisor above us wants to control the restarts.
+ %%
+ %% If we're running standalone --heart can restart the entire node
+ %% If heart is not used, we die.
+ %% 0, 1 means that we never want supervisor restarts
+ {ok,{{one_for_all, 0, 1}, ChildSpecs}}.
+
+%%----------------------------------------------------------------------
+%%----------------------------------------------------------------------
+child_specs() ->
YawsLog = {yaws_log, {yaws_log, start_link, []},
permanent, 5000, worker, [yaws_log]},
YawsServArgs = [_Env = get_app_args()],
YawsServ = {yaws_server, {yaws_server, start_link, YawsServArgs},
permanent, 5000, worker, [yaws_server]},
- %% and this guy, will restart auxilliary procs that can fail
+ %% and this guy will restart auxiliary procs that can fail
Sup = {yaws_sup_restarts,
{yaws_sup_restarts, start_link, []},
transient, infinity, supervisor, [yaws_sup_restarts]},
-
- %% The idea behind this is if we're running in an embedded env,
- %% typically the supervisor above us wants to control the restarts.
- %%
- %% If we're running standalone --heart can restart the entire node
- %% If heart is not used, we die.
- %% 0, 1 means that we never want supervisor restarts
- {ok,{{one_for_all, 0, 1}, [YawsLog, YawsServ, Sup]}}.
+ [YawsLog, YawsServ, Sup].
%%----------------------------------------------------------------------
%%----------------------------------------------------------------------
View
436 www/embed.yaws
@@ -1,160 +1,204 @@
<erl>
-out(A) ->
+out(A) ->
{ssi, "TAB.inc", "%%",[{"embed", "choosen"}]}.
</erl>
<div id="entry">
- <h1>Running yaws embedded in another larger application</h1>
+ <h1>Running yaws embedded in another application</h1>
<p>
- Yaws is ideal to embed inside another larger erlang application.
- Many typical erlang applications are control applications
- in need of a webgui specific for the actual application.
+ Yaws is ideal for embedding within another larger erlang application.
+ Many typical erlang applications are control applications in need of a
+ webgui specific to the actual application.
</p>
<p>In order to run Yaws inside another application, we need to
perform the following steps.
</p>
<ol>
- <li> <p>Either integrate yaws into the build system of the
- larger application or specifically provide the ebin path to
- yaws for the larger application. </p>
+ <li> <p>Either integrate Yaws into the build system of the larger
+ application, or specifically provide the <code>ebin</code> path to Yaws
+ for the larger application. </p>
</li>
- <li><p> Provide the application environment {embedded, true}
- to Yaws.</p>
+ <li><p> Provide the application environment <code>{embedded,
+ true}</code> to Yaws.</p>
</li>
</ol>
- <p> The large application typically has it's configuration
- data fed from internal databases, anyway it's usually not feasible
- to let Yaws read it's configuration data from /etc/yaws/yaws.conf.</p>
+ <p>Since the containing application typically has its configuration data
+ fed from internal databases or other sources, it's usually not feasible
+ to let Yaws read its configuration data from
+ <code>/etc/yaws/yaws.conf</code> when it's running in embedded mode.</p>
+
+ <p>To solve this, when Yaws is started in embedded mode, it doesn't read
+ its configuration from <code>/etc/yaws/yaws.conf</code>, but rather it
+ expects the larger application to feed its configuration through the
+ function call <code>yaws_api:setconf(GC, Groups)</code>. The two
+ arguments to this function are:</p>
+ <ul>
+ <li><p><code>GC</code>, which is a <code>#gconf{}</code> record</p></li>
+ <li><p><code>Groups</code>, which is a list of lists of <code>#sconf</code>
+ records</p></li>
+ </ul>
+
+ <p>The details of these records are unimportant, and we'll talk more
+ about the <code>yaws_api:setconf</code> function later. First, let's
+ discuss two ways applications can start Yaws in embedded mode.</p>
+
+ <h2>Starting under your own supervisor</h2>
+
+ <p>When not embedded, Yaws starts and runs as a regular application, but
+ typically an application embedding Yaws wants to control it under its own
+ supervisor(s). This means that an embedding application requires access
+ to the Yaws supervisor child specifications. The exact list of Yaws child
+ specifications depends on how the application intends to configure
+ Yaws.</p>
+
+ <p>The <code>yaws_api:embedded_start_conf/1,2,3,4</code> functions return
+ the information an application needs to configure Yaws and start it under
+ application supervisors. There are four variants of this function:</p>
- <p>To solve this, when Yaws is started in embedded mode, it doesn't
- read it's config from /etc/yaws/yaws.conf, rather it expects the larger application
- to feed it the Yaws configuration through the function call
- yaws_api:setconf(GC, Groups)
- </p>
-
- <p> The two arguments here are</p>
<ol>
- <li><p>GC is a #gconf{} record. The definition of the
- record is:</p>
-
-<div class="box">
- <verbatim>
-%% global conf
--record(gconf,{file,
- yaws_dir,
- tty_trace = false,
- trace,
- debug,
- logdir,
- ebin_dir = [],
- runmods = [],
- keepalive_timeout = 15000,
- max_num_cached_files = 400,
- max_num_cached_bytes = 1000000, %% 1 MEG
- max_size_cached_file = 8000,
- large_file_chunk_size = 10240,
- cache_refresh_secs = 30, % seconds (auto zero when debug)
- default_type = "text/html",
- timeout = 30000,
- include_dir = [],
- mnesia_dir = [],
- yaws, %% server string
- username, %% maybe run as a different user than root
- uid %% unix uid of user that started yaws
- }).
- </verbatim>
-</div>
-
- <p>The easiest way to figure out what the individual record
- fields mean is to have a look in the source file yaws_config.erl</p>
- </li>
-
- <li><p>Groups, is a list of lists of #sconf records.
- Yaws is capable of listening on several IP address and also
- do Virtual Hosting on each IP address.
- </p>
- <p>Each #sconf{} record describes one web server, whereas a list of
- #sconf{} records describe a web server Virt Hosting several different
- servers.
- </p>
- <p>
- The sconf record is defined as:</p>
-<div class="box">
- <verbatim>
-
--record(ssl,
- {
- keyfile,
- certfile,
- verify = 0,
- depth = 1,
- password,
- cacertfile,
- ciphers,
- cachetimeout}).
-
-
-
-
-%% a list of lists of #sconfs
-%% one list of #sconf's per listen ip
-
-
-%% server conf
--record(sconf,
- {port = 8000, %% which port is this server listening to
- rhost, %% forced redirect host (+ optional port)
- rmethod, %% forced redirect method
- docroot, %% path to the docs
- access_log = true, %% log acces
- listen = {127,0,0,1}, %% bind to this IP, {0,0,0,0} is possible
- servername = "localhost", %% servername is what Host: header is
- add_port = true, %% add port after reading config
- ets, %% local store for this server
- ssl,
- authdirs = [],
- partial_post_size = nolimit,
- appmods = [], %% list of appmod specs
- errormod_404 = yaws_404, %% the default 404 error module
- errormod_crash = yaws_404, %% use the same module for crashes
- arg_rewrite_mod = yaws,
- tilde_expand = false, %% allow public_html user dirs
- dir_listings = false, %% allow dir listings
- opaque = [], %% useful in embedded mode
- start_mod, %% user provided module to be started
- allowed_scripts = [yaws]
- }).
-
- </verbatim>
- </div>
- </li>
+ <li><p><code>yaws_api:embedded_start_conf/1</code> takes a single
+ argument, which is the document root path for the web server. This
+ variant uses default values for the <code>#gconf{}</code> and
+ <code>#sconf{}</code> records.</p></li>
+
+ <li><p><code>yaws_api:embedded_start_conf/2</code> takes a document
+ root, same as the first variant above, and also a server configuration
+ list. Such a list is either a list of properties for a single web
+ server, or a list of property lists for multiple servers. We'll explain
+ more about server configuration lists later, but for now note that
+ they're used to create suitable <code>#sconf{}</code> record
+ values. This variant uses a default value of the <code>#gconf{}</code>
+ record.</p></li>
+
+ <li><p><code>yaws_api:embedded_start_conf/3</code> takes a document
+ root and a server configuration list, same as the second variant above,
+ and also a global configuration list. Such a list is a property list
+ that provides global configuration settings for the embedded Yaws
+ instance, and is used to create a suitable <code>#gconf{}</code> record
+ value. We'll explain more about global configuration lists
+ later.</p></li>
+
+ <li><p><code>yaws_api:embedded_start_conf/4</code>, the final variant,
+ takes the same 3 arguments as the previous variant and also takes a
+ string to identify the embedded Yaws instance.</p>
</ol>
+ <p>The values returned from these functions are described later.</p>
+
+ <h3>Global configuration list</h3>
+
+ <p>A global configuration list is a property list that provides global
+ configuration settings for an embedded Yaws instance. Each property is a
+ tuple consisting of property name and value. Allowed property names are
+ those of the field names of the <code>#gconf{}</code> record type; see
+ <code>yaws.hrl</code> for more details. An example global configuration
+ list is shown below:</p>
+
+ <div class="box">
+ <pre>
+ [{logdir, "/var/log/my_server"},
+ {ebin_dir, ["/example1/ebin", "/example2/ebin"]},
+ {id, "my_server"}].
+ </pre>
+ </div>
+ <br/>
+
+ <h3>Server configuration list</h3>
+
+ <p>A server configuration list is a property list that provides
+ configuration settings for a given web server instance. Because Yaws
+ supports multiple servers simultaneously listening for requests, it's
+ possible to supply a list of server configuration lists so that multiple
+ servers can be configured in a single <code>yaws_api:setconf</code>
+ function call. Each element in a server configuration list is a tuple
+ consisting of property name and value. Allowed property names are those
+ of the field names of the <code>#sconf{}</code> record type; see
+ <code>yaws.hrl</code> for more details. An example server configuration
+ list is shown below:</p>
+
+ <div class="box">
+ <pre>
+ [{docroot, "/var/yaws/www"},
+ {port, 8080},
+ {listen, {127,0,0,1}},
+ {appmods, [{"/", my_appmod}]}].
+ </pre>
+ </div>
+ <br/>
+
+ <h3>Using embedded_start_conf</h3>
+
+ <p>The <code>yaws_api:embedded_start_conf/1,2,3,4</code> functions return
+ <code>{ok, SCList, GC, ChildSpecs}</code>. The latter three elements of
+ this tuple are described below.</p>
+
+ <ul>
+
+ <li><p><code>SCList</code> is a list of <code>#sconf{}</code> records
+ created using the values from the passed-in server configuration
+ lists</p></li>
+
+ <li><p><code>GC</code> is a <code>#gconf{}</code> record created using
+ the values from the passed-in global configuration list</p></li>
+
+ <li><p><code>ChildSpecs</code> is a list of supervisor child
+ specifications for the components of Yaws the application wants to
+ start</p></li>
+
+ </ul>
+
+ <p>Below is an example of using the
+ <code>yaws_api:embedded_start_conf/1,2,3,4</code> functions. It follows
+ the steps of obtaining the embedded configuration and child
+ specifications, starting the Yaws children under its own supervisor, and
+ then setting the Yaws configuration.</p>
+
+ <div class="box">
+ <pre>
+Id = "my_server",
+GconfList = [{logdir, "/var/log/my_server"},
+ {ebin_dir, ["/example1/ebin", "/example2/ebin"]},
+ {id, Id}],
+Docroot = "/var/yaws/www",
+SconfList = [{docroot, Docroot},
+ {port, 8080},
+ {listen, {127,0,0,1}},
+ {appmods, [{"/", my_appmod}]}],
+{ok, SCList, GC, ChildSpecs} =
+ yaws_api:embedded_start_conf(Docroot, SconfList, GconfList, Id),
+
+%% assume our supervisor is registered as my_sup
+[supervisor:start_child(my_sup, Ch) || Ch <- ChildSpecs],
+
+%% now configure Yaws
+yaws_api:setconf(GC, SCList),
+ </pre>
+ </div>
+
+ <h2>Starting yaws as an embedded application</h2>
+
+ <p>The four functions <code>yaws:start_embedded/1,2,3,4</code> start Yaws
+ in embedded mode using <code>application:start</code>. This approach
+ differs from the one above in that the embedding application need not
+ start any Yaws components under its own supervisors, nor does it need to
+ explicitly call <code>yaws:setconf</code> to set the Yaws
+ configuration. This approach is slightly simpler but also gives the
+ embedding application less control over Yaws.</p>
+
+ <p>The arguments for these four functions are identical to those for the
+ <code>yaws_api:embedded_start_conf/1,2,3,4</code> functions described
+ earlier.</p>
+
+ <p>See the example below:</p>
- <h2>The quick and easy way to get in the air</h2>
- <p>The following three functions yaws:start_embedded/1,2,3
- will start Yaws in embedded mode
- and provide the minimal information that Yaws requires.</p>
- <p>NB: With this method you don't need to specify any -yaws switches
- to your (system) start script.</p>
- <p>The only thing that you really need to specify is the "DocRoot", i.e
- the directory path to where your .html and .yaws files lives.
- You will then get the same default values for all the other configuration
- parameters as you can find in the <i>yaws.hrl</i> header file. So, for
- example: your server name will be: <i>localhost</i>, listen port: <i>8000</i>,
- etc.</p>
- <p>By using yaws:start_embedded/2 you can set some other values
- than the default ones for the server configuration (#sconf{}), and with
- yaws:start_embedded/3 you also can specify global configuration (#gconf{}.
- See the example below:</p>
<div class="box">
<pre>
%%
@@ -165,114 +209,116 @@ out(A) ->
%%
%% Alternative ways
%%
-1> yaws:start_embedded("/home/tobbe/docroot", [{servername, "sej"}, {listen, {0,0,0,0}}]).
+1> yaws:start_embedded("/home/tobbe/docroot",
+ [{servername, "sej"}, {listen, {0,0,0,0}}]).
-1> yaws:start_embedded("/home/tobbe/docroot",
+1> yaws:start_embedded("/home/tobbe/docroot",
[{servername, "sej"}, {listen, {0,0,0,0}}],
[{auth_log, false}, {copy_errlog, false}]).
</pre>
</div>
- <p>If you need more control on how to setup Yaws in embedded mode,
- then read on.</p>
+ <p>If you need more control on how to setup Yaws in embedded mode, use
+ the <code>yaws_api:embedded_start_conf</code> functions instead.
- <h2> A very small actual example </h2>
- <p>We provide a minimal example which "embeds" yaws in
- a normal Erlang shell.
- </p>
- <p>We start Erlang as:
- </p>
-<div class="box">
- <pre>
-# erl -pa /usr/local/lib/yaws/ebin -yaws embedded true -s ybed
- </pre>
-</div>
+ <h2>A very small example</h2>
- <p>The ybed module is very small and is named
- <a href="code.yaws?file=/ybed.erl">ybed.erl</a>
- </p>
+ <p>We provide a minimal example that embeds Yaws in a small Erlang
+ function.</p>
- <p>The above "erl" command line gives:
- </p>
+ <p>The <code>ybed</code> module is very small and is named <a
+ href="code.yaws?file=/ybed.erl"><code>ybed.erl</code></a>. It has an
+ accompanying simple supervisor named <a
+ href="code.yaws?file=/ybed_sup.erl"><code>ybed_sup.erl</code></a>.</p>
+
+ <p>If you compile both modules, you can run them as shown below:</p>
<div class="box">
<verbatim>
-# erl -pa /usr/local/lib/yaws/ebin -yaws embedded true -s ybed
-Erlang (BEAM) emulator version 5.3.b1 [source] [hipe]
-
-Eshell V5.3.b1 (abort with ^G)
-1>
-=INFO REPORT==== 25-Nov-2003::00:27:18 ===
-Yaws: Listening to 0.0.0.0:8888 for servers
- - foobar under /tmp
-
-1>
-</verbatim>
+1> {ok, Sup} = ybed_sup:start_link().
+{ok,<0.40.0>}
+2>
+=INFO REPORT==== 12-Apr-2010::02:42:09 ===
+Yaws: Listening to 0.0.0.0:8888 for <1> virtual servers:
+ - http://foobar:8888 under /tmp
+
+2>
+ </verbatim>
</div>
-
-<p>The actual web server then runs inside the larger application
-and _all_ that remain is to design a decent web GUI. This is
-harder than it might seem at a first glance. The configuration of the
-web server was programmatically fed into Yaws from the surrounding application,
-in this case, the Erlang shell + the module
-<a href="code.yaws?file=/ybed.erl">ybed.erl</a>
-</p>
-
+<p>The actual web server runs inside the larger application. The
+configuration of the web server was programmatically fed into Yaws from the
+surrounding application, in this case, the <a
+href="code.yaws?file=/ybed.erl"><code>ybed.erl</code></a> module. Note also
+how the Yaws children are started under the same <a
+href="code.yaws?file=/ybed_sup.erl"><code>ybed_sup.erl</code></a>
+supervisor as the code in the <code>ybed</code> module itself.
<h2>The opaque field in the sconf structure </h2>
-<p>The sconf structure (which is constructed by the program that
-starts and configures Yaws), contains a field, SC#sconf.opaque
-</p>
-
+<p>The <code>#sconf{}</code> record, which is constructed by the program
+that starts and configures Yaws, contains a field,
+<code>SC#sconf.opaque</code>.</p>
-<p> This field is passed on into the #arg{} record, so that any application
-specific configuration data which is needed by the .yaws pages that
-make up the web GUI application, is easily available there.
-</p>
+<p>This field is passed into the <code>#arg{}</code> record, so that any
+application specific configuration data which is needed by the
+<code>.yaws</code> pages that make up the web GUI application, is easily
+available there.</p>
-<p>In essence, if we construct the #sconf as</p>
+<p>In essence, if we construct the <code>#sconf</code> as</p>
<div class="box">
-<verbatim>
+ <verbatim>
SC#sconf{opaque = {mystruct, foobar},
.....
-</verbatim>
+ </verbatim>
</div>
-<p>A .yaws web page, can do:</p>
+<p>A <code>.yaws</code> web page can then do:</p>
<div class="box">
-<verbatim>
+ <verbatim>
out(Arg) ->
MyStruct = Arg#arg.opaque
.....
-</verbatim>
+ </verbatim>
</div>
-<p>Thus passing data from the surrounding applications configuration routines
- down to each .yaws web page.</p>
+<p>thus passing data from the surrounding applications configuration
+routines down to each <code>.yaws</code> web page.</p>
-<p>Another important fact to consider when choosing weather to run your yaws
-application as an embedded yaws app or not is that all the yaws control
-functions are disabled when we use yaws as an embedded web server. I.e
-yaws --ls, yaws --stop etc. This under the assumption that you already have support for this type of functionality in your application.
-</p>
+<p>Another important fact to consider when choosing whether to run your
+Yaws application as an embedded yaws app or not is that all the Yaws
+control functions are disabled when we use Yaws as an embedded web server,
+including capabilities such as <code>yaws --ls</code> and <code>yaws
+--stop</code>. Embedding thusassumes that you already have support for this
+type of functionality in your application.</p>
+
+<p>Finally, an interesting appmod definition that may apply to many
+embedded yaws installations is the <code>/</code> appmod with a set of
+exclude dirs. Here is an example server configuration list:</p>
-<p>Finally, an interesting appmod definition that may apply to many embedded yaws installations is that / appmod with a set of exclude dirs. Here is an example:
-</p>
<div class="box">
-<verbatim>
+ <verbatim>
+ [...
+ {appmods, [{"/", myapp, [["js"], ["top", "static"], ["icons"]]}]},
+ ...].
+ </verbatim>
+</div>
+
+<p>or in <code>#sconf{}</code> record terms:</p>
+
+<div class="box">
+ <verbatim>
SC#sconf{.....
appmods = {"/", myapp, [["js"], ["top", "static"], ["icons"]]},
....
-</verbatim>
+ </verbatim>
</div>
View
35 www/ybed.erl
@@ -1,26 +1,19 @@
-%%%-------------------------------------------------------------------
-%%% File : ybed.erl
-%%% Author : <klacke@hyber.org>
-%%% Description : Small embedded yaws example
-%%%
-%%% Created : 25 Nov 2003 by <klacke@hyber.org>
-%%%-------------------------------------------------------------------
-module(ybed).
-compile(export_all).
--include("/usr/local/lib/yaws/include/yaws.hrl").
-
start() ->
- application:start(yaws),
- Id = "default",
- GC = yaws_config:make_default_gconf(false, Id),
- SC = #sconf{port = 8888,
- servername = "foobar",
- listen = {0,0,0,0},
- docroot = "/tmp"},
- yaws_api:setconf(GC, [[SC]]).
-
-
-
-
+ {ok, spawn(?MODULE, run, [])}.
+run() ->
+ Id = "embedded",
+ GconfList = [{id, Id}],
+ Docroot = "/tmp",
+ SconfList = [{port, 8888},
+ {servername, "foobar"},
+ {listen, {0,0,0,0}},
+ {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()}.
View
16 www/ybed_sup.erl
@@ -0,0 +1,16 @@
+-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]}}.

0 comments on commit 6b26557

Please sign in to comment.