Основы API. Создание собственного API. API: описание и использование интерфейса программирования приложений API - SEO термины - Реклама в Интернете от Ingate Простая фильтрация по значению

Рассказывает Владимир, веб-разработчик Noveo

Большинству разработчиков сайтов, веб-сервисов и мобильных приложений рано или поздно приходится иметь дело с клиент-серверной архитектурой, а именно разрабатывать web API или интегрироваться с ним. Чтобы не изобретать каждый раз что-то новое, важно выработать относительно универсальный подход к проектированию web API, основываясь на опыте разработки подобных систем. Предлагаем вашему вниманию объединенный цикл статей, посвящённых этому вопросу.

Приближение первое: Действующие лица

В один прекрасный момент, в процессе создания очередного веб-сервиса, я решил собрать все свои знания и размышления на тему проектирования web API для обслуживания нужд клиентских приложений и оформить их в виде статьи или серии статей. Разумеется, мой опыт не претендует на абсолют, и конструктивная критика и дополнения более чем приветствуются.

Чтиво получилось больше философское, нежели техническое, но и для любителей технической части здесь будет над чем поразмыслить. Сомневаюсь, что скажу в этой статье что-то принципиально новое, то, о чем вы никогда не слышали, не читали и о чем не думали сами. Просто попытаюсь уложить все в единую систему, в первую очередь в своей собственной голове, а это уже дорогого стоит. Тем не менее, буду рад, если мои измышления будут вам полезны в вашей практике. Итак, поехали.

Клиент и сервер

Сервером в данном случае мы считаем абстрактную машину в сети, способную получить HTTP-запрос, обработать его и вернуть корректный ответ. В контексте данной статьи совершенно не важны его физическая суть и внутренняя архитектура, будь то студенческий ноутбук или огромный кластер из промышленных серверов, разбросанных по всему миру. Нам в той же мере совершенно неважно, что у него под капотом, кто встречает запрос у дверей, Apache или Nginx, какой неведомый зверь, PHP, Python или Ruby выполняет его обработку и формирует ответ, какое хранилище данных используется: Postgresql, MySQL или MongoDB. Главное, чтобы сервер отвечал главному правилу - услышать, понять и простить ответить.

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

По большей части мы будем говорить о способе общения между выше перечисленными двумя, таком способе, чтобы они друг друга понимали, и ни у одного не оставалось вопросов.

Философия REST

REST (Representational state transfer) изначально был задуман как простой и однозначный интерфейс для управления данными, предполагавший всего несколько базовых операций с непосредственным сетевым хранилищем (сервером): извлечение данных (GET), сохранение (POST), изменение (PUT/PATCH) и удаление (DELETE). Разумеется, этот перечень всегда сопровождался такими опциями, как обработка ошибок в запросе (корректно ли составлен запрос), разграничение доступа к данным (вдруг этого вам знать не следует) и валидация входящих данных (вдруг вы написали ерунду), в общем, всеми возможными проверками, которые сервер выполняет перед тем, как выполнить желание клиента .

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

Независимость сервера от клиента - серверы и клиенты могут быть мгновенно заменены другими независимо друг от друга, так как интерфейс между ними не меняется. Сервер не хранит состояний клиента.
Уникальность адресов ресурсов - каждая единица данных (любой степени вложенности) имеет свой собственный уникальный URL, который, по сути, целиком является однозначным идентификатором ресурса.

Пример: GET /api/v1/users/25/name

Независимость формата хранения данных от формата их передачи - сервер может поддерживать несколько различных форматов для передачи одних и тех же данных (JSON, XML и т.д.), но хранит данные в своем внутреннем формате, независимо от поддерживаемых.

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

Чего нам не хватает

Классический REST подразумевает работу клиента с сервером как с плоским хранилищем данных, при этом ничего не говорится о связанности и взаимозависимости данных между собой. Все это по умолчанию целиком ложится на плечи клиентского приложения. Однако современные предметные области, для которых разрабатываются системы управления данными, будь то социальные сервисы или системы интернет-маркетинга, подразумевают сложную взаимосвязь между сущностями, хранящимися в базе данных. Поддержка этих связей, т.е. целостности данных, находится в зоне ответственности серверной стороны, в то время, как клиент является только интерфейсом для доступа к этим данным. Так чего же нам не хватает в REST?

Вызовы функций

Чтобы не менять данные и связи между ними вручную, мы просто вызываем у ресурса функцию и «скармливаем» ей в качестве аргумента необходимые данные. Эта операция не подходит под стандарты REST, для нее не существует особого глагола, что заставляет нас, разработчиков, выкручиваться кто во что горазд.

Самый простой пример – авторизация пользователя. Мы вызываем функцию login, передаем ей в качестве аргумента объект, содержащий учетные данные, и в ответ получаем ключ доступа. Что творится с данными на серверной стороне – нас не волнует.

Еще вариант – создание и разрыв связей между данными. Например, добавление пользователя в группу. Вызываем у сущности группа функцию addUser, в качестве параметра передаем объект пользователь , получаем результат.

А еще бывают операции, которые вообще не связаны напрямую с сохранением данных как таковых, например, рассылка уведомлений, подтверждение или отклонение каких-либо операций (завершение отчетного периода etc).

Множественные операции

Часто бывает так, и разработчики клиентов поймут, о чем я, что клиентскому приложению удобнее создавать/изменять/удалять/ сразу несколько однородных объектов одним запросом, и по каждому объекту возможен свой вердикт серверной стороны. Тут есть как минимум несколько вариантов: либо все изменения выполнены, либо они выполнены частично (для части объектов), либо произошла ошибка. Ну и стратегий тоже несколько: применять изменения только в случае успеха для всех, либо применять частично, либо откатываться в случае любой ошибки, а это уже тянет на полноценный механизм транзакций.

Для web API, стремящегося к идеалу, тоже хотелось бы как-то привести подобные операции в систему. Постараюсь сделать это в одном из продолжений.

Статистические запросы, агрегаторы, форматирование данных

Частенько бывает так, что на основе хранимых на сервере данных нам нужно получить статистическую выжимку или данные, отформатированные особым образом: например, для построения графика на стороне клиента. По сути это данные, генерируемые по требованию, в той или иной мере на лету, и доступные только для чтения, так что имеет смысл вынести их в отдельную категорию. Одной из отличительных особенностей статистических данных, на мой взгляд, является то, что они не имеют уникального ID.

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

