# Руководство по API для фронтенда ## Обзор изменений После рефакторинга старый `ParserController` был разделен на три специализированных контроллера для лучшей организации и масштабируемости: - **`MarketItemController`** (`/api/items`) - для получения данных - **`ParserAdminController`** (`/api/admin/parsers`) - для управления парсерами - **`HealthCheckController`** (`/api/health`) - для мониторинга системы --- ## 📊 MarketItemController - Получение данных **Базовый URL**: `/api/items` ### 1. Получение списка новостей с фильтрацией и пагинацией ```http GET /api/items ``` **Параметры запроса:** - `sourceName` (optional) - фильтр по источнику (например: "Kursiv Media", "Kapital.kz", "LSM.kz", "РБК", "Ведомости") - `startDate` (optional) - начальная дата в формате ISO (например: "2024-01-01T00:00:00") - `endDate` (optional) - конечная дата в формате ISO (например: "2024-12-31T23:59:59") - `page` (optional) - номер страницы (по умолчанию: 0) - `size` (optional) - размер страницы (по умолчанию: 20) - `sort` (optional) - сортировка (по умолчанию: "publishedAt,desc") **Примеры запросов:** ```javascript // Получить все новости fetch('/api/items'); // Получить новости с пагинацией fetch('/api/items?page=0&size=10'); // Получить новости от конкретного источника fetch('/api/items?sourceName=Kursiv Media'); // Получить новости за последние 7 дней const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(); fetch(`/api/items?startDate=${weekAgo}`); // Получить новости с сортировкой по дате (старые сначала) fetch('/api/items?sort=publishedAt,asc'); ``` **Ответ:** ```json { "success": true, "message": "Записи получены успешно", "data": { "content": [ { "id": "64f1a2b3c4d5e6f7g8h9i0j1", "sourceName": "Kursiv Media", "url": "https://kursiv.media/news/example", "title": "Заголовок новости", "publishedAt": "2024-01-15T10:30:00", "addedAt": "2024-01-15T10:35:00", "rawText": "Текст новости без HTML тегов", "hash": "abc123def456...", "category": "Бизнес", "analytics": { "summary": null, "sentiment": null, "tags": [], "entities": {} } } ], "pageable": { "sort": { "sorted": true, "unsorted": false }, "pageNumber": 0, "pageSize": 20, "offset": 0, "paged": true, "unpaged": false }, "totalElements": 150, "totalPages": 8, "last": false, "first": true, "numberOfElements": 20, "size": 20, "number": 0, "empty": false } } ``` ### 2. Получение новости по ID ```http GET /api/items/{id} ``` **Пример:** ```javascript fetch('/api/items/64f1a2b3c4d5e6f7g8h9i0j1'); ``` **Ответ:** ```json { "success": false, "message": "Функция поиска по ID пока не реализована" } ``` ### 3. Получение статистики ```http GET /api/items/stats ``` **Ответ:** ```json { "success": true, "message": "Статистика получена успешно", "data": { "totalItems": 1250, "sourceStatistics": { "Kursiv Media": 300, "Kapital.kz": 250, "LSM.kz": 200, "РБК": 300, "Ведомости": 200 }, "lastUpdate": "2024-01-15T10:35:00" } } ``` ### 4. Получение списка источников ```http GET /api/items/sources ``` **Ответ:** ```json { "success": true, "message": "Источники получены успешно", "data": ["Kursiv Media", "Kapital.kz", "LSM.kz", "РБК", "Ведомости"] } ``` ### 5. Получение новостей по конкретному источнику ```http GET /api/items/source/{sourceName} ``` **Пример:** ```javascript fetch('/api/items/source/Kursiv Media?page=0&size=10'); ``` **Ответ:** Аналогичен ответу от `/api/items`, но только с новостями от указанного источника. --- ## ⚙️ ParserAdminController - Управление парсерами **Базовый URL**: `/api/admin/parsers` > ⚠️ **Важно**: Эти эндпоинты предназначены для административных функций и могут потребовать аутентификации в будущем. ### 1. Запуск конкретного парсера ```http POST /api/admin/parsers/parse/{sourceName} ``` **Доступные источники:** - `kursiv` - `kapital` - `lsm` - `rbc` - `vedomosti` **Пример:** ```javascript // Запустить парсер Kursiv fetch('/api/admin/parsers/parse/kursiv', { method: 'POST' }); // Запустить парсер РБК fetch('/api/admin/parsers/parse/rbc', { method: 'POST' }); ``` **Ответ:** ```json { "success": true, "message": "Парсинг kursiv завершен", "data": { "source": "kursiv", "processedItems": 15, "totalItemsInDb": 1265, "status": "completed" } } ``` ### 2. Запуск всех парсеров ```http POST /api/admin/parsers/parse/all ``` **Пример:** ```javascript fetch('/api/admin/parsers/parse/all', { method: 'POST' }); ``` **Ответ:** ```json { "success": true, "message": "Парсинг всех источников завершен", "data": [ { "source": "kursiv", "processedItems": 12, "totalItemsInDb": 1277, "status": "completed" }, { "source": "kapital", "processedItems": 8, "totalItemsInDb": 1285, "status": "completed" }, { "source": "lsm", "processedItems": 5, "totalItemsInDb": 1290, "status": "completed" }, { "source": "rbc", "processedItems": 20, "totalItemsInDb": 1310, "status": "completed" }, { "source": "vedomosti", "processedItems": 7, "totalItemsInDb": 1317, "status": "completed" } ] } ``` ### 3. Получение списка доступных парсеров ```http GET /api/admin/parsers ``` **Ответ:** ```json { "success": true, "message": "Список парсеров получен", "data": ["kapital", "kursiv", "lsm", "rbc", "vedomosti"] } ``` ### 4. Получение информации о парсерах ```http GET /api/admin/parsers/info ``` **Ответ:** ```json { "success": true, "message": "Информация о парсерах получена", "data": { "totalParsers": 5, "availableParsers": ["kapital", "kursiv", "lsm", "rbc", "vedomosti"], "totalItems": 1317, "sourceStatistics": { "Kursiv Media": 300, "Kapital.kz": 250, "LSM.kz": 200, "РБК": 300, "Ведомости": 200 } } } ``` ### 5. Проверка существования парсера ```http GET /api/admin/parsers/exists/{sourceName} ``` **Пример:** ```javascript fetch('/api/admin/parsers/exists/kursiv'); ``` **Ответ:** ```json { "success": true, "message": "Проверка завершена", "data": true } ``` --- ## 🔍 HealthCheckController - Мониторинг системы **Базовый URL**: `/api/health` ### 1. Базовая проверка состояния ```http GET /api/health ``` **Ответ:** ```json { "success": true, "message": "Сервис работает", "data": { "status": "UP", "service": "RSS Parser System", "timestamp": 1705312500000, "details": "Enabled - runs every 30 minutes" } } ``` ### 2. Проверка подключения к MongoDB ```http GET /api/health/mongodb ``` **Ответ (успех):** ```json { "success": true, "message": "MongoDB подключение успешно", "data": { "status": "UP", "service": "MongoDB подключение успешно", "timestamp": 1705312500000, "details": "Всего записей: 1317" } } ``` **Ответ (ошибка):** ```json { "success": false, "message": "Ошибка подключения к MongoDB", "data": { "status": "DOWN", "service": "Ошибка подключения к MongoDB: Connection refused", "timestamp": 1705312500000, "suggestion": "Проверьте учетные данные в application.properties" } } ``` ### 3. Информация о планировщике ```http GET /api/health/scheduler ``` **Ответ:** ```json { "success": true, "message": "Информация о планировщике получена", "data": { "schedulerEnabled": true, "cronExpression": "0 0/30 * * * ?", "description": "Запуск каждые 30 минут (в 0 и 30 минут каждого часа)", "nextRun": "Следующий запуск будет в ближайшие 0 или 30 минут часа", "activeParsers": ["kapital", "kursiv", "lsm", "rbc", "vedomosti"], "totalParsers": 5, "sources": ["Kursiv Media", "Kapital.kz", "LSM.kz", "РБК", "Ведомости"] } } ``` ### 4. Общая информация о системе ```http GET /api/health/system ``` **Ответ:** ```json { "success": true, "message": "Информация о системе получена", "data": { "parsers": { "total": 5, "available": ["kapital", "kursiv", "lsm", "rbc", "vedomosti"] }, "data": { "totalItems": 1317, "sourceStatistics": { "Kursiv Media": 300, "Kapital.kz": 250, "LSM.kz": 200, "РБК": 300, "Ведомости": 200 } }, "system": { "javaVersion": "17.0.2", "osName": "Linux", "osVersion": "5.4.0-74-generic", "uptime": 1705312500000 } } } ``` ### 5. Проверка состояния парсеров ```http GET /api/health/parsers ``` **Ответ:** ```json { "success": true, "message": "Проверка парсеров завершена", "data": { "totalParsers": 5, "availableParsers": ["kapital", "kursiv", "lsm", "rbc", "vedomosti"], "status": "UP", "message": "Все парсеры доступны" } } ``` --- ## 🚀 Примеры использования для фронтенда ### React/JavaScript примеры ```javascript // Сервис для работы с API class NewsApiService { constructor(baseUrl = '') { this.baseUrl = baseUrl; } // Получить новости с фильтрацией async getNews(filters = {}) { const params = new URLSearchParams(); if (filters.sourceName) params.append('sourceName', filters.sourceName); if (filters.startDate) params.append('startDate', filters.startDate); if (filters.endDate) params.append('endDate', filters.endDate); if (filters.page !== undefined) params.append('page', filters.page); if (filters.size) params.append('size', filters.size); if (filters.sort) params.append('sort', filters.sort); const response = await fetch(`${this.baseUrl}/api/items?${params}`); return response.json(); } // Получить статистику async getStats() { const response = await fetch(`${this.baseUrl}/api/items/stats`); return response.json(); } // Получить источники async getSources() { const response = await fetch(`${this.baseUrl}/api/items/sources`); return response.json(); } // Запустить парсер (админ функция) async runParser(sourceName) { const response = await fetch( `${this.baseUrl}/api/admin/parsers/parse/${sourceName}`, { method: 'POST', } ); return response.json(); } // Запустить все парсеры (админ функция) async runAllParsers() { const response = await fetch( `${this.baseUrl}/api/admin/parsers/parse/all`, { method: 'POST', } ); return response.json(); } // Проверить состояние системы async getHealthStatus() { const response = await fetch(`${this.baseUrl}/api/health`); return response.json(); } } // Использование const apiService = new NewsApiService(); // Получить последние новости const news = await apiService.getNews({ page: 0, size: 20, sort: 'publishedAt,desc', }); // Получить новости от конкретного источника const kursivNews = await apiService.getNews({ sourceName: 'Kursiv Media', page: 0, size: 10, }); // Получить новости за последнюю неделю const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(); const recentNews = await apiService.getNews({ startDate: weekAgo, sort: 'publishedAt,desc', }); ``` ### Vue.js примеры ```javascript // composable для работы с API export function useNewsApi() { const baseUrl = ''; const getNews = async (filters = {}) => { const params = new URLSearchParams(); Object.entries(filters).forEach(([key, value]) => { if (value !== undefined && value !== null) { params.append(key, value); } }); const response = await fetch(`${baseUrl}/api/items?${params}`); return response.json(); }; const getStats = async () => { const response = await fetch(`${baseUrl}/api/items/stats`); return response.json(); }; const getSources = async () => { const response = await fetch(`${baseUrl}/api/items/sources`); return response.json(); }; return { getNews, getStats, getSources, }; } ``` --- ## 📝 Важные замечания 1. **Пагинация**: Все эндпоинты для получения данных поддерживают пагинацию через параметры `page` и `size`. 2. **Сортировка**: По умолчанию новости сортируются по дате публикации (новые сначала). Можно изменить через параметр `sort`. 3. **Фильтрация**: Поддерживается фильтрация по источнику и диапазону дат. 4. **Формат дат**: Используйте ISO 8601 формат для дат (например: "2024-01-15T10:30:00"). 5. **Обработка ошибок**: Все ответы содержат поле `success` для проверки успешности операции. 6. **Административные функции**: Эндпоинты `/api/admin/parsers/*` предназначены для административных функций. 7. **Мониторинг**: Используйте эндпоинты `/api/health/*` для проверки состояния системы. --- ## 🔄 Миграция с старого API Если у вас был код, использующий старый `ParserController`, вот соответствие эндпоинтов: | Старый эндпоинт | Новый эндпоинт | | ---------------------------------- | ----------------------------------------- | | `POST /api/parser/parse/kursiv` | `POST /api/admin/parsers/parse/kursiv` | | `POST /api/parser/parse/kapital` | `POST /api/admin/parsers/parse/kapital` | | `POST /api/parser/parse/lsm` | `POST /api/admin/parsers/parse/lsm` | | `POST /api/parser/parse/rbc` | `POST /api/admin/parsers/parse/rbc` | | `POST /api/parser/parse/vedomosti` | `POST /api/admin/parsers/parse/vedomosti` | | `POST /api/parser/parse/all` | `POST /api/admin/parsers/parse/all` | | `GET /api/parser/items` | `GET /api/items` | | `GET /api/parser/stats` | `GET /api/items/stats` | | `GET /api/parser/health` | `GET /api/health` | | `GET /api/parser/health/mongodb` | `GET /api/health/mongodb` | | `GET /api/parser/scheduler/info` | `GET /api/health/scheduler` |