- med_diag_json_error() — ошибки в формате {'error': '...'} (WP_REST_Response)
- 4 проверки лимита 100 МБ (CONTENT_LENGTH, UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE, size)
- Проверка расширения файла (mp4/avi/mov/mkv/webm/m4v)
- Имя файла только ASCII (med-diag-upload.ext) — защита multipart
- filename скачивания из Content-Disposition бэкенда
- Овал .med-scan-oval (inset 12%, затемнение вне зоны)
- escapeHtml() + parseJson() — безопасная обработка ответов (XSS, HTML-ошибки)
- README: nginx лимиты, таблица ошибок
136 lines
9.0 KiB
Markdown
136 lines
9.0 KiB
Markdown
# Med Diagnostics — WordPress-плагин
|
||
|
||
Репозиторий: https://git.itguild.info/apuc/sber-med-wordpress
|
||
|
||
Интеграция сервиса «Диагностика по видео» (API-бэкенд med.my-dpr.ru) в WordPress.
|
||
Плагин выводит вёрстку сервиса (загрузка видео, сканирование с камеры, результат) прямо на странице сайта — без iframe.
|
||
|
||
## Установка
|
||
|
||
### Вариант 1: через админку (zip)
|
||
|
||
```bash
|
||
# из корня репозитория (папка репозитория = папка плагина)
|
||
zip -r med-diagnostics.zip . -x README.md
|
||
```
|
||
|
||
1. В админке WordPress: **Плагины → Добавить новый → Загрузить плагин** → выберите `med-diagnostics.zip` → **Установить** → **Активировать**.
|
||
|
||
### Вариант 2: копированием файлов
|
||
|
||
1. Скопируйте содержимое репозитория в `wp-content/plugins/med-diagnostics/` вашего WordPress.
|
||
2. В админке: **Плагины → Установленные** → активируйте **Med Diagnostics**.
|
||
|
||
### Использование
|
||
|
||
Вставьте шорткод в нужную страницу/запись:
|
||
|
||
```
|
||
[med_diagnostics]
|
||
```
|
||
|
||
Дополнительно можно задать заголовок:
|
||
|
||
```
|
||
[med_diagnostics title="Проверь своё здоровье"]
|
||
```
|
||
|
||
## Настройки
|
||
|
||
**Настройки → Med Diagnostics**:
|
||
|
||
| Поле | Описание |
|
||
|---|---|
|
||
| **Режим подключения** | `Через сервер (внутренний IP)` — браузер шлёт видео на этот WordPress, PHP проксирует запрос на внутренний IP бэкенда (по умолчанию, рекомендуется когда WordPress и API на одном сервере). `Напрямую из браузера (CORS)` — браузер обращается к публичному URL API. |
|
||
| **Внутренний URL бэкенда** | Адрес API, доступный с этого сервера (по умолчанию `http://127.0.0.1:18018`). Используется в режиме «Через сервер». |
|
||
| **Публичный URL API-бэкенда** | Публичный адрес Flask-приложения (по умолчанию `https://med.my-dpr.ru`). Используется в режиме «Напрямую» и для ссылки «Поделиться». |
|
||
|
||
Можно также переопределить кодом:
|
||
|
||
```php
|
||
add_filter('med_diag_api_url', fn() => 'https://другой-домен.ru');
|
||
add_filter('med_diag_internal_url', fn() => 'http://10.0.0.5:18018');
|
||
add_filter('med_diag_mode', fn() => 'direct');
|
||
```
|
||
|
||
## Как это работает
|
||
|
||
- **Режим «Через сервер» (по умолчанию)**: JS отправляет видео на REST-эндпоинт этого же WordPress (`/wp-json/med-diag/v1/analyze`), PHP пересылает его на внутренний IP бэкенда (`http://127.0.0.1:18018/analyze`). Скачивания PDF/DOCX/видео идут через `/wp-json/med-diag/v1/download/<id>/<type>`. CORS не нужен — все запросы same-origin.
|
||
- **Режим «Напрямую»**: JS отправляет видео на публичный URL API (`POST /analyze`) — тогда нужен CORS на стороне Flask.
|
||
- Результат (сводка, показатели, рекомендации, кнопки PDF/DOCX/видео/поделиться) рендерится на странице WordPress.
|
||
- Сканирование с камеры работает на мобильных (canvas 720×720 + MediaRecorder).
|
||
|
||
## Требования к серверу WordPress (режим «Через сервер»)
|
||
|
||
Видео сначала загружается в PHP, поэтому в `php.ini` должны быть подняты лимиты:
|
||
|
||
```ini
|
||
upload_max_filesize = 100M
|
||
post_max_size = 100M
|
||
max_execution_time = 300
|
||
```
|
||
|
||
Проверить текущие значения: `php -i | grep -E "upload_max_filesize|post_max_size|max_execution_time"`.
|
||
|
||
Если WordPress стоит за nginx, поднимите лимит и там — иначе nginx вернёт HTML-страницу `413 Request Entity Too Large`:
|
||
|
||
```nginx
|
||
client_max_body_size 100M;
|
||
client_body_timeout 300s;
|
||
proxy_read_timeout 300s;
|
||
```
|
||
|
||
## Обработка ошибок и лимитов
|
||
|
||
Серверная часть и плагин отдают ошибки **всегда в JSON** (`{"error": "..."}`), поэтому фронтенд никогда не получает HTML-страницу
|
||
вместо данных и не падает с `Unexpected token '<'` (аналог обработчиков `413/404/500` во Flask-бэкенде):
|
||
|
||
| Ситуация | Ответ | Сообщение |
|
||
|---|---|---|
|
||
| Файл больше 100 МБ (в т.ч. тело отброшено из-за `post_max_size`, `UPLOAD_ERR_INI_SIZE`) | `413` | «Видео слишком большое (максимум 100 МБ)» |
|
||
| Файл не передан | `400` | «Видео не загружено» |
|
||
| Формат не из списка `mp4/avi/mov/mkv/webm/m4v` | `400` | «Неподдерживаемый формат…» |
|
||
| Бэкенд недоступен | `502` | «Бэкенд недоступен: …» |
|
||
| Бэкенд вернул не JSON (HTML-страница ошибки nginx/Flask) | `502` | «Бэкенд вернул некорректный ответ (HTTP …)» |
|
||
| Ошибка анализа на бэкенде | статус бэкенда | текст бэкенда + `video_url` (ссылка «Скачать записанное видео») |
|
||
|
||
На стороне браузера ответ разбирается безопасно: если вместо JSON пришёл HTML, из него вырезаются теги и показывается короткое
|
||
текстовое сообщение (и оно экранируется перед вставкой в страницу).
|
||
|
||
## Требования к бэкенду (Flask)
|
||
|
||
В `app.py` серверного репозитория уже добавлена поддержка CORS (нужна только в режиме «Напрямую»):
|
||
|
||
- `Access-Control-Allow-Origin` — по умолчанию `*`, можно ограничить через env `CORS_ORIGINS` (список через запятую, например `https://site1.ru,https://site2.ru`).
|
||
- Preflight `OPTIONS /analyze` возвращает `204`.
|
||
|
||
Также во Flask добавлены обработчики ошибок `413/404/500`, всегда возвращающие JSON, и `try/except` вокруг сохранения видео —
|
||
поэтому и `POST /analyze`, и `/download/...` отдают ошибки в виде `{"error": "..."}`. Плагин ожидает такой же формат
|
||
(см. «Обработка ошибок и лимитов»), а на не-JSON (HTML) ответы реагирует безопасно.
|
||
|
||
## Локальное тестирование
|
||
|
||
1. Поднимите API-бэкенд локально (см. README серверного репозитория) или используйте прод `https://med.my-dpr.ru`.
|
||
2. Установите плагин в локальный WordPress (например, на `http://wp.loc` через Apache vhost).
|
||
3. Создайте страницу с шорткодом `[med_diagnostics]` и откройте её.
|
||
4. Проверьте в консоли браузера, что `MED_DIAG.apiUrl` указывает на нужный бэкенд, и что запрос `POST /analyze` проходит (CORS).
|
||
|
||
## Ограничения
|
||
|
||
- Шорткод используйте **один раз на странице** (id элементов фиксированы).
|
||
- Для работы сканирования с камеры нужен HTTPS на сайте WordPress (getUserMedia требует secure context).
|
||
- В режиме «Через сервер» видео загружается в PHP — следите за лимитами `upload_max_filesize`/`post_max_size`/`max_execution_time` (см. выше).
|
||
- Ссылка «Поделиться» всегда ведёт на публичный URL API (`/r/<share_id>`).
|
||
|
||
## Структура
|
||
|
||
Корень репозитория = папка плагина:
|
||
|
||
```
|
||
med-diagnostics/
|
||
├── med-diagnostics.php — главный файл плагина (шорткод, настройки, ассеты)
|
||
├── README.md — этот файл (в zip не попадает)
|
||
└── assets/
|
||
├── css/med-diag.css — стили сервиса (префикс med-)
|
||
└── js/med-diag.js — логика (fetch на API, сканирование, рендер результата)
|
||
``` |