Pound -- history of user-visible changes. 2023-10-13
See the end of file for copying conditions.

Pound is a continuation of the software originally developed by
Robert Segall at Apsis GmbH, which was officially discontinued
on 2022-09-19.  See the README file for details.

Please send pound bug reports to <gray@gnu.org>

Version 4.10, 2023-10-13

* Global "Backend" definitions

A "Backend" statement is allowed to appear in global scope.  In this
case it must be followed by a symbolic name, as in:

  Backend "name"
    ...
  End

The "name" must uniquely identify this backend among other backends
defined in global scope.

Global backend definitions can be used in services using the
"UseBackend" statement:

  UseBackend "name"

A single globally defined backend can be used in multiple services.
Its actual global definition may appear before as well as after the
service or services it is used in.

A named form of Backend statement is also allowed for use in
Service sections.  In this case it acts as "UseBackend" statement,
except that statements between "Backend" and "End" modify the
parameters of the backend for use in this particular service.  Only
two statements are allowed in such named form: "Priority" and
"Disabled".  The following example attaches the globally defined
backend "assets" to the service and modifies its priority:

  Backend "assets"
    Priority 8
  End

* Response header modification

The "Rewrite" statement accepts optional argument specifying whether
it applies to the incoming request, or to the response.  The following
statement applies to requests and is exactly equivalent to "Rewrite"
without argument:

  Rewrite request
    ...
  End

In contrast, the following statement:

  Rewrite response
    ...
  End

applies to the response (received from the regular backend or generated
by error backend).  In this form, the set of statements that can
appear inside the section (denoted by ellipsis above) is limited to
the following: "Not", "Match", "Header", "StringMatch", 
"SetHeader", and "DeleteHeader".  For example:

  Rewrite response
    Match
      Header "Content-Type: text/(.*)"
    End
    SetHeader "X-Text-Type: $1"
  End

The same applies to "Else" branches.

* Basic authentication

New request matching statement "BasicAuth" is implemented.  Its
syntax is:

  BasicAuth "FILE"

It evaluates to true, if the incoming request contains Authorization
header with scheme "Basic", such that user name and password obtained
from it match a line in the given disk file.  FILE must be a
plain-text file created with htpasswd(1) or similar utility, i.e. each
non-empty line of it must contain username and password hash separated
by a colon.  Password hash can be one of:

  . Password in plain text.
  . Hash created by the system crypt(3) function.
  . Password hashed using SHA1 algorithm and encoded in base64.
    This hash must be prefixed by {SHA}
  . Apache-style "APR1" hash.

Combined with the response rewriting described above, this can be
used to implement basic HTTP authentication in Pound as shown in
the following example:

  Service "auth"
      Not BasicAuth "/etc/pound/htpass"
      Rewrite response
          SetHeader "WWW-Authenticate: Basic realm=\"Restricted access\""
      End
      Error 401
  End

Unless the file name starts with a slash, it is taken relative to the
"IncludeDir" directory.  The file is cached in the memory on the first
authorization attempt, so that further authorizations do not result in
disk i/o operations.  It will be rescanned if Pound notices that the
file's modification time has changed.

* Bugfixes

** The Host statement assumes exact match by default.
** Fix detection of duplicate Transfer-Encoding headers.

Version 4.9, 2023-08-22

* HTTP request logging

In addition to six built-in log formats, you can define your own
"named" formats and use them in the LogLevel directive.  Log format is
defined using the following statement:

  LogFormat "name" "format_string"

The "name" argument specifies a string uniquely identifying this
format.  "Format_string" is the format specification.  It is
modelled after Apache's mod_log_config LogFormat string.  For example,
the built-in format 3 is defined as:

  "%a - %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\""

The LogLevel directive has been extended to take symbolic format name
as argument.  For example:

  LogLevel "my_format"

The traditional built-in formats are assigned the following symbolic names:

  0 - "null"
  1 - "regular"
  2 - "extended"
  3 - "vhost_combined"
  4 - "combined"
  5 - "detailed"

