Commits on Jan 31, 2017
  1. Improve finding of private ports

    Since df1d7bf Yaws does not really open port 0 anymore, but tries to
    open one from 49152 onwards. This leads to "badbind" errors when e.g.
    executing multiple separate common test runs which use Yaws repeatedly.
    With this patch port 0 is opened instead, the port number retrieved, and
    closed again. This still is not completely safe, as the port could be
    taken by another application in the short time Yaws tries to listen on
    it again, but in practice I could not reproduce badbind errors.
    This approach leaves all advantages of df1d7bf, but also respects the
    local range for dynamic ports if specified, see
    Here is a test program which illustrates the problem. With this patch
    it runs continuously, without it stops with "badbind":
        trap "exit" INT TERM
        trap "kill 0" EXIT
        sim_testcase () {
            echo "ct run $1, testcase $2"
            output=`erl -pa ebin -noshell \
                -eval 'yaws:start_embedded("www/testdir", [{port, 0}], [], "'$1'")' \
                -eval 'timer:sleep(1000)' \
                -eval 'yaws:stop()' \
                -eval 'init:stop()' \
            if [[ $retval -ne 0 ]] ; then
                case $output in
                    *badbind*) echo "---> BADBIND <---" ;;
                    *) echo "$output" ;;
            return $retval
        sim_ct_run () {
            if sim_testcase $1 $n ; then
                sim_ct_run $1 $n
                kill 0
        set -m
            for tag in `seq 1 $NUM_CT_CONCURRENT` ; do
                sim_ct_run $tag 0 &
    weisslj committed with capflam Dec 12, 2016
  2. Get the port number from the Host header in yaws_api:request_url/1

    yaws_api:request_url/1 returns the parsed url (a #url{} record) that the
    client requested. field is get from the Host header, with a fallback
    on #sconf.servername. But #url.port was always retrived from the #sconf record
    without any checks on the Host header.
    With this patch, we try to extract the port number from the Host header and we
    fallback on the #sonf record only if there is no Host header. This way,
    yaws_api:request_url/1 is now returning the expected result.
    Fix #297. Thanks to Thomas Rackwitz for reporting the issue and working on it.
    capflam committed Jan 31, 2017
Commits on Dec 22, 2016
  1. Add supervisor for websocket callback processes

    Add the yaws_ws_sup simple_one_for_one supervisor to start and manage
    websocket callback handler processes.
    vinoski committed Dec 22, 2016
Commits on Nov 24, 2016
  1. SSL restart bug fixed

    Testing tools that stress SSL by sending junk, crashes SSL and yaws
    handles it nicely and restarts - all good. However we're counting
    number of connections erroneously when this happens, and eventually
    we run out of connections.
    If e.g max_connections is 1024, and SSL dies 1024 times, we get into
    "max connections reached" case.
    Found and fixed by Per Hedeland and Tail-f test team
    Klacke Wikstrom committed Nov 24, 2016
  2. Merge pull request #293 from weisslj/purge_yaws_dynopts

    Purge old code of yaws_dynopts after loading
    capflam committed on GitHub Nov 24, 2016
  3. Add scripts/systemd directory in the dist files

    A systemd service script was added to Yaws in 5b362c4; But it was not listed
    in the EXTRA_DIST varaible in scripts/
    [ci skip]
    capflam committed Nov 24, 2016
Commits on Nov 23, 2016
  1. Purge old code of yaws_dynopts after loading

    After starting Yaws the yaws_dynopts module has old code loaded:
        > erlang:check_old_code(yaws_dynopts).
    This causes Erlang/OTP monitoring systems like WombatOAM to raise an
        New alarm raised.
        Alarm id: {old_code,yaws_dynopts}.
        Additional information: <<"yaws_dynopts has old code loaded">>
    This patch purges the old code if the generated yaws_dynopts module is
    loaded. It cannot be done in the yaws_dynopts itself.
    weisslj committed Nov 23, 2016
Commits on Nov 18, 2016
  1. Update known dialyzer warning

    capflam committed Nov 18, 2016
  2. Fix dialyzer warnings about missing function

    On old Erlang/OTP releases, dialyzer fails because of missing functions. So we
    use a small workaround to bypass this issue. Instead of calling
    we call
       (fun module:function/N)(Args)
    Ref. #292
    capflam committed Nov 18, 2016
  3. Fix yaws_dynopts:compare_version/2 function

    It failed to compare versions of different length.
    Ref. #292
    capflam committed Nov 17, 2016
  4. Use a dynamic wrapper around ssl:connection_information/2

    This function has been introduced int Erlang/OTP 18. So for previous releases we
    need to have a wrapper function.
    Ref. #292
    capflam committed Nov 18, 2016
  5. Remove dynamic wrapper on rand_bytes/1 function

    Because crypto:rand_bytes/1 is deprecated since releases 19, we had added a
    wrapper function in yaws_dynopts module to use crypto:strong_rand_bytes/1 when
    possible. This was mandatory for R14 and R15 releases. But, since we have
    removed the support for these releases, the wrapper function is useless.
    Now, use use crypto:strong_rand_bytes/1 directly.
    Ref #292
    capflam committed Nov 17, 2016
  6. Fix a typo in yaws_ls

    capflam committed Nov 18, 2016
  7. Fix a typo in yaws_config

    capflam committed Nov 18, 2016
  8. Specify the port in proc_cleanup_SUITE testsuite

    Instead of using the default port (8000) in proc_cleanup_SUITE testsuite, we use
    a reserved port.
    capflam committed Nov 18, 2016
Commits on Oct 30, 2016
  1. Remove forgotten debug messages

    [ci skip]
    capflam committed Oct 30, 2016
  2. Add support of unicode characters in the configuration file

    By default, Erlang VM opens files using latin1 encoding. So it was impossible to
    use Docroot path with unicode characters. Though, there is an option to open
    file using unicode encoding.
    So now, it is possible to choose. With the yaws script, the option '--encoding'
    can be used to choose between latin1 and unicode. It is also possible to set the
    yaws application environment variable '{encoding, latin1|unicode}'.
    If you load the configuration file by hand, using yaws_config:load/1, you must
    set #env.encoding field. By default, latin1 is used.
    IMPORTANT: if you use Docroot path with unicode characters, you MUST use
    quotes. For example:
       docroot = "/tmp/ẅẅẅ"
    Ref: issue #290
    capflam committed Oct 30, 2016
Commits on Sep 22, 2016
  1. Preparing for 2.0.4

    Klacke Wikstrom committed Sep 22, 2016
Commits on Sep 20, 2016
  1. Add support for salted hashes in users credentials

    Now, it is possible to use a random salt to hash passwords. The salt must be
    provided, encoded in base64.
    In yaws configuration is must follow the format:
      user = "User:{Algo}$Salt$Hash"
    And in .yaws_file:
      {"User", "Algo", "Salt", "Hash"}.
    Using clear passwords or hashes without salt is still possible. Yaws startup
    script always uses salted hashes
    capflam committed Sep 13, 2016
  2. Remove support for Erlang/OTP R14 and R15 releases

    Now, R16B01 or higher is required.
    capflam committed Sep 13, 2016
  3. Add support of hashed passwords in yaws configuration and in .yaws_au…

    …th files
    Now, it is possible to used hashed password to define user's credential. In the
    yaws configuration, you can add following lines is <auth> sections:
      user = "User:{Algo}Base64Hash"
    and in .yaws_auth files:
      {"User", "Algo", "Base64Hash"}.
    Algo is one of: md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512
    and Base64Hash is the result of the hash functions, encoded in base64. For
      "/N4rLtula/QIYB+3If6bXDONEO5CnqBPrlURto+/j7k=" for "bar" password.
    yaws startup script has been updated to add a way to generate user's credential:
      $> yaws --auth --algo sha256 USER
      User's credential successfully generated:
          Put this line in your Yaws config (in <auth> section): user = "USER:{sha256}uqWglk0zIPvAxqkiFARTyFE+okq4/QV3A0gEqWckgJY="
          Or in a .yaws_auth file: {"USER", "sha256", "uqWglk0zIPvAxqkiFARTyFE+okq4/QV3A0gEqWckgJY="}.
    capflam committed Sep 13, 2016
  4. Remove sensitive information from crash messages in yaws_outmod

    This is probably a bad idea to keep yaws_outmd to print crash messages in
    production. This module was developped to ease debugging. But, to avoid
    problems, as far as possible, authentication information are removed, if any.
    capflam committed Sep 12, 2016
  5. Store the hash of passwords in #auth{} records instead of the clear v…

    So, if passwords leak (in logs, in crash messages or whatever), it will be
    significantly harder for hacker to use it. Passwords are hashed using SHA256.
    capflam committed Sep 12, 2016
  6. Revert "Move username/password tuples from server state to an ETS table"

    This reverts commit 37f44d0.
    There are many flaws with this patch. First, the ETS table used to store
    user/password tuples is always created during the configuration parsing (or
    during the loading in embedded mode). So during a configuration reload, the old
    server configurations and the new one never match because the table id in
    used, when Yaws configuration is reloaded, the servers are restarted, even when
    there is no changes.
    Then, the ETS table is owned by the process that parses the configuration (or
    that loads it in embedded mode). So the table is deleted when this process
    dies. This happens when the configuration is reloaded using the startup
    script. This is a huge bug, because after a reload, all requests requiring a
    user/password authentication will crash because the table is gone.
    And finally, ETS table owned by old server configurations is never garbaged.
    capflam committed Sep 12, 2016
  7. Fix a leak when a server conf is updated because of a forgotten ets t…

    …able ref
    Each server owns an ets table to store some information about files and scripts
    and to cache small static files. When the server configuration is updated, the
    old #sconf record is replaced by a new one and a new ets table is created. But
    the old one was never deleted. So we could have a proliferation of forgotten ets
    tables leading to a memoring leak after successive updates.
    So now, instead of creating a new ets table when a server configuration is
    updated, we keep the old one. This avoids useless creation of ets tables and
    fixes the memory leak.
    capflam committed Sep 12, 2016
  8. Support strong/basic_validation options in yaws_compile

    Because these options don't generate binary code, the corresponding '<erl>'
    block is ignored. So, in the result of yaws_compile:compile/2, following spec
        {mod, Line, Script, NumChars,  Mod, Fun}
    will be replaced by
        {skip, NumChars}
    capflam committed Sep 19, 2016
  9. Remove temporary files generated during scripts parsing when job is done

    When .yaws scripts are parsed, each "<erl>" block produces a temporary erlang
    module (i.e a .erl file). These modules are compiled and used during page
    Instead of keeping these files til the next parsing, we remove them just after
    the compilation.
    capflam committed Sep 16, 2016
  10. Support user-defined options to compile .yaws scripts

    The function yaws_compile:compile_file/2 has been exported. It can be used to
    set some additional compiler options. By default, following options are used:
      * [binary,return_errors] during normal scripts compilation, when yaws is
      * [binary,return_errors,return_warnings,debug_info] during a check
        (yaws --check)
    So the additional options must be compatible with these ones. For example, 'P',
    'S' or 'E' options must not be used. There is no check to validate provided
    capflam committed Sep 16, 2016
  11. Fix small typo in testsuites

    capflam committed Sep 15, 2016
  12. Rewrite yaws_compile module to improve .yaws script parsing

    yaws_compile modules has been rewritten from scratch to be more flexible. Now,
    it can handle following syntaxes:
        <erl>out(_A) -> {html, "test1"}. </erl>
        <b><erl>out(_A) -> {html, "test2"}. </erl></b>
          out(_A) -> {html, "test3"}.
    In addition, it support strange tag syntaxes with spaces and newlines, like:
           module =
           out(_A) -> {html, "test"}.
    The sames syntaxes are supported for verbatim blocks of course.
    Unknown attributes in erl tags (all except "module") are ignored instead of
    crashing the Yaws process. When a module name is provided for an erl block, we
    check it to be sure that it will not override an existing module (owned by
    another yaws script or a "real" module, like yaws !).
    About verbatim blocks, it is now possible to add HTML attributes that will be
    keep after substitution. For example:
         <verbatim class="code" id="listing-1">
    will be replaced by:
         <pre class="code" id="listing-1">
    Finally, about performance, the new parser tends to be faster in many cases when
    one file is compiled. But it is really faster when many scripts are compiled in
    parallel. The old parser used a global lock on the node. So when a script was
    parsed, all others was blocked. Now, a lock is set per script. So two different
    script can be parsed in same time.
    capflam committed Sep 14, 2016