"""Minimal DWG-to-DXF conversion microservice via libredwg.""" import os import subprocess import tempfile import uuid from flask import Flask, request, send_file, jsonify app = Flask(__name__) MAX_FILE_SIZE = 100 * 1024 * 1024 # 100 MB @app.route("/health", methods=["GET"]) def health(): """Health check — verifies dwg2dxf binary is callable.""" try: subprocess.run(["dwg2dxf", "--version"], capture_output=True, timeout=5) return jsonify({"status": "ok", "dwg2dxf": "available"}), 200 except Exception as e: return jsonify({"status": "error", "detail": str(e)}), 503 @app.route("/convert", methods=["POST"]) def convert(): """Accept a DWG file via multipart upload, return DXF.""" if "file" not in request.files: return jsonify({"error": "Missing 'file' field in upload."}), 400 uploaded = request.files["file"] original_name = uploaded.filename or "input.dwg" if not original_name.lower().endswith(".dwg"): return jsonify({"error": "File must have .dwg extension."}), 400 safe_name = "".join( c if c.isalnum() or c in "._-" else "_" for c in original_name ) tmp_dir = os.path.join(tempfile.gettempdir(), f"dwg-{uuid.uuid4().hex}") os.makedirs(tmp_dir, exist_ok=True) input_path = os.path.join(tmp_dir, safe_name) output_path = input_path.rsplit(".", 1)[0] + ".dxf" try: uploaded.save(input_path) file_size = os.path.getsize(input_path) if file_size > MAX_FILE_SIZE: return jsonify({"error": f"File too large ({file_size} bytes)."}), 413 result = subprocess.run( ["dwg2dxf", input_path], capture_output=True, timeout=120, ) if not os.path.exists(output_path): stderr = result.stderr.decode("utf-8", errors="replace") return jsonify({ "error": f"Conversion failed: {stderr or 'no output file'}" }), 500 dxf_name = safe_name.rsplit(".", 1)[0] + ".dxf" return send_file( output_path, mimetype="application/dxf", as_attachment=True, download_name=dxf_name, ) except subprocess.TimeoutExpired: return jsonify({"error": "Conversion timed out (120s limit)."}), 504 except Exception as e: return jsonify({"error": f"Unexpected error: {str(e)}"}), 500 finally: for f in os.listdir(tmp_dir): try: os.unlink(os.path.join(tmp_dir, f)) except OSError: pass try: os.rmdir(tmp_dir) except OSError: pass if __name__ == "__main__": app.run(host="0.0.0.0", port=5001)