So, instead of

  LogLevel 3

one may write

  LogLevel "vhost_combined"

* New statements: ForwardedHeader and TrustedIP

These statements control how the %a log format conversion specifier
determines the originator IP address:

  ForwardedHeader "name"
    Defines the name of HTTP header that carries the list of
    proxies the request has passed through.  It is used to
    report the originator IP address when logging.

    The default is "X-Forwarded-For".  This statement can be
    used in global, listener, and service scope.

  TrustedIP
    Defines a list of trusted proxy IP addresses, which is used to
    determine the originator IP.  This is a special form of the ACL
    statement and, as the latter, it can appear in two forms: directive
    and section.

    In directive form, it takes a single argument referring to a
    named access control list, which must have been defined previously
    using the ACL statement.

    In section form, it is followed by a list of one or more CIDRs
    each appearing on a separate line.  The End directive on a
    separate line terminates the statement.

    This statement can be used in global, listener, and service scope.

* New service statement: LogSuppress

Suppresses HTTP logs for requests that resulted in response status
codes from a particular group or groups.  The statement takes one or more
arguments specifying status code groups to suppress log messages for:

  info or 1      1xx status codes
  success or 2   2xx status codes
  redirect or 3  3xx status codes
  clterr or 4    4xx status codes
  srverr or 5    5xx status codes
  all            all status codes

Suggested usage is for special services that are likely to accept
large numbers of similar requests, such as Openmetrics services.  For
example:

   Service "metrics"
       URL "/metrics"
       Metrics
       LogSuppress success
   End

* New request matching directive: StringMatch

The syntax is:

  StringMatch "SUBJECT" [OPTIONS] "PATTERN"

OPTIONS are usual matcher options.  The directive matches if SUBJECT,
after backreference expansion and accessor interpretation, matches
PATTERN.

This directive allows you to build complex service selection criteria.
For example:

  Service
      Host "^foobar\.(.+)$"
      StringMatch "$1" -file "domain.list"
      ...
  End

The service above will be used for requests whose Host header value is
"foobar." followed by a domain name from the file "domain.list".

* New request accessors: host and port

The %[host] accessor returns the hostname part of the Host header
value.  The %[port] accessor returns port number with leading
column character.  If no explicit port number is given in the Host
value, %[port] returns empty string.

* Bugfixes

** Fix the QueryParam statement.

** Improve testsuite and documentation.

Version 4.8, 2023-05-28

* Support for libpcre2-posix

* Fix coredump on -c -v

* poundctl: ignore empty lines in pound.cfg


Version 4.7, 2023-04-17

* Default include directory

Configuration directives that take filenames as their argument, search
for files in the include directory (unless the filename is absolute).
Initial value of the include directory is set to the system configuration
directory, as configured at compile time.   It can be changed:

1. from the command line, using the -Winclude-dir=DIR or -Wno-include-dir
   options.  The latter form resets it to the current working
   directory.

2. in the global scope of the configuration file, using the IncludeDir
   configuration statement.

* The "Include" directive

The "Include" directive can appear not only at the topmost level, but
also in any sections (ListenHTTP, Service, ACL, etc.). In short -
anyplace where a statement is allowed.

* Reading patterns from file

All request matching directives (Header, Host, URL, etc.) take an
additional option "-file".  When this option is specified, the
argument to the directive is treated as the name of a file to read
patterns from.  If the filename is relative, it is looked up in the
include directory (see above).  Patterns are read from the file line
by line, empty lines and comments are ignored.  For example:

   Service
      Host -file "pound/webhosts"
      ...
   End

* Early pthread_cancel probe

Pound calls pthread_cancel(3p) during its shutdown sequence.  In GNU
libc, a call to this function involves loading the libgcc_s.so.1
shared library.  In previous versions, this would fail if pound
was running in chrooted environment (RootJail), unless that library
had previously been copied to the chroot directory.  The following
diagnostics would be printed

   libgcc_s.so.1 must be installed for pthread_cancel to work

