Re[2]: Возврат ошибок в API
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 04.09.19 12:12
Оценка:
Здравствуйте, RushDevion, Вы писали:

Прошу прощения, что поднимаю старый топик, но давно хотел спросить, а всё как-то было не у кого...
А для чего в практическом плане возвращать разные положительные коды?
RD>200 (OK) — все OK, в теле ответа будут данные
RD>201 (Created) — все ОК, новая сущность создана. Обычно в ответ на POST, в хидере Location — адрес новой сущности. В теле ответа могут быть данные.
RD>202 (Accepted) — все ОК, мы твой запрос приняли, обработаем позже (e.g. положили в очередь). В теле ответа могут быть данные.
RD>204 (No Content) — все ОК, мы твой запрос обработали, но контент вернуть не можем (обычно в ответе на DELETE)

Чем это удобнее, в сравнении с возвращением всегда ровно одного кода, того же 200 и всё?
Т.е. мне представлялось, что какой именно положительный результат мы получим (можем получить) — понятен уже из контекста. Если мы вызывали метод создания — то результатом и должно быть создание, а при удалении контента не будет, и т.д.
Различать может быть полезно в случаях вроде "'вернуть' или 'создать новый и вернуть'", но и то, вроде как не критично нужный случай...

Если не сложно, проясните этот момент.
Re[4]: Возврат ошибок в API
От: GarryIV  
Дата: 04.09.19 13:25
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Не согласен. Если я забыл задеплоить варку, у меня внезапно куда-то исчезли все юзеры? Не так ведь.


Вот это и надо фиксить если уж на то пошло, 503 вполне подойдет.
WBR, Igor Evgrafov
Re[5]: Возврат ошибок в API
От: vsb Казахстан  
Дата: 04.09.19 14:34
Оценка:
Здравствуйте, GarryIV, Вы писали:

vsb>>Не согласен. Если я забыл задеплоить варку, у меня внезапно куда-то исчезли все юзеры? Не так ведь.


GIV>Вот это и надо фиксить если уж на то пошло, 503 вполне подойдет.


Ну а как ты это пофиксишь, весь серверный софт так работает: апач, нджинкс, томкат. Никогда не видел, чтобы по дефолту кидалось 5xx.
Re[6]: Возврат ошибок в API
От: GarryIV  
Дата: 04.09.19 16:28
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Ну а как ты это пофиксишь, весь серверный софт так работает: апач, нджинкс, томкат. Никогда не видел, чтобы по дефолту кидалось 5xx.


Например спереди стоит haproxy и форвардит реквесты только если health check урл возвращает ожидаемые данные.
WBR, Igor Evgrafov
Re[3]: Возврат ошибок в API
От: RushDevion Россия  
Дата: 04.09.19 19:13
Оценка: 14 (2)
МР>Если не сложно, проясните этот момент.

Попробую.
Прежде всего, идеологически это соответствует описанию статус-кодов HTTP-протокола.
И там много чисто HTTP-шных нюансов. Например, 200 ответы по-умолчанию кэшируется, а 201/202 — нет.
Кроме того, клиенту никто не мешает просто интерпретировать любой 2xx код как успешный.

С практической же точки зрения, попробую объяснить на примерах:

1. 200 vs 202 (Accepted)
POST /api/payments { id, amount, operationType }
Сервер в зависимости от параметров платежа (сумма, тип) и текущего состояния системы (высокая нагрузка, конкретный провайдер платежа лежит и т.п.) может либо исполнить платеж сразу, либо отложить его на потом.
Поэтому:
200 OK — исполнили сразу, результат вернули, его можно сразу прочитать и отобразить пользователю.
202 Accepted — приняли к исполнению, исполним позже. Клиенту можно не читать body, а сразу идти на GET /api/payments/{id} и проверять статус там.

