Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Commits on Apr 27, 2015
  1. @capflam

    Check support for the SSL 'log_alert' option

    capflam authored
    This fix the commit 1bf94af for Erlang releases older than R16B02.
Commits on Oct 16, 2014
  1. @vinoski

    Add SSL protocol_version configuration element

    vinoski authored
    Add protocol_version configuration element to allow supported protocols for
    SSL servers to be specified.
    
    Also add a new unit test for protocol_version.
Commits on Sep 22, 2014
  1. @capflam

    Add 'honor_cipher_order' option in ssl part

    capflam authored
    This option can be used to set to true/false the 'honor_cipher_order' parameter
    on the ssl socket. This option was introduced in SSL application in Erlang/OTP
    17.0, so it will be ignored by Yaws for previous releases. When supported, this
    option is set by default to true.
Commits on Jul 7, 2014
  1. Do not set recbuf by default on listening sockets

    Christopher Faulet authored
    This patch removes a bug I experienced on FreeBSD during tests on the loopback
    interface because of its MTU. So, I don't really know why that happens on
    FreeBSD and not on Linux, but because loopback MTU is greater than the recbuf
    value (16K on loopback vs 8k in Yaws), if a client sends data, Yaws will read
    them very slowly.
    
    Furthermore, there is no good reason to tweak this value by default. And, if
    required, it is always possible to configure it.
  2. Massive autotools refactoring & cleanup

    Christopher Faulet authored
    Now, all makefile are generated by automake. This way, many things are more
    configurable and maintainable.
    
    Main (visible) changes:
    
     * Now, you can configure and compile Yaws outside the source directory. It is
       also possible to generate an archive for distribution, using the 'dist' target
       (from now, 'distcheck' target should always pass).
    
     * We track .erl dependencies using '-M*' flags of ERLC.
    
     * generated header 'yaws_configure.hrl' disappears. HAVE_SENDFILE,
       HAVE_ERLANG_SENDFILE and HAVE_CRYPTO_HASH macros are defined in ERLC flags.
    
     * yaws_generated:localinstall/0 function disappears (see comment about local
       install).
    
     * To create a windows installer, we just need to run the 'mkinstaller'
       target. Read win32/README.developer for details.
    
     * We use standard Erlang installation path for Yaws, relative to the erlang
       library directory (/usr/lib/erlang/lib). Now, '$(libdir)/yaws' is a link. We
       do the same for yapp application.
    
     * "local install" was removed. Now, to do a "developer install", we just need
       to set a prefix during the project configuration using --prefix option. So,
       you need to install yaws to test it.
    
     * DESTDIR variable is still supported.
    
     * scripts/make-release was rewritten to use 'dist' and 'mkinstaller' targets.
    
     * Installation of Yaws applications has slightly changed. Now they are
       installed in their own directory, in '$(localstatedir)/yaws'. So, chat
       application will be installed in '$(localstatedir)/yaws/chat', with 'www' and
       'ebin' subdirs.
    
    Main targets (others than all/install/clean....):
    
      * all           : compile Yaws
      * debug         : compile Yaws with debug flags
      * clean         : remove files produced by all or debug target
      * install       : do a proper install of Yaws
      * doc or docs   : build the documentation
      * check or test : launch tests
      * cleantest     : remove files produced by check target
      * dialyzer      : run dialyzer on Yaws
      * mkinstaller   : build an installer for windows
      * cleaninstaller: remove files produced by mkinstaller target
      * apps          : compile Yaws applications (chat,mail,wiki,yapp)
      * cleanapps     : remove files produced by apps target
      * installapps   : install Yaws applications
      * fullinstall   : install + installapps
      * fullclean     : clean + cleantest + cleanapps + cleaninstaller
    
      To install an application, run: (cd application/{APP} && make install)
    
    Of course, many things can be customized during configuration and Rebar still
    works as expected. To do an install with (almost) the same tree than with
    previous of Yaws, do:
    
      $> ./configure yawsdir=${prefix}/lib/yaws yappdir=${prefix}/lib/yapp \
            --sysconfdir=/etc --localstatedir=/var
      $> make install
    
    Here is the default installation tree on my debian:
    
       usr
        ├── lib
        │   └── erlang
        │       └── lib
        │           ├── yapp-0.4.2
        │           │   ├── doc/
        │           │   ├── ebin/
        │           │   ├── examples/
        │           │   └── priv/docroot/
        │           └── yaws-1.98
        │               ├── ebin/
        │               ├── include/
        │               └── priv/
        │               ├── examples/
        │
        ├── local/bin/yaws
        │
        ├── local/etc/init.d/yaws
        ├── local/etc/yaws/
        ├── local/etc/mail/yaws-webmail.conf
        │
        ├── local/lib/pkgconfig/yaws.pc
        ├── local/lib/yapp -> /usr/lib/erlang/lib/yapp-0.4.2
        ├── local/lib/yaws -> /usr/lib/erlang/lib/yaws-1.98
        │
        ├── local/share/doc/yaws/yaws.pdf
        ├── local/share/man/{man1,man5}/
        │
        ├── local/var/log/yaws
        ├── local/var/run/yaws
        └── local/var/yaws
            ├── chat/{ebin,www}
            ├── mail/{ebin,www}
            ├── wiki/{ebin,www}
            └── www
