178 lines
7.2 KiB
Python
178 lines
7.2 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
Сервер для управления данными бизнес-объединений ДНР.
|
|
Поддерживает:
|
|
- GET /data.json - получение данных
|
|
- POST /save - сохранение данных в файл
|
|
- POST /reset - сброс к дефолтным данным (загружает из data.default.json)
|
|
"""
|
|
|
|
import http.server
|
|
import socketserver
|
|
import json
|
|
import os
|
|
import shutil
|
|
from urllib.parse import urlparse
|
|
|
|
PORT = 8092
|
|
DATA_FILE = 'data.json'
|
|
DEFAULT_DATA_FILE = 'data.default.json'
|
|
|
|
|
|
# Дефолтные данные вынесены в отдельный файл data.default.json
|
|
# Если нужно создать файл с дефолтом - раскомментировать функцию ниже
|
|
|
|
class CustomHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
|
|
|
|
def end_headers(self):
|
|
self.send_header('Access-Control-Allow-Origin', '*')
|
|
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
|
|
self.send_header('Access-Control-Allow-Headers', 'Content-Type')
|
|
super().end_headers()
|
|
|
|
def do_OPTIONS(self):
|
|
self.send_response(200)
|
|
self.end_headers()
|
|
|
|
def do_GET(self):
|
|
parsed_path = urlparse(self.path)
|
|
|
|
# Отдаём data.json
|
|
if parsed_path.path == '/data.json':
|
|
self.send_response(200)
|
|
self.send_header('Content-Type', 'application/json; charset=utf-8')
|
|
self.end_headers()
|
|
try:
|
|
with open(DATA_FILE, 'r', encoding='utf-8') as f:
|
|
self.wfile.write(f.read().encode('utf-8'))
|
|
except FileNotFoundError:
|
|
self.send_error(404, 'data.json not found')
|
|
return
|
|
|
|
# Отдаём index.html
|
|
if parsed_path.path == '/' or parsed_path.path == '/index.html':
|
|
self.path = '/index.html'
|
|
|
|
# Статические файлы
|
|
if self.path.endswith('.html'):
|
|
self.send_response(200)
|
|
self.send_header('Content-Type', 'text/html; charset=utf-8')
|
|
self.end_headers()
|
|
try:
|
|
with open(self.path[1:], 'rb') as f:
|
|
self.wfile.write(f.read())
|
|
except FileNotFoundError:
|
|
self.send_error(404, 'File not found')
|
|
return
|
|
|
|
super().do_GET()
|
|
|
|
def do_POST(self):
|
|
parsed_path = urlparse(self.path)
|
|
|
|
# Сохранение данных
|
|
if parsed_path.path == '/save':
|
|
content_length = int(self.headers.get('Content-Length', 0))
|
|
post_data = self.rfile.read(content_length)
|
|
|
|
try:
|
|
data = json.loads(post_data.decode('utf-8'))
|
|
|
|
with open(DATA_FILE, 'w', encoding='utf-8') as f:
|
|
json.dump(data, f, ensure_ascii=False, indent=2)
|
|
|
|
self.send_response(200)
|
|
self.send_header('Content-Type', 'application/json')
|
|
self.end_headers()
|
|
response = json.dumps({'success': True, 'message': 'Данные сохранены'})
|
|
self.wfile.write(response.encode('utf-8'))
|
|
|
|
except json.JSONDecodeError as e:
|
|
self.send_response(400)
|
|
self.send_header('Content-Type', 'application/json')
|
|
self.end_headers()
|
|
response = json.dumps({'success': False, 'message': f'Ошибка JSON: {str(e)}'})
|
|
self.wfile.write(response.encode('utf-8'))
|
|
except Exception as e:
|
|
self.send_response(500)
|
|
self.send_header('Content-Type', 'application/json')
|
|
self.end_headers()
|
|
response = json.dumps({'success': False, 'message': f'Ошибка сервера: {str(e)}'})
|
|
self.wfile.write(response.encode('utf-8'))
|
|
return
|
|
|
|
# Сброс к дефолту (если есть файл data.default.json)
|
|
if parsed_path.path == '/reset':
|
|
try:
|
|
if os.path.exists(DEFAULT_DATA_FILE):
|
|
shutil.copy(DEFAULT_DATA_FILE, DATA_FILE)
|
|
self.send_response(200)
|
|
self.send_header('Content-Type', 'application/json')
|
|
self.end_headers()
|
|
response = json.dumps({'success': True, 'message': 'Данные сброшены к исходным'})
|
|
self.wfile.write(response.encode('utf-8'))
|
|
else:
|
|
self.send_response(404)
|
|
self.send_header('Content-Type', 'application/json')
|
|
self.end_headers()
|
|
response = json.dumps({'success': False, 'message': 'Файл с дефолтными данными не найден'})
|
|
self.wfile.write(response.encode('utf-8'))
|
|
except Exception as e:
|
|
self.send_response(500)
|
|
self.send_header('Content-Type', 'application/json')
|
|
self.end_headers()
|
|
response = json.dumps({'success': False, 'message': str(e)})
|
|
self.wfile.write(response.encode('utf-8'))
|
|
return
|
|
|
|
self.send_response(404)
|
|
self.end_headers()
|
|
|
|
def log_message(self, format, *args):
|
|
print(f"[{self.address_string()}] {format % args}")
|
|
|
|
|
|
def ensure_data_file():
|
|
"""Проверяет наличие data.json, если нет - создаёт из дефолта или пустой"""
|
|
if not os.path.exists(DATA_FILE):
|
|
if os.path.exists(DEFAULT_DATA_FILE):
|
|
shutil.copy(DEFAULT_DATA_FILE, DATA_FILE)
|
|
print(f"📄 Создан файл данных из {DEFAULT_DATA_FILE}")
|
|
else:
|
|
# Создаём минимальный пустой файл
|
|
empty_data = {
|
|
"organizations": [],
|
|
"additionalOrganizations": [],
|
|
"metadata": {"lastUpdated": "2026-01-15", "totalOrganizations": 0}
|
|
}
|
|
with open(DATA_FILE, 'w', encoding='utf-8') as f:
|
|
json.dump(empty_data, f, ensure_ascii=False, indent=2)
|
|
print(f"📄 Создан пустой файл данных: {DATA_FILE}")
|
|
print(f"⚠️ Для работы с данными создайте файл {DEFAULT_DATA_FILE} с дефолтными данными")
|
|
|
|
|
|
def run_server():
|
|
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
|
ensure_data_file()
|
|
|
|
with socketserver.TCPServer(("", PORT), CustomHTTPRequestHandler) as httpd:
|
|
print("=" * 60)
|
|
print(f"🚀 Сервер запущен!")
|
|
print(f"📁 Директория: {os.getcwd()}")
|
|
print(f"🌐 Локальный доступ: http://localhost:{PORT}")
|
|
print(f"📄 Файл данных: {DATA_FILE}")
|
|
print(f"📄 Дефолтный файл (если есть): {DEFAULT_DATA_FILE}")
|
|
print(f"⏹️ Для остановки сервера нажмите Ctrl+C")
|
|
print("=" * 60)
|
|
|
|
try:
|
|
httpd.serve_forever()
|
|
except KeyboardInterrupt:
|
|
print("\n🛑 Сервер остановлен.")
|
|
httpd.shutdown()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
run_server() |