Уже в момент запуска Яндекс.Диск дал многим разработчиками возможность использовать его в своих приложениях и программах. И обеспечивает это то, что протоколом для десктопных клиентов Диска мы выбрали WebDAV.
Так как именно протокол определяет то, как общаются между собой программы и сервер, от его выбора зависит примерно всё. И то, как будут устроены клиенты, и то, какие возможности работы с файлами у них будут.
Сегодня мы хотим рассказать о причинах, которые остановили наш выбор именно на WebDAV и сделали его протоколом для клиентов Яндекс.Диска.
Благодаря API, реализованному на его базе, с нашим сервисом уже работают ABBYY FineScanner, Handy Backup 7, ES Проводник и неофициальный клиент Яндекс.Диска для Linux.
Перед тем как выбрать протокол, мы определили для себя важнейшие требования к нему:
- Скорость работы;
- Открытая лицензия;
- Возможность реализации всех необходимых действий: аутентификации, поддержки файловых операций, конкурентного доступа к файлам, докачки с сервера и возобновления закачки на сервер;
- Распространённость — он должен работать с целевыми операционными системами (в первую очередь Windows, Mac OS X, Linux) «из коробки» или с минимальными доработками.
Мы даже были готовы разрабатывать свой собственный протокол, если бы существующие нам не подошли. Изменение протокола после запуска потребовало бы много человекочасов работы, поэтому нужно было изучить разные варианты и выбрать лучше всего отвечающий нашим требованиям.
FTP. Этот протокол для удалённой работы с файлами проверен временем. Но создавался он без учёта требований информационной безопасности, что стало для нас его существенным недостатком. Помимо этого, он не поддерживает многие необходимые нам операции, например, передачу метаданных вместе с содержимым файла. И требует для подключения специальные приложения.
BitTorrent. Так как речь сразу шла о синхронизации между девайсами, то использовать соединение между ними без создания нагрузки на серверы было бы очень полезно, но это потребовало бы двойной работы по разработке клиента. В добавок возникли бы проблемы при работе через NAT-ы и firewall-ы, что сильно снизило бы пользу от использования этого протокола.
Amazon S3. Это хранилище использует свой собственный протокол, основанный на HTTP. Мы рассматривали возможность использования API S3, однако отказались от этой идеи из-за отсутствия в нём привычной работы с каталогами и из-за необходимости использовать специальные приложения для доступа.
WebDAV. Основанный на HTTP и XML и нетрудно расширяемый, он поддерживает в спецификациях практически все, что нам нужно. C ним достаточно хорошо работают предустановленные пакеты во всех целевых операционных системах. Кроме того отдел разработки десктопных клиентов Яндекс.Диска, занимавшийся XMPP-сервером Яндекса, на тот момент уже имел опыт работы с открытыми протоколами на базе XML.
Главной причиной, по которой нам не хотелось создавать свой собственный протокол, было то, что работать с ним смогут только наши приложения, а мы хотели открытости.
В итоге, из всех обсуждавшихся вариантов мы выбрали WebDAV. Единственное, чего не хватало в протоколе — это информирования клиента об изменениях на сервере, очень важной фичи синхронизации. Но так как протокол расширяем, это не стало проблемой.
После выбора протокола началась работа над прототипом Яндекс.Диска. Наш WebDAV-сервер мы написали на Erlang. В качестве фреймворка для веб-сервера был выбран mochiweb, достаточно легковесная и хорошо знакомая нашим разработчикам библиотека. Она же была использована в известной статье о подключении миллиона пользователей к одному серверу — A million user comet application. Также мы думали и об использовании веб-сервера Yaws, который можно сравнить с Apache. Это полноценный веб-сервер, умеющий отдавать статику, запускать CGI-скрипты, обрабатывать специальные страницы с серверными скриптами. Но это всё было нам не нужно. Если бы мы начинали делать проект сейчас, выбор пал бы на Cowboy, так как он предоставляет больше возможностей по определению проблем с соединением.
После изучения протокола WebDAV началась работа над операциями листинга файлов и каталогов на сервере. В качестве хранилища для прототипа использовались mysql-база данных, в которой хранилась мета-информация и обычная файловая система для хранения содержимого файлов. Масштабирования и высокой надёжности на этом этапе не требовалось.
Схема была довольно простой, так как это был прототип. Как обычно бывает с файловыми системами, встал вопрос ограничений на пути. Так как максимальная длина пути к ресурсу в протоколе не оговаривалась, было решено сделать длину компоненты пути в 255 символов, а количество уровней вложенности неограниченным. Примерно таблица хранилища файлов выглядела так:
id | число, автоинкремент, уникальный идентификатор ресурса |
uid | пользователь, владелец ресурса |
path | строка длины 255, имя ресурса |
type | тип ресурса, файл или каталог |
parent | число, id владельца |
depth | число, уровень вложенности ресурса использовалось для оптимизации запросов на выборку |
Одной из первых нетривиальных задач стал листинг корня, в котором ничего нет. Сложность в том, что метод PROPFIND, кроме просто листинга, выполняет ещё и задачу чтения свойств ресурса. Необходимо было правильно разбирать запрос, понимать, что мы можем выдать, а что нет; формировать правильный ответ. В качестве первого клиента использовался встроенный в Ubuntu gvfs. Отладив работу с ним, мы решили проверить работу подключения из Windows 7 и обнаружили, что он с нами не работает. Исследование работы с другими серверами показало, что встроенные в Windows клиенты не обрабатывают пространство имён «DAV:», если оно объявлено дефолтным, без префикса. Другие стандартные клиенты оказались более терпимыми и легко переваривали выдачу, сформированную специально для клиентов Windows. К счастью, это была единственная несовместимость, которую нам удалось найти.
Когда работа над листингом была завершена, мы реализовали тривиальные операции создания каталогов и удаления ресусов.
Дальше требовалось научиться заливать файлы, но эта операция была не так проста. А почему — если эта тема будет вам интересна — мы расскажем в следующем посте.
Автор: bedmitry