2. 200 vs 201 (Created)
POST /api/payments { id, amount, operationType }
ID платежа определяет клиент (скажем, это GUID).
А мы со своей стороны гарантируем идемпотентность операции создания, т.е.
мы говорим: "если ты будешь пытаться создать платеж с одним и тем же id много раз, то для нас это нормально".
По HTTP протоколу POST запросы не идемпотентные, но это бывает нужно, если, например у нас слабый канал и клиент реализует какую-то политику ретрая.
Или клиент пропихивает платежи из своей системы в нашу в несколько потоков/процессов.
В этом случае:
201 (Created) — клиент уверен, что это именно он создал платеж. Можно, например, обновлять балансы в своей локальной системе.
200 OK — такой платеж уже есть, но его создали не мы. Просто игнорируем.

Если бы мы возвращали чисто 200, нам бы пришлось как-то менять модель платежа (добавлять какие-то доп. поля/признаки) для обработки такой ситуации, что как-то не очень чисто.

3. 200 vs 204 (No Content)
POST /api/articles/{id} => [ content ]
Допустим мы пишем редактор постов на wiki для такой API-шки (POST соответствует сохранению).
Тогда у нас возможны варианты:
200 OK — твои данные сохранились. Но, похоже, кто-то делал изменения в других частях статьи, и мы их смержили. Прочитай новое тело статьи из тела ответа и обнови UI.
204 OK — твои данные сохранили. Статья на сервере такая же, как локальная, поэтому контента мы тебе не шлем.
Отредактировано 04.09.2019 19:44 RushDevion . Предыдущая версия .
Re[4]: Возврат ошибок в API
От: AK107  
Дата: 05.09.19 17:23
Оценка: +1 -1
Здравствуйте, RushDevion, Вы писали:

RD>2. 200 vs 201 (Created)

RD>POST /api/payments { id, amount, operationType }
RD>ID платежа определяет клиент (скажем, это GUID).
RD>А мы со своей стороны гарантируем идемпотентность операции создания, т.е.
RD>мы говорим: "если ты будешь пытаться создать платеж с одним и тем же id много раз, то для нас это нормально".
RD>По HTTP протоколу POST запросы не идемпотентные, но это бывает нужно, если, например у нас слабый канал и клиент реализует какую-то политику ретрая.
RD>Или клиент пропихивает платежи из своей системы в нашу в несколько потоков/процессов.
RD>В этом случае:
RD>201 (Created) — клиент уверен, что это именно он создал платеж. Можно, например, обновлять балансы в своей локальной системе.
RD>200 OK — такой платеж уже есть, но его создали не мы. Просто игнорируем.

это явный 409 Conflict. и ни в коем случае не 200 ОК.
Re[4]: Возврат ошибок в API
От: Ночной Смотрящий Россия  
Дата: 11.09.19 20:43
Оценка:
Здравствуйте, RushDevion, Вы писали:

RD>201 (Created) — клиент уверен, что это именно он создал платеж. Можно, например, обновлять балансы в своей локальной системе.

RD>200 OK — такой платеж уже есть, но его создали не мы. Просто игнорируем.

Вот это не очень удачная идея. Лучше возвращать 409, а не 200.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[5]: Возврат ошибок в API
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.09.19 04:20
Оценка: +1
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Вот это не очень удачная идея. Лучше возвращать 409, а не 200.

Это если параметры платежа отличаются от того, который записан в системе.
А если совпадают — то 200.
Потому что иначе клиент не может понять, принят ли вообще его платёж, или нет.
В более простом случае: бронируем место в самолёте. Отправляем: "Вася сядет на место 15С".
Если мы получаем 4хх, то мы должны сказать Васе: "извини, не получилось". Конкретно для 409 — "пока мы с тобой тупили, кто-то уже сел на 15С".
Если клиент получил 409 не с первого раза, то он не знает, доходили ли до сервера его предыдущие запросы — т.е. не может отличить ситуацию конликта с самим собой от конфликта с кем-то ещё.
Поэтому если мы получаем такой запрос, а в системе уже записано, что Вася сидит на месте 15С, то мы отдаём 200 — это требование идемпотентности. Мы же не знаем, увидел ли Вася наши предыдущие ответы.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: Возврат ошибок в API
От: KOLRH Финляндия  
Дата: 12.09.19 06:00
Оценка:
Здравствуйте, Sinclair,
S>Поэтому если мы получаем такой запрос, а в системе уже записано, что Вася сидит на месте 15С, то мы отдаём 200 — это требование идемпотентности. Мы же не знаем, увидел ли Вася наши предыдущие ответы.

