Может ли веб-приложение возвращать 400 Bad Request при некорректных параметрах?
От: Geri Россия http://web-notes.ru/
Дата: 02.10.12 07:14
Оценка:
Довольно часто при разработке веб-приложений возникает необходимость выдать пользователю какой-то ответ, означающий, что пользователь не передал какой-то обязательный параметр или переданный параметр имеет недопустимое значение. При беглом просмотре списка кодов ошибок HTTP, кажется, что для этого наиболее подходит код 400 Bad Request. Однако, в описании к нему говорится, что этот код используется, когда запрос не может быть понят сервером из-за синтаксической ошибки в запросе. Например, какие-то недопустимые символы в URI, нет обязательного заголовка "Host" в запросе HTTP/1.1, и т.п. То есть все те ошибки, которые обрабатывает веб-сервер ещё до вызова скрипта-обработчика (например, PHP). Следовательно сам PHP-скрипт не должен выдавать код 400, т.к. если PHP-скрипт вызвался, значит запрос прошел формальную проверку на уровне веб-сервера и с синтаксисом у него всё в порядке.

Для ряда ситуаций нас вполне может спасти код 404 Not Found (даже когда речь идёт о query-параметре, т.к. query является частью URI). Но не всегда. Например, в POST-запросе не пришел параметр, который должен был придти, без которого запрос теряет всякий смысл -- посылать 404 в данном случае было бы неправильно, т.к. сам URL правильный. Обычно в таких случаях разработчики просто кидают какое-то общее исключение, которое потом где-то на уровне index.php или Front-контроллера перехватывается и трансформируется в ошибку 500 Internal Server Error. Иногда, вместо нее шлют 503 Service Unavailable, чтобы показать тем самым временность проблемы (если проблема связана с каким-то сбоем или ошибкой в коде), чтобы типа поисковики не удаляли сайт из индекса. На мой взгляд это неправильно, т.к. статус ошибки фактически не соответствует её сути.

Главная проблема в том, что 500-ые ошибки в такого рода ситуациях говорят клиенту о том, что проблема находится на стороне сервера, тогда как 400-ые ошибки говорят в основном о проблеме на стороне клиента. RFC-2616 говорит о том, что при получении клиентом 400-ой ошибки клиент НЕ ДОЛЖЕН повторять запрос без изменения запроса. И действительно, если запрос изначально некорректный, сколько его не повторяй -- результат не изменится. Тогда как при получении 500 ошибки клиент может продолжать "долбить" сервер снова и снова в то время как проблема -- в неправильном запросе. RFC-2616 очень скуп на описание данной ошибки и ограничивается всё тем же синтаксисом и приводом пары частных примеров. Однако, что такое ошибка синтаксиса? Можно ли считать отсутствующий или неправильный параметр, который требуется в каком-то частном обработчике, синтаксической ошибкой? Я раньше считал, что нет, хотя и были сомнения. Но недавно я обнаружил, что Facebook возвращает 400 Bad Request в случае если при авторизации через OAuth передан неправильный query-параметр с кодом, и об этом написано в официальной документации. То есть фэйсбук считает неправильный GET-параметр синтаксической ошибкой.

Кто-нибудь может дать пояснение по данной теме? Вопрос весьма не тривиальный, на большинстве форумов топик бы засрали прыщавые быдлокодеры, не дав ни одного ценного ответа. На RSDN вроде бы достаточно зрелая аудитория, поэтому вся надежда на неё. Меня интересует не личный опыт применения кода 400 Bad Request теми или иными программистами, я понимаю, что из скрипта можно послать любой код HTTP, а официальное подтверждение допустимости такого использования со ссылкой на какой-нибудь RFC или IETF.
-- С уважением, Павел Мелехов, Екатеринбург.
http 400 bad request rfc-2616
Re: Может ли веб-приложение возвращать 400 Bad Request при некорректных параметр
От: A13x США  
Дата: 02.10.12 10:11
Оценка: 6 (1) +1
Здравствуйте, Geri, Вы писали:

G>...


Из REST API Design Guide:

Rule: 400 (“Bad Request”) may be used to indicate nonspecific failure
400 is the generic client-side error status, used when no other 4xx error code is
appropriate.
For errors in the 4xx category, the response body may contain a docu-
ment describing the client’s error (unless the request method was
HEAD). See “Error Representation” on page 68 for error response body
design.


Короче, я бы не парился сделал бы обработку ошибки на неверные параметры запроса путем возврата 400 статуса + описание подтипа ошибки в теле.

Рекомендую почитать.
Re: Может ли веб-приложение возвращать 400 Bad Request при некорректных параметр
От: okman Беларусь https://searchinform.ru/
Дата: 02.10.12 10:29
Оценка: 5 (2) -1
Здравствуйте, Geri.

В контексте данного вопроса HTTP можно рассматривать, как транспорт для протоколов более высокого уровня.
И в архитектурном плане очень сомнительно использовать транспорт для сигнализации о логических
ошибках и разделять с ним его коды состояний. Представьте, что вместо HTTP использовался бы TCP и
тогда, по аналогии, сервер в случае некорректно сформированного запроса отправлял бы FIN- или RST-пакет.
Можно ли назвать такое решение правильным ? Нет. В идеале транспорт вообще не должен "знать" о том,
что происходит наверху и отвечать только за передачу данных. Успешная передача — код из группы 200.
Неуспешная — другой код, в зависимости от обстоятельств. И так достигается определенная гибкость.
Например, при смене транспорта не придется переделывать систему обработки ошибок.

Коды состояний HTTP не смогут обеспечить клиента точной информацией о том, на каком этапе обработки запроса
произошел сбой — на транспортном или логическом. Если, к примеру, и front end, и back end сервера могут
отдавать "500 Internal Server Error", то рано или поздно наступает ситуация, когда клиент получает такой
ответ и не знает, от кого именно он пришел и по каким правилам обрабатывать его содержимое. В то же время
"надпротокольные" сообщения об ошибках, возвращенные с кодом 200, могут быть и более структуированными, и
более информативными, и вообще более соответствующими духу системы, в которой они используются.

Я встречал мнение, что можно использовать зарезервированные коды HTTP-состояний. Например, диапазон
512-599 в настоящее время свободен. Но это, во-первых, решает проблему лишь частично (точнее, отодвигает
ее на более поздний срок), а во-вторых, никто не гарантирует, что завтра-послезавтра IANA не присвоит
этим кодам осмысленные значения и семантику, после чего снова возможны проблемы.

Что касается RFC — я могу лишь привести выдержку из документа, касающуюся рекомендаций
правильной организации уровней в модели OSI:

ISO/IEC 7498-1

6.2 The principles used to determine the seven layers in the Reference Model.

...

c) Create separate layers to handle functions that are manifestly different in the
process performed or the technology involved.

d) Collect similar functions into the same layer.

...

j) Allow changes of functions or protocols to be made within layer without affecting other layers; and

k) Create for each layer, boundaries with its upper and lower layers only.

По-моему, очень неплохая отправная точка.
Re[2]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: Geri Россия http://web-notes.ru/
Дата: 03.10.12 09:40
Оценка: +1
Здравствуйте, okman, Вы писали:

O>В контексте данного вопроса HTTP можно рассматривать, как транспорт для протоколов более высокого уровня.

O>И в архитектурном плане очень сомнительно использовать транспорт для сигнализации о логических
O>ошибках и разделять с ним его коды состояний.

Буквально до вчерашнего дня я считал примерно так же, как и вы. Я считал, что 400-ый код -- это код ответа на некорректный с точки зрения HTTP-протокола запрос, и использовать его для индикации каких-то ошибок уровня логики приложения неправильно. Но вчера во мне закралось сомнение, которое почти полностью оправдалось после ответа A13x. Если бы мы использовали HTTP-протокол как транспорт для более высокоуровнего протокола, то, например, в случае не нахождения запрашиваемого объекта нам бы следовало возвращать не 404-ый код, а "200 OK", а в теле ответа некое закодированное сообщение, содержащие код ошибки от высокоуровнего протокола, который бы разбирался бы принимающей стороной в соответствии с высокоуровневым протоколом.

Но дело в том, что мы не используем HTTP как транспорт для протоколов более высокого уровня, PHP скрипт не создает новый уровень протокола (по крайней мере при создании обычных сайтов, на которые ходят браузерами). HTTP -- это уже протокол высокого уровня, и мы используем его самого напрямую, не как только транспорт. Поэтому работу веб-сервера и PHP-скрипта следует рассматривать как единое целое. В конце-концов, такое разделение на веб-сервер и скрипт всего лишь частный случай. Мы можем написать на Си++ приложение, которое при запуске будет открывать 80-ый порт, и отвечать на HTTP-запросы какими-то осмысленными динамически создаваемыми HTTP-ответами. Клиент (пользователь) в общем случае не знает как архитектурно реализовано приложение. Он обращается с ним как с черным ящиком, в который можно посылать какие-то HTTP-запросы и получать какие-то HTTP-ответы. По кодам ответов пользователь может узнавать о том, что он что-то делает не так, некоторые дополнительные предписания и рекомендации по дальнейшему использованию.

Ошибки синтаксиса в общем-то могут быть не ограничены тем синтаксисом, который содержится в RFC2616. HTTP -- это расширяемый протокол, поэтому на мой взгляд вполне допустимо вводить не только новые HTTP-коды и новые методы HTTP-запросов в своих приложениях, но и дополнительные правила синтаксиса, которые требуются для правильной обработки того или иного запроса. Понятие синтаксиса это ведь не только формальное соответствие строки некоемому шаблону регулярного выражения, но и сочетаемость отдельных частей запроса между собой (как сочетаемость слов в предложениях). К тому же в самом RFC2616 даётся указание о том, что 400-ый код следует посылать всякий раз, когда клиент использует версию HTTP-протокола 1.1 и при этом в запросе отсутствует заголовок "Host". Наличие заголовков в HTTP вещь опциональная, так что тут уже идет некий элемент логического несоответствия некоего параметра (заголовка) некоемому запросу.

O>Я встречал мнение, что можно использовать зарезервированные коды HTTP-состояний. Например, диапазон

O>512-599 в настоящее время свободен. Но это, во-первых, решает проблему лишь частично (точнее, отодвигает
O>ее на более поздний срок), а во-вторых, никто не гарантирует, что завтра-послезавтра IANA не присвоит
O>этим кодам осмысленные значения и семантику, после чего снова возможны проблемы.

Задействовать не зарезервированные коды -- это последнее дело. Клиент всё равно не поймет их, либо поймёт их неправильно, если выбранный нами код когда-нибудь станет каким-нибудь расширением стандарта, описанным в каком-нибудь отдельном RFC, которое кто-то может поддерживать, кто-то нет. В любом случае, разработчики браузеров не будут считаться с тем расширением стандарта, которое придумал какой-то отдельно взятый программист, нигде не задокументировал, а просто стал по тихому использовать в своих приложениях. При этом в RFC2616 сказано, что для всех неизвестных кодов HTTP клиенты должны учитывать лишь первую цифру, а интерпретировать их как код x00, где x — первая цифра неизвестного кода. То есть, например, код "456 Missing Query Parameter" будет для браузера эквивалентен ответу "400 Bad Request". С той лишь разницей, что ответы с неизвестными кодами запрещено кэшировать.

O>Что касается RFC — я могу лишь привести выдержку из документа, касающуюся рекомендаций

O>правильной организации уровней в модели OSI:
O>По-моему, очень неплохая отправная точка.

Боюсь, что модель OSI здесь не очень уместна.
-- С уважением, Павел Мелехов, Екатеринбург.
Re[2]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: Geri Россия http://web-notes.ru/
Дата: 03.10.12 09:42
Оценка:
Здравствуйте, A13x, Вы писали:

A>Здравствуйте, Geri, Вы писали:


A>Из REST API Design Guide:

A>Rule: 400 (“Bad Request”) may be used to indicate nonspecific failure
A>Короче, я бы не парился сделал бы обработку ошибки на неверные параметры запроса путем возврата 400 статуса + описание подтипа ошибки в теле.

