v0.0.1: revert to v7.0.0 code — api_bp unified, no Connection close, version reset
Deploy drhider / validate (push) Waiting to run
Deploy drhider / validate (push) Waiting to run
This commit is contained in:
+1
-1
@@ -20,7 +20,7 @@ if _sys_path_root not in sys.path:
|
|||||||
sys.path.insert(0, _sys_path_root)
|
sys.path.insert(0, _sys_path_root)
|
||||||
|
|
||||||
# Версия приложения (меняется при изменениях)
|
# Версия приложения (меняется при изменениях)
|
||||||
VERSION = "0.0.3"
|
VERSION = "0.0.1"
|
||||||
|
|
||||||
|
|
||||||
def create_app():
|
def create_app():
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
from .main_bp import main_bp
|
from .main_bp import main_bp
|
||||||
from .health_bp import health_bp
|
from .health_bp import health_bp
|
||||||
from .upload_bp import upload_bp
|
from .api_bp import api_bp
|
||||||
from .process_bp import process_bp
|
|
||||||
from .download_bp import download_bp
|
|
||||||
|
|
||||||
|
|
||||||
def register_routes(app):
|
def register_routes(app):
|
||||||
|
"""Зарегистрировать все blueprint'ы на Flask-приложении.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
app: Экземпляр Flask-приложения
|
||||||
|
"""
|
||||||
app.register_blueprint(main_bp)
|
app.register_blueprint(main_bp)
|
||||||
app.register_blueprint(health_bp)
|
app.register_blueprint(health_bp)
|
||||||
app.register_blueprint(upload_bp)
|
app.register_blueprint(api_bp)
|
||||||
app.register_blueprint(process_bp)
|
|
||||||
app.register_blueprint(download_bp)
|
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
"""
|
||||||
|
Blueprint: API DrHider.
|
||||||
|
|
||||||
|
Three endpoints:
|
||||||
|
- POST /api/upload — upload one file -> {session_id}
|
||||||
|
- POST /api/process/{sid} — process all session files -> {status:"done"}
|
||||||
|
- GET /api/download/{sid} — download ZIP
|
||||||
|
"""
|
||||||
|
|
||||||
|
import io
|
||||||
|
import zipfile
|
||||||
|
import traceback
|
||||||
|
from flask import Blueprint, request, send_file, jsonify
|
||||||
|
|
||||||
|
from drhider import obfuscate_files, LLMClient
|
||||||
|
from drhider.builder import build_zip, build_mapping_csv
|
||||||
|
from session import create_session, add_file, get_files, store_result, get_result, cleanup, file_count
|
||||||
|
|
||||||
|
api_bp = Blueprint("api", __name__, url_prefix="/api")
|
||||||
|
|
||||||
|
|
||||||
|
@api_bp.route("/upload", methods=["POST"])
|
||||||
|
def upload():
|
||||||
|
"""Upload one file to session."""
|
||||||
|
sid = request.form.get("session", "")
|
||||||
|
if not sid:
|
||||||
|
sid = create_session()
|
||||||
|
uploaded = request.files.getlist("files")
|
||||||
|
if not uploaded:
|
||||||
|
return jsonify({"ok": False, "error": "No file"}), 400
|
||||||
|
f = uploaded[0]
|
||||||
|
if not f.filename:
|
||||||
|
return jsonify({"ok": False, "error": "No filename"}), 400
|
||||||
|
ok = add_file(sid, f.filename, f.read())
|
||||||
|
if not ok:
|
||||||
|
return jsonify({"ok": False, "error": "Session not found"}), 404
|
||||||
|
return jsonify({"ok": True, "session": sid, "count": file_count(sid)})
|
||||||
|
|
||||||
|
|
||||||
|
@api_bp.route("/process/<sid>", methods=["POST"])
|
||||||
|
def process(sid):
|
||||||
|
"""Process all session files one by one -> ZIP."""
|
||||||
|
files = get_files(sid)
|
||||||
|
if files is None:
|
||||||
|
return jsonify({"ok": False, "error": "Session not found"}), 404
|
||||||
|
if not files:
|
||||||
|
return jsonify({"ok": False, "error": "No files"}), 400
|
||||||
|
try:
|
||||||
|
llm = LLMClient()
|
||||||
|
all_results = []
|
||||||
|
all_mapping = {}
|
||||||
|
for fname, content in files:
|
||||||
|
zip_data, _csv = obfuscate_files([(fname, content, "")], llm_client=llm)
|
||||||
|
with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
|
||||||
|
for name in zf.namelist():
|
||||||
|
if name == "mapping.csv":
|
||||||
|
csv_text = zf.read(name).decode("utf-8")
|
||||||
|
lines = csv_text.strip().split("\n")
|
||||||
|
if len(lines) > 1:
|
||||||
|
for line in lines[1:]:
|
||||||
|
parts = line.split(",", 2)
|
||||||
|
if len(parts) >= 3:
|
||||||
|
all_mapping[parts[1]] = parts[2]
|
||||||
|
elif not name.endswith("/"):
|
||||||
|
all_results.append((name, zf.read(name)))
|
||||||
|
csv_str = build_mapping_csv(all_mapping) if all_mapping else ""
|
||||||
|
final_zip = build_zip(all_results, mapping_csv=csv_str)
|
||||||
|
store_result(sid, final_zip)
|
||||||
|
return jsonify({"ok": True, "status": "done", "files": len(all_results)})
|
||||||
|
except Exception as e:
|
||||||
|
traceback.print_exc()
|
||||||
|
return jsonify({"ok": False, "error": str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
|
@api_bp.route("/download/<sid>", methods=["GET"])
|
||||||
|
def download(sid):
|
||||||
|
"""Download result and cleanup session."""
|
||||||
|
zip_data = get_result(sid)
|
||||||
|
if zip_data is None:
|
||||||
|
return jsonify({"ok": False, "error": "Not found"}), 404
|
||||||
|
cleanup(sid)
|
||||||
|
return send_file(io.BytesIO(zip_data), mimetype="application/zip",
|
||||||
|
as_attachment=True, download_name="drhider_output.zip")
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
"""
|
|
||||||
GET /api/download/{sid} — скачать ZIP и удалить сессию.
|
|
||||||
|
|
||||||
После этого вызова — всё чисто, памяти ноль.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import io
|
|
||||||
from flask import Blueprint, send_file, jsonify
|
|
||||||
from session import get_result, cleanup
|
|
||||||
|
|
||||||
download_bp = Blueprint("download", __name__, url_prefix="/api")
|
|
||||||
|
|
||||||
|
|
||||||
@download_bp.route("/download/<sid>", methods=["GET"])
|
|
||||||
def download(sid):
|
|
||||||
zip_data = get_result(sid)
|
|
||||||
if zip_data is None:
|
|
||||||
return jsonify({"ok": False, "error": "Not found"}), 404
|
|
||||||
cleanup(sid)
|
|
||||||
return send_file(io.BytesIO(zip_data), mimetype="application/zip",
|
|
||||||
as_attachment=True, download_name="drhider_output.zip")
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
"""
|
|
||||||
POST /api/process/{sid} — обработать ВСЕ файлы сессии по одному.
|
|
||||||
|
|
||||||
Блокирует до завершения. Результат сохраняется в сессии.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import io, zipfile, traceback
|
|
||||||
from flask import Blueprint, jsonify
|
|
||||||
from drhider import obfuscate_files, LLMClient
|
|
||||||
from drhider.builder import build_zip, build_mapping_csv
|
|
||||||
from session import get_files, store_result
|
|
||||||
|
|
||||||
process_bp = Blueprint("process", __name__, url_prefix="/api")
|
|
||||||
|
|
||||||
|
|
||||||
@process_bp.route("/process/<sid>", methods=["POST"])
|
|
||||||
def process(sid):
|
|
||||||
files = get_files(sid)
|
|
||||||
if files is None:
|
|
||||||
return jsonify({"ok": False, "error": "Session not found"}), 404
|
|
||||||
if not files:
|
|
||||||
return jsonify({"ok": False, "error": "No files"}), 400
|
|
||||||
try:
|
|
||||||
llm = LLMClient()
|
|
||||||
all_results = []
|
|
||||||
all_mapping = {}
|
|
||||||
for fname, content in files:
|
|
||||||
zip_data, _csv = obfuscate_files([(fname, content, "")], llm_client=llm)
|
|
||||||
with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
|
|
||||||
for name in zf.namelist():
|
|
||||||
if name == "mapping.csv":
|
|
||||||
csv_text = zf.read(name).decode("utf-8")
|
|
||||||
lines = csv_text.strip().split("\n")
|
|
||||||
if len(lines) > 1:
|
|
||||||
for line in lines[1:]:
|
|
||||||
parts = line.split(",", 2)
|
|
||||||
if len(parts) >= 3:
|
|
||||||
all_mapping[parts[1]] = parts[2]
|
|
||||||
elif not name.endswith("/"):
|
|
||||||
all_results.append((name, zf.read(name)))
|
|
||||||
csv_str = build_mapping_csv(all_mapping) if all_mapping else ""
|
|
||||||
final_zip = build_zip(all_results, mapping_csv=csv_str)
|
|
||||||
store_result(sid, final_zip)
|
|
||||||
return jsonify({"ok": True, "status": "done", "files": len(all_results)})
|
|
||||||
except Exception as e:
|
|
||||||
traceback.print_exc()
|
|
||||||
return jsonify({"ok": False, "error": str(e)}), 500
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
"""
|
|
||||||
POST /api/upload — загрузить ОДИН файл.
|
|
||||||
|
|
||||||
Каждый вызов — новое соединение, передал → закрыл.
|
|
||||||
Сессия связывает файлы через session_id.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from flask import Blueprint, request, jsonify
|
|
||||||
from session import create_session, add_file, file_count
|
|
||||||
|
|
||||||
upload_bp = Blueprint("upload", __name__, url_prefix="/api")
|
|
||||||
|
|
||||||
|
|
||||||
@upload_bp.route("/upload", methods=["POST"])
|
|
||||||
def upload():
|
|
||||||
sid = request.form.get("session", "")
|
|
||||||
if not sid:
|
|
||||||
sid = create_session()
|
|
||||||
uploaded = request.files.getlist("files")
|
|
||||||
if not uploaded:
|
|
||||||
return jsonify({"ok": False, "error": "No file"}), 400
|
|
||||||
f = uploaded[0]
|
|
||||||
if not f.filename:
|
|
||||||
return jsonify({"ok": False, "error": "No filename"}), 400
|
|
||||||
ok = add_file(sid, f.filename, f.read())
|
|
||||||
if not ok:
|
|
||||||
return jsonify({"ok": False, "error": "Session not found"}), 404
|
|
||||||
return jsonify({"ok": True, "session": sid, "count": file_count(sid)})
|
|
||||||
+3
-11
@@ -15,18 +15,10 @@ import gc
|
|||||||
# Настраиваем пути
|
# Настраиваем пути
|
||||||
_site = os.path.join(os.path.dirname(__file__), "..", "site")
|
_site = os.path.join(os.path.dirname(__file__), "..", "site")
|
||||||
sys.path.insert(0, _site)
|
sys.path.insert(0, _site)
|
||||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
sys.path.insert(0, os.path.dirname(_site)) # project root for drhider
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
|
from routes.api_bp import api_bp
|
||||||
# Импортируем напрямую, минуя routes/__init__.py (process_bp тянет drhider)
|
|
||||||
import importlib.util
|
|
||||||
_spec = importlib.util.spec_from_file_location(
|
|
||||||
"upload_bp", os.path.join(_site, "routes", "upload_bp.py")
|
|
||||||
)
|
|
||||||
_upload_mod = importlib.util.module_from_spec(_spec)
|
|
||||||
_spec.loader.exec_module(_upload_mod)
|
|
||||||
upload_bp = _upload_mod.upload_bp
|
|
||||||
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════════════════
|
||||||
@@ -36,7 +28,7 @@ upload_bp = _upload_mod.upload_bp
|
|||||||
def _new_client():
|
def _new_client():
|
||||||
"""Создать свежий тестовый клиент."""
|
"""Создать свежий тестовый клиент."""
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.register_blueprint(upload_bp)
|
app.register_blueprint(api_bp)
|
||||||
return app.test_client()
|
return app.test_client()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user