and the program would abort.  That means that normal pound shutdown
sequence was not performed properly.  Starting with this version, pound
will create and cancel a dummy thread right before doing chroot.  This
ensures that libgcc_s.so.1 is loaded early, so that pthread_cancel is
run successfully even when chrooted later.

This early probe is enabled if pound is linked with GNU libc.  The
--enable-pthread-cancel-probe configure option is available to
forcefully enable or disable it, if the need be.

* PID file and control socket are properly removed when in RootJail mode.

This doesn't cover the case where the privileges of the user the
program runs at (as set by the "User" and "Group" configuration
statements) forbid to remove the file.

* Control socket ownership and mode

The "Control" configuration directive has two forms: inline and
section.  The inline form is the same as in previous versions.
The block "Control" statement allows you to manage the file mode
and ownership of the socket file.  Its syntax is:

  Control
    Socket "FILE"
    Mode OCTAL
    ChangeOwner BOOL
  End

The Socket statement sets the name of the UNIX socket file.  This is
the only mandatory statement in the Control block.  The Mode statement
sets mode of the socket file (default is 600).  Finally, if ChangeOwner
is true, the ownership of the socket file will be changed
to the user defined by the User and/or Group statements in global
scope.

Version 4.6, 2023-03-07

* Load-balancing strategies

A load balancing strategy defines algorithm used to distribute
incoming requests between multiple regular backends.  This version
of pound implements two such strategies:

** Weighted Random Balancing

This is the default strategy and the one implemented by prior versions
of pound.  Each backend is assigned a numeric priority between 0 and 9
(inclusive).  The backend to use for each request is determined at
random taking into account backend priorities, so that backends with
numerically greater priorities have proportionally greater chances of
being selected than the ones with lesser priorities.

** Interleaved Weighted Round Robin Balancing

Requests are assigned to each backend in turn.  Backend priorities, or
weights, are used to control the share of requests handled by each
backend.  The greater the weight, the more requests will be sent to
this backend.

* New statement: Balancer

The Balancer statement can appear in global and in Service scope.  It
defines the load balancer to use.  Possible arguments are: random, to
use weighted random balancing (default), and iwrr to use interleaved
weighted round robin balancing.

* Backreferences

Up to eight most recent matches are saved.  They can be referenced
as $N(M), where N is number of the parenthesized subexpression, and
M is number of the match.  Matches are numbered in reverse chronological
order with the most recent one being at index 0.  The (0) can be
omitted ($1 is the same as $1(0)).

For example, given the following statements:

  Host -re "www\\.(.+)"
  Header -re -icase "^Content-Type: *(.*)"
  Path "^/static(/.*)?"

"$1" refers to the subgroup of Path, "$1(1)" - to that of Header, and
"$1(2)" - to that of Host.

Curly braces may be used to delimit reference from the text that
follows it.  This is useful if the reference is immediately followed
by a decimal digit or opening parenthesis, as in: "${1}(text)".

* Request matching directives

In addition to "URL" and "Header", the following matching directives
are provided

  Path [options] "value"
    Match path.

  Query [options] "value"
    Match query.

  QueryParam "name" [options] "value"
    Match query parameter.

* Request modification directives

Request modification directives apply changes to the incoming request
before passing it on to the service or backend.  They can be used both
in ListenHTTP (ListenHTTPS) and Service sections.  The following
directives are provided:

  DeleteHeader "header: pattern"
      Remove matching headers from the incoming requests.

  SetHeader "header: to add"
      Add the defined header to the request passed.  If the header
      already exists, change its value.

  SetURL "value"
      Sets the URL part of the request.

  SetPath "value"
      Sets the path part.

  SetQuery "value"
      Sets the query part.

  SetQueryParam "name" "value"
      Sets the query parameter "name" to "value".

  Rewrite ... [ Else ... ] End
      Conditionally apply request modification depending on whether request
      matches certain conditions, e.g.:

		Rewrite
			Path "\\.(jpg|gif)$"
			SetPath "/images$0"
		Else
			Match AND
				Host "example.org"
				Path "\\.[^.]+$"
			End
			SetPath "/static$0"
		Else
			Path "\\.[^.]+$"
			SetPath "/assets$0"
		End