Это как раз то, что я и надеялся получить в ответ. Спасибо!
-- С уважением, Павел Мелехов, Екатеринбург.
Re[3]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: okman Беларусь https://searchinform.ru/
Дата: 03.10.12 12:17
Оценка: 4 (1) +1 -2
Здравствуйте, Geri, Вы писали:

G>Буквально до вчерашнего дня я считал примерно так же, как и вы. Я считал, что 400-ый код -- это код ответа на некорректный с точки зрения HTTP-протокола запрос, и использовать его для индикации каких-то ошибок уровня логики приложения неправильно. Но вчера во мне закралось сомнение, которое почти полностью оправдалось после ответа A13x. Если бы мы использовали HTTP-протокол как транспорт для более высокоуровнего протокола, то, например, в случае не нахождения запрашиваемого объекта нам бы следовало возвращать не 404-ый код, а "200 OK", а в теле ответа некое закодированное сообщение, содержащие код ошибки от высокоуровнего протокола, который бы разбирался бы принимающей стороной в соответствии с высокоуровневым протоколом.


А веб-сервисы обычно именно так и работают, обратите внимание.
Когда мы в каком-нибудь интернет-магазине жмем "add to card", забыв выбрать товар, или пытаемся
залогиниться, указав неверный пароль, — то есть, совершаем логически ошибочное действие, — сервер,
тем не менее, возвращает успешный код "HTTP/1.1 200 OK" (транспорт), а в теле ответа — HTML с
соответствующим сообщением о том, что именно произошло (логика). С картинками и пояснительными знаками.
Это и есть разделение. Если сделать по-другому, чтобы сервер возвращал "400 Bad Request" или "404 Not
Found", то клиент не сможет узнать, по какой именно причине произошла ошибка и что делать дальше.

Другой момент заключен в том, что у кодов HTTP своя семантика, которая может использоваться компонентами,
такими как браузерами или прокси-серверами, в противоречии с логикой веб-сервиса, явно или неявно.
Например, по RFC 2616 клиенту не рекомендуется повторять один и тот же запрос, в ответ на который
пришел код 400. И какой-нибудь прокси-сервер, зная эту рекомендацию, запросто может закэшировать
ответ на запрос и отдавать его без изменений еще очень долгое время, даже если это идет вразрез с
логикой веб-сервиса и без участия прокси такой запрос мог быть успешно завершен намного раньше.

Так что разделение, даже если оно местами кажется весьма условным, может оказаться очень полезным.
В самих браузерах сетевые компоненты и компоненты, отвечающие за работу с HTML (рендеринг), стараются по
возможности изолировать друг от друга. А в серверных технологиях есть понятие frontend-а и backend-а.
И это неспроста.

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


Это как ? У меня ощущение, что мы друг друга не совсем понимаем.
Вы же передаете по HTTP какие-то осмысленные данные ? Тот же HTML/XML/JSON или просто текст ?
Вот эти данные и являются тем самым протоколом высокого уровня.

G>В конце-концов, такое разделение на веб-сервер и скрипт всего лишь частный случай. Мы можем написать на Си++ приложение, которое при запуске будет открывать 80-ый порт, и отвечать на HTTP-запросы какими-то осмысленными динамически создаваемыми HTTP-ответами.


Это ничего не меняет. Разделение на уровни — понятие чисто архитектурное. Можно намешать в кучу работу с HTTP,
многопоточность, кэширование и туда же понапихать серверную логику, а еще load balancer.
А можно аккуратно разбить это все на слои, занимающиеся каждый строго своей зоной ответственности и
разместить их так, чтобы они не зависели один от другого.

G>Клиент (пользователь) в общем случае не знает как архитектурно реализовано приложение. Он обращается с ним как с черным ящиком, в который можно посылать какие-то HTTP-запросы и получать какие-то HTTP-ответы. По кодам ответов пользователь может узнавать о том, что он что-то делает не так, некоторые дополнительные предписания и рекомендации по дальнейшему использованию.


Если под клиентским ПО подразумевается браузер, тогда да, лучше оставить коды состояний, потому что
браузер ни с чем иным работать и не умеет, если не считать HTML. А если речь идет о специальном клиентском
приложении, то здесь возможностей гораздо больше.
Re[4]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: Geri Россия http://web-notes.ru/
Дата: 04.10.12 10:11
Оценка: +1
Здравствуйте, okman, Вы писали:

O>Когда мы в каком-нибудь интернет-магазине жмем "add to card", забыв выбрать товар, или пытаемся

O>залогиниться, указав неверный пароль, — то есть, совершаем логически ошибочное действие, — сервер,
O>тем не менее, возвращает успешный код "HTTP/1.1 200 OK" (транспорт),

Ну, мало ли что там возвращают какие-то сайты. У нас некоторые сайты при не найденной странице возвращают 200 OK. В результате этого в поисковой выдаче на этот сайт куча ссылок на страницы с сообщением о не найденной странице, потому что поисковик думает, что эти страницы содержат полезный текст. Или вместо ответа 404 делают редирект (303) на страницу "/404.php", что не многим лучше.

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

O>Это и есть разделение. Если сделать по-другому, чтобы сервер возвращал "400 Bad Request" или "404 Not

O>Found", то клиент не сможет узнать, по какой именно причине произошла ошибка и что делать дальше.

