Files
nas_control_bot/.history/test_api_headers_20250830084440.py
2025-08-30 10:33:46 +09:00

392 lines
22 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Тестовый скрипт для диагностики проблемы с использованием специальных заголовков
"""
import requests
import logging
import json
import sys
import os
import urllib3
import time
import socket
from requests.adapters import HTTPAdapter
from urllib3.util import Retry
# Отключение предупреждений о небезопасных 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__)
# Тестовые учетные данные (для примера)
SYNOLOGY_HOST = "192.168.0.102"
SYNOLOGY_PORT = 5000
SYNOLOGY_USERNAME = "superadmin"
SYNOLOGY_PASSWORD = "Cl0ud_1985!"
SYNOLOGY_SECURE = False
SYNOLOGY_TIMEOUT = 10
def test_api_with_headers():
"""Тестирование API с использованием специальных заголовков для решения проблемы 119"""
# Создаем сессию
session = requests.Session()
session.verify = False # Отключаем проверку SSL
# Настройки повторных попыток
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: Получение SID с настройкой cookie и user-agent
logger.info("Тест 1: Авторизация с настройкой cookie и user-agent")
# Добавление пользовательских заголовков
custom_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7',
'X-Requested-With': 'XMLHttpRequest',
'Connection': 'keep-alive',
'Referer': f'{protocol}://{SYNOLOGY_HOST}:{SYNOLOGY_PORT}/'
}
session.headers.update(custom_headers)
try:
# Определяем путь для авторизации
auth_info_url = f"{base_url}/entry.cgi"
auth_info_params = {
"api": "SYNO.API.Info",
"version": "1",
"method": "query",
"query": "SYNO.API.Auth"
}
auth_info_response = session.get(auth_info_url, params=auth_info_params)
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}")
# Используем версию 3 вместо 6 - тестирование на возможное решение проблемы
auth_version = min(3, auth_max_version) # Пробуем более старую версию API
# Выполняем авторизацию
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": "DirectHeaderTest",
"format": "cookie"
}
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)
auth_data = auth_response.json()
if auth_data.get("success"):
sid = auth_data.get("data", {}).get("sid")
logger.info(f"Авторизация успешна! SID: {sid[:10]}...")
# Теперь проверим, работает ли получение информации о системе
# с настройкой cookie и заголовков
# Сначала настроим куки для сохранения SID
cookies = {
'id': sid,
'sid': sid
}
session.cookies.update(cookies)
# Определяем путь для SYNO.DSM.Info
info_info_url = f"{base_url}/entry.cgi"
info_info_params = {
"api": "SYNO.API.Info",
"version": "1",
"method": "query",
"query": "SYNO.DSM.Info"
}
info_info_response = session.get(info_info_url, params=info_info_params)
info_info_data = info_info_response.json()
if info_info_data.get("success"):
info_info = info_info_data.get("data", {}).get("SYNO.DSM.Info", {})
info_path = info_info.get("path", "entry.cgi")
info_max_version = info_info.get("maxVersion", 1)
info_min_version = info_info.get("minVersion", 1)
logger.info(f"API SYNO.DSM.Info: путь={info_path}, версия={info_min_version}-{info_max_version}")
# Используем правильную версию API
info_version = min(2, info_max_version)
# Делаем запрос для получения информации о системе
# с использованием sid как параметр запроса
logger.info("Тест 2: Получение информации о системе с SID как параметром")
info_url = f"{base_url}/{info_path}"
info_params = {
"api": "SYNO.DSM.Info",
"version": str(info_version),
"method": "getinfo",
"_sid": sid
}
logger.info(f"Запрос информации с использованием SYNO.DSM.Info v{info_version}")
info_response = session.get(info_url, params=info_params)
info_data = info_response.json()
if info_data.get("success"):
logger.info("Успешно получена информация о системе!")
logger.info(f"Данные: {json.dumps(info_data.get('data', {}), indent=2)}")
else:
error_code = info_data.get("error", {}).get("code", -1)
logger.error(f"Не удалось получить информацию о системе. Ошибка: {error_code}")
# Пробуем альтернативный способ
logger.info("Тест 3: Попытка получить базовую информацию через SYNO.Core.System")
# Определяем путь для SYNO.Core.System
system_info_url = f"{base_url}/entry.cgi"
system_info_params = {
"api": "SYNO.API.Info",
"version": "1",
"method": "query",
"query": "SYNO.Core.System"
}
system_info_response = session.get(system_info_url, params=system_info_params)
system_info_data = system_info_response.json()
if system_info_data.get("success"):
system_info = system_info_data.get("data", {}).get("SYNO.Core.System", {})
system_path = system_info.get("path", "entry.cgi")
system_max_version = system_info.get("maxVersion", 1)
system_min_version = system_info.get("minVersion", 1)
logger.info(f"API SYNO.Core.System: путь={system_path}, версия={system_min_version}-{system_max_version}")
# Используем правильную версию API
system_version = 1
# Пробуем альтернативную стратегию с X-SYNO-TOKEN
# Некоторые API Synology требуют специальный токен в заголовках
token = auth_data.get("data", {}).get("synotoken")
if token:
session.headers.update({'X-SYNO-TOKEN': token})
logger.info(f"Добавлен X-SYNO-TOKEN: {token}")
# Делаем запрос для получения информации о системе
system_url = f"{base_url}/{system_path}"
system_params = {
"api": "SYNO.Core.System",
"version": str(system_version),
"method": "info",
"_sid": sid
}
logger.info(f"Запрос информации с использованием SYNO.Core.System v{system_version}")
system_response = session.get(system_url, params=system_params)
system_data = system_response.json()
if system_data.get("success"):
logger.info("Успешно получена информация о системе через SYNO.Core.System!")
logger.info(f"Данные: {json.dumps(system_data.get('data', {}), indent=2)}")
else:
error_code = system_data.get("error", {}).get("code", -1)
logger.error(f"Не удалось получить информацию через SYNO.Core.System. Ошибка: {error_code}")
# Пробуем другие методы для диагностики
logger.info("Тест 4: Попытка использовать различные методы и заголовки")
# Пробуем создать полностью новую сессию
new_session = requests.Session()
new_session.verify = False
new_session.headers.update(custom_headers)
# Пробуем версию 1 для авторизации
auth_version = 1
auth_params["version"] = str(auth_version)
auth_response = new_session.get(auth_url, params=auth_params)
auth_data = auth_response.json()
if auth_data.get("success"):
sid = auth_data.get("data", {}).get("sid")
logger.info(f"Новая авторизация (v{auth_version}) успешна! SID: {sid[:10]}...")
# Добавляем SID как куки
cookies = {
'id': sid,
'sid': sid
}
new_session.cookies.update(cookies)
# Пробуем другой подход: разделение запросов во времени
logger.info("Тест 5: Разделение запросов во времени")
# Даем некоторое время для инициализации сессии на сервере
time.sleep(2)
# Пробуем получить список файлов
filestation_info_url = f"{base_url}/entry.cgi"
filestation_info_params = {
"api": "SYNO.API.Info",
"version": "1",
"method": "query",
"query": "SYNO.FileStation.List"
}
filestation_info_response = new_session.get(filestation_info_url, params=filestation_info_params)
filestation_info_data = filestation_info_response.json()
if filestation_info_data.get("success"):
filestation_info = filestation_info_data.get("data", {}).get("SYNO.FileStation.List", {})
filestation_path = filestation_info.get("path", "entry.cgi")
filestation_max_version = filestation_info.get("maxVersion", 1)
logger.info(f"API SYNO.FileStation.List: путь={filestation_path}, макс. версия={filestation_max_version}")
# Используем правильную версию API
filestation_version = min(2, filestation_max_version)
# Делаем запрос для получения списка общих папок
filestation_url = f"{base_url}/{filestation_path}"
filestation_params = {
"api": "SYNO.FileStation.List",
"version": str(filestation_version),
"method": "list_share",
"_sid": sid
}
logger.info(f"Запрос списка общих папок с использованием SYNO.FileStation.List v{filestation_version}")
filestation_response = new_session.get(filestation_url, params=filestation_params)
filestation_data = filestation_response.json()
if filestation_data.get("success"):
logger.info("Успешно получен список общих папок!")
shares = filestation_data.get("data", {}).get("shares", [])
logger.info(f"Общие папки: {json.dumps(shares, indent=2)[:200]}...")
else:
error_code = filestation_data.get("error", {}).get("code", -1)
logger.error(f"Не удалось получить список общих папок. Ошибка: {error_code}")
else:
error_code = auth_data.get("error", {}).get("code", -1)
logger.error(f"Новая авторизация не удалась! Код ошибки: {error_code}")
else:
logger.error("Не удалось получить информацию о SYNO.Core.System API")
else:
logger.error("Не удалось получить информацию о SYNO.DSM.Info API")
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)}")
# Тест 6: Проверка сетевой доступности
logger.info("Тест 6: Проверка сетевой доступности")
try:
# Проверка базового TCP-соединения
socket_obj = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_obj.settimeout(SYNOLOGY_TIMEOUT)
result = socket_obj.connect_ex((SYNOLOGY_HOST, SYNOLOGY_PORT))
socket_obj.close()
if result == 0:
logger.info("TCP-соединение успешно установлено")
else:
logger.error(f"Не удалось установить TCP-соединение, код ошибки: {result}")
except Exception as e:
logger.error(f"Ошибка при проверке TCP-соединения: {str(e)}")
# Тест 7: Запрос без аутентификации для проверки доступности API
logger.info("Тест 7: Запрос без аутентификации для проверки доступности API")
try:
# Создаем новую сессию без аутентификации
simple_session = requests.Session()
simple_session.verify = False
# Запрос к SYNO.API.Info не требует аутентификации
api_info_url = f"{base_url}/entry.cgi"
api_info_params = {
"api": "SYNO.API.Info",
"version": "1",
"method": "query",
"query": "all"
}
logger.info("Запрос информации о всех API без аутентификации")
api_info_response = simple_session.get(api_info_url, params=api_info_params)
if api_info_response.status_code == 200:
logger.info("API доступно без аутентификации")
api_info_data = api_info_response.json()
if api_info_data.get("success"):
logger.info("Успешно получена информация о всех API")
api_count = len(api_info_data.get("data", {}))
logger.info(f"Количество доступных API: {api_count}")
# Поиск API для управления питанием
power_apis = []
for api_name, api_info in api_info_data.get("data", {}).items():
if "power" in api_name.lower() or "reboot" in api_name.lower() or "shutdown" in api_name.lower():
power_apis.append(f"{api_name}: {api_info}")
logger.info(f"Найдены API для управления питанием: {power_apis}")
# Поиск API для получения информации о системе
info_apis = []
for api_name, api_info in api_info_data.get("data", {}).items():
if "info" in api_name.lower() or "system" in api_name.lower() or "status" in api_name.lower():
info_apis.append(f"{api_name}: {api_info}")
logger.info(f"Найдены API для информации о системе: {info_apis[:5]} и еще {len(info_apis)-5}")
else:
error_code = api_info_data.get("error", {}).get("code", -1)
logger.error(f"Запрос к API без аутентификации не удался! Код ошибки: {error_code}")
else:
logger.error(f"API не доступно без аутентификации. HTTP статус: {api_info_response.status_code}")
except Exception as e:
logger.error(f"Ошибка при проверке доступности API: {str(e)}")
if __name__ == "__main__":
logger.info("Запуск теста API с заголовками")
test_api_with_headers()