Yaws applications - Yapps

Yaws applications, Yapps, are actually ordinary Erlang/OTP applications with some optional information in their .app files and the web pages in the priv/docroot directory as default. The Yaws applications handler takes care of adding, and removing, the applications into a running server. When anyone access the server with an URL that matches the path for an added application, the docroot will be temporarily switched to where the web pages for that application are located.

Using the application handler

Installing

The application handler is named just yapp and is located in the directory yaws/applications/yapp. Yaws itself should have been built first, then in the yapp directory we do

  1. make
  2. make docs
    - if we want documentation
  3. make install
    - unless yaws was installed with make local_install

Setting up yaws.conf

First we include the ebin directory of the yapp handler application by adding the line

ebin_dir = /<yaws_root>/{applications,lib}/yapp/ebin

The "applications" part is used for a local_installed Yaws, and "lib" for a real installed one. Then we make sure that the yapp handler application is started when Yaws is started, by using the runmod directive

runmod = yapp

For every virtual server that we want to use yapps we add yapp as an arg_rewrite_mod and set the opaque parameter yapp_server_id to a unique name.

<server myexternalserver>
        port = 8000
        listen = 0.0.0.0
        docroot = /yawsdocrootpath/www
        arg_rewrite_mod = yapp
        <opaque>
           yapp_server_id = edo
        </opaque>
</server>

The web applications that are configured in the Yapp registry will be loaded into Yaws configuration when the yapp application is started. A prerequisite is that the applications are found in the Erlang code loader path. There is also an option to define yapps in yaws.conf for every server directly by using the opaque parameter bootstrap_yapps = webapp1, webapp2 etc.

For instance the yapp handler application (named yapp) is a yapp in itself, got it?, that provides a web gui to list active yapps and add/remove yapps from the registry. But since we can not add itself to the registry before it is added we have to bootstrap into the server when Yaws is started.

<server myinternalserver>
        port = 8001
        listen = 0.0.0.0
        docroot = /docrootpath/www
        arg_rewrite_mod = yapp
        <opaque>
           yapp_server_id = ido
           bootstrap_yapps = yapp
        </opaque>
</server>

Executing

The current default Yapp registry implementation uses Mnesia, we have made it easy to plug in other future registry implementations by configuring the yapp.app file, but Mnesia is recommended to be future proof for clustered application servers. In order to use mnesia one has to prepare a schema, we start an erlang shell with the same node name as Yaws is using:

erl -sname node_name
1> mnesia:create_schema([node()]).

(we can leave out the -sname options, then the mnesia schema name will be "nonode@nohost") then we exit and start yaws with the same name:

yaws -sname node_name

Now we can access the yapp handler web console from a browser with url:

http://myinternalserver:8001/yapp/

Making yapps

In order to make a "yapp" we need to know how to make an ordinary Erlang application, that is we will need a directory layout as specified by the design principles and a proper appname.app file in the ebin directory. Yaws itself or yapp are standard applications and can serve as introductionary examples.

Internal paths

Making paths to other documents in the same web application using root paths like href="/doc2.html" will not work since a yapp is always below the top. Instead use relative paths href="doc2.html" or use the prepath library function in any .yaws file: href=yapp:prepath(A) ++ "doc2.html", where A is a #arg record.

Appmods

The yapp handler takes care of throwing in "private" appmods for a yapp when it is accessed. The appmods modules are put in the applications ebin directory as any other Erlang module and configured in the .app file with the the environment variable yapp_appmods. For instance; if we have a yapp named yappx with root path "/yappx" and add:

  {env, [
         {yapp_appmods,[{"ctrl",yappx_controller}]}
        ]},

to the env part in the yappx.app file, an access to the URL http://servername/yappx/ctrl will cause a call to the yappx_controller:out/1 function, while http://servername/yappy/ctrl will not do it.

Opaque variables

In a similar way the yapp handler adds "private" opaques for a yapp with the the environment variable yapp_opaque. As an example ErlyWeb applications uses both appmods and opaques in yaws.conf. These can be put in the .app file instead if one makes a yapp of it:

 {application, myapp1,
 [{description,"myapp1 is an erlyweb yapp"},
  {vsn,"0.1"},
  {modules,[]},
  {registered, []},
%  {mod,{myapp1_app,[]}}, %% Only needed if the application needs to be started
  {env, [
         {yapp_docroot,"www"},
         {yapp_appmods,[{"erlyweb",erlyweb}]},
         {yapp_opaque,[{"appname","myapp1"}]}
        ]},
  {applications,[kernel,stdlib]}]}.

Also note that the docroot is www instead of the default priv/docroot in ErlyWeb applications.

Problems

Embedded ssi directives in ehtml parts will not work for now.

Future

It may look as an extra complexity to use Erlang applications but in this way we can benefit from Erlangs own framework for application handling. For instance, in the future we hope to add features for release handling to add/remove/upgrade/downgrade yapps on a running Yaws server, or even many clustered servers.

Valid XHTML 1.0!