Разновидности данных

Объекты

Ключевым типом данных в общении между клиентом и сервером выступает объект. По сути, объект – это перечень свойств и соответствующих им значений. Мы можем отправить объект на сервер в запросе и получить в результат запроса в виде объекта. При этом объект не обязательно будет реальной сущностью, хранящейся в базе данных, по крайней мере, в том виде, в котором он отправлен или получен. Например, учетные данные для авторизации передаются в виде объекта, но не являются самостоятельной сущностью. Даже хранимые в БД объекты склонны обрастать дополнительными свойствами внутрисистемного характера, например, датами создания и редактирования, различными системными метками и флагами. Свойства объектов могут быть как собственными скалярными значениями, так и содержать связанные объекты и коллекции объектов , которые не являются частью объекта. Часть свойств объектов может быть редактируемой, часть системной, доступной только для чтения, а часть может носить статистический характер и вычисляться на лету (например, количество лайков). Некоторые свойства объекта могут быть скрыты, в зависимости от прав пользователя.

Коллекции объектов

Говоря о коллекциях, мы подразумеваем разновидность серверного ресурса, позволяющую работать с перечнем однородных объектов, т.е. добавлять, удалять, изменять объекты и осуществлять выборку из них. Помимо этого коллекция теоретически может обладать собственными свойствами (например, максимальное число элементов на страницу) и функциями (тут я в замешательстве, но такое тоже было).

Скалярные значения

В чистом виде скалярные значения как отдельная сущность на моей памяти встречались крайне редко. Обычно они фигурировали как свойства объектов или коллекций, и в этом качестве они могут быть доступны как для чтения, так и для записи. Например, имя пользователя может быть получено и изменено в индивидуальном порядке GET /users/1/name . На практике эта возможность пригождается редко, но в случае необходимости хотелось бы, чтобы она была под рукой. Особенно это касается свойств коллекции, например числа записей (с фильтрацией или без нее): GET /news/count .

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

Приближение второе: Правильный путь

В этом приближении я хотел бы отдельно поговорить о подходах к построению уникальных путей к ресурсам и методам вашего web API и о тех архитектурных особенностях приложения, которые влияют на внешний вид этого пути и его компоненты.

О чем стоит подумать, стоя на берегу

Версионность

Рано или поздно любая действующая система начинает эволюционировать: развиваться, усложняться, масштабироваться, усовремениваться. Для разработчиков REST API это чревато в первую очередь тем, что необходимо запускать новые версии API при работающих старых. Здесь я говорю больше не об архитектурных изменениях под капотом вашей системы, а о том, что изменяется сам формат данных и набор операций с ними. В любом случае версионность нужно предусмотреть как в изначальной организации исходного кода, так и в принципе построения URL. Что касается URL, здесь существует два наиболее популярных способа указания версии API, которой адресован запрос. Префиксация пути example-api.com/v1/ и разведение версий на уровне субдомена v1.example-api.com . Использовать можно любой из них, в зависимости от потребности и необходимости.

Автономность компонентов

Web API сложных систем, поддерживающих несколько пользовательских ролей, зачастую требует разделения на части, каждая из которых обслуживает свой спектр задач. По сути, каждая часть может быть самостоятельным приложением, работать на разных физических машинах и платформах. В контексте описания API нам совершенно не важно, как сервер обрабатывает запрос и какие силы и технологии в этом замешаны. Для клиента API – система инкапсулированная. Тем не менее разные части системы могут обладать совершенно разной функциональностью, например, административная и пользовательская часть. И методология работы с одними и теми же, казалось бы, ресурсами может существенно отличаться. Поэтому такие части необходимо разделять на уровне домена admin.v1.example-api.com или префикса пути example-api.com/v1/admin/ . Это требование не является обязательным, и многое зависит от сложности системы и её назначения.

Формат обмена данными

Самым удобным и функциональным, на мой взгляд, форматом обмена данными является JSON, но никто не запрещает использовать XML, YAML или любой другой формат, позволяющий хранить сериализованные объекты без потери типа данных. При желании можно сделать в API поддержку нескольких форматов ввода/вывода. Достаточно задействовать HTTP заголовок запроса для указания желаемого формата ответа Accept и Content-Type для указания формата переданных в запросе данных. Другим популярным способом является добавление расширения к URL ресурса, например, GET /users.xml , но такой способ кажется менее гибким и красивым, хотя бы потому, что утяжеляет URL и верен скорее для GET-запросов, нежели для всех возможных операций.

Локализация и многоязычность

На практике многоязычность API чаще всего сводится к переводу сервисных сообщений и сообщений об ошибках на требуемый язык для прямого отображения конечному пользователю. Многоязычный контент тоже имеет место быть, но сохранение и выдача контента на разных языках, на мой взгляд, должна разграничиваться более явно, например, если у вас одна и та же статья существует на разных языках, то по факту это две разных сущности, сгруппированные по признаку единства содержания. Для идентификации ожидаемого языка можно использовать разные способы. Самым простым можно считать стандартный HTTP-заголовок Accept-Language . Я встречал и другие способы, такие, как добавление GET-параметра language="en" , использование префикса пути example-api.com/en/ или даже на уровне доменного имени en.example-api.com . Мне кажется, что выбор способа указания локали зависит от конкретного приложения и задач, стоящих перед ним.

Внутренняя маршрутизация

Итак, мы добрались до корневого узла нашего API (или одного из его компонентов). Все дальнейшие маршруты будут проходить уже непосредственно внутри вашего серверного приложения, в соответствии с поддерживаемым им набором ресурсов.

Пути к коллекциям

Для указания пути к коллекции мы просто используем название соответствующей сущности, например, если это список пользователей, то путь будет таким /users . К коллекции как таковой применимы два метода: GET (получение лимитированного списка сущностей) и POST (создание нового элемента). В запросах на получение списков мы можем использовать множество дополнительных GET параметров, применяемых для постраничного вывода, сортировки, фильтрации, поиска etc, но они должны быть опциональными, т.е. эти параметры не должны передаваться как часть пути!

Элементы коллекции

Для обращения к конкретному элементу коллекции мы используем в маршруте его уникальный идентификатор /users/25 . Это и есть уникальный путь к нему. Для работы с объектом применимы методы GET (получение объекта), PUT/PATCH (изменение) и DELETE (удаление).

