From 414dfaf468eb54fd8aca3d73e98fdc858e8c8c20 Mon Sep 17 00:00:00 2001 From: "Iztok Fister Jr." Date: Sat, 18 Jul 2026 14:29:15 +0200 Subject: [PATCH] enforce MAX_CONTENT_LENGTH on Flask app --- succulent/api.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/succulent/api.py b/succulent/api.py index f9f1350..5116cf3 100644 --- a/succulent/api.py +++ b/succulent/api.py @@ -20,8 +20,19 @@ class SucculentAPI: format (str): The format of the data ('csv', 'json', 'sqlite', or 'image'). app (Flask): Flask application. processing (Processing): Instance of the Processing class. + + Configuration: + max_content_length (int, optional): Maximum accepted size (in bytes) + of an incoming request body. Defaults to + ``DEFAULT_MAX_CONTENT_LENGTH`` (5 MB) when not set in the + configuration file. Requests exceeding this size are rejected + with a 413 response before being processed, to protect the + server against oversized or flooding POST requests. """ + # Default maximum size (in bytes) accepted for a single request body. + DEFAULT_MAX_CONTENT_LENGTH = 5 * 1024 * 1024 # 5 MB + def __init__(self, config, host='0.0.0.0', port=8080, format='csv'): self.host = host self.port = port @@ -36,6 +47,14 @@ def __init__(self, config, host='0.0.0.0', port=8080, format='csv'): # Initialise Flask self.app = Flask(__name__, static_url_path='/succulent/static') + + # Limit the maximum accepted size of incoming request bodies to + # protect the server against oversized or flooding POST requests. + # Can be overridden via the 'max_content_length' (bytes) setting + # in the configuration file. + self.app.config['MAX_CONTENT_LENGTH'] = int( + self.config.get('max_content_length', self.DEFAULT_MAX_CONTENT_LENGTH)) + self.app.add_url_rule('/', 'index', self.index, methods=['GET']) self.app.add_url_rule('/measure', 'url', self.url, methods=['GET']) self.app.add_url_rule('/measure', 'measure', @@ -43,6 +62,8 @@ def __init__(self, config, host='0.0.0.0', port=8080, format='csv'): self.app.add_url_rule('/data', 'data', self.data, methods=['GET']) self.app.add_url_rule('/export', 'export', self.export, methods=['GET']) + self.app.register_error_handler( + 413, self.payload_too_large) def index(self): """Generate index HTML page with information about the API. @@ -125,6 +146,17 @@ def export(self): return response, 200 + def payload_too_large(self, error): + """Handle requests whose body exceeds 'MAX_CONTENT_LENGTH'. + + Args: + error (HTTPException): The raised 413 error. + + Returns: + Response: JSON response with an error message. + """ + return jsonify({'message': 'Payload too large.'}), 413 + def start(self): """Start the Flask application on the specified host and port.