* Request accessors

These are special constructs that, when used in string values, are
replaced with the corresponding parts of the incoming request.  The
supported accessors are:

 %[url]
   The URL of the request.

 %[path]
   The path part of the request.

 %[query]
   The query part of the request.

 %[param NAME]
   The value of the query parameter NAME.

 %[header NAME]
   The value of the request header NAME.

Request accessor can be used in all strings where the use of
backreferences is allowed: i.e. arguments to Redirect, ACME,
Error directives, and to all request modification directives described
above.

* Listener labels

Listeners can be assigned symbolic labels.  The syntax is:

  ListenHTTP "name"
or
  ListenHTTPS "name"

The "name" must be unique among all listeners defined in the
configuration.

This symbolic name can be used to identify listener in poundctl
requests (see below).

* Service labels

Service labels must be unique among all services within the
listener (or in the configuration file, for global ones).

* Use of listener and service labels in poundctl

Listeners and services can be identified both by their numbers and
labels.  For example:

  poundctl list /main/static/1

* Use of multiple redirects in single service

Use of multiple redirect backends in single service, as well as mixing
them with regular backends is deprecated and causes a warning message.


Version 4.5, 2023-02-12

* RPC over HTTP support withdrawn

It has been officially discontinued by Microsoft on 2017-10-31.  It's
no use trying to support it five years after.

* Support for 303 and 308 redirection codes

* Improved default error responses

* New special backend: Error

The Error statement defines a special backend that returns the
HTTP error page.  It takes one to two arguments:

  Error STATUS [FILE]

The STATUS argument supplies HTTP status code.  Optional FILE argument is
the name of a disk file with the error page content (HTML).  If not
supplied, the text is determined as usual: first the Err<STATUS> statement
for the enclosing listener is consulted.  If it is not present, the
default error page is used.

* New special backend: Metrics

This backend type implements openmetrics telemetry endpoint.  The
minimal configuration is:

  Service
      URL "/metrics"
      Metrics
  End

Enabling backend statistics (see below) is strongly suggested when
using the Metrics backend.

* Backend statistics

Backend usage statistics is enabled by the BackendStats configuration
directive:

  BackendStats true

When enabled, the "stats" object will be added to the JSON output for
each backend.  This object holds the following fields:

  request_count          Number of requests processed by this backend.
  request_time_avg       Average request processing time.
  request_time_stddev    Standard deviation of the above.

The Metrics backend, if declared, will then include the following
metric families in its output

  pound_backend_requests
  pound_backend_request_time_avg_nanoseconds
  pound_backend_request_stddev_nanoseconds

These three families are labeled by the corresponding backend index,
e.g. (output split in two lines for readability):

  pound_backend_request_time_avg_nanoseconds
      {listener="1",service="1",backend="1"} 17232220

* Core statistics

The default output returned by pound control thread now includes
additional core statistics: pound version, PID, worker subsystem
configuration and state.  The default poundctl template has been
changed to reflect it.

* New options: -F and -e

The -F option forces the foreground mode: the program won't detach
itself from the controlling terminal and will remain in foreground even
if configuration settings require otherwise.

The -e option directs error diagnostics to stderr (stdout for
LOG_DEBUG and LOG_INFO facilities).  It implies foreground mode.

* Changes in verbose mode (-v)

Error messages emitted to stderr (stdout) are duplicated in the
syslog, if the configuration settings require so.

* Arithmetic operations in poundctl templates

The four new functions are provided to implement basic arithmetic
operations in templates: add, sub, mul, and div.

* Fixed the LogFacility configuration statement


Version 4.4, 2023-01-19

* New directive: HeaderOption