Уникальные объекты

Во множестве сервисов существуют уникальные для текущего пользователя объекты, например профиль текущего пользователя /profile , или персональные настройки /settings . Разумеется, с одной стороны, это элементы одной из коллекций, но они являются отправной точкой в использовании нашего Web API клиентским приложением, и к тому же позволяют намного более широкий спектр операций над данными. При этом коллекция, хранящая пользовательские настройки может быть вообще недоступна из соображений безопасности и конфиденциальности данных.

Свойства объектов и коллекций

Для того, чтобы добраться до любого из свойств объекта напрямую, достаточно добавить к пути до объекта имя свойства, например получить имя пользователя /users/25/name . К свойству применимы методы GET (получение значения) и PUT/PATCH (изменение значения). Метод DELETE не применим, т.к. свойство является структурной частью объекта, как формализованной единицы данных.

В предыдущей части мы говорили о том, что у коллекций, как и у объектов, могут быть собственные свойства. На моей памяти мне пригодилось только свойство count, но ваше приложение может быть более сложным и специфичным. Пути к свойствам коллекций строятся по тому же принципу, что и к свойствам их элементов: /users/count . Для свойств коллекций применим только метод GET (получение свойства), т.к. коллекция – это только интерфейс для доступа к списку.

Коллекции связанных объектов

Одной из разновидностей свойств объектов могут быть связанные объекты или коллекции связанных объектов. Такие сущности, как правило, не являются собственным свойством объекта, а лишь отсылками к его связям с другими сущностями. Например, перечень ролей, которые были присвоены пользователю /users/25/roles . По поводу работы с вложенными объектами и коллекциями мы подробно поговорим в одной из следующих частей, а на данном этапе нам достаточно того, что мы имеем возможность обращаться к ним напрямую, как к любому другому свойству объекта.

Функции объектов и коллекций

Для построения пути к интерфейсу вызова функции у коллекции или объекта мы используем тот же самый подход, что и для обращения к свойству. Например, для объекта /users/25/sendPasswordReminder или коллекции /users/disableUnconfirmed . Для вызовов функций мы в любом случае используем метод POST. Почему? Напомню, что в классическом REST не существует специального глагола для вызова функций, а потому нам придется использовать один из существующих. На мой взгляд, для этого больше всего подходит метод POST т.к. он позволяет передавать на сервер необходимые аргументы, не является идемпотентным (возвращающим один и тот же результат при многократном обращении) и наиболее абстрактен по семантике.

Надеюсь, что все более-менее уложилось в систему 🙂 В следующей части мы поговорим подробнее о запросах и ответах, их форматах, кодах статусов.

Приближение третье: Запросы и ответы

В предыдущих приближениях я рассказал о том, как пришла идея собрать и обобщить имеющийся опыт разработки web API. В первой части я постарался описать, с какими видами ресурсов и операций над ними мы имеем дело при проектировании web API. Во второй части были затронуты вопросы построения уникальных URL для обращения к этим ресурсам. А в этом приближении я попробую описать возможные варианты запросов и ответов.

Универсальный ответ

Мы уже проговаривали, что конкретный формат общения сервера с клиентом может быть любым на усмотрение разработчика. Для меня наиболее удобным и наглядным кажется формат JSON, хотя в реальном приложении может быть реализована поддержка нескольких форматов. Сейчас же сосредоточимся на структуре и необходимых атрибутах объекта ответа. Да, все данные, возвращаемые сервером, мы будем оборачивать в специальный контейнер - универсальный объект ответа , который будет содержать всю необходимую сервисную информацию для его дальнейшей обработки. Итак, что это за информация:

Success - маркер успешности выполнения запроса

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

POST /api/v1/articles/22/publish { "success": true }

Error - сведения об ошибке

В случае, если выполнение запроса завершилось неудачей - о причинах и разновидностях отрицательных ответов сервера поговорим чуть позже, - к ответу добавляется атрибут «error», содержащий в себе HTTP-код статуса и текст сообщения об ошибке. Прошу не путать с сообщениями об ошибках валидации данных для конкретных полей. Правильнее всего, на мой взгляд, возвращать код статуса и в заголовке ответа, но я встречал и другой подход - в заголовке всегда возвращать статус 200 (успех), а детали и возможные данные об ошибках передавать в теле ответа.

GET /api/v1/user { "success": false, "error": { "code" : 401, "message" : "Authorization failed" } }

Data - данные, возвращаемые сервером

Большинство ответов сервера призваны возвращать данные. В зависимости от типа запроса и его успеха ожидаемый набор данных будет разным, тем не менее атрибут«data» будет присутствовать в подавляющем большинстве ответов.

Пример возвращаемых данных в случае успеха. В данном случае ответ содержит запрашиваемый объект user.

GET /api/v1/user { "success": true, "data": { "id" : 125, "email" : "[email protected]", "name" : "John", "surname" : "Smith", } }

Пример возвращаемых данных в случае ошибки. В данном случае содержит имена полей и сообщения об ошибках валидации.

PUT /api/v1/user { "success": false, "error": { "code" : 422, "message" : "Validation failed" } "data": { "email" : "Email could not be blank.", } }

Pagination - сведения, необходимые для организации постраничной навигации

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

Минимальный набор значений для пагинации состоит из:

  • общего числа записей;
  • числа страниц;
  • номера текущей страницы;
  • числа записей на странице;
  • максимального числа записей на странице, поддерживаемого серверной стороной.

Некоторые разработчики web API также включают в пагинацию набор готовых ссылок на соседние страницы, а также первую, последнюю и текущую.

GET /api/v1/articles Response: { "success": true, "data": [ { "id" : 1, "title" : "Interesting thing", }, { "id" : 2, "title" : "Boring text", } ], "pagination": { "totalRecords" : 2, "totalPages" : 1, "currentPage" : 1, "perPage" : 20, "maxPerPage" : 100, } }

Работа над ошибками

Как уже упоминалось выше, не все запросы к web API завершаются успехом, но это тоже часть игры. Система информирования об ошибках является мощным инструментом, облегчающим работу клиента и направляющим клиентское приложение по правильному пути. Слово «ошибка» в этом контексте не совсем уместно. Здесь больше подойдёт слово исключение , так как на самом деле запрос успешно получен, проанализирован, и на него возвращается адекватный ответ, объясняющий, почему запрос не может быть выполнен.