Commits on Apr 15, 2014
  1. @dumbbell

    Add a nslookup_pref global parameter

    dumbbell authored
    This parameter allows to change the name resolution and connection
    preference for fcgi servers and revproxy URLs. It takes a list of the
    form [inet | inet6].
    
    For instance, to perform only IPv4 resolution:
        nslookup_pref = [inet]
    
    To perform both IPv4 and IPv6, but try IPv6 first:
        nslookup_pref = [inet6, inet]
    
    The default value is [inet]. Therefore, the behavior remains the same
    with this addition.
    
    This parameter is used by two new functions:
        o  yaws:tcp_connect/{3,4}
        o  yaws:ssl_connect/{3,4}
    
    They are wrappers around gen_tcp:connect/{3,4} and ssl:connect/{3,4} and
    take care of connection retries for each configured family.
Commits on Feb 26, 2014
  1. Add 'secure_renegotiate' option in ssl part

    Christopher Faulet authored
    This option can be used to set to true/false the 'secure_renegotiate' parameter
    on the ssl socket.
Commits on Sep 19, 2013
  1. @capflam

    Add the way to configure the version of sendfile method to use

    capflam authored
    Now, at compile time, we only check if sendfile syscall and file:sendfile/5
    are supported. Then, dynamically, we can configure which version to use.
    This can be done using the directive large_file_sendfile. Supported values
    are:
    
     * erlang: if supported, use file:sendfile/5
     * yaws: if supported, use the Yaws sendfile linked-in driver
     * disable: do not use any sendfile method, but gen_tcp:send/2
    
    If an unsupported method is configured, we fall back on gen_tcp:send/2.
    
    file:sendfile/5 implementation is buggy (in R15 & R16). When async-threads
    are enabled, in efile driver, the tcp socket is set in blocking mode and the
    sendfile syscall is executed on an async-thread. So an unresponsive client
    could block it for a very long time and therefore block the async-thread.
    In this way, all async-threads could be easily blocked.
    So, by default, the use of sendfile is disable.
Commits on Sep 6, 2013
  1. @capflam

    Add support of many options for tcp/ssl sockets

    capflam authored
    By adding a "<listen_opts> ... </listen_opts>" block in vhosts
    configuration, it is possible to define some options to be set on listen
    sockets and, by inheritance, on accepted sockets. Supported options are
    (see inet:setopts for details):
    
      * buffer
      * delay_send
      * linger
      * nodelay
      * priority
      * sndbuf
      * recbuf
      * send_timeout
      * send_timeout_close
    
    send_timeout / send_timeout_close options could be very useful to handle
    unresponsive clients and thus avoid some sorts of DoS.
Commits on Jun 13, 2013
  1. Keep the original request in #arg{} and check it against auth rules

    Christopher Faulet authored
    Because the request can be rewritten, it could be useful to backup the
    original one. Appmods or Yaws scripts could access it by reading the field
    orig_reg in #arg{}. For CGI scripts, the variable REQUEST_URI is now built
    using the original request (SCRIPT_NAME, PATH_INFO and QUERY_STRING could
    be used to know the info about the rewritten request, if needed).
    
    The original request is also checked against the authorization rules. So, if
    the request is rewritten, Yaws will check the original request and the
    rewritten one. Access must be granted for both urls to accept the request.
