Pull to refresh

Comments 20

Перегружай семантикой стандартные методы HTTP-протокола

То ли перевод неудачный, то ли что. Но в общем и в целом REST API over HTTP не обязан использовать семантику HTTP. Она ориентирована на такую работу с ресурсами, которая предполагает что клиент задает в целом состояние ресурса, в которое он перейдёт после отработки команды.

При желании можно впихнуть всю логику в POST, ссылаясь на ограниченную поддержку других методов HTTP, те перегрузить семантикой метод POST.

Следует различать REST API over HTTP и HTTP REST API. Первое использует HTTP только в качестве транспорта, а второе должно соблюдать семантику HTTP.

{
    'photos': [1, 2, 3],
    'photo_uri_template': 'http://example.com/ph/{id}'
}

В таком случае клиент должен будет сходить на сервер за каждой фоткой, чтобы отрендерить, например, галерею.
Вариант вернуть сразу, что-то вроде:
{
    'photos': [
        {
           'id': 1,
           'alt': 'text',
           'uri': 'https://domain.net/path/img.png'
        },
        {...}, 
        ....
    ],

}

не true REST way?
Это первый указанный вариант решения проблемы «Просто используйте готовые URL». Вы дополнили URL метаданными, тут всё ок.
Пример показывает принцип, а не демонстрирует самое эффективное решение. Замените photos на tracks, если вас так коробит.
Или, если волосы встают дыбом от дублирования, сообщите формат URL

Спасибо за идею.
Пусть твой API поддерживает только один формат возвращаемых данных

JSON это, конечно, круто и его точно нужно поддерживать с самого начала. Но с развитием системы должна быть возможность выбора формата выходных данных, например, AtomPub.

Какое-то противоречие.

Причем, формат вывода должен определяться нативно, через заголовок HTTP Accept, а не через лишние конструкции вида ?format=xml.

Ну и какой профит это дает?
Пусть твой API поддерживает только один формат возвращаемых данных

Это же сарказм, вредные советы же. Это следует читать как Поддерживайте разные форматы.

Про формат в заголовке:
можно ведь и токен, и данные из формы передавать гет-параметрами, но зачем?
Хотя в урле конечно нагляднее, но в заголовках тоже ок.
Посыл такой что если уже предусмотрены стандартные документированные хедеры для этого, зачем накручивать что-то поверх.

Эх. Вот только сегодня смотрел на REST API от ArcGIS. Параметр f=json указывает формат ответа, а на выходе Content-type: text/plain. Хм. Видимо они вашу статью еще не прочли :)

Про формат в заголовке:
Имхо, немного сложнее становится кеширование, если через HTTP Accept
Объединяй модели и ресурсы

В этом нет ничего плохого. Наоборот, получается весьма гибко и лаконично. Для агрегационных ресурсов просто создаются виртуальные модели (у которых все свойства — динамически вычисляемые). Например, модель "полнотекстовый поиск", имеющая свойства "поисковой запрос" и "список найденных моделей". Запрашивать соответственно можно не модели по отдельности, но и сразу связанные модели. При этом выдача всегда должна быть в нормализованном виде, чтобы не было комбинаторного взрыва данных. Пример ответа на запрос /search/query=api?fetch=query,found(type,name,title,author(name),articles!count):


{
    '/search/query=api' : {
        'query' : 'api',
        'found' : [ '/user=jin' , '/article=best-api' ]
    },
    '/user=jin' : {
        'type' : 'user' ,
        'name' : 'Nin Jin' ,
        'articles!count' : 1
    },
    '/article=best-api' : {
        'type' : 'article' ,
        'title' : 'Best API ever' ,
        'author' : '/user=jin'
    }
}

Жестко зашивай конкретную подсистему контроля доступа в код API

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


Причем, формат вывода должен определяться нативно, через заголовок HTTP Accept, а не через лишние конструкции вида ?format=xml.

У дополнительного параметра есть следующие преимущества:


  1. Клиенту не надо париться с установкой заголовка Accept.
  2. Серверу не надо париться с установкой заголовка Vary.
  3. При отладке, перейдя по ссылке ты получаешь ровно то, что и приложение.

