REST/CRUD. Я неправильно его готовлю?
Вступление
Must have для всех ресурсов
Важное отличие slug от id
А теперь принимаем за аксиому «все объекты должны иметь указаные свойства», и, чтоб не размазываться по объекту запихиваем их например в свойство «__link__»:
Кстати, это — валидный объект. Он мог вернуться с какого нибудь url (не «localhost/api/users»). Разработчик, получив такой объект, должен запросить данные по url/urn из __link__, но об этом позже.
Кстати, «по правильному» — не вносить доп. свойство «__lnk__», а использовать для этих целей заголовки формата X-URI, X-URN, X-URL, etc, но не всем веберам нравится работать с заголовками. Мол взял body и побежали.
Хммм… а сколько реализаций REST API имеет подобные свойства? Может я изобрел велосипед?
CRUD/Read или HTTP/GET
Тут все просто. Берем URL, запрашиваем объект, и… А что «и»? И иногда наблюдаем вот такой ответ:
Пример:
Ответ должен быть таким:
При этом count должен жить в HTTP/HEAD, т.к. не имеет на прямую отношения к ресурсу, а характеризует состояние коллекции. Опят же, Вам надо вывести кол-во пользователей. Как быть? Выбирать все и считать в JavaScript? Писать новый url для получения кол-ва элементов? Зачем? Сделайте HTTP/HEAD запрос к колекции. Данных не будет, вернутся только зголовки.
Скептики скажут: для отрисовки всех элементов придется делать множество запросов к бекенду,
Отвечу: HTTP/1.1/Keep-alive спасет нас всех. При использовании javascript-фреймворков и кеширования — большинство данных будут запрошены при инициализации, разово, а после — будут только обмениваться запросами с ответом HTTP/304 (ресурс не изменился).
Знаете почему веберам не нравится такой подход? Им приходится контролировать получение данных с сервера для нормального отображения.
Например: Если данные прилетают сразу со свойствами — можно сразу отрисовать несколько дивов в цикле не заботясь о синхронизации. Если же делать 4 запроса для вывода 4-строк с пользователями — надо как-то отслеживать состояние всех запросов. Т.е. пока ВСЕ запросы не отработают — ничего не рисовать. См. Promise и Future для решения подобных проблем. Они все имеет код для принудительной синхронизации, хотя я бы рисовал сразу как есть…
Алгоритм CRUD
API должен выполнять четыре типа функций. Он должен иметь возможность создавать новые данные, а также читать, обновлять и удалять существующие. В информатике мы называем эти параметры CRUD.
Метод CRUD необходим при создании веб-приложений, поскольку он позволяет структурировать модели, которые вы создаёте для своих API. Но как работает CRUD? Как вы взаимодействуете с API с помощью CRUD?
В этой статье мы отвечаем на эти вопросы. Мы начнём с обсуждения основ CRUD, а затем рассмотрим несколько примеров того, как взаимодействовать с API с помощью CRUD.
Зачем нам нужен CRUD
Допустим, мы создаём API, в котором хранится кофе, продаваемый в нашем кафе. Этот API должен иметь возможность хранить различные объекты кофе. Кофейный объект может включать:
Мы хотим убедиться, что пользователи могут взаимодействовать и изменять данные, хранящиеся в нашем API. Вот почему нам нужно следовать структуре CRUD. В конце концов, для чего нужен API, в котором хранится кофе, если компания не может изменить цену на свой кофе? Зачем компании использовать API, который не позволяет удалять записи?
Что такое CRUD
CRUD — это аббревиатура от Create, Read, Update и Delete.
Когда вы работаете с веб-службами, CRUD соответствует следующим HTTP-методам, которые используются, чтобы сообщить веб-серверу, как вы хотите взаимодействовать с веб-сайтом:
Давайте рассмотрим каждого в отдельности.
Мы собираемся использовать утилиту командной строки cURL для создания примеров запросов к API кофе, чтобы вы могли увидеть, как работают эти операции. Прежде чем мы начнём, запустите следующую команду в терминале на вашем компьютере, чтобы убедиться, что cURL установлен:
Если в вашем терминале появляется ошибка «curl: command not found», вам необходимо установить cURL. В противном случае вы готовы приступить к работе!
Создать
API, который хранит данные для нашего кафе, должен позволить нам добавлять новые записи в меню. В этом случае мы сможем создать новый кофейный элемент, указав его название и цену.
Чтобы добавить новый кофе в меню, мы можем использовать запрос POST, который позволяет нам отправлять данные в наш API, которые будут храниться в базе данных.
Вот информация о кофейном элементе, который мы хотим добавить:
Следующая команда cURL позволяет нам создать кофе с этими деталями с помощью нашего API:
Эта команда создаёт новый кофе в нашей базе данных с именем «Эспрессо» и ценой «1,95».
Читать
Наш API должен позволять нам видеть список всех сортов кофе в нашем меню. Чтобы увидеть эти данные, мы можем использовать запрос GET. Это позволяет нам видеть список кофе в нашем меню, не внося изменений в данные, хранящиеся в нашем API.
Эта команда позволяет нам получить список кофе из нашего API:
REST vs CRUD: Объяснение REST и CRUD операций :перевод
Некоторая путаница вокруг REST и CRUD связана с перекрытием основных команд, предписанных обоими процессами. Это еще более усиливается сообществом Rails, охватывающим REST и его характер GET, PUT, POST.
REST: Основы и Принципы
Каждая REST команда сосредоточено вокруг ресурсов. В RESTе, на самом деле ресурс это все на что может указать протокол HTTP. Например, картинка, веб-сайт, документ, или сервис прогноза погоды. Возможности почти безграничны.
Термины, определяющие принципы REST, были введены в диссертации доктора Роя Филдинга «Архитектурные стили и проектирование сетевой инфраструктуры программного обеспечения». В целом, REST можно рассматривать как стандарт в разработке сервисных приложений. Он предлагает альтернативу простому объектному протоколу доступа (SOAP), COBRA, RMI и многим другим.
Принципы REST
Существует 6 обязательных ограничений у RESTа. Вот они:
Модель Client-Server
Эту модель подчеркивает тот факт, что REST является распределенным подходом через характерное разделения архитектуры между клиентом и сервером. Каждый сервис имеет несколько возможностей и прослушивает запросы. Запросы совершаются клиентом и принимаются или отклоняются сервером.
Отсутствие состояния
Из-за характера отсутствия состояния этот принцип является руководящим в архитектуре RESTful. Он определяет, какие команды могут быть предоставлены между клиентом и сервером. Реализация запросов без сохранения состояния означает, что связь между потребителем и сервисом инициирована запросом, и запрос содержит всю необходимую информацию для ответа сервера.
Кэширование
Кэширование обязует, что ответы сервера должны быть помечены либо кэшируемыми или нет. Кэширование помогает снизить некоторые ограничения отсутствия состояний. Например, запрос который закеширован потребителем в попытке избежать повторную отправку запроса дважды.
Единообразие интерфейса/контракта
RESTful архитектура следует принципам, которые определяют Единый Контракт. Они запрещают использование нескольких отдельных интерфейсов в API. Вместо этого, один интерфейс распределяется по гипермедиа-соединениями.
К унифицированным интерфейсам предъявляются следующие четыре ограничительных условия:
Все ресурсы идентифицируются в запросах, например, с использованием URI в интернет-системах. Ресурсы концептуально отделены от представлений, которые возвращаются клиентам. Например, сервер может отсылать данные из базы данных в виде HTML, XML или JSON, ни один из которых не является типом хранения внутри сервера.
Если клиент хранит представление ресурса, включая метаданные — он обладает достаточной информацией для модификации или удаления ресурса.
Каждое сообщение содержит достаточно информации, чтобы понять, каким образом его обрабатывать. К примеру, обработчик сообщения (parser), необходимый для извлечения данных, может быть указан в списке MIME-типов.
Клиенты изменяют состояние системы только через действия, которые динамически определены в гипермедиа на сервере (к примеру, гиперссылки в гипертексте). Исключая простые точки входа в приложение, клиент не может предположить, что доступна какая-то операция над каким-то ресурсом, если не получил информацию об этом в предыдущих запросах к серверу. Не существует универсального формата для предоставления ссылок между ресурсами, RFC 5988 и JSON Hypermedia API Language являются двумя популярными форматами предоставления ссылок в REST HYPERMEDIA сервисах.*
Это позволяет добавлять новые команды и промежуточное программное обеспечение, не влияя на исходные команды и функционируя между клиентом и сервером.
Код по требованию (необязательное ограничение)
Приложения RESTful не должны включать Код-По-Требованию, но они должны иметь клиент-сервер, отсутсвие состояния, кэширование, унифицированный контракт и слои. Код по требованию позволяет отделить логику на клиентах от логики на серверах. Это позволяет им обновляться независимо от логики сервера.
REST: в двух словах
REST соответсвует набору определяющих принципов для разработки API. Он использует HTTP-протоколы, такие как GET, PUT, POST, чтобы связать ресурсы с действиями в отношениях клиент-сервер. В дополнение к модели клиент-сервер у него есть несколько других определяющих ограничений. Принципы RESTful архитектуры служат, чтобы создать стабильное и жизнеспособное приложение, которое предлагает простоту и удовлетворение конечному пользователю.
CRUD: Основы и Принципы
С лучшим пониманием RESTful архитектуры, время погрузиться в CRUD.
CRUD это акроним от CREATE, READ, UPDATE, DELETE. Это форма стандартных команд баз данных, которые основывают CRUD.
Многие разработчики в лучшем случае, видят эти команды как примитивное руководство(*отклонюсь от перевода и добавлю свои 3 копейки, по сути это самый минимум тех знаний которые от вас как от программиста могут потребовать начиная с позиции Junior разработчика*)
Это потому, что CRUD не был разработан как способ разработки современного API. Фактически, CRUD берет свое начало в записях баз данных.
По определению, CRUD это больше цикл чем архитектурный подход. На любом динамическом вебсайте, существует многообразие CRUD приемов.
Для примера, покупатель на eCommerce сайте может CREATE(создать) учетную запись, UPDATE(обновить) информацию по учетной записи, и DELETE(удалить) товары из корзины.
Менеджер операционного склада использует этот же сайт, чтобы CREATE(создать) запись о транспортировке товаров, RETRIEVE(получить) их как понадобится, и UPDATE(обновить) список сырья. Retrieve иногда заменяет READ(чтение) в цикле CRUD.
Происхождение Баз Данных
В современной разработке программного обеспечения CRUD превзошел свое происхождение как основополагающие функции базы данных и теперь сопоставляет себя с принципами разработки для динамических приложений, таких как протокол HTTP, DDS и SQL.
Принципы CRUD
Как уже говорилось выше, принципы CRUD операций определены как CREATE(создание), READ/RETRIEVE(чтение/получение), UPDATE(обновление), и DELETE(удаление).
Создать
CREATE procedures generate new records via INSERT statements.
Прочитать/Получить
READ процедуры читают данные основываясь на входных параметрах. Подобным образом, RETRIEVE процедуры берут данные основываясь на входных параметрах.
Обновить
UPDATE процедуры изменяют записи без их затирания.
Удалить
DELETE процедуры удаляют записи, где задано.
REST и CRUD общие черты
Отсутствие ясности между ними теряется для многих, когда они не могут определить, когда заканчивается CRUD и начинается REST. Мы упомянали ранее, что CRUD может быть сопоставлен к DDS, SQL, и HTTP протоколами. И что HTTP протоколы транспорт между ресурсами в RESTful архитектуре, часть ядра REST основы.
Отображение принципов CRUD в REST означает понимание того, что GET, PUT, POST и CREATE, READ, UPDATE, DELETE имеют поразительное сходство, поскольку первая группа применяет принципы последней.
Однако важно также отметить, что часть архитектуры программного обеспечения RESTful означает больше, чем отображение команд GET, PUT, POST.
REST и CRUD: Какие отличия?
CRUD это операции которые могут сопоставляться с REST, по дизайну. Permanence, as defined in the context of CRUD, is a smart way for applications to mitigate operational commands between clients and services.
But REST governs much more than permanence within its principles of architecture. Here are some of the ways that REST is not only different than CRUD but also offers much more:
Путь вперед
Разработчики выбирают REST по ряду причин:
Не удивительно, запрос на RESTful архитектуру продолжает расти из года в год. И так как REST становится еще более популярен как архитектурный стиль, программистам нужно уметь отличать различия между принципами других инструментов как SOAP, COBRA, и RMI.
Что такое REST, RESTFul и CRUD
REST — это концепция для взаимодействия компонентов основанный на протоколе HTTP. Не хочу останавливаться на скучной теории (вики в помощь), а дам простое объяснение применительно к сайтам.
Так вот, REST говорит что этого делать не нужно. Данные передаём как есть, только у HTTP-запроса указывается метод (параметр) для этих данных. Обычно мы оперируем GET и POST, поскольку они работают «из коробки» в HTML и их поддерживает любой браузер. Но на самом деле, метод у HTTP может быть абсолютно любым. Есть некие общепринятые: PUT, DELETE, OPTIONS, PATCH, но это совсем не стандарт.
То есть, например мы хотим отправить на сервер GET-запрос по адресу сайт/task и получить список задач (таски). Потом мы хотим добавить новую задачу: отправляем на тот же адрес сайт/task, но уже методом POST. Потом решили, что для редактирования задачи нужно отправить уже PUT и опять же на тот же адрес. И, уж коли пошла такая пьянка, то отправляем и метод DELETE для удаления какой-то задачи.
Формирование GET-запроса очень простое — достаточно набрать адрес в браузере. Для POST уже нужна html-форма с method=post. Эти же методы прекрасно работают и через AJAX. Но, что касается PUT и DELETE, то ни HTML, ни браузер о них ничего не знают. Формально мы всё-таки можем их указывать, но наткнёмся на последнюю стенку — сервер, который также как правило ничего не знает об этих методах и рубанётся с ошибкой 501 или 405.
Таким образом, хоть HTTP и поддерживает произвольные методы, но в реальности работают только два: GET и POST.
Чтобы обойти это ограничение и применить REST к нашим сайтам, придумали хитрость. Все «нестандартные» запросы в своём теле должны содержать отдельное поле, где и указывается «желаемый» метод.
Устоявшаяся практика — метод указывать в поле _method формы или Ajax-запроса.
То есть реальная отправка это POST, но приложение проверяет поле _method и по нему уже принимает решение что делать дальше.
Такой разбор выполняет роутер приложения. Если это так, то правила роутинга указываются примерно так:
Обратите внимание, что во всех случаях используется один http-адрес: сайт/task — меняются только методы, которые указываются либо в html-форме, либо Ajax-запросе.
Если не использовать REST, то скорее всего пришлось бы указывать действие либо по отдельному url-адресу, либо в get-параметрах. Как-то так:
Дальше роутер смотрит правила и находит php-метод для запуска.
REST — это только концепция, набор правил. Если же применять эти правила к приложению, то уже говорят о RESTFul. Например REST предполагает использование модели «клиент-сервер». Если мы предположим, что сервер — это реальный сервер хостинга, а клиент — пользователь сайта, то для RESTFul нужно уже настраивать реальный сервер, чтобы он понимал используемые http-методы. Вряд ли кто-то будет это делать, поэтому с этой точки зрения приложение не может считаться RESTFul.
В целом стоит отметить, что сейчас REST и RESTFul — фактически синонимы. Если php-приложение может принимать хоть каким-то способом http-метод, то считается, что это уже полноценный RESTFul. Нужно просто понимать, что архитектура REST позволяет нам использовать HTTP примерно так, как он изначально и задумывался.
Создаем свою CRUD API на Express и MySQL: часть первая
Всем привет. В преддверии старта курса «Fullstack разработчик JavaScript», хотим поделиться небольшим материалом, который был написан нашим внештатным автором.
Express один из самых популярных веб-фреймворков, который поддерживает роутинг, миддлвейрс и систему шаблонов. Делать бэкенд на Node.js без Express в 2020 году — довольно странное занятие, ведь Express де-факто — каркас для создания веб-приложения на Node.js.
Сегодня мы попробуем создать несложное CRUD API используя базу данных MySQL. Опытный в Node.js читатель спросит, а где же MongoDB, с которым Node.js обычно применятся в паре но, скажу сразу, это статья больше для PHP разработчиков, которые хотят немного потрогать Node.js, и чтобы смягчить переход в новую экосистему мы воспользуемся MySQL. API мы будем создавать для несложного Todo приложения, на тот случай, если кто-то захочет к своей todo (и даже неважно, написанной с помощью React или нет), присоединить немного бэка и поиграть с ним.
«Архитектура» и суть нашего приложения
В нашем приложении можно будет создавать, получать, обновлять и удалять Todo. В общем, у нас будет минимальный набор функций CRUD (create read update delete).
В конце мы совместим приложение c приложением на React и все протестируем.
Для начала приведу структуру файлов приложения:
Дальше я приведу таблицу действий и методов, которые есть в нашем приложении:
| Методы | Url | Действия |
|---|---|---|
| GET | /deals | получение всех дел |
| GET | /deals/2 | Получение id c номером 2 |
| POST | /deals | добавление нового дела |
| PUT | /deals/3 | Обновить пользователя с > |
| DELETE | /deals/3 | удалить пользователя с > |
| DELETE | /deals | удалить всех пользователей |
Создание своего Node.js приложения
Переходим в вашу любимую директорию, запускаем терминал и создаем ваше приложение. Кстати, из заголовка, наверное, понятно, что Node.js у вас уже должна быть установлена. Если вы еще этого не сделали, то этого просто не может быть скачайте по ссылке отсюда.
Дальше необходимо инициализировать наше приложение с помощью npm init. Т.к. приложение у нас скорее тестовое и обучающее, я воспользуюсь командной, которая заполнит все данные по дефолту, чтобы не тратить время на мелкие детали:
Если что, потом руками в package.json вы сможете поменять данные на те, которые вам нужны: репозиторий github, тэги, автора, и т.д.
Потом нам нужно поставить все необходимые для работы приложения пакеты:
Базовая настройка Express
В корневой папке проекта создаем файл server.js :
Теперь мы можем запустить сервер с помощью:
Сейчас наш сервер умеет следующее:
Создаем свою таблицу данных MySQL
Я очень надеюсь, что у читателя данной статьи нет проблемы с тем, чтобы самостоятельно скачать и установить MySQL и MySQLWorkBranch. Дальше вы самостоятельно создаете scheme(БД) с названием, которое вам больше нравится (в моем случае TODO), и потом выбрать молнию-запрос и скопировать/набрать следующую команду:
В нашей базе данных будет все по минимуму: только id и сам текст дел. Однако добавить ещё колоночку, в которой может описана, к примеру, срочность вашего дела, надеюсь, проблем не вызовет.
Конфигурация & коннект с нашей базой данных
После этого создаем папку для описания наших моделей app/mode, в которой мы потом создадим модель:
Создаем Модель
Остальную часть кода я размещу в spoiler, потому, что не вижу смысла приводить его весь, ведь там по сути повторяется паттерн кода, меняются только sql — команды и аргументы:
Deal.findById = (dealId, result) => <
sql.query(`SELECT * FROM TODO WHERE (err, res) => <
if (err) <
console.log(«error: », err);
result(err, null);
return;
>
if (res.length) <
console.log(«найдено дело: », res[0]);
result(null, res[0]);
return;
>
Deal.getAll = result => <
sql.query(«SELECT * FROM TODO», (err, res) => <
if (err) <
console.log(«error: », err);
result(null, err);
return;
>
console.log(«deals: », res);
result(null, res);
>);
>;
Deal.updateById = (id, deal, result) => <
sql.query(
«UPDATE TODO SET text =? WHERE > [deal.text, id],
(err, res) => <
if (err) <
console.log(«error: », err);
result(null, err);
return;
>
Deal.remove = (id, result) => <
sql.query(«DELETE FROM TODO WHERE id, (err, res) => <
if (err) <
console.log(«error: », err);
result(null, err);
return;
>
if (res.affectedRows == 0) <
// если дело не удалось получить по id
result(< kind: «not_found» >, null);
return;
>
console.log(«Удален пользователь с », id);
result(null, res);
>);
>;
Deal.removeAll = result => <
sql.query(«DELETE FROM TODO», (err, res) => <
if (err) <
console.log(«error: », err);
result(null, err);
return;
>
На этом пока все. На подходе следующая часть этой статьи, в которой мы закончим написание бэка и примемся за его тестирование. И по традиции, несколько полезных ссылок:






