Новый REST API Яндекс.Диска и Полигон. А также зачем Диску ещё один API и как мы его делали

Многие знают, что у Диска уже достаточно давно есть API на WebDAV. Он достаточно узко заточен под работу с файловой структурой, а у его реализации на разных платформах часто бывают некритичные, но не очень приятные недостатки. Поэтому в дополнение к WebDAV мы запускаем REST API, который позволит разработчикам делать всё то же и немного больше.Например, при использовании нового API все приложения, которым просто нужно хранить свои файлы в Диске, смогут получать доступ только к своей папке, лежащей в Диске пользователя в папке «Приложения». В WebDAV API сервису для этого придётся получать у пользователя разрешение на запись/чтение всего Диска, а не только конкретной папки.

d725774b8569795c8f4fc0c9c18ee9da.jpg

В этом посте я хочу рассказывать не о структуре или об операциях, которые умеет выполнять наш API — там всё довольно очевидно —, а сразу перейду к интересным вещам: что такое Hypermedia и Machine-readable and Self-describing API, и как мы все это реализовали.

Hypermedia APIМы снабдили наш API гиперссылками, которые связывают его ресурсы между собой. Они позволяют превратить работу клиента из дёрганья захардкоденных URL в перемещение по ссылкам, которые предоставляет API в теле возвращаемых объектов. Мы взяли за основу стандартHAL, как один из наиболее простых и зрелых стандартов в этой области. В настоящее время HAL имеет драфт RFC-стандарта и его уже можно встретить в API некоторых крупных компаний.Благодаря поддержке HAL клиент понимает, что можно делать с каждым объектом, знает готовый или шаблонизированный в соответствии с RFC 6570 URL и HTTP-метод действия. В свою очередь, разработчики клиентских приложений могут писать меньше кода, тратя на это меньше времени, а этот код становится проще и легче для восприятия. Например, код, выполняющий базовые операции с папками в Диске, не использующий гиперссылки, будет выглядеть примерно так:

Скрытый текст # -*- coding: utf-8 -*- import urllib import httplib import json import uritemplate

headers = {'Authorization': '', 'Accept': 'application/hal+json'} connection = httplib.HTTPSConnection ('cloud-api.yandex.net') resource_url = '/v1/disk/resources? path={path}'

def request (method, url, params=None): url = uritemplate.expand (url, params or {}) connection.request (method, url, headers=headers) resp = connection.getresponse () content = resp.read () obj = json.loads (content) if content else None status = resp.status if status == 201: # получаем созданный объект status, obj = request (obj['method'], obj['href']) return status, obj

def do (resource, action, params=None): link = resource['_links'][action] _, obj = request (link['method'], link['href'], params) return obj

if __name__ == '__main__': # создаём папку _, folder = request ('PUT', uritemplate.expand (resource_url, {'path': '/foo'}))

# перемещаем папку и получаем перемещённую folder = do (folder, 'move', {'path': '/bar'})

# копируем папку и получаем новую папку folder_copy = do (folder, 'copy', {'path': '/foobar'})

# удаляем папки do (folder, 'delete') do (folder_copy, 'delete') При использовании гиперссылок пропадает необходимость вручную собирать URL и беспокоиться о параметрах запроса и без того известных объекту, над которым выполняется операция: Скрытый текст # -*- coding: utf-8 -*- import urllib import httplib import json import uritemplate

headers = {'Authorization': ''} connection = httplib.HTTPSConnection ('cloud-api.yandex.net') resource_url = '/v1/disk/resources'

def request (method, url, query=None): if query: qs = urllib.urlencode (query) url = '%s?%s' % (url, qs) connection.request (method, url, headers=headers) resp = connection.getresponse () content = resp.read () obj = json.loads (content) if content else None status = resp.status if status == 201: # получаем созданный объект obj = request (obj['method'], obj['href']) return obj

if __name__ == '__main__': # создаём папку path = '/foo' folder = request ('PUT', resource_url, {'path': path})

# перемещаем папку и получаем перемещённую new_path = '/bar' folder = request ('POST', '%s/move' % resource_url, {'path': new_path, 'from': path})

# копируем папку и получаем новую папку copy_path = '/foobar' folder_copy = request ('POST', '%s/copy' % resource_url, {'path': copy_path, 'from': new_path})

# удаляем папки request ('DELETE', resource_url, {'path': new_path}) request ('DELETE', resource_url, {'path': copy_path}) Machine-readable & Self-describing API Кроме гипермедиа мы решили сделать наш API самоописываемым и машиночитаемым. В процессе подготовки мы изучили различные стандарты описания REST API, такие как RAML, WADL, JSON Schema+JSON HyperSchema, IO Docs, Apiary Blueprints, однако окончательный выбор пал на Swagger. Одно из основных преимуществSwagger заключается в том, что он развивается как стандарт (API Яндекс.Диска поддерживает версию спецификации 1.2, но сейчас уже ведётся разработка версии стандарта 2.0). Он описывает REST API с помощью JSON, достаточно прост для понимания и имеет неплохую экосистему инструментов для работы с описаниями API.Swagger-документация охватывает все доступные в API ресурсы и методы их вызова. Для каждого метода ресурса есть описание принимаемых им параметров и структуры возвращаемых объектов.

Это описание можно использовать, как в качестве отправной точки для универсальных Swagger-клиентов, так и для автогенерации части кода нативных SDK для различных языков.

Полигон Благодаря наличию Swagger-документации API мы запустили проект Полигонкоторый даёт разработчикам возможность, не написав ни строчки кода, отправлять боевые запросы в API. Кроме того, Полигон может служить примером универсального клиента для любого API, поддерживающего Swagger-описание. Наш разработчик Рома Акинфеев подготовил скринкаст, в котором рассказал немного о возможностях Полигона.Больше приложений хороших и разных! Сейчас функциональности API Диска более чем достаточно для разработки приложений, работающих с контентом пользователей, например, фоторедакторов, генераторов слайд-шоу, медиа-проигрывателей и т.д. С помощью нашего API можно хранить и синхронизировать данные приложения между девайсами пользователя, например, сохранять прогресс в играх или хранить избранное и закладки пользователя, созданные в вашем приложении.

Мы старались сделать новый API Диска таким, чтобы вам было легко и приятно им пользоваться, меньше штудируя документацию и больше интуитивно осваивая его на практике. Поэтому без лишних слов предлагаем воспользоваться Полигоном и самостоятельно познакомиться с новым REST API Яндекс.Диска.

© Habrahabr.ru