REST API для обработки данных и цепочки методов
Я заранее приношу извинения, если качество вопроса плохое. Я все еще начинаю изучать концепции REST API. Я пытаюсь реализовать масштабируемый REST API для обработки данных. Вот что я смог придумать до сих пор.
Рассмотрим некоторые числовые данные, которые можно получить с помощью вызова
GET: GET http://my.api/data/123/
Пользователи могут применять последовательность арифметических операций, таких как
add и multiply. Не-спокойный способ сделать это это: GET http://my.api/data/123?add=10&multiply=5
Assupmtions:
- Исходные данные в БД не изменяются. Пользователю возвращается только измененная его версия.
Данные имеют большой размер (скажем, большой многомерный массив), поэтому мы не можем позволить себе возвращать все данные при каждом вызове opertation. Вместо этого мы хотим применять операции в виде пакета и возвращать конечные измененные данные в конце.
Есть 2 спокойных способа, которыми я в настоящее время конисдеринг:
[37]}1. Модельные арифметические операции как подресурсы данных.
Если рассматривать add и multiply как подресурсы данных , то как здесь. В этом случае мы можем использовать:
GET http://my.api/data/123/add/10/
Который был бы безопасным и идемпотентным, учитывая, что исходные данные никогда не изменяются. Однако нам нужно связать несколько операций в цепочку. Мы можем это сделать?
GET http://my.api/data/123/add/10/multiply/5/
, где multiply является создание дочерних ресурсов из add/10/ который сам является одним из дочерних ресурсов из data/123
Плюсы:
- безгражданство: Север не хранит никакой информации об измененных данных.
- легкий доступ к измененным данным: это всего лишь простой вызов GET.
Минусы:
- цепочка: я не знаю, Может ли это быть легко реализовано.
- длинные URI: с каждой применяемой операцией URI становится все длиннее и длиннее.
[37]}2. Создайте редактируемый объект данных:
В этом в этом случае пользователь создает редактируемую версию исходных данных:
POST http://my.api/data/123/
Вернется
201 Created
Location: http://my.api/data/123/edit/{uniqueid}
Пользователи могут затем PATCH эти редактируемые данные
PATCH http://my.api/data/123/edit/{uniqueid}
{add:10, multiply:5}
И, наконец, GET отредактированные данные
GET http://my.api/data/123/edit/{uniqueid}
Плюсы:
- Чистые Ури.
Минусы:
- сервер должен сохранять состояние редактируемых данных.
- получение отредактированных данных требует, чтобы пользователи сделали не менее 3 звонки.
Редактирование не является долгим идемпотентом.
Существует ли более чистый, более семантический способ реализации обработки данных в режиме покоя?
Правка:
Если вам интересно, в чем заключается реальная проблема, стоящая за этим, я имею дело с цифровой обработкой сигналов.
В качестве простого примера можно привести применение визуальных фильтров к изображениям. Следуя этому примеру, веб-служба RESTful может сделать:
GET http://my.api/image/123/blur/5px/rotate/90deg/?size=small&format=png
4 ответов:
Пара вещей, которые стоит рассмотреть в вашем вопросе.
API, основанные на REST, основаны на ресурсах
Итак, рассмотрим ваш первый пример, пытаясь связать свойства преобразования в URL-путь, следующий за идентификатором ресурса..
GET http://my.api/data/123/add/10/multiply/5/..не подходит хорошо (а также сложно реализовать динамически, как вы уже догадались)
Безгражданство
Идея безгражданства в REST построена вокруг одного HTTP вызов содержит достаточно информации, чтобы обработать запрос и предоставить результат, не возвращаясь к клиенту за дополнительной информацией. Хранение результата HTTP-вызова на сервере - это не состояние, а кэш.
теперь, учитывая, что API на основе REST, вероятно, не подходит для вашего использования, если вы все еще хотите его использовать, вот ваши варианты:1. Используйте строку запроса с общей операцией URL
Вы могли бы использовать Querystring, но упростите путь к ресурсу, чтобы принять все преобразования в одном URI. Учитывая ваши примеры и нежелание хранить преобразованные результаты, это, вероятно, ваш лучший вариант.
GET http://my.api/data/123/transform?add=10&multiply=52. Используйте POST non-RESTfully
Можно использовать запросы POST и использовать тело HTTP для отправки параметров преобразования. Это гарантирует, что у вас никогда не закончится место в строке запроса, если вы когда-нибудь решите сделатьмного обработки и это также будет держать ваше общение аккуратнее. Это не считается успокаивающим, если сообщение возвращает данные изображения.
3. Используйте POST RESTfully
Наконец, если вы решите, что хотите кэшировать вещи, ваш пост может фактически хранить преобразованный объект (обратите внимание, что REST не диктует, как он хранится, в памяти или БД и т. д.) который может быть повторно извлечен по Id с помощью GET.
Вариант А
Отправка в URI создает подчиненное значение ресурс.
POST http://my.api/data/123 {add:10, multiply:5}Возвращает
201 Created Location: http://my.api/data/123/edit/{uniqueid}Затем получите отредактированные данные
GET http://my.api/data/123/edit/{uniqueid}Вариант В
Удалите идентификатор ресурса из URL-адреса, чтобы было ясно, что вы создаете новый элемент, а не изменяете существующий. Результирующий URL-адрес также находится на том же уровне, что и исходный, поскольку предполагается, что это тот же тип результата.POST http://my.api/data {original: 123, add:10, multiply:5}Возвращает
201 Created Location: http://my.api/data/{uniqueid}Затем получите отредактированные данные
GET http://my.api/data/{uniqueid}
Существует несколько способов это может быть сделано. В конце концов он должен быть чистым, независимо от того, какую метку вы хотите ему дать (REST non-REST). REST - это не протокол с RFC,поэтому не беспокойтесь слишком сильно о том, какую информацию вы передаете в виде URL-путей или URL-парамов. Базовый веб-сервис должен быть в состоянии предоставить вам данные независимо от того, как они передаются. Например, Java Jersey даст вам ваши params независимо от того, являются ли они param или URL path, это просто аннотация разница.
Возвращаясь к вашей конкретной проблеме, я думаю, что ресурс в этом вызове типа REST - это не столько данные, которые используются для выполнения числовых операций, сколько фактический ответ. В этом случае может быть достаточно записи, в которой идентификатор данных и операции являются полями.
POST http://my.api/operations/{ "dataId": "123", "operations": [ { "type": "add", "value": 10 }, { "type": "multiply", "value": 5 } ] }Ответ должен был бы указывать на место, где результат может быть получен, как вы указали. Результат, на который ссылается местоположение (и идентификатор) в ответ, по существу, является неизменным объектом. Таким образом, это фактически ресурс, созданный постом, а не данные, используемые для расчета этого результата. Это просто другой способ его просмотра.
EDIT: в ответ на ваш комментарий о нежелании хранить результаты операций, вы можете использовать обратный вызов для передачи результатов операции вызывающему абоненту. Вы можете легко добавить поле a во вход JSON для хоста или URL обратного вызова. Если URL обратного вызова присутствует, затем вы можете опубликовать на этом URL-адресе результаты операции.
{ "dataId": "123", "operations": [ { "type": "add", "value": 10 }, { "type": "multiply", "value": 5 } ], "callBack": "<HOST or URL>" }
пожалуйста, не рассматривайте это как ответ на мой собственный вопрос,а скорее как дополнение к обсуждению.
Я дал много думал в это. Основная проблема с предлагаемыми в настоящее время архитектурами-это масштабируемость, так как сервер создает копии данных каждый раз, когда он работает.
Единственный способ избежать этого-моделироватьoperationsиdataотдельно. Итак, подобно ответу Хосе, мы создаем ресурс:POST http://my.api/operations/ {add:10, multiply:5}Обратите внимание, что я этого не делал. укажите данные вообще. Созданный ресурс представляет собой только серию операций.
POSTвозвращает:201 Created Location: http://my.api/operations/{uniqueid}Следующим шагом является применение
operationsк данным:GET http://my.api/data/123/operations/{uniqueid}Этот подход к моделированию отдельных объектов имеет несколько преимуществ:
- данные не реплицируются каждый раз, когда применяется другой набор операций.
Пользователи создают только ресурсыoperations, и поскольку их размер мал, нам не нужно беспокоиться о масштабируемости.Пользователи создают новый ресурс только тогда, когда им требуетсяНовый набор операций.Переход к примеру изображения: если я разрабатываю веб-сайт в оттенках серого и хочу, чтобы все изображения были преобразованы в оттенки серого, я могу сделать
POST http://my.api/operations/ {greyscale: "50%"}А затем примените эту операцию ко всем моим изображениям следующим образом:
GET http://my.api/image/{image_id}/operations/{geyscale_id}Пока я не хочу изменять набор операций, я могу использовать только
GET.Общие операции могут быть созданы и сохранены на сервере, поэтому пользователи не делают этого. придется их создавать. Например:
GET http://my.api/image/{image_id}/operations/flip, где
operations/flip- уже доступный набор операций.- Легко, применяя один и тот же набор операций к разным данным, и наоборот.
GET http://my.api/data/{id1},{id2}/operations/{some_operation}Позволяет сравнить два набора данных, которые обрабатываются аналогично. Альтернативно:
GET http://my.api/data/{id1}/operations/{some_operation},{another_operation}Позволяет увидеть, как различные процедуры обработки влияют на результат.
Я бы не стал пытаться описать вашу математическую функцию с помощью URI или тела запроса. У нас есть более или менее стандартный язык для описания математики, поэтому вы можете использовать какой-то шаблон.
GET http://my.api/data/123?transform="5*(data+10)" POST http://my.api/data/123 {"transform": "5*({data}+10)"}Вам нужен код на стороне клиента, который может создавать такие шаблоны, и другой код на стороне сервера, который может проверять, анализировать и т. д... шаблоны, созданные клиентом.
Comments