HTTP-ответ 412 — можете ли вы включить контент?

Я создаю хранилище данных RESTful и использую условные GET и PUT. Во время условного PUT клиент может включить Etag из предыдущего GET в ресурс, и если текущее представление не соответствует, сервер вернет код состояния HTTP 412 (сбой предварительного условия). Обратите внимание, что это сервер/протокол на основе Atom.

Мой вопрос: когда я возвращаю статус 412, могу ли я также включить новое представление ресурса или пользователь должен выдать новый GET? Спецификация HTTP, похоже, не говорит «да» или «нет», как и спецификация Atom (хотя их пример показывает пустое тело объекта в ответе). Кажется довольно расточительным не возвращать новое представление и не заставлять клиента ПОЛУЧАТЬ его. Мысли?


person Gandalf    schedule 22.04.2010    source источник


Ответы (3)


Хотя условные GET и PUT обобщаются как «условные запросы», они концептуально сильно различаются. Условные GET — это оптимизация производительности, а условные PUT — это механизм управления параллелизмом. Их сложно обсуждать вместе.

На ваш вопрос относительно условного GET: если вы отправляете GET и включаете заголовок If-None-Match, сервер отправит 200 Ok, если ресурс изменился, и 304 Not Modified, если это не так (если условие не выполнено). 412 следует использовать только с условными PUT.

ОБНОВЛЕНИЕ: кажется, я немного неправильно понял вопрос. К вашему замечанию относительно «обновления» локальной копии после неудачного условного PUT: вполне может быть, что в кеше уже есть самая новая версия, и что ваш Refresh-GET будет обслуживаться из какого-то кеша. Если сервер возвращает текущую сущность с ошибкой 412, это может привести к ухудшению производительности.

person Jan Algermissen    schedule 23.04.2010
comment
Да, я не следил за вашим первоначальным ответом, но ваша точка зрения о возможном промежуточном кеше очень хороша. Честно говоря, лучший ответ, который я когда-либо видел. - person Gandalf; 23.04.2010

Нет, технически вы не должны. Коды ошибок обычно указывают, что что-то пошло не так. Хотя ничто не помешает вам вернуть контент (и на самом деле некоторые ошибки, такие как 404, возвращают красивую страницу с надписью «Вы не нашли то, что ищете»), смысл ответа не в том, чтобы вернуть другой контент, а чтобы вернуть что-то, что говорит вам, что было не так. Технически вы также не должны возвращать эти данные, потому что вы передали тег If-None-Match: etag (я предполагаю, что вы передали это?)

С другой стороны, вам действительно нужно оптимизировать один дополнительный http-вызов?

Чем больше я об этом думаю, тем больше убеждаюсь, что это плохая идея. Собираетесь ли вы вернуть контент при любых других ошибках? PUT семантика для PUT. Семантика GET должна использоваться для GET.

person Kylar    schedule 22.04.2010
comment
Оптимизация одного HTTP-вызова может легко означать миллионы сохраненных запросов в день, так что да, я бы поддержал это. Семантика POST аналогична POST, но вполне допустимо возвращать контент при успешном POST, поэтому я не согласен с вашим аргументом. - person Gandalf; 22.04.2010
comment
Вы не делаете POST, вы делаете PUT. Семантика POST отличается от обоих, и допустимо возвращать контент в сообщении, потому что семантика гласит: Фундаментальное различие между запросами POST и PUT отражается в различном значении цели запроса. URI в запросе POST идентифицирует ресурс, который будет обрабатывать вложенный объект. Этот ресурс может быть процессом, принимающим данные, шлюзом для какого-либо другого протокола или отдельным объектом, который принимает аннотации. Это означает, что POST может возвращать содержимое, не связанное с URI. - person Kylar; 22.04.2010

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

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

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

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

person Darrel Miller    schedule 22.04.2010