Pull to refresh
10
24.1
Александр Зайцев @id_bones

Разработчик

Send message

Уместный комментарий! Чтобы из статьи получилась шпаргалка, я постарался сократить теорию до фактов. Для углубления прикрепил "полезные ссылки".

  1. GET /resources/:id - не найден = 404, GET /resources/ - не найдено ни одного = 200

  2. PUT /v1/resources/{id} - 404, если не позволено создавать ресурс "со своим идентификатором"? внезапно.


GET /resources/{id} -> 404, когда конкретного ресурса не существует
GET /resources/ -> 200 с пустой коллекцией ([] или { items: [], total: 0 }), когда коллекция существует, но в ней пока ничего нет.

{id} - конкретный ресурс, он либо есть, либо его нет
resources - ресурс-коллекция, она можно сказать существует всегда (если конечно существует родительский ресурс /parent/{parentId}/resources).

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

POST /v1/resources/batch-get

Но как же "без изменения состояния"? Я понимаю, что мера вынужденная, но "как же принципы"?

Это осознанный компромисс и допустимая практика. Да GET - обязан быть безопасным. Но POST тоже может быть таким, если вы его так определили

Так в чем проблема получить тело и десериализовать его из JSON в объект типа Result, который содержит Success или Fault?

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

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

Отличный пример в тему статьи! Тоже бывало ломал голову тот ли dns адрес получилось собрать.
Есть практика: "когда сервер намеренно не хочет раскрывать, что ресурс существует", я опираюсь чаще всего на неё, но не пропагандирую)

На самом деле вот то, что мы здесь обсуждаем и есть одна из самых больших проблем REST

Согласен с вами! Тема очень холиварная

Понял почему возник вопрос, в статье поправил немного формулировку:
Просмотр ресурса -> Увеличение счетчика просмотра ресурса

POST - потому что подразумевается изменение состояния (увеличение счетчика)

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

Добрый день!

Имхо в статье много противоречий, исключений и заплаток.

Относительно какой теоретической базы противоречия?

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

А можно подробнее что за ELK проблема?

Допустим у меня есть базовый HttpClient и у меня стоит задача: отказоустойчивость, логгирование ошибок, метрики. Я как разработчик хочу просто вызвать метод типа PostAsync(url, query, body ...) и получить в ответе модель, которую создал. Чтобы это было просто и удобно обычно создают или используют готовые библиотеки.

Как библиотека поймет что нужно залоггировать/сделать ретрай запрос? В согласованных системах достаточно будет проверки статус кода.

В вашем же случае нужно вычитывать всё тело запроса и искать там заветное слово: "ok": true|false? "success": true|false ? Вот например API slack, где я с этим сталкивался:
https://docs.slack.dev/apis/web-api/#responses
(elk не прикладываю, так как по итогу использовал библиотеку, а не api на прямую)

Когда в теле все же уместно слать 200 и status/status_code?
Когда есть ясная архитектурная особенность, например работа с большим количеством данных => batch методы.
Я в статье рекомендую:

Атомарность: либо всё, либо ничего.

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

Не успел вовремя ответить, пример с ELK очень в тему, сам с данной проблемой много возился, спасибо!

HTTP это не просто транспорт, а протокол прикладного уровня, на который опираются разработчики браузеров, CDN, прокси. Да и при обычной интеграции многие инфраструктуры на это завязаны: ретраи, SLO, алерты и тд. Всегда 2хх, остальное в body, как правило, ломает поведение экосистемы веба. Понимаю, что требование к приложениям у нас могут быть разные, но вся эта практика, книги и гайдлайны не на пустом месте появились - на это я и обращаю внимание читателя

Спасибо за комментарий! Цель статьи обозначить вектор проектирования, конкретная реализация в разных компаниях и командах может отличаться, всё зависит от контекста.

Использование POST для всего подряд усложняет настройки кэширования, ссылки/закладки и другие оптимизации опирающиеся на rest стандарты

UPD (библиотечка обновилась)
Используйте
"Telegram": {
"LogLevel": {
"Default": "Warning"
},
"AccessToken": "1234567890:AAAaaAAaa_AaAAaa-AAaAAAaAAaAaAaAAAA",
"ChatId": @channel_namee",
"Source": "Human Readable Project Name"
}


Вместо
"Telegram": {
"LogLevel": "Warning",
"AccessToken": "1234567890:AAAaaAAaa_AaAAaa-AAaAAAaAAaAaAaAAAA",
"ChatId": @channel_namee",
"Source": "Human Readable Project Name"
}
:)

Information

Rating
315-th
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Date of birth
Registered
Activity

Specialization

Backend Developer
C#
PostgreSQL
Docker
RabbitMQ