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

от автора

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

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

В этом посте я хочу рассказывать не о структуре или об операциях, которые умеет выполнять наш 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': '<OAuth токен>', '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': '<OAuth токен>'} 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 Яндекс.Диска.

ссылка на оригинал статьи http://habrahabr.ru/company/yandex/blog/227377/