Каковы же потенциальные причины получаемых исключений?

500 Internal server error - всё сломалось, но мы скоро починим

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

400 Bad request - а теперь у вас всё сломалось

Ответ прямо противоположный предыдущему. Возвращается в тех случаях, когда клиентское приложение отправляет запрос, который в принципе не может быть корректно обработан, не содержит обязательных параметров или имеет синтаксические ошибки. Обычно это лечится повторным прочтением документации к web API.

401 Unauthorized - незнакомец, назови себя

Для доступа к этому ресурсу требуется авторизация. Разумеется, наличие авторизации не гарантирует того, что ресурс станет доступным, но не авторизовавшись, вы точно этого не узнаете. Возникает, например, при попытке обратиться к закрытой части API или при истечении срока действия текущего токена.

403 Forbidden - вам сюда нельзя

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

404 Not found - по этому адресу никто не живёт

Такой ответ возвращается, как правило, в трёх случаях: путь к ресурсу неверен (ошибочен), запрашиваемый ресурс был удалён и перестал существовать, права текущего пользователя не позволяют ему знать о существовании запрашиваемого ресурса. Например, пока просматривали список товаров, один из них внезапно вышел из моды и был удалён.

405 Method not allowed - нельзя такое делать

Эта разновидность исключения напрямую связана с использованным при запросе глаголом (GET, PUT, POST, DELETE), который, в свою очередь, свидетельствует о действии, которое мы пытаемся совершить с ресурсом. Если запрошенный ресурс не поддерживает указанное действие, сервер говорит об этом прямо.

422 Unprocessable entity - исправьте и пришлите снова

Одно из самых полезных исключений. Возвращается каждый раз, когда в данных запроса существуют логические ошибки. Под данными запроса мы подразумеваем либо набор параметров и соответствующих им значений, переданных методом GET, либо поля объекта, передаваемого в теле запроса методами POST, PUT и DELETE. Если данные не прошли валидацию, сервер в секции «data» возвращает отчет о том, какие именно параметры невалидны и почему.

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

Запросы

Получение элементов коллекции

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

Постраничная навигация

page - параметр указывает на то, какая страница должна быть отображена. Если этот параметр не передан, то отображается первая страница. Из первого же успешного ответа сервера будет ясно, сколько страниц имеет коллекция при текущих параметрах фильтрации. Если значение превышает максимальное число страниц, то разумнее всего вернуть ошибку 404 Not found .

GET /api/v1/news?page=1

perPage - указывает на желаемое число элементов на странице. Как правило, API имеет собственное значение по умолчанию, которое возвращает в качестве поля perPage в секции pagination, но в ряде случаев позволяет увеличивать это значение до разумных пределов, предоставив максимальное значение maxPerPage:

GET /api/v1/news?perPage=100

Сортировка результатов

Зачастую результаты выборки требуется упорядочить по возрастанию или убыванию значений определенных полей, которые поддерживают сравнительную (для числовых полей) или алфавитную (для строковых полей) сортировку. Например, нам нужно упорядочить список пользователей по имени или товары по цене. Помимо этого мы можем задать направление сортировки от A до Я или в обратном направлении, причём разное для разных полей.

sortBy - существует несколько подходов к передаче данных о сложной сортировке в GET параметрах. Здесь необходимо четко указать порядок сортировки и направление.

В некоторых API это предлагается сделать в виде строки:

GET /api/v1/products?sortBy=name.desc,price.asc

В других вариантах предлагается использовать массив:

GET /api/v1/products? sortBy=name& sortBy=desc& sortBy=price& sortBy=asc

В целом оба варианта равносильны, так как передают одни и те же инструкции. На мой взгляд, вариант с массивом более универсален, но тут, как говорится, на вкус и цвет…

Простая фильтрация по значению

Для того, чтобы отфильтровать выборку по значению какого либо поля, в большинстве случаев достаточно передать в качестве фильтрующего параметра имя поля и требуемое значение. Например, мы хотим отфильтровать статьи по ID автора:

GET /api/v1/articles?authorId=25

Усложнённые варианты фильтрации

Многие интерфейсы требуют более сложной системы фильтрации и поиска. Перечислю основные и наиболее часто встречаемые варианты фильтрации.

Фильтрация по верхней и нижней границе с использованием операторов сравнения from (больше или равно), higher (больше), to (меньше или равно), lower (меньше). Применяется к полям, значения которых поддаются ранжированию.

GET /api/v1/products?price=500&price=1000

Фильтрация по нескольким возможным значениям из списка. Применяется к полям, набор возможных значений которых ограничен, например, фильтр по нескольким статусам:

GET /api/v1/products?status=1&status=2

Фильтрация по частичному совпадению строки. Применяется к полям, содержащим текстовые данные или данные, которые могут быть приравнены к текстовым, например, числовые артикулы товаров, номера телефонов и т. д.

GET /api/v1/users?name=John GET /api/v1/products?code=123

Именованные фильтры

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

GET /api/v1/products?filters=recommended

Именованные фильтры могут также иметь свои параметры.

GET /api/v1/products?filters=kidds

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

6.1 Метод CheckDimensions

Синтаксис:

Boolean CheckDimenshions (Dimensions DimensionsList,

Out float Length,

Out float Width,

Out float Height,

Out float Weight,

Out string Comment)

Параметры:

Имя параметра Входной / Выходной Тип Описание
DimensionsList входной Dimensions Массив
габаритно­весовых
характеристик товаров
Length выходной float Длина посылки
Width выходной float Ширина посылки
Height выходной float Высота посылки
Weight выходной float Вес посылки
Comment выходной float Текстовое описание при превышении
предельных значений габаритно­весовых
характеристик

Описание:

В метод передается список габаритно­весовых характеристик всех товаров
(DimensionsList). После расчета выходные параметры Length, Width, Height (длина,
ширина и высота соответственно) заполняются габаритами посылки, после решения
задачи «оптимальной укладки», а в параметр Weight передается суммарный вес всех
товаров, без учета упаковочных материалов. В том случае если габариты отправления
превышают предельные значения в параметр Comment передается текстовое описание
несоответствия.

Возвращаемое значение: Метод возвращает булево значение True, если
габаритно­весовые характеристики не превышают предельных значений и доставка
возможна хотя бы одним доступным способом, иначе False. Предположительно данный
метод может использоваться на стороне клиента для оперативной оценки
принципиальной возможности отправки заказа и своевременного принятия каких­либо
решений, если сделать этого невозможно.

6.1.1 Пример вызова метода CheckDimensions



// Предположим, что в корзине 2 позиции и необходимо проверить не превышают ли он
ограничения по допустимым габаритам и весу
aplix.Dimensions Dimensions = new aplix.Dimensions;
aplix.Dimensions Item;

Item.Length = 0.130f;
Item.Width = 0.100f;
Item.Height = 0.001f;
Item.Weight = 0.1f;
Item.Qty = 2;
Dimensions = Item;
Item = new aplix.Dimensions();
Item.Length = 0.1331f;
Item.Width = 0.0998f;
Item.Height = 0.0788f;
Item.Weight = 0.575f;
Item.Qty = 1;
Dimensions = Item;
// Выходные параметры
float Length;
float Width;
float Height;
float Weight;
string Comment;
// Выполнить проверку габаритно‐весовых характеристик
bool Result = ws.CheckDimenshions(Dimensions, out Length, out Width, out Height, outWeight, out Comment);
// Визуализация результата
Response.Write("Result:" + Result.ToString() + "");
Response.Write("Length:" + Length.ToString() + "");
Response.Write("Width:" + Width.ToString() + "");
Response.Write("Height:" + Height.ToString() + "");
Response.Write("Weight:" + Weight.ToString() + "");
Response.Write("Weight:" + Comment + "");

6.2 Метод CalculateShippingCost

Синтаксис:
Long CalculateShippingCost (string OrderNumber,
Float DeclaredCost,
Goods Goods,
Address Address,
Byte TypeOfSeal,
Boolean SturdyPackaging,
Boolean CashOnDelivery,
Out DeliveryType Types,
Out string Comments)Параметры:

Имя параметра Входной / Выходной Тип Описание
OrderNumber входной string Номер заказа, если известен в системе
потребителя. Если будет задан, то расчет
в будущем будет привязан к заказу.
DeclaredCost входной Float Объявленная ценность отправления. На

страховка.
Goods входной Goods Список товаров массив структур
(Артикул,
Наименование,
Длина,
Ширина, Высота, Вес, Количество)
Address входной Address Адрес получателя (структура: Почтовый
индекс,
Регион,
Район,
Город,
Населенный пункт, Улица, Дом, Корпус,
Картира)
TypeOfSeal входной Byte Вариант
уплотнения,
возможные
значения:1 ­Не требуется

2 ­Пузырчатая пленка

3­ Наполнитель

SturdyPackagin входной Boolean Обязательно ли требуется жесткая
упаковка
CashOnDelivery входной Boolean Требуется ли наложенный платеж
Types выходной DeliveryType
Comments выходной DeliveryType Список доступных вариантов доставки

Описание:

Метод по заданным параметрам выдает список доступных вариантов доставки
(выходной параметр Types) в виде массива структур <Идентификатор способа доставки, Наименование способа доставки, Себестоимость доставки, Страховую премию, Затраты на упаковку и маркировку, Адрес нахождения почтового отделения, либо точки самовывоза, Режим работы почтового отделения, либо точки самовывоза, Минимальное количество дней доставки, Максимальное количество дней доставки, Доп.информация>. Если в процессе расчета возникли какие­либо исключения, то
описание ошибки будет возвращено в параметр Comments.

Возвращаемое значение:

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

6.2.1 Пример вызова метода CalculateShippingCost



ws.Credentials = new NetworkCredential("test", "test");


Address.Index = "684005";


Address.City = "Елизово г";

Address.Home = "16";


aplix.Goods Item;
Item = new aplix.Goods();
Item.SKU = "216293";

Item.Length = 0.130f;
Item.Width = 0.100f;
Item.Height = 0.001f;
Item.Weight = 0.1f;
Item.Qty = 2;
Goods = Item;
Item = new aplix.Goods();
Item.SKU = "499687";