Content Negotiation хорош, когда у нас есть куча пользовательских агентов, каждый из которых понимает разные форматы и серверу нужно уметь работать с каждым из них. В случае API всё наоборот — клиентское приложение разрабатывается под конкретную выдачу сервера, а в этих условиях лучше всего, если для получения данных достаточно просто скопипастить ссылку в код. Поэтому в ссылку имеет смысл зашивать и формат выдачи и версию API.


Просто используйте готовые URL

Но лучше всё же использовать не абсолютные урлы, а относительные, потому что:


  1. Они занимают меньше места, а в некоторых случаях гораздо меньше места.
  2. Их проще формировать. не надо приклеивать правильную схему, хост, порт и другие параметры урла.
  3. Ваше API по тем или иным причинам может быть доступно по разным доменным именам и вы не всегда можете получить именно то имя, по которому обращается клиент.
  4. Меньше визуального шума при отладке.
  5. Эти относительные ссылки можно хранить в БД в качестве человекопонятных глобальных уникальных идентификаторов не привязанных к конкретному доменному имени.

Жестко привяжи REST API к своему приложению

Деление на API и APP не имеет особого смысла. Лучше иметь кластер кроссфункциональных нод, который будет адекватно реагировать на изменения нагрузки по разным запросам, чем поддерживать несколько отдельных приложений, которые по хорошему должны развиваться синхронно. Ну и, если на клиенте у вас SPA, то зачем вам что-то кроме API? :-)

Деление на API и APP не имеет особого смысла.

В случае SOA вполне имеет. App-серверы имеют один-единственный серверный API (в том числе с собственным протоколом/форматом), работающий исключительно в рамках ответственности сервиса, а API-серверы предоставляют множество клиентских API к множеству сервисов, в том числе агрегируя данные для клиентов с нескольких сервисов в один ответ.

Для агрегационных ресурсов просто создаются виртуальные модели (у которых все свойства — динамически вычисляемые).

Ровно об этом и написано ;)
«Тут же полезно вспомнить паттерн фасад — ресурс это фасад для моделей, а не конкретная модель»

Правила же вынесенные, например, в БД, напротив, требуют очень осторожного обращения при изменении.

Немножко однобокий взгляд «на вынос контроля доступа». Контроль доступа можно агрегировать в контроллеры на уровне кода. Описать в виде декораторов или возвращаемых значений шаблонных методов.

У дополнительного параметра есть следующие преимущества

Установка хедера Accept и передача параметра ?format=xxx равнозначны по объему кода. Версия API обычно зашивается в сам URL, а не в параметры GET-запроса.

Деление на API и APP не имеет особого смысла. Лучше иметь кластер кроссфункциональных нод, который будет адекватно реагировать на изменения нагрузки по разным запросам,

Расскажите это инженерам Twitter :)
Ровно об этом и написано ;)

Не совсем. "Полнотекстовый поиск" — не является фасадом для других моделей. Он делает запрос к базе и возвращает список идентификаторов. Он сам по себе является моделью и как любая модель доступен через REST, WS, SOAP и прочие протоколы.


Немножко однобокий взгляд «на вынос контроля доступа». Контроль доступа можно агрегировать в контроллеры на уровне кода. Описать в виде декораторов или возвращаемых значений шаблонных методов.

Я не понял, вы со мной спорите или соглашаетесь? :-)


Установка хедера Accept и передача параметра ?format=xxx равнозначны по объему кода.

Не равнозначны по объёму вручную написанного кода. Урл просто копипастится и всё. Установку Accept необходимо специально прописать руками.


Версия API обычно зашивается в сам URL, а не в параметры GET-запроса.

Совершенно не важно в какую часть ссылки её зашивать.


Расскажите это инженерам Twitter :)

Тоже мне авторитет.

UFO just landed and posted this here
Для однородных запросов я предпочитаю загонять поля в массив, а их названия выносить в массив заголовков.

Боюсь без примера не могу понять о чём это вы.

Sign up to leave a comment.

Articles