@@ -7,6 +7,7 @@
|
|||||||
* Cleanup: deprecate config option 'ldap_use_ssl' for good
|
* Cleanup: deprecate config option 'ldap_use_ssl' for good
|
||||||
* Performance: improve `path_to_filesystem()`
|
* Performance: improve `path_to_filesystem()`
|
||||||
* Performance: preload access rights from file
|
* Performance: preload access rights from file
|
||||||
|
* Add: [server] delay_on_error option
|
||||||
|
|
||||||
## 3.6.1
|
## 3.6.1
|
||||||
|
|
||||||
|
|||||||
@@ -831,6 +831,14 @@ The maximum number of parallel connections. Set to `0` to disable the limit.
|
|||||||
|
|
||||||
Default: `8`
|
Default: `8`
|
||||||
|
|
||||||
|
##### delay_on_error
|
||||||
|
|
||||||
|
_(>= 3.7.0)_
|
||||||
|
|
||||||
|
Base delay in case of error response (seconds)
|
||||||
|
|
||||||
|
Default: `0.01`
|
||||||
|
|
||||||
##### max_content_length
|
##### max_content_length
|
||||||
|
|
||||||
The maximum size of the request body. (bytes)
|
The maximum size of the request body. (bytes)
|
||||||
|
|||||||
3
config
3
config
@@ -21,6 +21,9 @@
|
|||||||
# Max parallel connections
|
# Max parallel connections
|
||||||
#max_connections = 8
|
#max_connections = 8
|
||||||
|
|
||||||
|
# Base delay in case of error response (seconds)
|
||||||
|
#delay_on_error = 0.01
|
||||||
|
|
||||||
# Max size of request body (bytes), default: 100 Mbyte
|
# Max size of request body (bytes), default: 100 Mbyte
|
||||||
# In case of using a reverse proxy in front of check also there related option
|
# In case of using a reverse proxy in front of check also there related option
|
||||||
#max_content_length = 100000000
|
#max_content_length = 100000000
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# Copyright © 2008 Pascal Halter
|
# Copyright © 2008 Pascal Halter
|
||||||
# Copyright © 2008-2017 Guillaume Ayoub
|
# Copyright © 2008-2017 Guillaume Ayoub
|
||||||
# Copyright © 2017-2019 Unrud <unrud@outlook.com>
|
# Copyright © 2017-2019 Unrud <unrud@outlook.com>
|
||||||
# Copyright © 2024-2025 Peter Bieringer <pb@bieringer.de>
|
# Copyright © 2024-2026 Peter Bieringer <pb@bieringer.de>
|
||||||
#
|
#
|
||||||
# This library is free software: you can redistribute it and/or modify
|
# This library is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -72,6 +72,7 @@ class Application(ApplicationPartDelete, ApplicationPartHead,
|
|||||||
|
|
||||||
_mask_passwords: bool
|
_mask_passwords: bool
|
||||||
_auth_delay: float
|
_auth_delay: float
|
||||||
|
_delay_on_error: float
|
||||||
_internal_server: bool
|
_internal_server: bool
|
||||||
_max_content_length: int
|
_max_content_length: int
|
||||||
_max_resource_size: int
|
_max_resource_size: int
|
||||||
@@ -97,6 +98,8 @@ class Application(ApplicationPartDelete, ApplicationPartHead,
|
|||||||
"""
|
"""
|
||||||
super().__init__(configuration)
|
super().__init__(configuration)
|
||||||
self._mask_passwords = configuration.get("logging", "mask_passwords")
|
self._mask_passwords = configuration.get("logging", "mask_passwords")
|
||||||
|
self._delay_on_error = configuration.get("server", "delay_on_error")
|
||||||
|
logger.info("delay_on_error set to: %.3f seconds", self._delay_on_error)
|
||||||
self._max_content_length = configuration.get("server", "max_content_length")
|
self._max_content_length = configuration.get("server", "max_content_length")
|
||||||
self._max_resource_size = configuration.get("server", "max_resource_size")
|
self._max_resource_size = configuration.get("server", "max_resource_size")
|
||||||
logger.info("max_content_length set to: %d bytes (%sbytes)", self._max_content_length, utils.format_unit(self._max_content_length, binary=True))
|
logger.info("max_content_length set to: %d bytes (%sbytes)", self._max_content_length, utils.format_unit(self._max_content_length, binary=True))
|
||||||
@@ -304,6 +307,15 @@ class Application(ApplicationPartDelete, ApplicationPartHead,
|
|||||||
flags_text = " (" + " ".join(flags) + ")"
|
flags_text = " (" + " ".join(flags) + ")"
|
||||||
else:
|
else:
|
||||||
flags_text = ""
|
flags_text = ""
|
||||||
|
# delay on error
|
||||||
|
if status >= 400:
|
||||||
|
if self._delay_on_error > 0:
|
||||||
|
random_delay = self._delay_on_error * (1 + random.random())
|
||||||
|
if status >= 500:
|
||||||
|
random_delay = 2 * random_delay
|
||||||
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
|
logger.debug("Response delay triggered by result code: %d -> %0.3f seconds", status, random_delay)
|
||||||
|
time.sleep(random_delay)
|
||||||
if answer is not None:
|
if answer is not None:
|
||||||
logger.info("%s response status for %r%s in %.3f seconds %s %s bytes%s: %s",
|
logger.info("%s response status for %r%s in %.3f seconds %s %s bytes%s: %s",
|
||||||
request_method, unsafe_path, depthinfo,
|
request_method, unsafe_path, depthinfo,
|
||||||
|
|||||||
@@ -171,6 +171,10 @@ DEFAULT_CONFIG_SCHEMA: types.CONFIG_SCHEMA = OrderedDict([
|
|||||||
"value": "100000000",
|
"value": "100000000",
|
||||||
"help": "maximum size of request body in bytes (default: 100 Mbyte)",
|
"help": "maximum size of request body in bytes (default: 100 Mbyte)",
|
||||||
"type": positive_int}),
|
"type": positive_int}),
|
||||||
|
("delay_on_error", {
|
||||||
|
"value": "0.01",
|
||||||
|
"help": "base delay in case of error response (seconds)",
|
||||||
|
"type": positive_float}),
|
||||||
("max_resource_size", {
|
("max_resource_size", {
|
||||||
"value": "10000000",
|
"value": "10000000",
|
||||||
"help": "maximum size of resource (default: 10 Mbyte)",
|
"help": "maximum size of resource (default: 10 Mbyte)",
|
||||||
|
|||||||
@@ -69,8 +69,10 @@ class TestBaseAuthRequests(BaseTest):
|
|||||||
with open(htpasswd_file_path, "w", encoding=encoding) as f:
|
with open(htpasswd_file_path, "w", encoding=encoding) as f:
|
||||||
f.write(htpasswd_content)
|
f.write(htpasswd_content)
|
||||||
self.configure({"auth": {"type": "htpasswd",
|
self.configure({"auth": {"type": "htpasswd",
|
||||||
|
"delay": 0,
|
||||||
"htpasswd_filename": htpasswd_file_path,
|
"htpasswd_filename": htpasswd_file_path,
|
||||||
"htpasswd_encryption": htpasswd_encryption}})
|
"htpasswd_encryption": htpasswd_encryption},
|
||||||
|
"server": {"delay_on_error": 0}})
|
||||||
if test_matrix == "ascii":
|
if test_matrix == "ascii":
|
||||||
test_matrix = (("tmp", "bepo", True), ("tmp", "tmp", False),
|
test_matrix = (("tmp", "bepo", True), ("tmp", "tmp", False),
|
||||||
("tmp", "", False), ("unk", "unk", False),
|
("tmp", "", False), ("unk", "unk", False),
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ collection: .*
|
|||||||
permissions: RrWw""")
|
permissions: RrWw""")
|
||||||
self.configure({"rights": {"file": rights_file_path,
|
self.configure({"rights": {"file": rights_file_path,
|
||||||
"type": "from_file"},
|
"type": "from_file"},
|
||||||
|
"server": {"delay_on_error": 0},
|
||||||
"logging": {"request_header_on_debug": "True",
|
"logging": {"request_header_on_debug": "True",
|
||||||
"request_content_on_debug": "True",
|
"request_content_on_debug": "True",
|
||||||
"response_header_on_debug": "True",
|
"response_header_on_debug": "True",
|
||||||
|
|||||||
Reference in New Issue
Block a user