Commits on Apr 27, 2013
  1. @capflam

    Add the global directive 'src_dir' to define source directories

    capflam authored
    Yaws will compile all erlang modules found in these directories. The
    compilation occurs when the configuration is loaded or reloaded. The
    include_dir directives are used to search for include files. Multiple
    src_dir directives may be used. There is no such directory configured by
    default.
  2. @capflam

    Add serveralias directive

    Christopher Faulet authored capflam committed
    Now it is possible to set alternate names for a virtual host. A server alias
    may contain wildcards:
     - '*' matches any sequence of zero or more characters
     - '?' matches one character unless that character is a period ('.')
    
    Here is an example:
    
      <server server.domain.com>
        serveralias = server server2.domain.com server2
        serveralias = *.server.domain.com *.server?.domain.com
        ...
      </server>
Commits on Mar 25, 2013
  1. @vinoski

    Move WebDAV to an appmod, the locking server to a runmod (tjeerd)

    vinoski authored
    All WebDAV functionality is moved to an appmod so the extension methods and
    additional response headers are not part of yaws_server.erl and yaws.erl
    anymore. Also the locking server is now a runmod so it is not started by
    the supervisor and can be used only when needed.
    
    Additionally the 100-Continue code is moved so it can be returned to all
    requests that contain a body.
    
    The WebDAV functionality is tested against the litmus test. All tests are
    passed, except the ones that require unsupported properties. The test shows
    this as a fail while returning 404 should be sufficient.
Commits on Feb 11, 2013
  1. Refactor WebSockets and add support of optional callback functions

    Christopher Faulet authored
    Main changes:
      * Fix some bugs about UTF-8 encoding and messages fragmentation
      * Add support of optional callback functions
      * Add support of many startup options
      * Add support of outgoing fragmented messages
      * Add a websocket testsuite
    
                                     - * -
    *** bug fixes ***
    
    First of all, an huge part of yaws_websocket.erl was rewritten to fix bugs
    about the messages fragmentation and the UTF-8 encoding of incoming text
    messages:
    
      * UTF-8 encoding
        before, when a text message was fragmented, only the first frame was
        checked and partial UTF-8 sequences were not supported. Now, checks
        are done on each message part and a partial UTF-8 sequence at the end
        of a frame is accumulated and checked with the next frame (for basic
        callback only).
    
      * Messages fragmentation
        for basic callback modules, because of a buggy mapping between frames
        and messages, the messages fragmentation was almost unusable. To fix
        this, the message handling was rewritten.
    
    Now, all tests in the autobahn testsuite[1] pass successfully.
    
                                     - * -
    *** Optional callback functions ***
    
    Then, from an idea of François de Metz[2], yaws_websocket module was
    extended to support optional callback functions. See the documentation for
    details (www/websockets.yaws).
    
    Quickly, optional callback functions are:
    
      * Module:init/1           (for basic and advanced callback modules)
      * Module:terminate/2      (for basic and advanced callback modules)
      * Module:handle_open/2    (for basic and advanced callback modules)
      * Module:handle_info/2    (for basic and advanced callback modules)
      * Module:handle_message/2 (for basic callback modules only, used in place
                                 of Module:handle_message/1)
    
    Thanks to Pablo Vieytes[3] which added handle_info to optional callback
    functions.
                                     - * -
    *** Startup options ***
    
    To start a websocket process a script must return the following term from
    its out/1 function:
    
      {websocket, CallbackMod, Options}
    
    where 'Options' is a (possibly empty) proplist. Following parameters are
    supported:
    
      * {origin, Orig}
      * {callback, Type}
      * {keepalive, Boolean}
      * {keepalive_timeout, Tout}
      * {keepalive_grace_period, Time}
      * {drop_on_timeout, Boolean}
      * {close_timeout, Tout}
      * {close_if_unmasked, Boolean}
      * {max_frame_size, Int}
      * {max_message_size, Int}
      * {auto_fragment_message, Boolean}
      * {auto_fragment_threshold, Int}
    
    See the documentation for details (www/websockets.yaws).
    
                                     - * -
    *** Outgoing fragmented messages ***
    
    A callback module can now send fragmented messages to clients using the
    record #ws_frame{}:
    
     #ws_frame{fin     = true,  %% true | false
               rsv     = 0,
               opcode,          %% text | binary | continuation...
               payload = <<>>}. %% binary(), unmasked data
    
    --
    [1] http://autobahn.ws/testsuite
    [2] #99
    [3] https://github.com/pvieytes