Это вовсе не так. Мы можем вернуть статус 400 Bad Request, "а в теле ответа — HTML с соответствующим сообщением о том, что именно произошло". Пользователь браузера увидит страницу, полученную с кодом 400, точно так же, как страницу, полученную с кодом 200. Мы также можем учитывать заголовок Accept и вернуть в соответствии с ним не HTML, а к примеру, картинку с изображением не найденной картинки. Коды статусов нужны не для пользователя, а для клиентов (браузеров, поисковых ботов, downloader'ов и т.п.)

O>Другой момент заключен в том, что у кодов HTTP своя семантика, которая может использоваться компонентами,

O>такими как браузерами или прокси-серверами, в противоречии с логикой веб-сервиса, явно или неявно.
O>Например, по RFC 2616 клиенту не рекомендуется повторять один и тот же запрос, в ответ на который
O>пришел код 400. И какой-нибудь прокси-сервер, зная эту рекомендацию, запросто может закэшировать
O>ответ на запрос и отдавать его без изменений еще очень долгое время, даже если это идет вразрез с
O>логикой веб-сервиса и без участия прокси такой запрос мог быть успешно завершен намного раньше.

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

Но, к счастью, этим есть возможность эффективно управлять при помощи заголовка "Cache-Control", в котором можно например запретить кэширование, в том числе отдельно для прокси, если вы хотите, чтобы ошибки 4xx в каких-то отдельных случаях не кэшировались.

Однако, стоит сделать оговорку. В моём понимании, код 400 допустимо выдавать лишь в тех случаях, когда противоречие содержится в самом запросе, а не вытекает из ранее сделанных запросов или в результате сохранения состояния через механизмы сессий. Когда нам в запросе не приходит обязательный параметр или когда параметр имеет заведомо недопустимое значение, то абсолютно безопасно выдавать 400 Bad Request и пофиг что оно может закэшироваться (это даже хорошо если оно закэшируется -- меньше нагрузка на наш сервер). А вот в случае с неправильным паролем всё уже не так однозначно. Ведь пользователь может (например, через другой браузер) зайти на сайт и поменять пароль, а первый браузер не будет знать об этом и посему может закэшировать ответ. Поэтому логично вместе со статусом 400 запрещать кэширование заголовком Cache-Control в случаях, когда повторное выполнение запроса теоретически может привести к успеху. Но этого можно не делать, когда запрос выполняется методом POST (а авторизация как правило именно этим методом выполняется), т.к. POST-запросы никогда не кэшируются. Так что кэширование не проблема. Собственно проблема кэширования (если она есть) абсолютно одинаковая что для статуса 200, что для 400. Если вы имеете проблему с кэшированием, отвечая статусом 400, то вы получите её и отвечая статусом 200.

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


O>Это как ? У меня ощущение, что мы друг друга не совсем понимаем.

O>Вы же передаете по HTTP какие-то осмысленные данные ? Тот же HTML/XML/JSON или просто текст ?
O>Вот эти данные и являются тем самым протоколом высокого уровня.

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

Кстати, создавая свой высокоуровневый протокол поверх HTTP, никто не мешает частично интегрировать его в HTTP. Например, при успешном запросе возвращать 200 OK, а при ошибке возвращать, к примеру, 500, а в теле ответа JSON с расшифровкой ошибки. Это конечно нарушит изоляцию слоя и затруднит в дальнейшем перенос на другой "низкоуровневый" протокол, но упростит обработку ответов, т.к. в каких-то случаях нам не нужно будет парсить JSON, чтобы понять, что произошла ошибка. Статус HTTP может просто дублировать смысл ответов высокоуровнего протокола, а не заменять их. Тогда не будет никаких проблем при переезде на другой транспорт, а все различия будут скрыты в реализациях адаптеров, обладающих единым интерфейсом.

O>Это ничего не меняет. Разделение на уровни — понятие чисто архитектурное. Можно намешать в кучу работу с HTTP,

O>многопоточность, кэширование и туда же понапихать серверную логику, а еще load balancer.
O>А можно аккуратно разбить это все на слои, занимающиеся каждый строго своей зоной ответственности и
O>разместить их так, чтобы они не зависели один от другого.

К слову сказать, не всё и не всегда можно разбить на такие вот независимые слои. Например, невозможно сделать эффективное кэширование отдельно от серверной логики, т.к. только серверная логика может знать можно ли кэшировать данный контент, и если да, то на сколько и каким именно способом. Под способом кэширования я имею в виду кэширование данных извлеченных из базы, загруженных с другого сайта, посчитанных в оперативной памяти, или же кэшировать конечный срендеренный HTML или его части, или же использовать client-side кэширование (при помощи механизма ETag/Last-Modified:If-None-Match/If-Modified-Since). Нельзя просто взять и завернуть сайт в слой кэширования как в обертку, т.к. это будет либо неэффективно, либо неизбежно приведет к ошибкам, связанным с нежелательным кэшированием.

O>Если под клиентским ПО подразумевается браузер, тогда да, лучше оставить коды состояний, потому что

O>браузер ни с чем иным работать и не умеет, если не считать HTML. А если речь идет о специальном клиентском
O>приложении, то здесь возможностей гораздо больше.

Я говорю в контексте браузера.
-- С уважением, Павел Мелехов, Екатеринбург.
Re[5]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: Centaur Россия  
Дата: 04.10.12 11:02
Оценка:
Здравствуйте, Geri, Вы писали:

G>Может быть если начать выдавать код 400 в ответ на неправильно введенный пароль, то браузер не будет предлагать его сохранить?


Неправильный пароль — это не 400 Bad Request. Это 403 Вам Нельзя.
Re[6]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: Geri Россия http://web-notes.ru/
Дата: 04.10.12 11:07
Оценка:
Здравствуйте, Centaur, Вы писали:

G>>Может быть если начать выдавать код 400 в ответ на неправильно введенный пароль, то браузер не будет предлагать его сохранить?

C>Неправильный пароль — это не 400 Bad Request. Это 403 Вам Нельзя.

Полностью согласен, моя ошибка.
-- С уважением, Павел Мелехов, Екатеринбург.
Re[4]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: A13x США  
Дата: 04.10.12 11:28
Оценка: +1
Здравствуйте, okman, Вы писали:

O>...

O>А веб-сервисы обычно именно так и работают, обратите внимание.

Если имеются в виду SOAP-based веб-сервисы, то на мой взгляд это не очень хороший пример REST API (почему — отдельная спорная тема).
Я бы здесь не следовал каким-то канонам, а выбирал то, что удобнее. Ну и смотрел как сделано у "крутых пацанов".

К примеру возьмем twitter API:


Bad Request The request was invalid. An accompanying error message will explain why...

Re: Может ли веб-приложение возвращать 400 Bad Request при некорректных параметр
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.10.12 04:31
Оценка: 18 (2) -1
Здравствуйте, Geri.

Я полностью согласен с A13x.

Философия: Искусственно разделять слои в приложениях не нужно. Полное использование возможностей нижележащего протокола — вот путь к успеху. Не надо слишком думать о том, что будет, если мы заменим транспортный протокол. Такая замена, скорее всего, потребует существенной переработки и прикладного протокола — потому, что идеальных абстракций не бывает. Ну вот, простой пример — если я пишу приложение поверх TCP, то я буду мучиться с самодельным кэшированием. А если я пишу поверх HTTP, то это будет преступной потратой ресурсов. Вместо этого нужно опираться на Cache-Control и Conditional Get.

Практика: как вы верно отметили, клиенту всё равно, какая там архитектура на серверной стороне. Есть некоторые соглашения. В частности, коды 4xx означают "виноват клиент", а коды 5xx — "виноват сервер".
В принципе, сервису достаточно кодов 400 и 500 для обработки "прикладных" ошибок. Отличие для клиента — только в том, что 400 не имеет смысл повторять, а 500 даёт шанс на то, что запрос таки удастся обработать.

А далее идёт по мере вашего увлечения семантикой: чем больше деталей вы сообщите клиенту, тем лучше он сможет обработать ситуацию. Тупой клиент будет трактовать любые 4xx как 400 — и ему будет достаточно.
А вот умный клиент может использовать некоторые дополнительные соглашения. 401 приглашает клиента к диалогу по выбору способа авторизации. 403 означает, что сам запрос в порядке, но прав доступа недостаточно — в клиента может быть встроена функция "обратиться к админам с запросом доступа". Кстати, в реально параноидальной системе 403 может быть запрещен как выдающий слишком много деталей неавторизованному клиенту, и вместо него лучше отдавать 404 (так, кстати, делает connect.microsoft.com).
Важно продумывать сценарии, которые вы хотите предоставить клиенту. Каждый раз, когда вы выбираете код результата, думайте о том, зачем вы возвращаете именно его.
Скажем, если вы хотите помочь клиенту выбрать время для повтора запроса, сломавшегося на сервере, можно вернуть 503 с заголовком Retry-After. Если не хотите — то клиенту всё равно, 500 или 503 вы отдали.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.10.12 09:15
Оценка: 1 (1)
Здравствуйте, okman, Вы писали:
Раз уж вы поставили мне минус, потрачу пару минут на ответ.

O>Например, при смене транспорта не придется переделывать систему обработки ошибок.

Ну, во-первых, всё-таки придётся. Смена транспорта смене транспорта рознь. Сделать прозрачный переезд с HTTP на TCP, может, и выйдет, но никаких преимуществ транспорта вы использовать не сможете.
Совершенно неясно, стоит ли овчинка выделки.

O>Коды состояний HTTP не смогут обеспечить клиента точной информацией о том, на каком этапе обработки запроса

O>произошел сбой — на транспортном или логическом. Если, к примеру, и front end, и back end сервера могут
O>отдавать "500 Internal Server Error", то рано или поздно наступает ситуация, когда клиент получает такой
O>ответ и не знает, от кого именно он пришел и по каким правилам обрабатывать его содержимое.
Отлично. Ну, вот расскажите мне, по каким правилам нужно обрабатывать ответ 500 Internal Server Error, в зависимости от того, кто его вернул.
В моей реальности клиент видит 500, и ему всё равно, откуда он взялся.

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

O>Я встречал мнение, что можно использовать зарезервированные коды HTTP-состояний. Например, диапазон

O>512-599 в настоящее время свободен.
Вас обманули. Делать этого ни в коем случае не надо. Потому, что вы сочетаете недостатки обоих подходов. Неизвестные науке коды не дают использовать стандартные механизмы, разработанные для протокола HTTP, и затрудняют портирование на другой транспорт.
Нужно вкладывать "более структурированные" и "более информативные" данные внутрь протокола, выбирая код статуса сообразно семантике ответа.
Это позволяет реализовывать схемы graceful degradation — это когда нет жёсткой зависимости между реализациями клиента и сервера; в диалоге выбирается уровень "наибольшего общего кратного" и партнёры общаются на нём.
А про "соответствие духу системы", я имею ровно противоположное мнение. Либо дух системы соответствует духу HTTP, тогда грех этим не воспользоваться. Либо дух системы противоречит духу HTTP — тогда мы имеем мертворожденного мутанта, вроде SOAP, авторов которого нужно судить за преступления против технического совершенства.

O>По-моему, очень неплохая отправная точка.

Не, она слишком далеко в прошлом. В отсутствие HTTP она бы имела смысл, но теперь игнорировать RFC2616 смысла нет.
Вместо того, чтобы строить свой протокол поверх HTTP, имеет смысл просто пользоваться самим HTTP (естественно, если суть задачи этому соответствует). Зачем рожать целый новый прикладной протокол поверх существующего, когда этого существующего достаточно? Да ещё и есть встроенные возможности по расширению протокола, и опять с поддержкой graceful degradation.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.10.12 09:20
Оценка: 1 (1)
Здравствуйте, A13x, Вы писали:


A>Если имеются в виду SOAP-based веб-сервисы, то на мой взгляд это не очень хороший пример REST API (почему — отдельная спорная тема).

Не особо спорная. SOAP — это не REST. В самой лучшей инкарнации, SOAP — это мучительные попытки переизобрести REST, отказавшись от возможностей нижележащей архитектуры. Это как если бы кто-то взял из всего TCP только возможность отправлять пакетики размером в 1 байт в рамках каждого соединения, и построил поверх этого потоковый протокол с гарантиями доставки.
Если такое собрал ребёнок в детском саду — можно умиляться. Если это предлагает инженер — его надо уволить за профнепригодность.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.10.12 09:38
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Я полностью согласен с A13x.

Да, ещё немного философии — для контекста — здесь
Автор: Sinclair
Дата: 03.04.08
.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: okman Беларусь https://searchinform.ru/
Дата: 17.10.12 12:23
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Философия: Искусственно разделять слои в приложениях не нужно.


Разделять слои в приложениях нужно не искусственно, а естественно.

S>Полное использование возможностей нижележащего протокола — вот путь к успеху. Не надо слишком думать о том, что будет, если мы заменим транспортный протокол.


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

O>>Коды состояний HTTP не смогут обеспечить клиента точной информацией о том, на каком этапе обработки запроса

O>>произошел сбой — на транспортном или логическом. Если, к примеру, и front end, и back end сервера могут
O>>отдавать "500 Internal Server Error", то рано или поздно наступает ситуация, когда клиент получает такой
O>>ответ и не знает, от кого именно он пришел и по каким правилам обрабатывать его содержимое.

S>Отлично. Ну, вот расскажите мне, по каким правилам нужно обрабатывать ответ 500 Internal Server Error, в зависимости от того, кто его вернул.


Вопрос не понят. При таком подходе, который я защищаю, "500 Internal Server Error" может вернуть
только фронт энд сервера. Если, копаясь в логах сервера в поисках какой-нибудь непонятной ошибки, я
нахожу код 500, то точно знаю, что до бэк энда дело вообще не дошло. И для этого мне не обязательно
вытаскивать тело ответа сообщения (которое, кстати, может быть сжато gzip-ом) или еще что-то.

S>В моей реальности клиент видит 500, и ему всё равно, откуда он взялся.


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

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

O>>"надпротокольные" сообщения об ошибках, возвращенные с кодом 200, могут быть и более структуированными, и

O>>более информативными, и вообще более соответствующими духу системы, в которой они используются.

S>И вот как раз это — очень плохо. Потому, что в рамках протокола вы не даёте никакой информации о семантике.


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

S>Например, прокси-сервер будет искренне полагать, что всё в порядке, и кэшировать результат такой ошибки.


Прокси может кэшировать и другие ответы. Так что данная проблема имеет малое отношение к вопросу.
Ну и есть же "pragma: no-cache".

S>Нужно вкладывать "более структурированные" и "более информативные" данные внутрь протокола,

S>выбирая код статуса сообразно семантике ответа.

Какие средства предоставляет HTTP для передачи структурированной информации об ошибке ?

S>А про "соответствие духу системы", я имею ровно противоположное мнение. Либо дух системы соответствует духу HTTP, тогда грех этим не воспользоваться. Либо дух системы противоречит духу HTTP — тогда мы имеем мертворожденного мутанта, вроде SOAP, авторов которого нужно судить за преступления против технического совершенства.


Да, судить за преступления. И уволить. А еще перед этим расстрелять.

Если надумаете ответить, напишите вот о чем — почему, когда я пытаюсь залогиниться на RSDN, используя
неправильный пароль, сервер не выкидывает мне "401 Unauthorized" или "403 Forbidden" ?
Re[4]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.10.12 15:44
Оценка:
Здравствуйте, okman, Вы писали:

O>Разделять слои в приложениях нужно не искусственно, а естественно.

С этим спорить я не буду, т.к. согласен. Давайте обсудим границы естественности.

O>Пример — веб-сервис может использовать HTTP для браузеров и бинарный протокол для других программ-клиентов.

Во-первых, я не вполне понимаю, что вы называете "браузерами". Вы имеете в виду JS-приложения, которые крутятся внутри браузеров и потребляют HTTP-сервисы?
Или вы говорите про пользовательское веб-приложение, которое работает на том же бэк-енде, что и веб-сервис для внешних приложений?

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

O>Вопрос не понят. При таком подходе, который я защищаю, "500 Internal Server Error" может вернуть

O>только фронт энд сервера. Если, копаясь в логах сервера в поисках какой-нибудь непонятной ошибки, я
O>нахожу код 500, то точно знаю, что до бэк энда дело вообще не дошло.
Так, давайте разберёмся. Вы — не клиент, вы разработчик. Вот разработчику конечно может быть интересно, какой именно из бесчисленных компонентов серверной стороны упал.
Но вы обещали показать какие-то отличия в логике клиента.
O>И для этого мне не обязательно вытаскивать тело ответа сообщения (которое, кстати, может быть сжато gzip-ом) или еще что-то.
Мы с вами как-то по разному понимаем процесс отладки веб-серверов. Вот вы вместо того, чтобы сравнить логи фронт-енда с логами бэк-енда, предлагаете отказаться от использования кода 500.
Зато вот отличить success response от error response от бэк-енда можно только путём вытаскивания тела сообщения (которое, кстати, может быть сжато gzip-ом). Почему вас это не смущает?

O>Правильно ли я понял, что в Вашей реальности несущественно, произошла ли ошибка передачи данных

O>или логическая ошибка самого сервиса ?
Клиенту — совершенно несущественно. В моей реальности клиент принимает только решения о том, повторять ли ему запрос, или не стоит. Если он получил 500 — это значит, что сервер не справился. Почему — это проблемы сервера.

O>Могу только прокомментировать, что системы и требования к ним бывают разные, но в тех, где мне

O>довелось поучаствовать, такое разделение практически всегда имело большой смысл.
Я буду рад, если вы объясните мне этот смысл.

O>Потому что в описываемой модели работа протокола-транспорта на данном этапе закончена — сообщение доставлено.

O>Остальным занимается прикладной протокол, расположенный выше.
Вы опять настаиваете на искусственном разделении протоколов.
O>Прокси может кэшировать и другие ответы. Так что данная проблема имеет малое отношение к вопросу.
Вопросы кэширования играют первоочередную роль в разработке распределённых сервисов.
O>Ну и есть же "pragma: no-cache".
Омг, омг. Я вижу, как вы одной рукой создаёте себе проблемы, а другой — решаете. Зачем?

O>Какие средства предоставляет HTTP для передачи структурированной информации об ошибке ?

Полные.
Статус код плюс хидеры позволяют самому тупому клиенту или прокси понять, что происходит.
Для большинства статусов (кроме нескольких особенных) можно передавать и контент. А в контенте как раз и предоставлять структурированную информацию об ошибке.

O>Да, судить за преступления. И уволить. А еще перед этим расстрелять.

Конечно.
O>Если надумаете ответить, напишите вот о чем — почему, когда я пытаюсь залогиниться на RSDN, используя
O>неправильный пароль, сервер не выкидывает мне "401 Unauthorized" или "403 Forbidden" ?
На это есть три ответа.
1. Сервер RSDN несовершенен, и не является образцом корректности.
2. Мы говорим не о веб-сервисе, а о веб-приложении. Для его клиентов наблюдаемой разницы между 400 и 200 нет.
3. Если уж быть педантом, то сервер не возвращает 401 потому, что не должен. Этот код не означает "неправильный пароль". Этот код означает "ресурс требует авторизации, а я не знаю, кто вы", и входит в специальный цикл HTTP Authentication, которая на RSDN не используется. А 403 означает, что сервер понял, кто вы, но вам туда нельзя, так что его семантика неприменима для случая неправильного пароля. Доступ до login.aspx у вас есть
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: A13x США  
Дата: 17.10.12 17:12
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, A13x, Вы писали:



A>>Если имеются в виду SOAP-based веб-сервисы, то на мой взгляд это не очень хороший пример REST API (почему — отдельная спорная тема).

S>Не особо спорная. SOAP — это не REST.

Мое отношение к SOAP так же в основном негативное, при наличии выбора я предпочту REST+JSON и т.п.

Что же касается спорности — я к тому, что тут есть почва для всякого рода разночтений и разногласий.
Навскидку по поводу дефектности связки HTTP+SOAP:
1. SOAP использует HTTP как канал доставки, SOAP может быть реализован поверх другого протокола (например JMS, SMTP).
Тут, бесспорно, можно заметить в ответ, что рассматривать HTTP как транспортный, а не прикладной протокол семантически неверно.
2. SOAP поверх HTTP можно считать частным случаем REST+XML, принимая во внимание намеренный отказ от следования рекомендациям RFC в пользу модели данных, предлагаемой SOAP-ом.
Специфичные заголовки?

However, new or experimental header fields MAY be given the semantics of request- header fields if all parties in the communication recognize them to be request-header fields. Unrecognized header fields are treated as entity-header fields.

Использование POST-only методов?
В RFC нет MUST/SHOULD требований по поводу того, что один URI на который делается POST не может выполнять несколько логически несвязанных действий, в том числе реализовывать идемпотентные операции.

Есть еще аргументы в стиле "все так делают" (поэтому можно считать это best practice) и "наработан большой опыт", но на них останавливаться не вижу смысла.
На всякий случай еще раз замечу, что лично мне SOAP не нравится по многим причинам, в основном из-за логического несоответствия протоколу (явный случай protocol misuse) и избыточности
Re[5]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: okman Беларусь https://searchinform.ru/
Дата: 17.10.12 19:17
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Так, давайте разберёмся. Вы — не клиент, вы разработчик. Вот разработчику конечно может быть интересно, какой именно из бесчисленных компонентов серверной стороны упал.

S>Но вы обещали показать какие-то отличия в логике клиента.

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

S>Вы опять настаиваете на искусственном разделении протоколов.


Во-первых, не настаиваю, а отстаиваю.
Во-вторых, критерии искусственности, пожалуйста, в студию.

O>>Прокси может кэшировать и другие ответы. Так что данная проблема имеет малое отношение к вопросу.


S>Вопросы кэширования играют первоочередную роль в разработке распределённых сервисов.


Как вопросы кэширования связаны с кодами состояний HTTP ?
Точнее, какие могут быть проблемы, если мы возвращаем 200 OK с логическим пакетом "ошибка" ?

O>>Ну и есть же "pragma: no-cache".


S>Омг, омг. Я вижу, как вы одной рукой создаёте себе проблемы, а другой — решаете. Зачем?


В чем дело ?
Вы не используете данный (или аналогичные) заголовок в своих "правильных" реализациях ?

O>>Какие средства предоставляет HTTP для передачи структурированной информации об ошибке ?


S>Полные.

S>Статус код плюс хидеры позволяют самому тупому клиенту или прокси понять, что происходит.
S>Для большинства статусов (кроме нескольких особенных) можно передавать и контент. А в контенте как раз и предоставлять структурированную информацию об ошибке.

Правильно, формат тела сообщения полностью на плечах вышележащего протокола, такого как HTML, XML или JSON.
Сам HTTP такой структурности не предоставляет, он является лишь транспортом для них, что подтверждается,
кстати, и его названием — "Hyper-Text Transfer Protocol".

O>>Если надумаете ответить, напишите вот о чем — почему, когда я пытаюсь залогиниться на RSDN, используя

O>>неправильный пароль, сервер не выкидывает мне "401 Unauthorized" или "403 Forbidden" ?
S>На это есть три ответа.
S>1. Сервер RSDN несовершенен, и не является образцом корректности.
S>2. Мы говорим не о веб-сервисе, а о веб-приложении. Для его клиентов наблюдаемой разницы между 400 и 200 нет.
S>3. Если уж быть педантом, то сервер не возвращает 401 потому, что не должен. Этот код не означает "неправильный пароль". Этот код означает "ресурс требует авторизации, а я не знаю, кто вы", и входит в специальный цикл HTTP Authentication, которая на RSDN не используется. А 403 означает, что сервер понял, кто вы, но вам туда нельзя, так что его семантика неприменима для случая неправильного пароля. Доступ до login.aspx у вас есть

Да, но ведь по Вашей "легенде" коды 401 или 403 (или другие) могли бы использоваться бэк эндом
сайта для "своих" логических ошибок, типа ошибки логина ? Выглядит как противоречие.
Re[6]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.10.12 11:13
Оценка:
Здравствуйте, okman, Вы писали:


O>Например, довольно типичная ситуация — отправка на сервер неких последовательных данных, когда

O>важно сохранить их порядок и не потерять ни одной записи. В этом случае программа-клиент будет
O>повторять каждый запрос до тех пор, пока он не будет обработан сервером, и только после этого
O>переходить к формированию и отправке следующего. И здесь очень важно уметь определять, был ли
O>запрос реально обработан веб-сервисом (бэк эндом), или он "застрял" где-то на более ранних фазах.
O>Причем определять нужно именно программно. Еще более актуальным это становится при использовании
O>прокси-серверов. Вот в решении данной задачи помогает ограничение, приведенное выше — коды,
O>отличные от группы 200 (успех), возвращаются только фронт эндом и сигнализируют исключительно об
O>ошибках транспорта (в данном случае HTTP), а коды 200 означают, что запрос прошел эту стадию и
O>был обработан бэк эндом (хотя может иметь место ошибка на логическом уровне).
Прекрасно, просто прекрасно. Вы приводите ровно те примеры, где REST в целом и HTTP в частности на ошмётки порвут любой альтернативный протокол.
Итак, клиент наблюдает код 500. Что он, в вашем примере, означает?
Я лично вижу три варианта:
1. Фронт-енд не смог связаться с бэк-ендом
2. Фронт-енд связался с бэк-ендом, но в процессе обработки записи возникла "логическая ошибка", транзакция была откачена
3. Фронт-енд связался с бэк-ендом, бэк-енд всё обработал, но в момент отдачи результата во фронт-енд упал канал.
Вы предлагаете елиминировать №2, возвращая в таких случаях 200.
Но это вам ничем не поможет — вы всё ещё не можете отличить №1 от №3.
Это потому, что вы плохо спроектировали протокол взаимодействия. Дело даже не в HTTP, а в отсутствии понятия идемпотентности в вашем протоколе.
Правильное решение — сделать операцию "обработать запись" идемпотентной. В терминах протокола HTTP это было бы выполнение глагола PUT на адрес нужного вам элемента.
Клиент трактует коды следующим образом:
1хх — мы игнорируем пока, поскольку схема 100 continue нас не особо пока интересует
2xx — всё получилось, можно посылать следующий
3хх — нужно скорректировать свои действия соотвествующим образом и попробовать снова (см. семантику 301, 302, и 307)
4хх — придётся скорректировать свои действия (например, вступить в цикл HTTP Authentication), либо отрапортовать ошибку
5xx — нужно выполнять повторный запрос в соответствии с настройками клиента и рекомендациями сервера.
Ошибки других типов (TCP connection lost и прочее) трактуются так же, как 5хх.

Всё. Не надо никаких больше гаданий, на каком там этапе "застрял" запрос.
Если вдруг оказалось, что запрос был успешен, просто клиент об этом так и не узнал по какой-то причине, сервер молча примет запрос и вернёт 2xx.

O>Во-вторых, критерии искусственности, пожалуйста, в студию.

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

O>Как вопросы кэширования связаны с кодами состояний HTTP ?

Напрямую. Может быть, настало время прочесть таки RFC 2616? Каждый код состояния имеет определённую семантику. Полное описание как-то выходит за рамки форумного поста.
O>Точнее, какие могут быть проблемы, если мы возвращаем 200 OK с логическим пакетом "ошибка" ?
Очень простые: никакие из стандартных инструментов не считают этот логический пакет ошибкой.

O>В чем дело ?

O>Вы не используете данный (или аналогичные) заголовок в своих "правильных" реализациях ?
Как правило — нет. Если вам потребовалась pragma:no-cache, то как правило, это означает, что вы делаете что-то неправильно.
В HTTP из коробки работают вполне разумные правила кэширования. Прагма позволяет отключить их и нужна, скажем, если вы внезапно решили изменить семантику глагола GET, сделав его небезопасным. Вот как раз так делать не надо.

O>>>Какие средства предоставляет HTTP для передачи структурированной информации об ошибке ?


O>Да, но ведь по Вашей "легенде" коды 401 или 403 (или другие) могли бы использоваться бэк эндом

O>сайта для "своих" логических ошибок, типа ошибки логина ? Выглядит как противоречие.
Нет, не выглядит. "Свои" логические ошибки могут вкладываться в существующие статусы HTTP, уточняя их.
А вы предлагаете их переопределить, т.е. дать им семантику, противоречащую стандартной семантике.
Посмотрите на так называемые substatus codes в IIS: там 20 разных вариантов 403.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Может ли веб-приложение возвращать 400 Bad Request при некорректных парам
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.10.12 11:22
Оценка:
Здравствуйте, A13x, Вы писали:

A>1. SOAP использует HTTP как канал доставки, SOAP может быть реализован поверх другого протокола (например JMS, SMTP).

A>Тут, бесспорно, можно заметить в ответ, что рассматривать HTTP как транспортный, а не прикладной протокол семантически неверно.
Насчёт семантики — я не против такого использования. Кто ж спорит, можно и на бентли цемент возить.
Раздражает исключительно неэффективность связки этих двух протоколов.
Хотя в современном мире такие решения считаются нормой: лично наблюдал конструкции, которые сам SOAP используют в качестве транспортного протокола, выставляя ровно один метод ProcessMessage(), в который отправляется полувалидный XML с указанием того, что именно следует сделать. Увы, уголовной ответственности за такое не предусмотрено ни в одной стране мира.

A>2. SOAP поверх HTTP можно считать частным случаем REST+XML, принимая во внимание намеренный отказ от следования рекомендациям RFC в пользу модели данных, предлагаемой SOAP-ом.

Лично мне это мешает сделать отсутствие внятных способов декларировать семантику SOAP — сообщений. Может я чего пропустил, но я не помню изкоробочного способа пометить сообщение как safe или idempotent.

A>Специфичные заголовки?

A>

A>However, new or experimental header fields MAY be given the semantics of request- header fields if all parties in the communication recognize them to be request-header fields. Unrecognized header fields are treated as entity-header fields.

A>Использование POST-only методов?
A>В RFC нет MUST/SHOULD требований по поводу того, что один URI на который делается POST не может выполнять несколько логически несвязанных действий, в том числе реализовывать идемпотентные операции.
Это понятно, что не обязан. Просто это выглядит как некоторый идиотизм. "Вот я имею safe операцию GetStockQuotes(), но я вам об этом не скажу, поэтому вы будете реально нагружать сервер каждый раз, как клиент захочет проверить обновления"

A>Есть еще аргументы в стиле "все так делают" (поэтому можно считать это best practice) и "наработан большой опыт", но на них останавливаться не вижу смысла.

О да. Я перестал рассматривать эти аргументы много лет назад — уж очень много в индустрии заблуждений, носящих маниакально-массовый характер. Диссертация по REST вышла 12 лет тому, и до сих пор мало кто знает, что это такое.
A>На всякий случай еще раз замечу, что лично мне SOAP не нравится по многим причинам, в основном из-за логического несоответствия протоколу (явный случай protocol misuse) и избыточности
Ага.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.