The HeaderOption directive controls what kind of "canned" headers
pound adds to the HTTP request before passing it on to the backend.
By default, it adds "forwarded" headers (X-Forwarded-For,
X-Forwarded-Proto, and X-Forwarded-Port) and, if serving a HTTPS
session, X-SSL-* headers.

The arguments to the HeaderOption directive enable or disable these
canned headers.  The default corresponds to

  HeaderOption forwarded ssl

To disable any kind of headers, precede its name with a "no-":

  HeaderOption no-forwarded

The special keywords "none" and "all", can be used to disable or
enable all canned headers.

The HeaderOption directive can appear in the global scope or within
a ListenerHTTP (or ListenerHTTPS) section.

* Header modification and service matching

Header modification directives are applied after service matching
directives (such as Header or HeadRequire).  This is a disruptive
change: in previous pound version header removal was done prior to
service selection.

* Header modification order

Header modification directives are applied in the following order:
HeaderOptions, HeaderRemove, HeaderAdd.  In other words, built-in headers
are added first.  Then, header removal directives are applied.
Finally, headers requested by the user are added.  Added headers
overwrite headers with the same name that may already be present in the
request.  Thus, you can use HeaderRemove and HeaderAdd to trim down
headers added by HeaderOptions.

* Back-references in Redirect and ACME statements

Arguments to Redirect and ACME statements can contain references to
parenthesized subexpressions in the most recently matched URL, Header,
or Host statements.  Syntactically, $N refers to URL subexpression and
%N refers to subexpression of Header (or Host).  $0 and %0 are
expanded to the entire URL or header (host).  For example, to redirect
all requests to https:

	Service
		Host -re ".+"
		URL ".*"
		Redirect "https://%0$0"
	End

Version 4.3, 2023-01-13

* Template support in poundctl

The output of poundctl is controlled by a template.  Templates
are read from a template file, which is looked up in template
search path (normally ~/.poundctl.tmpl:/usr/share/pound/poundctl.tmpl).
The poundctl.tmpl file shipped with the distribution defines templates
for the traditional (plain-text) and XML output.

The option "-t FILE" instructs poundctl to use FILE instead of the
default template file.  The option "-T NAME" supplies the name of
the template to be used.

* Fix parsing of Subject in X509 certificates


Version 4.2, 2022-12-31

* Rewrite periodic tasks

The timer thread is rewritten completely in order to do periodic
operations (such as backend probing and session expiration)
precisely when needed, instead of waking up in fixed intervals and
checking what should be done.  Among others, this helps reduce the CPU
load.

Whenever a backend is marked as dead, a periodic job is scheduled
for "alive_to" seconds from the current time, which will probe the
backend and either mark it as alive (if it responds) or reschedule
itself for a later time (if it does not).  Thus, no unnecessary
iterations over listeners/servers/backends occur.

Sessions are kept on per-service basis in a combined structure
consisting of a hash table (to quickly look-up a session) and
a doubly-linked list (to provide for session expiration).  Sessions
within the latter are sorted by their expiration time.  A periodic
job is scheduled to the expiration time of the first session in the
list, i.e. the least recently used one.  After removing the expired
session, the job reschedules itself to the expiration time of the
next session (which becomes first in the list), if any.

* The "haport" feature has been removed.

* Control interface rewritten

The new control interface uses REST API.

* Poundctl rewritten

Version 4.1, 2022-12-10

* Worker Model

Each incoming request is processed by a specific worker, i.e. a
thread in the running program.  The number of running workers is
controlled by three configuration parameters.  WorkerMinCount
defines the minimum number of workers that should always be running
(5, by default). Another parameter, WorkerMaxCount sets the
upper limit on the number of running workers (defaults to 128).

At each given moment, a worker can be in one of two states: idle
or active (processing a request).  If an incoming request
arrives when all running workers are active, and total number of
workers is less than maximum, a new thread is started and the new
request is handed to it.  If the number of active workers has already
reached maximum, the new request is added to the request queue, where
it will wait for a worker to become available to process it.

