FileScan API

Документация REST API

Сервис для проверки файлов на вирусы четырьмя независимыми движками. Поддерживается одиночное сканирование, пакетная обработка и кеширование результатов по SHA-256.

shield ClamAV policy YARA Forge verified_user Kaspersky bug_report Dr.Web

info 1. Назначение и принцип работы

Сервис принимает загруженный файл и прогоняет его через четыре антивирусных движка одновременно. Если хотя бы один движок нашёл угрозу — файл считается заражённым (infected: true). Если все движки сказали «чисто» — файл безопасен (clean: true).

Результаты сканирования кешируются по SHA-256 хешу файла. При повторной загрузке того же файла ответ возвращается из кеша мгновенно.

Базовый URL

https://scan.fdw.ru

Движки

ДвижокТипЧто детектит
ClamAVOpen-source AVИзвестные семейства malware по сигнатурам
YARA ForgePattern-matching~10 000 курируемых правил, malware и эксплойты
Kaspersky KESLКоммерческий AVПолный движок Касперского + KSN облако
Dr.WebКоммерческий AVДвижок Доктор Веб

lock 2. Авторизация

Все запросы к API требуют HTTP-заголовок X-Api-Key с действующим ключом. Ключ выдаёт администратор.

X-Api-Key: ваш_ключ_здесь

Если ключ неверный, сервер вернёт 403 Forbidden.

api 3. Эндпоинты

POST /api/scan

Сканировать один файл. Тело запроса — multipart/form-data, поле file.

curl -X POST https://scan.fdw.ru/api/scan \ -H "X-Api-Key: YOUR_API_KEY" \ -F "file=@/path/to/file.exe"

POST /api/scan-batch

Сканировать пачку файлов (до 20 за один запрос). Тело — multipart/form-data, поле files повторяется несколько раз.

curl -X POST https://scan.fdw.ru/api/scan-batch \ -H "X-Api-Key: YOUR_API_KEY" \ -F "files=@a.exe" -F "files=@b.pdf" -F "files=@c.doc"

Внутри сервер обрабатывает файлы последовательно. Для параллельной обработки делайте несколько запросов /api/scan с клиента (см. раздел 6).

GET /api/check/{sha256}

Проверить, есть ли результат сканирования для файла с заданным SHA-256 в кеше. Файл загружать не нужно.

curl https://scan.fdw.ru/api/check/275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f

Если файл никогда не сканировался — {"found": false, "sha256": "..."}.

GET /api/stats

