Files
Juan Denis 55d8fb1e44 Read route bodies through json_object()
328 more routes used a JSON body as a dict straight from
request.get_json(), so a body of null, [] or a bare string crashed them
into a 500. Bare reads become json_object(); the
'get_json(silent=True) or {}' reads of action routes become
json_object(optional=True), which still treats a missing body as {}.
Routes that take arrays or pass the body through untouched are left
alone. The full backend suite shows no new failures.

Also carries three files' bare section citations (apps, backups,
notifications) and the extended citation guard, which needed them.
2026-10-10 20:53:43 -04:00

37 lines
1.3 KiB
Python

"""Small tools blueprint for .htaccess conversion.
Kept out of apps.py on purpose (separate ownership); intended registration:
from app.api.htaccess_tools import htaccess_tools_bp
app.register_blueprint(htaccess_tools_bp, url_prefix='/api/v1/apps')
which exposes POST /api/v1/apps/htaccess-convert.
"""
from flask import Blueprint, jsonify
from flask_jwt_extended import jwt_required
from app.services.htaccess_converter import MAX_INPUT_BYTES, convert
from app.api._request import json_object
htaccess_tools_bp = Blueprint('htaccess_tools', __name__)
@htaccess_tools_bp.route('/htaccess-convert', methods=['POST'])
@jwt_required()
def htaccess_convert():
"""Convert pasted .htaccess text to nginx directives.
Pure text transform (no server state touched), so any authenticated
user may call it. Body: {'htaccess': '<text>'}.
"""
data = json_object(optional=True)
text = data.get('htaccess')
if not isinstance(text, str) or not text.strip():
return jsonify({'error': 'htaccess text is required'}), 400
if len(text.encode('utf-8', errors='replace')) > MAX_INPUT_BYTES:
return jsonify({'error': '.htaccess input exceeds the 256KB limit'}), 413
try:
return jsonify(convert(text))
except ValueError as exc:
return jsonify({'error': str(exc)}), 400