The third parameter, WorkerIdleTimeout, specifies maximum time
a thread is allowed to spend in the idle state.  If a worker
remains idle longer than that and total number of workers is greater
than the allotted minimum, the idle worker is terminated.  The default
value for WorkerIdleTimeout is 30 seconds.

* URL expansion in Redirect statement

URL argument to the Redirect statement can contain references to
parethesized subexpressions in the most recently matched URL statement
of the enclosing Service.  References are of the form $N, where N
is the number of the parenthesized subgroup.  To insert literal $
sign, use $$.

* New statement: PIDFile

Defines the name of the PID file.  The -p command line option
overrides this setting.

* New statement: ACME

The ACME statement creates a service specially crafted for answering
ACME HTTP-01 challenge requests.  It takes a single argument,
specifying a directory where ACME challenges are stored.  It is
supposed that another program is started periodically, which checks
for certificates approaching their expiration, issues renewal requests
and stores the obtained ACME challenges in that directory.

The statement can appear in ListenHTTP block.

Example usage:

  ListenHTTP
    ACME "/var/www/acme"
    ...
  End

* New statement: Host

The "Host" statement is provided to facilitate handling of virtual
services.  The statement:

  Host "example.com"

is equivalent to:

  HeadRequire "Host:[[:space:]]*example\\.com"

* ACLs

Access control lists (ACLs) allow you to make some services available
for users coming from certain IP ranges.  There are two kinds of ACLs:
named and unnamed.  Named ACLs are defined in the global scope, using
the following syntax:

  ACL "name"
     "CIDR"
     ...
  End

where ... denotes more CIDR lines.  A CIDR is an IPv4 or IPv6 address,
optionally followed by a slash and network mask length.  Named ACLs
can be referred to in Service sections using the following syntax:

  Service
     ACL "name"
     ...
  End

This service will be used only if the request comes from IP address
that matches the given ACL.

Unnamed ACLs are defined within the service itself, as shown in the
following example

  Service
     ACL
	"127.0.0.1"
	"192.0.2.0/26"
	"203.0.113.0/24"
     End
     ...
  End

Semantically they are entirely equivalent to named ACLs.

* Boolean operations over request matching directives

By default, request matching directives are joined with an implicit
boolean "AND".  This can be changed using the new "Match" directive,
e.g.:

  Match OR
      HeadRequire "Host:[[:space:]]*example\\.org"
      HeadRequire "Host:[[:space:]]*example\\.net"
  End

Match directives can be nested to any depth.

Any request matching directive (including "Match") can be prefixed
with "not", to invert its result (boolean negation).

* Alternative spelling for header matching/manipulation directives

For consistency, the following configuration directives have been
provided as alternatives for existing header manipulation directives:

  Old name        New name          Comment
  --------        --------          -------
  HeadRequire     Header            Service section
  HeadDeny        Not Header        Service section.  See "Boolean operations".
  HeadRemove      HeaderRemove      ListenHTTP and ListenHTTPS sections
  AddHeader       HeaderAdd         ListenHTTP and ListenHTTPS sections

The use of new names is preferred.

Version 4.0, 2022-12-02

* Support for OpenSSL 3.0

* Added testsuite.

* Fixes in configuration parsing.

=========================================================================
Copyright information:

Copyright (C) 2018-2023 Sergey Poznyakoff

   Permission is granted to anyone to make or distribute verbatim copies
   of this document as received, in any medium, provided that the
   copyright notice and this permission notice are preserved,
   thus giving the recipient permission to redistribute in turn.

   Permission is granted to distribute modified versions
   of this document, or of portions of it,
   under the above conditions, provided also that they
   carry prominent notices stating who last changed them.

Local variables:
mode: outline
paragraph-separate: "[  ]*$"
eval: (add-hook 'write-file-hooks 'time-stamp)
time-stamp-start: "changes. "
time-stamp-format: "%:y-%02m-%02d"
time-stamp-end: "\n"
end:
