hgweb: send proper HTTP response after uncaught exception
This patch fixes a bug where hgweb would send an incomplete HTTP
response.
If an uncaught exception is raised when hgweb is processing a request,
hgweb attempts to send a generic error response and log that exception.
The server defaults to chunked transfer coding. If an uncaught exception
occurred, it was sending the error response string / chunk properly.
However, RFC 7230 Section 4.1 mandates a 0 size last chunk be sent to
indicate end of the entity body. hgweb was failing to send this last
chunk. As a result, properly written HTTP clients would assume more data
was coming and they would likely time out waiting for another chunk to
arrive.
Mercurial's own test harness was paving over the improper HTTP behavior
by not attempting to read the response body if the status code was 500.
This incorrect workaround was added in ba6577a19656 and has been removed
with this patch.
Mercurial has the ability to add new features through the use of
extensions. Extensions may add new commands, add options to
existing commands, change the default behavior of commands, or
implement hooks.
To enable the "foo" extension, either shipped with Mercurial or in the
Python search path, create an entry for it in your configuration file,
like this::
[extensions]
foo =
You may also specify the full path to an extension::
[extensions]
myfeature = ~/.hgext/myfeature.py
See :hg:`help config` for more information on configuration files.
Extensions are not loaded by default for a variety of reasons:
they can increase startup overhead; they may be meant for advanced
usage only; they may provide potentially dangerous abilities (such
as letting you destroy or modify history); they might not be ready
for prime time; or they may alter some usual behaviors of stock
Mercurial. It is thus up to the user to activate extensions as
needed.
To explicitly disable an extension enabled in a configuration file of
broader scope, prepend its path with !::
[extensions]
# disabling extension bar residing in /path/to/extension/bar.py
bar = !/path/to/extension/bar.py
# ditto, but no path was supplied for extension baz
baz = !