Item.Length = 0.1331f;
Item.Width = 0.0998f;
Item.Height = 0.0788f;
Item.Weight = 0.575f;
Item.Qty = 1;
Goods = Item;
//Заполним параметры для калькулятора
string OrderNumber="1234567890";
float DeclaredCost = 36370;
sbyte TypeOfSeal = 1;
bool SturdyPackaging = true;
bool CashOnDelivery = false;
aplix.DeliveryType Types; string Comments;
//Вызов калькулятора
long Status = ws.CalculateShippingCost(OrderNumber, DeclaredCost, Goods, Address,TypeOfSeal, SturdyPackaging,CashOnDelivery, out Types, out Comments);
//Визуализация результата
Response.Write("Id расчета:"+Status.ToString()+"
");
Response.Write("Доп.информация по расчету:" + Comments + "
");
Response.Write(@"
");
foreach (aplix.DeliveryType type in Types) {
Response.Write(""+ " "+ " "+ " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " "); }
Response.Write("
































TypeId TypeName TypeDescription Cost Insurance PostalRate PreparingCost Address Worktime MinPeriod MaxPeriod AdditionalInformation
" + type.TypeId.ToString() + " " + type.TypeName + " " + type.TypeDescription + " " + type.Cost.ToString() + " " + type.Insurance.ToString() + " " + type.PostalRate.ToString() + " " + type.PreparingCost.ToString() + " " + type.Address + " " + type.Worktime + " " + type.MinPeriod.ToString() + " " + type.MaxPeriod.ToString() + " " + type.AdditionalInformation + "

");
}

6.3 Метод PushOrder

Синтаксис:
    Long PushOrder (
          ID,
          Number,
          Date,
          Customer,
          DeclaredCost,
          AmountToBePaid,
          DeliveryTypeId,
          TypeOfSeal,
          SturdyPackaging,
          Activity,
          Goods,
          DeliveryDate,
          StartTimeDelivery,
          EndTimeDelivery,
          Сomment,
          ShipperId,
          Marker)
Параметры:

Имя параметра Входной / Выходной Тип Описание
ID входной String Идентификатор заказа в системе
потребителя (уникальное значение)
Number входной String Номер заказа в системе потребителя
(будет распечатываться в комментариях
при маркировке отправлений)
Date входной DateTime Дата заказа в системе потребителя (будет
распечатываться в комментариях при
маркировке отправлений
Customer входной Customer Информация о покупателя, струкутра
DeclaredCost входной Float Объявленная ценность отправления. На
указанную сумму будет оформленная
страховка.
AmountToBeP
aid
входной Float Сумма
к
оплате.
Если
заказ
предоплаченю то 0.
DeliveryTypeId входной Int Идентификатор выбранного способа
доставки.
TypeOfSeal входной Int Вариант
уплотнения,
возможные
значения:
1­Не требуется
2­Пузырчатая пленка
3­Наполнитель
SturdyPackaging входной Boolean Обязательно ли требуется жесткая
упаковка
Activity входной Boolean Актуальность заказа. True – если заказ
актуален, False – если заказ отменен.
Goods входной Goods Список товаров
DeliveryDate входной DateTime Дата доставки, заполняется если выбрана
курьерская доставка
StartTimeDeliv
ery
входной Int Желаемое
время
доставки
«С»,

доставка
EndTimeDelivery входной Int Желаемое время доставки «До»,
заполняется если выбрана курьерская
доставка
Сomment входной String Комментарий к заказу
ShipperId входной String Идентификатор
отправителя,
заполняется
если
у контрагента
несколько интернет магазинов
Marker входной String Маркер заказа, заполняется если
отправления маркируются метками
сайт

Описание:
Метод размещает информацию о заказе в системе исполнителя. Система­потребитель
передает номер и дату заказа, уникальный идентификатор заказа, информацию о
получателе, включая его адрес и телефон, объявленную ценность, сумму наложенного
платежа если таковая есть, состав товарного вложения, тип упаковки и выбранный
способ и детали доставки.

Возвращаемое значение:
Метод возвращает уникальный идентификатор заказа в системе исполнителя.

6.3.1 Пример вызова метода PushOrder


aplix.Delivery ws = new aplix.Delivery();
ws.Credentials = new NetworkCredential("test", "test");
// Подготовим струкутру "Получатель отправления"
aplix.Customer Customer = new aplix.Customer();
// 684005, Камчатский край, Елизовский р‐н, Елизово г, Ленинская ул, дом No 16
aplix.Address Address = new aplix.Address();
Address.Index = "684005";
Address.Region = "Камчатский край";
Address.District = "Елизовский р‐н";
Address.City = "Елизово г";
Address.Street = "Ленинская ул";
Address.Home = "16";
Customer.Address = Address;
Customer.ID = "[email protected]";
Customer.Name = "Сергей";
Customer.Email = "[email protected]";
Customer.Phone = "+7(916)975‐53‐54";
//Заполним параметры заказа
string ID = "2013‐1234567890"; // Уникальный идентификатор заказа в системе клиента
string Number = "1234567890"; // Номер заказа в системе клиента
DateTime Date = new DateTime(2013, 08, 30);
float DeclaredCost = 36350.0f; // Объявленная ценность
float AmountToBePaid = 0; // Нет наложенного платежа
int DeliveryTypeId = 4; // ЕМС
sbyte TypeOfSeal = 2; // Пузырчатая пленка
bool SturdyPackaging = true; // Жесткая упаковка (для хрупких вещей)
bool Activity = true; // Документ актуален
// Предположим, что заказ состоит из 2 позиций
aplix.Goods Goods = new aplix.Goods;
aplix.Goods Item;
Item = new aplix.Goods();
Item.SKU = "216293";
Item.Name = "карта памяти SDXC 64Gb Class 10 Transcend";
Item.Length = 0.130f;
Item.Width = 0.100f;
Item.Height = 0.001f;
Item.Weight = 0.1f;
Item.Qty = 1;
Item.Price = 2080.0f;
Item.VATRate = "НДС18";
Goods = Item;
Item = new aplix.Goods();
Item.SKU = "499687";
Item.Name = "зеркальный фотоаппарат Canon EOS 650D Kit Tamron AF 18‐270mm Black";
Item.Length = 0.1331f;
Item.Width = 0.0998f;
Item.Height = 0.0788f;
Item.Weight = 0.575f;
Item.Qty = 1;
Item.Price = 34270.0f;
Item.VATRate = "НДС18";
Goods = Item;
DateTime DeliveryDate = new DateTime(2013, 09, 05); //Доставка на 05 09 2013 года
int StartTimeDelivery = 10; // интервал доставки с 10
int EndTimeDelivery = 14; // до 14
string Comment = "Тестовый заказ";
//Впулить заказ в систему
long OrderId = ws.PushOrder(ID, Number, Date, Customer, DeclaredCost, AmountToBePaid,DeliveryTypeId, TypeOfSeal, SturdyPackaging, Activity, Goods, DeliveryDate, StartTimeDelivery,EndTimeDelivery, Comment, "", "");
Response.Write("Id заказа:" + OrderId.ToString() + "
");

6.4 Метод GetDetailsOfCost

Синтаксис:        DetailsOfCostList GetDetailsOfCost (ID, TypeId) Параметры:

Входной / Выходной
Тип
Описание

входной
Long
Идентификатор расчета (уникальное значение), полученный при вызове метода CalculateShippingCost

входной
Int

Имя параметра
ID TypeId

Описание: Метод возвращает детализированный список затрат на маркировку и упаковку отправления по заданным идентификатору расчета и идентификатору варианта доставки. Возвращаемое значение: Метод возвращает массив структур

Каждый элемент массива содержит описание затраты, количество, цену и стоимость.

6.4.1 Пример вызова метода GetDetailsOfCost


aplix.Delivery ws = new aplix.Delivery();
ws.Credentials = new NetworkCredential("test", "test");
long ID = 168; // Идентификатор расчета, полученный методом CalculateShippingCost
int TypeId = 3; // Почтовая доставка

aplix.DetailsOfCost Details = ws.GetDetailsOfCost(ID, TypeId);
//Визуализация результата
Response.Write("Id расчета:" + ID.ToString() + "
");
Response.Write("Id метода доставки:" + TypeId.ToString() + "
");
Response.Write(@"


");
foreach (aplix.DetailsOfCost DetailOfCost in Details)
{
Response.Write("" + " " + " " + " " + " " + " ");
}
Response.Write("















Description Price Qty Cost
" + DetailOfCost.Description + " " + DetailOfCost.Price.ToString() + " " + DetailOfCost.Qty.ToString() + " " + DetailOfCost.Cost.ToString() + "

");

6.5 Метод PushReestr

Синтаксис: Long PushOrder (ID, Number, Date, DateOfShipment, IDs) Параметры:

Входной / Выходной
Тип
Описание

входной
String
Идентификатор реестра в системе потребителя (уникальное значение)

входной
String
Идентификатор варианта доставки, по которому необходимо получить детализацию

входной
DateTime
Дата реестра (будет распечатываться в актах приема­передачи отправлений)

входной
DateTime
Ожидаемая дата передачи отправлений исполнителю

входной
String
Массив идентификаторов заказов, которые включаются в данный реестр

Имя параметра
ID Number Date DateOfShipment IDs

Описание: Метод размещает информацию о реестре в системе исполнителя. Система­потребитель передает номер и дату реестра, уникальный идентификатор реестра, ожидаемую дату передачи отправлений исполнителю. Возвращаемое значение: Метод возвращает уникальный идентификатор реестра в системе исполнителя.

6.5.1 Пример вызова метода PushReestr


aplix.Delivery ws = new aplix.Delivery();
ws.Credentials = new NetworkCredential("test", "test");
// Список идентификаторов заказов, которые входят в данный реестр
string IDs={"2013‐1234567890", "2013‐1234567891"};
// Уникальный идентификатор реестра в системе клиента
string ID = "2013‐r12345";
// Номер реестра в системе клиента
string Number = "r12345";
// Дата формирования реестра в системе клиента
DateTime Date = new DateTime(2013, 10, 22);
// Предполагаемая дата передачи заказов на доставку
DateTime DateOfShipment = new DateTime(2013, 10, 23);
// Получим детализацию расчета
long ReestID = ws.PushReestr(ID, Number, Date, DateOfShipment, IDs);
//Визуализация результата
Response.Write("Id реестра:" + ReestID.ToString() + "
");

6.6 Метод GetTrackNumbers

Синтаксис: DateTime GetTrackNumbers (DateOfLastGetting, TrackNumbers) Параметры:

Входной / Выходной
Тип
Описание

входной
DateTime
Дата последнего успешного получения трек­номеров. Параметр используется для того чтобы сократить объем передаваемых данных и не дублировать данные, которые были выгружены ранее.

входной
TrackNumber
Массив трек­номеров по заказам

Имя параметра
DateOfLastGetting TrackNumbers

Описание: Метод возвращает список трек­номеров, которые были привязаны к заказам за период с DateOfLastGetting по текущее время. Результата помещается в выходной параметр TrackNumbers. Свойство Activity имеет значение true, если трек­номер актуален, иначе ложь. Возможны ситуации, когда отправлению присваивается один трек­номер, а по истечении некоторого второй трек номер, в этом случае трек­номер, присвоенный изначально становиться не актуальным. Возвращаемое значение: Метод возвращает дату и время на которое актуальны выгружаемые данные. Данное значение необходимо использовать при следующем вызове метода GetTrackNumbers в параметре DateOfLastGetting.

6.6.1 Пример вызова метода GetTrackNumbers


aplix.Delivery ws = new aplix.Delivery();
ws.Credentials = new NetworkCredential("test", "test");
// Дата последнего удачного получения треков
DateTime DateOfLastGetting = new DateTime(2013, 08, 01);
aplix.TrackNumber TrackNumbers;
// Получим список трек‐номеров
DateTime NewDateOfLastGetting = ws.GetTrackNumbers(DateOfLastGetting, out TrackNumbers);
//Визуализация результата
Response.Write("NewDateOfLastGetting: " + NewDateOfLastGetting.ToString() +"
");
Response.Write(@"


");
foreach (aplix.TrackNumber TrackNumber in TrackNumbers)
{
Response.Write("" + " " + " " + " " + " ");
}
Response.Write("













OrderID TrackNumber Activity
" + TrackNumber.OrderID.ToString() + " " + TrackNumber.Number + " " + TrackNumber.Activity+ "

");

API (от англ. Application Program Interface) – это интерфейс взаимодействия между сайтом клиента и сервером. Представляет собой ресурс, который сервер открывает для работы извне, т.е. программист может воспользоваться им для получения доступа к функционалу программы, библиотеки, модуля. API делает возможным работу ресурсов, которые используют потенциал и мощность предоставляющего сайта, а также запуск дополнительных компонентов к ним, расширяющих возможности web-проекта.

Преимущества:

Типы

  • возвращающие. На запрос стороннего приложения какого-либо метода с заданными параметрами сервер дает запрашиваемую информацию в определенном формате;
  • изменяющие. Клиент вызывает некоторую функцию сервера, которая вводит новую информацию или изменяет на нем определенные настройки.

API Яндекс.Директа

Для продвижения сайтов эффективен API .

  1. На его базе разработчики могут создавать приложения, которые напрямую взаимодействуют со службой поисковой системы. Такие программы позволят рекламодателям гибко управлять масштабными , получать статистические отчеты по каждой из них, точно прогнозировать бюджеты.
  2. Рекламные агентства с помощью API Директа могут просмотреть весь список своих клиентов, клиенты – представителей.
  3. Если определенные фразы, используемые для поисковой оптимизации , дают низкий CTR в контекстной рекламе, показ по ним можно автоматически отключить. На тематических площадках через API можно задавать ставки, определенные доноры могут быть удалены.
  4. API Яндекс.Директа имеет SOAP-интерфейс, т.е предоставляет широкий выбор языков программирования для создания приложений. Данный протокол поддерживается такими языками, как Perl, Java,

API (Application Programming Interface) — это определенное представление данных для взаимодействия между приложениями. В частном случае, в качестве ответного приложения, может выступать сервер. АПИ — это описанный формат, которому должны соответствовать обе стороны обмена данными.

Технология различных API — это набор методов взаимодействия. Система АПИ в том или ином виде представлена везде. Например, у нас в руках смартфон с приложением покупки билетов. На самом «высоком» уровне мы видим графическую часть приложения с полями ввода данных. Мы запрашиваем рейсы по маршруту на определенный день и что в этот момент происходит:

  1. Мобильное приложение формирует запрос к серверу. Запрос формируется в определенном формате. Например: Вылет:МоскваDME,Прилет:АмстердамAMS,Дата:01-01-2017,Мест:2,Класс:Эконом. Эта строчка содержит строгий формат — Заголовок:Значение, все значения через запятую, обязательные поля Вылет, Прилет и Дата, если не указаны другие данные, то они будут по-умолчанию: Мест:1, Класс:Эконом.
  2. Сервер авиакомпании получает этот запрос и программа понимает, что от нее требуется найти рейсы и цены.
  3. Сервер обращается к базе данных на языке SQL, что тоже является частным представлением API
  4. База данных обращается к файлу через API файловой системы
  5. Файловая система обращается к жесткому диску — через его API-протокол.

Можно продолжить углубление, но и так понятно, что любая задача программирования — это выстраивание иерархии API.

Сегодня в том или ином виде, вся информация в компьютерном виде представляется посредством АПИ.

Мы разрабатываем системы API для высшего уровня, где следующим потребителем является клиентское приложение.

Классификация видов АПИ

В зависимости от решаемой задачи, протоколы передачи АПИ могут быть как стандартизированные, так и собственного формата. Наиболее часто применяются стандартизированные протоколы, это позволяет разработчикам задействовать готовые модули для их обработки, что сокращает время на разработку приложения. Различные специфические типы применяются для достижения определенного преимущества, например снижения трафика, скорость распознавания команд, а в некоторых случаях — это единственная возможность — разработка собственного формата — к примеру вещание видео с эфимеридной составляющей.

По виду передаваемой информации АПИ подразделяется на следующие форматы:

  • Стандартные протоколы API
    • Текстовый
  • Бинарный
    • Поточный
    • Кадровый

По виду взаимодействия клиент-сервер, наиболее распространены следующие виды:

  • Пакетные
    • HTTP/HTTPS
    • Sockets
  • Процедурные (протокольные)
  • Поточные
  • Широковещательные

Применение систем АПИ

Все онлайн-сервисы и системы имеют публичные API. В некоторых случаях за использование доступа к API приходится оплатить подписку или определенное количество обращений. Если в Ваших целях стоит создание онлайн-сервиса, который будет предоставлять какую-либо информацию, обратите на API особенное внимание. Подход и хорошее документирование возможностей API, это ключ к успеху. Все сторонние разработчики, которые в последующем будут создавать дополнительные приложения, обязаны использовать именно этот протокол.

Довольно частая практика, когда сервер API, это единственное представление данных всего сервиса, а клиентская часть работает только через приложение. Яркие примеры Viber, Instagram, Swarm- еще эти приложения называют Mobile only (только в мобильном). В связи с этим, должна быть создана система распределения нагрузки между серверами API, что позволит создать сервис 24/7 при масштабируемой мощности. Перед созданием серверной части, следует сразу оценить возможности данного мероприятия и учитывать эти возможности при разработке программ.

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

Мы описали, как это работает, давайте взглянем, как на этом зарабатывать? Первый метод напрашивается сам собой — предоставление услуги через АПИ. Вы можете продавать услуги или товары напрямую — обращение к АПИ Вашего ресторана, сформирует заказ на доставку еды на дом. Или предоставлять полезный сервис на платной основе, например формирование бухгалтерских отчетов.

Второй метод заработка на АПИ заключается в аггрегировании нескольких систем в один сервис. Мы уже обсудили вид АПИ для авиакомпании, но авиакомпаний десятки, а то и сотни. Сейчас стали популярны сервисы по продаже билетов — Aviasales, OneTwoTrip, Momondo, которые фактически из себя ничего не представляют, а только берут разные АПИ от авиакомпаний и публикуют собственный сервис, который собирает данные с этих компаний. Практика очень распространенная и высокодоходная.

Третий метод заработка на API, это «подмешивание данных». Если опять вернемся к авиакомпании, то мы можем создать сопутствующую услугу на их базе, к примеру, страхование. Мы публикуем сервис или альтернативную точку входа АПИ, где помимо рейсов, в данные АПИ будет добавлена информация по страхованию с привязкой к конкретному рейсу. Также поступают, к примеру, авиакомпании или посредники, расширяя АПИ для информирования об отелях.

Создание технологий АПИ

Мы предлагаем свои услуги по созданию серверов API всех описанных ранее типов и протоколов. Мы имеем опыт построения взаимодействия в различных высоконагруженных системах. На выходе мы представляем не только готовый сервер (черный ящик) но и полное описание протокола в виде конструкторской документации. Данное описание протокола может быть предоставлено следующим разработчикам, применяемым эти данные, либо в открытом доступе для OpenSource.

Помимо непосредственно сервера, мы можем создать систему слежения и аналитики, которая будет сигнализировать об ошибках и превышением регламентированной нагрузки сервера(-ов).

API Server принимает все API-запросы от внешних приложений. Для проверки подлинности пользователей, API Server использует систему аутентификации, аналогичную системе шифрования открытым ключом (public-key encryption).

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

Все запросы к API Server осуществляются на файл фронт-контроллера. Именно в этом файле происходит идентификация открытого и секретного ключей.

Вот пошаговое описание этого процесса:

  • На сервер по адресу расположения файла фронт-контроллера приходит запрос от API клиента. В запросе содержатся APP ID (открытый ключ клиента) и APP KEY (32-символьная, шифрованная с помощью секретного ключа клиента строка). Секретный ключ никогда не отправляется на сервер, он используется только для шифрования запроса. В запросе содержатся параметры вызова сервера – пользователь, пароль доступа, название контроллера и действия, которое должно обработать вызов клиента. Например, массив параметров может выглядеть так:
$items = array("controller" => "todo", "action" => "read", "username" => $username, "userpass" => $userpass);
  • Когда на API Server приходит запрос, сервер проверяет список приложений на наличие открытого ключа (APP ID);
  • Если открытый ключ не найден – выбрасывается исключение типа «Request is not valid». Если ключ имеется, сервер берет секретный ключ, который соответствует этому открытому ключу, и пытается расшифровать пришедший запрос;
  • Если расшифровка была успешной, из пришедшего запроса вытягиваются и обрабатываются параметры controller и action. Фронт-контроллер, который обрабатывает запрос, подключает нужный файл контроллера и вызывает действие, содержащееся в параметре action;
  • В случае успеха/неудачи обработки запроса клиент получает ответ от API Server.
В продолжение темы:
Ошибки

В Российской Федерации при формировании бухгалтерской отчетности в электронном виде действует Приказ ФНС России от 20.03.2017 N ММВ-7-6/228 "Об утверждении рекомендуемых...

Новые статьи
/
Популярные