Общая статистика: сколько уникальных файлов в кеше, сколько из них заражённых, сколько всего запросов сканирования (с учётом cache-hit'ов).

curl https://scan.fdw.ru/api/stats

data_object 4. Формат ответа

Все ответы — JSON. Результат для одного файла:

{ "filename": "report.pdf", "size": 13264, "sha256": "3df79d34abbca99308e79cb94461c1893582604d68329a41fd4bec1885e6adb4", "clean": true, "infected": false, "cached": false, "results": { "clamav": { "status": "clean", "threat": null }, "yara": { "status": "clean", "threat": null }, "kaspersky": { "status": "clean", "threat": null }, "drweb": { "status": "clean", "threat": null } } }

Поля верхнего уровня

ПолеТипОписание
filenamestringИмя файла из запроса
sizeintegerРазмер файла в байтах
sha256stringSHA-256 хеш файла (используется как ключ кеша)
cleanbooleantrue, если ни один движок не нашёл угрозу
infectedbooleantrue, если хотя бы один движок нашёл угрозу
cachedbooleantrue, если ответ взят из кеша (файл уже сканировался ранее)
scan_datestringДата исходного сканирования (только для cached: true)
scan_countintegerСколько раз файл проверяли (только для cached: true)
resultsobjectРезультаты по каждому движку (см. ниже)

Статусы движков (поле status)

cleanДвижок не нашёл угрозу
infectedУгроза найдена, имя в поле threat
unavailableДвижок временно недоступен (нет лицензии, не запущен)
errorОшибка сканирования, подробности в error

Ответ при заражённом файле (пример с EICAR)

{ "filename": "test.com", "size": 68, "sha256": "275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f", "clean": false, "infected": true, "cached": false, "results": { "clamav": { "status": "infected", "threat": "Eicar-Test-Signature" }, "yara": { "status": "infected", "threat": "TRELLIX_ARC_Malw_Eicar" }, "kaspersky": { "status": "infected", "threat": "EICAR-Test-File" }, "drweb": { "status": "clean", "threat": null } } }

Ответ /api/scan-batch

{ "count": 3, "infected_count": 1, "results": [ { /* объект как для /api/scan */ }, { /* ... */ }, { /* ... */ } ] }

Привязка ответа к конкретному файлу запроса — по полю filename или sha256 внутри каждого элемента results[].

tune 5. Лимиты

ПараметрЗначение
Максимальный размер одного файла100 МБ
Максимум файлов в одном /api/scan-batch20
Таймаут одного скана (KESL и Dr.Web)120 секунд
Параллельных запросов на сервере2 worker'а (см. раздел 6)

Превышение лимита файла413 Payload Too Large. Превышение лимита пакета400 Bad Request с описанием.

bolt 6. Параллельные запросы

Сервис запущен с двумя worker-процессами. Реальная производительность параллелизма зависит от размера файлов:

Лёгкие файлы (< 1 МБ)
До 4–5 параллельных запросов с минимальным замедлением. ClamAV+YARA реально параллелятся между worker'ами.
Тяжёлые файлы (5+ МБ)
Kaspersky и Dr.Web сериализуют свою часть. Параллелятся только ClamAV+YARA. Прирост ~10%.

Если нужно сканировать много файлов разом — используйте либо /api/scan-batch (до 20 файлов одним запросом), либо concurrent.futures на клиенте с несколькими параллельными запросами /api/scan.

code 7. Примеры на Python

Один файл

import requests resp = requests.post( "https://scan.fdw.ru/api/scan", headers={"X-Api-Key": "YOUR_API_KEY"}, files={"file": open("file.exe", "rb")}, timeout=180, ) data = resp.json() print(f"SHA-256: {data['sha256']}") print(f"Cached: {data['cached']}") print("Clean" if data["clean"] else "INFECTED!")

Пачка файлов через batch

import requests files = [("files", open(p, "rb")) for p in ["a.exe", "b.pdf", "c.doc"]] resp = requests.post( "https://scan.fdw.ru/api/scan-batch", headers={"X-Api-Key": "YOUR_API_KEY"}, files=files, timeout=600, ) data = resp.json() print(f"{data['infected_count']}/{data['count']} infected") for r in data["results"]: print(r["filename"], r["sha256"], "INFECTED" if r.get("infected") else "ok")

Несколько параллельных запросов с клиента

import requests from concurrent.futures import ThreadPoolExecutor def scan_one(path): with open(path, "rb") as f: return requests.post( "https://scan.fdw.ru/api/scan", headers={"X-Api-Key": "YOUR_API_KEY"}, files={"file": f}, timeout=180, ).json() with ThreadPoolExecutor(max_workers=4) as ex: for r in ex.map(scan_one, ["a.exe", "b.pdf", "c.doc"]): print(r["filename"], "INFECTED" if r["infected"] else "ok")

Проверка по хешу без загрузки файла

import hashlib, requests sha = hashlib.sha256(open("file.exe","rb").read()).hexdigest() r = requests.get(f"https://scan.fdw.ru/api/check/{sha}").json() if r["found"]: print("Уже сканировали:", "INFECTED" if r["infected"] else "clean") else: print("Файла нет в кеше, нужен полноценный /api/scan")

help 8. Коды ответа

КодОписание
200 OKЗапрос выполнен, файл просканирован, см. JSON
400 Bad RequestНеверный запрос (например, > 20 файлов в batch)
403 ForbiddenНеверный X-Api-Key
413 Payload Too LargeФайл больше 100 МБ
422 Unprocessable EntityНеверная структура multipart-формы
500 / 504Внутренняя ошибка / таймаут одного из движков (попробуйте позже)