Commits on Jan 3, 2013
  1. Add access functions for #gconf{} and #sconf{} records

    Christopher Faulet authored
    Applications may want to retrieve information in it. yaws:gconf_*/1 and
    yaws:sconf_*/1 should be used in preference to a direct access to reduce
    the dependence of your code on these records. So internal modifications
    could be done avoiding the need to update and recompile your application.
    
    Update www/internals.yaws accordingly and remove dependency on 'yaws.hrl'
    in examples and applications. Add unit tests to check #gconf{} and #sconf{}
    setup.
  2. Add support of the 'Vary' header in response

    Christopher Faulet authored
    With this patch, Yaws will add 'Accept-Encoding' in 'Vary' header if the
    support of gzip compression is enabled or if the response is compressed.
    The 'Vary' header can be set using 'yaws:outh_set_vary(Fields)' or by
    returning '{header, {vary, Fields}}' from scripts (where Fields is a list
    of header names).
Commits on Nov 9, 2012
  1. Remove invalid macro in yaws.hrl

    Christopher Faulet authored
    ?sc_set_ssl is never used and rely on the undefined macro ?SC_SSL.
Commits on Oct 13, 2012
  1. @vinoski

    WebDAV compliancy rework (Tjeerd van der Laan)

    vinoski authored
    The WebDAV support is reworked and adds class 1, 2 and 3 compliancy
    which includes:
    
    * XML request body parsing and  multistatus responses
    
    * PROPFIND and PROPPATCH methods returning properties asked for
    
    * all RFC4918 properties, the Apache executable property plus some
      Microsoft extensions
    
    * locking mechanism (class 2 compliancy) on all destructive methods
    
    * If header parsing
Commits on Oct 9, 2012
  1. @vinoski

    add a configurable dispatch module

    vinoski authored
    Allow an application to supply its own dispatch module for a server by
    setting the new dispatchmod variable in the server config. The module is
    expected to export a dispatch/1 function that returns one of the following
    atoms:
    
    * done: this indicates the dispatch module has handled the request and sent
      the response, and Yaws should go look for a new request on this
      connection
    
    * closed: same as "done" but also indicates the dispatch module has closed
      the connection
    
    * continue: this tells Yaws to continue with the normal dispatch path
Commits on Jul 25, 2012
  1. @capflam

    Make the mime types mappings configurable

    Christopher Faulet authored capflam committed
    Now, it possible to customize the global mime types mappings and to overload
    it for each virtual server. It can be done using following directives in the
    global part or the server part of the configuration:
    
    * default_type: Defines the default mime type to be used where Yaws cannot
      determine it by its mime types mappings (default: text/plain).
      In the server part, this directive overloads the global one.
    
    * default_charset: Defines the default charset to be added when a response
      content-type is text/* (default: none). In the server part, this directive
      overloads the global one.
    
    * mime_types_file: Overrides the default mime.types file included with Yaws
      (default: ${PREFIX}/lib/yaws/priv/mime.types). In the server part, this
      directive overloads the global one but mappings defined in this file will
      not overload those defined by add_types directives in the global part.
    
    * add_types: Specifies one or more mappings between mime types and file
      extensions. More than one extension can be assigned to a mime type. If a
      mapping is defined in the global part and redefined in a server part using
      this directive, then the later is used. Else the global one is kept.
    
    * add_charsets: Specifies one or more mappings between charsets and file
      extensions. More than one extension can be assigned to a charset. If a
      mapping is defined in the global part and redefined in a server part using
      this directive, then the later is used. Else the global one is kept.
    
    Here is an example:
    
      default_type = text/html
    
      <server localhost>
          port = 8000
          listen = 0.0.0.0
          docroot = /var/www
          # nothing is overloaded in the vhost
      </server>
    
      <server localhost>
          port = 8001
          listen = 0.0.0.0
          docroot = /var/www
    
          # overload global configuration:
          default_type    = text/plain
          mime_types_file = /etc/mime.types
          add_types       = <text/xhtml, yaws> <application/x-test, tst test>
          default_charset = UTF-8
          add_charsets    = <ISO-8859-1, php html yaws> <US-ASCII, tst>
      </server>
    
    During Yaws compilation, a default module 'mime_types' is created using the
    default mime.types file. Then, when yaws starts up, this module is
    re-generated, re-compiled and loaded dynamically. The new module replaces the
    default one but the .beam file is unchanged. So if one of these steps failed,
    we fall back on the default module.
Commits on Jul 11, 2012
  1. Add index_files directive into the server part configuration

    Christopher Faulet authored
    This directive sets the list of resources to look for, when a directory is
    requested by the client. If the last entry begins with a "/", and none of
    the earlier resources are found, Yaws will perform a redirect to this uri.
    
    Default is:
      index_files = index.yaws index.html index.php
Commits on Jul 10, 2012
  1. Refactor Set-Cookie/Cookie header parsing to follow RFC6265

    Christopher Faulet authored
    RFC6265 obsoletes RFC2965 and RFC2109. #setcookie{} and #cookie{} are
    changed to reflect this new RFC. So, yaws_api:parse_set_cookie/1 and
    yaws_api:parse_cookie/1 are refactored accordingly:
    
    * yaws_api:parse_set_cookie/1: Because RFC2109 and RFC2965 are still used,
      we try to be backward compatible with these old RFCs. So this function
      returns a #setcookie{} record when only one cookie is found else it returns
      a list of #setcookie{} records.
      in RFC2109 and RFC2965, cookies are separated by comma. So, comma is
      forbidden in 'path-av' and 'extension-av' except for double-quoted value.
      The parsing are not really strict because of the compatibility and can lead
      to unwanted behaviors.
      Old attributes (like 'Comment' or 'Port') are still parsed and can be
      found into #setcookie.extensions field.
    
    * yaws_api:parse_cookie/1: This function follows the RFC6265, so all cookie
      attributes (like '$Domain' or '$Path') are parsed like any other cookie.
Commits on Jul 4, 2012
  1. @capflam

    Fix parse_set_cookie/1 and format_set_cookie/1 functions

    capflam authored
    1. According to the RFCs 2109 and 2965, multiple cookies can be set in a
    single 'Set-Cookie' header. So, yaws_api:parse_set_cookie/1 now returns a
    list of #setcookie{} records. If no cookie was found or if an error occurred,
    it returns []. The parsing is also improved.
    Note that this fix breaks the compatibility with previous versions.
    
    2. In yaws_api:format_set_cookie/1, options are now always formated as
    quoted-strings.
    
    3. 2 new functions are added, yaws_api:parse_cookie/1 and
    yaws_api:format_cookie/1, to parse and format 'Cookie' headers. To let these
    functions to work, the #cookie{} record was introduced.
    
    Documentation and testsuite are updated accordingly.
Commits on Jun 21, 2012
  1. @vinoski

    add reverse proxy intercept module capability

    vinoski authored
    Users can now specify an interception module that can rewrite requests and
    responses as they pass through the Yaws reverse proxy. See the
    documentation for details (yaws.conf.5 man page or the yaws.pdf file).
    
    Also add new set_header, get_header, and delete_header functions to the
    yaws_api module to allow intercept modules and arg rewriters to more easily
    examine and modify #headers{} records.
    
    Add new tests for the new header manipulation functions and for the reverse
    proxy interception feature.
Commits on May 11, 2012
  1. Add support for precompressed static files

    Christopher Faulet authored
    By setting use_gzip_static to true in deflate options, in a vhost
    configuration, It is possible to serve precompressed versions of
    static files. Yaws will look for precompressed files in the same
    location as original files that end in ".gz".
    
    Only files that do not fit in the cache are concerned and the mtime
    of a precompressed file must be higher than the one of original file.
  2. Improve how the responses compression is handled

    Christopher Faulet authored
    Among other things, we can now disable the compression in yaws scripts by
    returning '{header, {content_encoding, "identity"}}'.
    A bug was also fixed when part of a large file is requested. The response
    content length was calculated using the file size and not the part size.
Commits on May 3, 2012
  1. Make the parameter "x_forwarded_for_log_proxy_whitelist" obsolete

    Christopher Faulet authored
    This parameter is now ignored and throws a warning when yaws starts.
    If necessary, it can be replaced by a simple logger_mod on top of
    yaws_log. To explain how to write such module, an example was added
    into the www directory (www/logger_mod.yaws).
Commits on Apr 25, 2012
  1. Add options to configure deflate compression behaviour

    Christopher Faulet authored
    By adding "<deflate> ... </deflate>" structure in vhosts configuration,
    it is possible to configure how deflate compression will be applied
    and when it will come into effect. Now we can:
    
     * define the smallest response size that will be compressed
     * define the compression level to be used
     * specify the zlib compression window size
     * specify how much memory should be allocated for the internal
       compression state
     * choose the strategy used to tune the compression algorithm
    
    All these parameters are used when a zlib stream is initialized for
    compression.
    
    It is also possible to define all compressible mime types.
    Here is an example:
    
    <server localhost>
      ...
      deflate = true
      <deflate>
        min_compress_size = 4096
        compression_level = best_compression
        mime_types        = defaults, image/*
        mime_types        = application/xml, application/xhtml+xml, application/rss+xml
        mem_level         = 9
        strategy          = default
        window_size       = 15
      </deflate>
      ...
    </server>
  2. cosmetic comment and whitespace cleanup in yaws.hrl

    Christopher Faulet authored
Commits on Apr 11, 2012
  1. @vinoski
Commits on Mar 17, 2012
  1. @kalski @vinoski

    added soap12 capability

    kalski authored vinoski committed
Commits on Feb 2, 2012
  1. Allow the server signature to be defined per virtual server

    Christopher Faulet authored
    Now, we can use the 'server_signature' directive into the server part
    to overload the global one for specific virtual server.
Commits on Dec 18, 2011
  1. @jbothma @vinoski

    update WebSockets implementation to support RFC 6455

    jbothma authored vinoski committed
    This change allows websocket connections to be set up between browsers
    and the yaws server. RFC 6455 for WebSocket connections is supported,
    in addition to the hybi working group RFC drafts 10 to 17.
    
    The quickest way to try this out is by compiling yaws as usual, then
    visiting /websockets_example.yaws at the default local installation
    host. This can be done using Google Chrome 14+, Firefox 7+ or any
    other browser supporting WebSocket version 8 or above. Information
    about getting started with WebSockets using this implementation is
    given in /websockets.yaws.
    
    This drops support for the older draft RFCs, specifically those of the
    hixie working group which were previously supported by yaws but are
    significantly different from the hybi working group's specification.
    
    The interface for using WebSocket with yaws has changed
    somewhat. Instead of spawning a websocket owner process which
    maintains a server loop such as that shown in the old
    websockets_endpoint.yaws, the application developer now implements a
    callback module such as those in src/basic_echo_callback.erl or
    src/advanced_echo_callback.erl -- the difference being that the
    advanced callback style is only necessary if you need advanced
    features of WebSocket such as fragmented messages. One suggested way
    to deploy your callback module and its dependencies is as part of an
    application in an OTP release, with yaws as a dependency. Rebar can be
    used to build the dependencies, fetch and build yaws, and create a
    release which will ensure the modules are in the path of the runtime
    system.
    
    Most behaviour tested by the Autobahn test suite 0.43 pass when
    configured to connect to the /websockets_autobahn_endpoint.yaws and
    /websockets_example_endpoint.yaws over an unencrypted
    connection. Significantly, websocket connection closing is not
    implemented and the socket is left to be cleaned up by the Runtime
    System when either the connection is lost or the owning processes
    dies. Secondly, certain cases where websocket frames are fragmented
    within UTF-8 code points cause the check for valid text type messages
    to incorrectly fail the connection.
    
    Subprotocols are not currently supported.
    
    Augment yaws.tex with a new WebSocket Protocol chapter (Steve
    Vinoski).
Commits on Sep 26, 2011
  1. @vinoski

    add config setting for acceptor pool size

    vinoski authored
    Add new config setting to allow the size of the acceptor process pool
    to be set to something other than the default. The default size is the
    same as what it was prior to this change. Also add documentation for
    the new setting, and augment the yaws.conf.template with information
    about it.
Commits on May 24, 2011
  1. @vinoski

    add shaper directive to control access (capflam)

    Christopher Faulet authored vinoski committed
    inspired by the mod_bwshare module of Apache, add the shaper directive
    to control access to virtual servers. Access can be controlled based
    on the client's IP address. It is also possible to throttle HTTP
    requests based on the client's download rate. External modules used to
    shape the traffic must implement the new behaviour yaws_shaper.
Something went wrong with that request. Please try again.