Загрузка файлов через JSON-RPC: multipart, валидация и CSRF

JSON-RPC — это протокол, который отлично подходит для вызова удалённых процедур, но в нём нет встроенного типа для передачи файлов. Тем не менее, задача загрузить файл через JSON-RPC возникает довольно часто, особенно при разработке API для веб-приложений. В этой статье мы разберём, как решить эту п

Загрузка файлов через JSON-RPC: multipart, валидация и CSRF

JSON-RPC — это протокол, который отлично подходит для вызова удалённых процедур, но в нём нет встроенного типа для передачи файлов. Тем не менее, задача загрузить файл через JSON-RPC возникает довольно часто, особенно при разработке API для веб-приложений. В этой статье мы разберём, как решить эту проблему на примере библиотеки otezvikentiy/json-rpc-api версии 5.2, которая недавно получила поддержку multipart-запросов. Вы узнаете, как это работает, как настроить валидацию загружаемых файлов и почему важно помнить о защите от CSRF.

Почему JSON-RPC не подходит для передачи файлов

JSON-RPC — это простой протокол, основанный на JSON, который позволяет клиенту вызывать методы на сервере. Он широко используется в современных API благодаря своей простоте и лёгкости. Однако JSON — это текстовый формат, который может представлять только базовые типы данных: строки, числа, булевы значения, массивы и объекты. Файлы — это бинарные данные, которые невозможно напрямую встроить в JSON без дополнительных ухищрений, таких как base64-кодирование. Но base64 увеличивает размер данных примерно на 33%, что неэффективно для больших файлов, и неудобно для потоковой передачи.

Поэтому разработчики часто ищут обходные пути. Один из них — использовать multipart/form-data, который изначально разработан для передачи файлов в HTTP-запросах. Но как совместить его с JSON-RPC? Именно эту задачу решает библиотека otezvikentiy/json-rpc-api, добавив поддержку multipart как транспортного адаптера.

Как работает multipart в otezvikentiy/json-rpc-api 5.2

Библиотека otezvikentiy/json-rpc-api — это PHP-реализация JSON-RPC 2.0, которая позволяет легко создавать JSON-RPC серверы и клиенты. В версии 5.2 появилась возможность принимать файлы через multipart-запросы. Идея заключается в том, что клиент отправляет обычный JSON-RPC запрос, но в поле params вместо JSON-объекта вставляет multipart-данные. Сервер распознаёт это и обрабатывает файлы как специальные параметры.

На практике это выглядит так: клиент формирует multipart-запрос, в котором поле jsonrpc содержит JSON-RPC запрос, а файлы передаются как отдельные части. Сервер получает запрос, извлекает JSON-RPC запрос из multipart-конверта и передаёт файлы в метод как объекты UploadedFile. Это позволяет разработчикам использовать стандартные механизмы валидации, например, Assert\File из Symfony Validator.

Валидация файлов через Assert\File

Одним из ключевых преимуществ такого подхода является то, что загруженные файлы проходят стандартную валидацию. В библиотеке используется компонент Symfony Validator, который предоставляет множество правил для проверки файлов: размер, MIME-тип, расширение и другие. Например, вы можете легко ограничить максимальный размер файла или разрешённые типы, просто добавив соответствующие аннотации к параметру метода.

Это значительно упрощает разработку, так как не нужно писать собственную логику проверки файлов. Достаточно один раз настроить правила валидации, и они будут применяться ко всем загрузкам. Кроме того, это повышает безопасность, так как вы можете строго контролировать, какие файлы принимаются.

Защита от CSRF: честный разбор

Когда речь идёт о загрузке файлов, особенно важно помнить о защите от CSRF (Cross-Site Request Forgery). В библиотеке otezvikentiy/json-rpc-api 5.2 предусмотрена встроенная защита от CSRF для multipart-запросов. Это сделано для того, чтобы злоумышленник не мог отправить поддельный запрос от имени пользователя, например, загрузив вредоносный файл.

Однако автор библиотеки честно признаёт, что реализация защиты от CSRF — это компромисс. Для работы с multipart-запросами необходимо использовать токены CSRF, которые должны быть переданы в запросе. Это добавляет некоторые сложности, но без этого нельзя гарантировать безопасность. В статье на Хабре подробно объясняется, как это работает и какие подводные камни могут возникнуть.

Предыстория: как внешний контрибьютор добавил фичу

Интересно, что поддержка multipart в otezvikentiy/json-rpc-api появилась благодаря внешнему контрибьютору. Это отличный пример того, как open-source проекты развиваются благодаря сообществу. Разработчик, которому не хватало функциональности, решил не просто попросить, а реализовать её самостоятельно и предложить свои изменения в основной проект. После ревью и доработок фича была включена в релиз 5.2.

Это показывает, что даже небольшие библиотеки могут активно развиваться, если у них есть активное сообщество. Для пользователей это означает, что они могут влиять на развитие инструментов, которые используют.

Как это влияет на разработчиков и проекты

Для разработчиков, использующих JSON-RPC, появление поддержки файлов открывает новые возможности. Теперь можно строить API, которые принимают не только простые данные, но и файлы, не отказываясь от преимуществ JSON-RPC. Это особенно актуально для мобильных приложений, одностраничных приложений и других клиентов, где удобно использовать единый протокол для всех операций.

Библиотека otezvikentiy/json-rpc-api используется в основном в PHP-проектах, поэтому нововведение в первую очередь будет полезно разработчикам на PHP. Однако подход, реализованный в этой библиотеке, может быть применён и в других языках, так как multipart — это стандартный механизм HTTP.

Что будет дальше

Можно ожидать, что в будущих версиях библиотеки будет улучшена работа с multipart, возможно, добавлена поддержка потоковой загрузки больших файлов или более гибкая настройка CSRF-защиты. Также вероятно, что другие реализации JSON-RPC последуют примеру и добавят аналогичную функциональность.

Для разработчиков, которые хотят использовать эту возможность, сейчас самое время изучить документацию и попробовать реализовать загрузку файлов в своих проектах. Библиотека активно развивается, и автор открыт для предложений и отзывов.

Итог

Загрузка файлов через JSON-RPC — это реальная задача, которую можно решить с помощью multipart-запросов. Библиотека otezvikentiy/json-rpc-api 5.2 предлагает готовое решение, которое включает валидацию файлов и защиту от CSRF. Это удобный инструмент для разработчиков, которые хотят использовать JSON-RPC в своих проектах, не отказываясь от возможности принимать файлы. Если вы работаете с JSON-RPC и сталкивались с проблемой передачи файлов, этот подход стоит рассмотреть.