А может в этом случае стоит возвращать 208 already reported? И не ошибка и известие, что место уже было для вас забронировано.
Re[7]: Возврат ошибок в API
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.09.19 06:35
Оценка:
Здравствуйте, KOLRH, Вы писали:

KOL>Здравствуйте, Sinclair,

S>>Поэтому если мы получаем такой запрос, а в системе уже записано, что Вася сидит на месте 15С, то мы отдаём 200 — это требование идемпотентности. Мы же не знаем, увидел ли Вася наши предыдущие ответы.

KOL>А может в этом случае стоит возвращать 208 already reported? И не ошибка и известие, что место уже было для вас забронировано.

Я бы удивился, получив такой респонс.
Его штатное применение — совсем другой сценарий:

The 208 status never appears as a true HTTP response code in the status line, and only appears in bodies.

https://evertpot.com/http/208-already-reported
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: Возврат ошибок в API
От: Ночной Смотрящий Россия  
Дата: 12.09.19 06:49
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Потому что иначе клиент не может понять, принят ли вообще его платёж, или нет.


Обычно передают некий request id, а не сравнивают поля. И возврат 409 вполне однозначно указывает на то, что запрос с таким id уже обработан.

S>Поэтому если мы получаем такой запрос, а в системе уже записано, что Вася сидит на месте 15С, то мы отдаём 200 — это требование идемпотентности.


POST неидемпотентен по спеке.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[7]: Возврат ошибок в API
От: Sinclair Россия https://github.com/evilguest/
Дата: 12.09.19 07:17
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Обычно передают некий request id, а не сравнивают поля.

Придётся делать и то и то.
НС>И возврат 409 вполне однозначно указывает на то, что запрос с таким id уже обработан.
Нет, так делать нельзя. Что вы будете возвращать в ответ на запрос, который конфликтует с результатом другого запроса с другим id?

S>>Поэтому если мы получаем такой запрос, а в системе уже записано, что Вася сидит на месте 15С, то мы отдаём 200 — это требование идемпотентности.

НС>POST неидемпотентен по спеке.
Поэтому надо делать PUT.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[8]: Возврат ошибок в API
От: Ночной Смотрящий Россия  
Дата: 12.09.19 07:28
Оценка:
Здравствуйте, Sinclair, Вы писали:

НС>>Обычно передают некий request id, а не сравнивают поля.

S>Придётся делать и то и то.

Зачем?

НС>>И возврат 409 вполне однозначно указывает на то, что запрос с таким id уже обработан.

S>Нет, так делать нельзя. Что вы будете возвращать в ответ на запрос, который конфликтует с результатом другого запроса с другим id?

400. Либо можно возвращать конкретную причину в теле 409. Главное — вся эта котовасия должна отрабатываться на уровне мидлвера и retry policy, а не лезть в BL.

S>>>Поэтому если мы получаем такой запрос, а в системе уже записано, что Вася сидит на месте 15С, то мы отдаём 200 — это требование идемпотентности.

НС>>POST неидемпотентен по спеке.
S>Поэтому надо делать PUT.

Про PUT совсем другой разговор, там свои заморочки. И вот там то как раз нужно полное сравнение всех полей.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[7]: Возврат ошибок в API
От: Sharov Россия  
Дата: 12.09.19 09:48
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>POST неидемпотентен по спеке.


Но имплементация в конкретном сервисе может быть идемпотентной?
Кодом людям нужно помогать!
Re[8]: Возврат ошибок в API
От: Ночной Смотрящий Россия  
Дата: 12.09.19 11:26
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Но имплементация в конкретном сервисе может быть идемпотентной?


Может. Но 409 при повторном вызове отсутствия идемпотентности не означает.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[4]: Возврат ошибок в API
От: VladiCh  
Дата: 13.09.19 23:48
Оценка:
Здравствуйте, MadHuman, Вы писали:

MH>Здравствуйте, Ночной Смотрящий, Вы писали:


MH>>>если сервера — 500 (это перегрузка сервера

НС>>Для перегрузки есть специальный код, 429.
MH>да, но 429 (Too Many Requests) — для более узкого случая, когда хотят на сервере ограничить частоту реквестов от клиента. в этом случае да, лучше его.
MH>я имел ввиду несколько другие ситуации, например для обработки реквеста надо сходить в базу, база перегружена и ответила соотвествующей ошибкой.
MH>или сервер под высокой нагрузкой и реквест клиента по каким-то причинам (особенно связанным с данными клиентам) выполняется слишком долго и его прервали.
MH>или сервер уже под высокой нагрузкой и пока лучше не начинать обработку новых запросов.
MH>типа такого.

Для других случаев обычно используется 503
Re: Возврат ошибок в API
От: white_znake  
Дата: 24.10.19 10:50
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Какие HTTP status code используются в ваших API?

Б>200, 401, 403, 404 и т.п.
Добавил бы 201 — Created со ссылкой на созданный ресурс в заголовке Location. 201-created полезен на случай когда клиент что-то создает и нужен переход на созданный ресурс (мало-ли пользователь захочет еще что-то отредактировать).
И 204 — No Content. Все ок, но контента нет. Полезен для ответов на Delete, на пример.

Иногда приходилось использовать 409 — Confilct для того, что бы показать, что модифицированные пользователем данные были изменены ранее.

Б>Передаете ли дополнительную информацию об ошибках? Какую?

Б>Код ошибки, текстовое сообщение, на каком языке (русский, английский), дополнительные параметры?
json: {code: <литеральный код ошибки>, message: <сообщение для разработчиков>, description: <пояснение ошибки и что надо сделать, что бы ее не получить для разработчиков>}.
Разработчики клиентской части уже обрабатывают коды ошибок. Текс ошибок и пояснение им нужны в отладке Rest API через swagger. Тестировщикам для локализации багов тоже будет полезно получать текст ошибок и описание.

Б>Кодируете ошибки, как? Единая нумерация для всего API, или свои ошибки для каждого endpoint?

Просто литералы. Который указываешь в описании API.

Б>Используете какие-то правила для возвратов ошибок?

Б>Например, по аналогии с JSON-RPC, в котором наличие в ответе поля errors означает, что произошла ошибка при обработке запроса.
На клиенте? Проверяешь http.status

Б>Что возвращаете, если клиент запрашивает существующий ресурс, к которому запрещен доступ:

Б>404 или 403?
Лучше все-таки различать 403 — Forbidden & 404 — Not Found. Будет меньше вопросов у клиентов.
Возможно, что в некоторых случай помимо 404, можно вернуть 410 — Gone. Если на клиенте кешируются ресурсы и идет запрос на обновление этого ресурса, которого уже нет на сервере, то имеет смысл вернуть 410, хотя, если вернуть 404 — это тоже небольшая проблема. Просто 404 говорит о том, что ресурс не найден, но возможно потом он будет доступен. А вот если ресурс был, но теперь ушел и больше не вернется, то 410.

Б>В общем, научите как надо возвращать информацию об ошибках в API


https://developer.mozilla.org/ru/docs/Web/HTTP?
Re[2]: Возврат ошибок в API
От: white_znake  
Дата: 24.10.19 10:58
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Уникальный код, severity, источник, нелокализуемое сообщение на английском, название параметра если применимо, значения подстановок для локализованного сообщения. В отладочных версиях еще stacktrace.

На мой взгляд, лучше делать так, что бы StackTrace ни когда не покидал бы сервер
Тогда не возникнет гипотетическая ошибка, по которой и на проде, stacktrace уйдет клиенту
Нормальный вариант логировать stacktrace, логи смотреть через http с авторизацией.
Re[3]: Возврат ошибок в API
От: Ночной Смотрящий Россия  
Дата: 24.10.19 11:02
Оценка:
Здравствуйте, white_znake, Вы писали:

_>На мой взгляд, лучше делать так, что бы StackTrace ни когда не покидал бы сервер

_>Тогда не возникнет гипотетическая ошибка, по которой и на проде, stacktrace уйдет клиенту

Если это в одном месте настраивается, то не возникнет.

_>Нормальный вариант логировать stacktrace, логи смотреть через http с авторизацией.


Логи обычно доступны только владельцам сервиса, а вот стектрейс часто полезен тем, кто использует отладочные версии.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.