init commit
This commit is contained in:
293
direct_api_test.py
Normal file
293
direct_api_test.py
Normal file
@@ -0,0 +1,293 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Тестовый скрипт для прямого доступа к API Synology для получения информации о системе.
|
||||
Используется для отладки и определения совместимых API.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import logging
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
import urllib3
|
||||
from requests.adapters import HTTPAdapter
|
||||
from urllib3.util import Retry
|
||||
|
||||
# Добавляем корневой каталог в путь для импорта
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from src.config.config import (
|
||||
SYNOLOGY_HOST,
|
||||
SYNOLOGY_PORT,
|
||||
SYNOLOGY_USERNAME,
|
||||
SYNOLOGY_PASSWORD,
|
||||
SYNOLOGY_SECURE
|
||||
)
|
||||
|
||||
# Отключение предупреждений о небезопасных SSL-соединениях
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
|
||||
# Настройка логирования
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def direct_api_test():
|
||||
"""Прямой тест API без использования классов для определения проблемы"""
|
||||
# Создаем базовую сессию
|
||||
session = requests.Session()
|
||||
session.verify = False # Отключаем проверку SSL
|
||||
|
||||
# Добавляем повторные попытки для HTTP-запросов
|
||||
retry_strategy = Retry(
|
||||
total=3,
|
||||
status_forcelist=[429, 500, 502, 503, 504],
|
||||
allowed_methods=["GET", "POST"],
|
||||
backoff_factor=1.0
|
||||
)
|
||||
adapter = HTTPAdapter(max_retries=retry_strategy)
|
||||
session.mount("http://", adapter)
|
||||
session.mount("https://", adapter)
|
||||
|
||||
# Формируем базовый URL
|
||||
protocol = "https" if SYNOLOGY_SECURE else "http"
|
||||
base_url = f"{protocol}://{SYNOLOGY_HOST}:{SYNOLOGY_PORT}/webapi"
|
||||
logger.info(f"Тестирование прямого API доступа к {base_url}")
|
||||
|
||||
# Шаг 1: Авторизация
|
||||
logger.info("Шаг 1: Попытка авторизации...")
|
||||
|
||||
# Сначала получаем информацию об API авторизации
|
||||
api_info_url = f"{base_url}/entry.cgi"
|
||||
api_info_params = {
|
||||
"api": "SYNO.API.Info",
|
||||
"version": "1",
|
||||
"method": "query",
|
||||
"query": "SYNO.API.Auth"
|
||||
}
|
||||
|
||||
try:
|
||||
auth_info_response = session.get(api_info_url, params=api_info_params, timeout=10)
|
||||
auth_info_data = auth_info_response.json()
|
||||
|
||||
if auth_info_data.get("success"):
|
||||
auth_info = auth_info_data.get("data", {}).get("SYNO.API.Auth", {})
|
||||
auth_path = auth_info.get("path", "auth.cgi")
|
||||
auth_max_version = auth_info.get("maxVersion", 6)
|
||||
|
||||
logger.info(f"API авторизации: путь={auth_path}, макс. версия={auth_max_version}")
|
||||
|
||||
# Пробуем версию 6 или максимальную доступную
|
||||
auth_version = min(6, auth_max_version)
|
||||
|
||||
# Выполняем авторизацию
|
||||
auth_url = f"{base_url}/{auth_path}"
|
||||
auth_params = {
|
||||
"api": "SYNO.API.Auth",
|
||||
"version": str(auth_version),
|
||||
"method": "login",
|
||||
"account": SYNOLOGY_USERNAME,
|
||||
"passwd": SYNOLOGY_PASSWORD,
|
||||
"session": "DirectApiTest",
|
||||
"format": "cookie"
|
||||
}
|
||||
|
||||
# Для версии 6+ используем немного другой формат
|
||||
if auth_version >= 6:
|
||||
auth_params["enable_syno_token"] = "yes"
|
||||
|
||||
logger.info(f"Авторизация с использованием SYNO.API.Auth v{auth_version}")
|
||||
auth_response = session.get(auth_url, params=auth_params, timeout=10)
|
||||
auth_data = auth_response.json()
|
||||
|
||||
if auth_data.get("success"):
|
||||
sid = auth_data.get("data", {}).get("sid")
|
||||
logger.info(f"Авторизация успешна! SID: {sid[:10]}...")
|
||||
|
||||
# Шаг 2: Тестирование различных API для получения информации о системе
|
||||
logger.info("Шаг 2: Тестирование различных API для получения информации о системе")
|
||||
|
||||
# Создаем список API для тестирования
|
||||
api_to_test = [
|
||||
{"name": "SYNO.DSM.Info", "method": "getinfo", "version": 1},
|
||||
{"name": "SYNO.DSM.Info", "method": "getinfo", "version": 2},
|
||||
{"name": "SYNO.Core.System", "method": "info", "version": 1},
|
||||
{"name": "SYNO.Core.System", "method": "info", "version": 2},
|
||||
{"name": "SYNO.Core.System.Status", "method": "get", "version": 1},
|
||||
{"name": "SYNO.Core.System.Status", "method": "get", "version": 2},
|
||||
{"name": "SYNO.Core.System.Utilization", "method": "get", "version": 1},
|
||||
{"name": "SYNO.Core.CurrentConnection", "method": "list", "version": 1}
|
||||
]
|
||||
|
||||
# Перебираем все API и тестируем их
|
||||
for api in api_to_test:
|
||||
# Сначала получаем информацию о конкретном API
|
||||
try:
|
||||
api_info_params = {
|
||||
"api": "SYNO.API.Info",
|
||||
"version": "1",
|
||||
"method": "query",
|
||||
"query": api["name"]
|
||||
}
|
||||
|
||||
api_info_resp = session.get(api_info_url, params=api_info_params, timeout=10)
|
||||
api_info_data = api_info_resp.json()
|
||||
|
||||
if api_info_data.get("success") and api["name"] in api_info_data.get("data", {}):
|
||||
api_details = api_info_data["data"][api["name"]]
|
||||
api_path = api_details.get("path", "entry.cgi")
|
||||
api_min_version = api_details.get("minVersion", 1)
|
||||
api_max_version = api_details.get("maxVersion", 1)
|
||||
|
||||
# Проверяем, поддерживается ли указанная версия
|
||||
if api["version"] < api_min_version:
|
||||
logger.warning(f"{api['name']} v{api['version']} ниже минимальной {api_min_version}, используем {api_min_version}")
|
||||
test_version = api_min_version
|
||||
elif api["version"] > api_max_version:
|
||||
logger.warning(f"{api['name']} v{api['version']} выше максимальной {api_max_version}, используем {api_max_version}")
|
||||
test_version = api_max_version
|
||||
else:
|
||||
test_version = api["version"]
|
||||
|
||||
# Выполняем запрос API
|
||||
test_url = f"{base_url}/{api_path}"
|
||||
test_params = {
|
||||
"api": api["name"],
|
||||
"version": str(test_version),
|
||||
"method": api["method"],
|
||||
"_sid": sid # Используем sid для аутентификации
|
||||
}
|
||||
|
||||
logger.info(f"Тестирование {api['name']}.{api['method']} v{test_version}")
|
||||
test_response = session.get(test_url, params=test_params, timeout=10)
|
||||
test_data = test_response.json()
|
||||
|
||||
if test_data.get("success"):
|
||||
logger.info(f"API {api['name']}.{api['method']} v{test_version} РАБОТАЕТ!")
|
||||
logger.info(f"Результат: {json.dumps(test_data.get('data', {}), indent=2)[:200]}...")
|
||||
else:
|
||||
error_code = test_data.get("error", {}).get("code", -1)
|
||||
logger.error(f"API {api['name']}.{api['method']} v{test_version} ОШИБКА: {error_code}")
|
||||
|
||||
# Если ошибка связана с сессией, попробуем еще раз авторизоваться
|
||||
if error_code == 119: # Session timeout
|
||||
logger.info("Повторная авторизация из-за ошибки 119...")
|
||||
|
||||
# Создаем новую сессию
|
||||
new_session = requests.Session()
|
||||
new_session.verify = False
|
||||
|
||||
auth_response = new_session.get(auth_url, params=auth_params, timeout=10)
|
||||
auth_data = auth_response.json()
|
||||
|
||||
if auth_data.get("success"):
|
||||
new_sid = auth_data.get("data", {}).get("sid")
|
||||
logger.info(f"Повторная авторизация успешна! Новый SID: {new_sid[:10]}...")
|
||||
|
||||
# Пробуем запрос с новым SID
|
||||
test_params["_sid"] = new_sid
|
||||
logger.info(f"Повторное тестирование {api['name']}.{api['method']} v{test_version}")
|
||||
test_response = new_session.get(test_url, params=test_params, timeout=10)
|
||||
test_data = test_response.json()
|
||||
|
||||
if test_data.get("success"):
|
||||
logger.info(f"API {api['name']}.{api['method']} v{test_version} теперь РАБОТАЕТ!")
|
||||
logger.info(f"Результат с новой сессией: {json.dumps(test_data.get('data', {}), indent=2)[:200]}...")
|
||||
else:
|
||||
error_code = test_data.get("error", {}).get("code", -1)
|
||||
logger.error(f"API {api['name']}.{api['method']} v{test_version} ВСЕ ЕЩЕ С ОШИБКОЙ: {error_code}")
|
||||
else:
|
||||
logger.warning(f"API {api['name']} не найден в информации API")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при тестировании {api['name']}.{api['method']} v{api['version']}: {str(e)}")
|
||||
|
||||
# Шаг 3: Тестирование комбинации запросов для решения проблемы
|
||||
logger.info("Шаг 3: Тестирование комбинации запросов для решения проблемы")
|
||||
|
||||
# Создаем новую сессию для каждого запроса
|
||||
for api in [{"name": "SYNO.DSM.Info", "method": "getinfo", "version": 1}]:
|
||||
try:
|
||||
fresh_session = requests.Session()
|
||||
fresh_session.verify = False
|
||||
|
||||
# Авторизуемся
|
||||
auth_response = fresh_session.get(auth_url, params=auth_params, timeout=10)
|
||||
auth_data = auth_response.json()
|
||||
|
||||
if auth_data.get("success"):
|
||||
fresh_sid = auth_data.get("data", {}).get("sid")
|
||||
logger.info(f"Авторизация в новой сессии успешна! SID: {fresh_sid[:10]}...")
|
||||
|
||||
# Сразу же делаем запрос для получения информации в той же сессии
|
||||
test_params = {
|
||||
"api": api["name"],
|
||||
"version": str(api["version"]),
|
||||
"method": api["method"],
|
||||
"_sid": fresh_sid
|
||||
}
|
||||
|
||||
test_url = f"{base_url}/entry.cgi" # Используем entry.cgi по умолчанию
|
||||
logger.info(f"Тест в свежей сессии: {api['name']}.{api['method']} v{api['version']}")
|
||||
test_response = fresh_session.get(test_url, params=test_params, timeout=10)
|
||||
test_data = test_response.json()
|
||||
|
||||
if test_data.get("success"):
|
||||
logger.info(f"API в свежей сессии РАБОТАЕТ!")
|
||||
logger.info(f"Результат: {json.dumps(test_data.get('data', {}), indent=2)[:200]}...")
|
||||
else:
|
||||
error_code = test_data.get("error", {}).get("code", -1)
|
||||
logger.error(f"API в свежей сессии ОШИБКА: {error_code}")
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при тестировании свежей сессии: {str(e)}")
|
||||
|
||||
# Шаг 4: Получаем информацию об остальных API
|
||||
logger.info("Шаг 4: Получаем информацию о доступных API для уточнения проблемы")
|
||||
|
||||
# Запрашиваем все API из SYNO.API.Info
|
||||
try:
|
||||
all_api_params = {
|
||||
"api": "SYNO.API.Info",
|
||||
"version": "1",
|
||||
"method": "query",
|
||||
"query": "all"
|
||||
}
|
||||
|
||||
all_api_response = session.get(api_info_url, params=all_api_params, timeout=15) # Больший таймаут для большого ответа
|
||||
all_api_data = all_api_response.json()
|
||||
|
||||
if all_api_data.get("success"):
|
||||
api_list = all_api_data.get("data", {})
|
||||
logger.info(f"Получен список всех API. Найдено {len(api_list)} API.")
|
||||
|
||||
# Ищем интересующие нас API для отладки
|
||||
interested_in = ["SYNO.DSM.Info", "SYNO.Core.System", "SYNO.Core.Hardware",
|
||||
"SYNO.Core.System.Status", "SYNO.API.Auth"]
|
||||
|
||||
logger.info("Информация о важных API:")
|
||||
for api_name in interested_in:
|
||||
if api_name in api_list:
|
||||
logger.info(f"{api_name}: {api_list[api_name]}")
|
||||
else:
|
||||
logger.warning(f"API {api_name} не найден")
|
||||
else:
|
||||
logger.error("Не удалось получить список всех API")
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при получении списка API: {str(e)}")
|
||||
|
||||
else:
|
||||
error_code = auth_data.get("error", {}).get("code", -1)
|
||||
logger.error(f"Авторизация не удалась! Код ошибки: {error_code}")
|
||||
else:
|
||||
logger.error("Не удалось получить информацию об API авторизации")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Произошла ошибка при выполнении теста: {str(e)}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.info("Запуск прямого теста API Synology")
|
||||
direct_api_test()
|
||||
Reference in New Issue
Block a user