Какой код ответа HTTP-статуса мне следует использовать, если в запросе отсутствует обязательный параметр?

Ответы:

389

Состояние 422 кажется наиболее подходящим на основании спецификации .

Код состояния 422 (Unprocessable Entity) означает, что сервер понимает тип содержимого объекта запроса (следовательно, код состояния 415 (Unsupported Media Type) является неподходящим), и синтаксис объекта запроса является правильным (таким образом, 400 (неверный запрос) ) код состояния не подходит), но не удалось обработать содержащиеся в нем инструкции. Например, это условие ошибки может возникнуть, если тело запроса XML содержит правильно сформированные (то есть синтаксически правильные), но семантически ошибочные инструкции XML.

Они утверждают, что неправильно сформированный xml является примером плохого синтаксиса (вызов 400). Неверно сформированная строка запроса выглядит аналогично этому, поэтому 400 не подходит для правильно сформированной строки запроса, в которой отсутствует параметр.

UPDATE @DavidV правильно указывает, что эта спецификация предназначена для WebDAV, а не для основного HTTP. Но некоторые популярные не-WebDAV API все равно используют 422 из-за отсутствия лучшего кода состояния ( см. Это ).

кельвин
источник
2
IMO Я бы использовал это, когда значение в строке запроса было неправильным, а не когда было дополнительное значение или отсутствующее значение. то есть. Ожидается электронное письмо и его значение «123123»
Дерек Лиц
2
Я склонен считать параметры GET и POST сигнатурой метода URL-пути, поэтому 404 имеет для меня смысл. В RESTful API, предназначенном для общего пользования, целесообразно возвращать отсутствующие / дополнительные параметры. В контексте URL параметры строки запроса обычно важны для идентификации ресурса, а дополнительные или отсутствующие параметры представляют ресурс, который не существует, без каких-либо предположений. Конечно, есть компромиссы с надежностью, поскольку они являются явными, а необязательные параметры делают ресурс потенциально столь же уязвимым для тихой ошибки. Тогда есть удобство ...
Дерек Лиц
13
Ссылка на спецификацию предназначена для WebDAV и не является стандартной спецификацией HTTP.
Дэвид V
1
@Kelvin Спасибо за указание на этот пост в блоге. Полезно видеть, что Twitter, например, использует 422. Я думаю, что ответ может быть лучше, если вы поясните, что спецификация - это WebDAV в первой строке. Когда я впервые прочитал ваш ответ, я думал, что вы имели в виду стандартную спецификацию HTTP, пока я не перешел по ссылке.
Давид V
3
Это стоит прочитать: bennadel.com/blog/… Я бы тоже не использовал 422 для пропущенного параметра. Я считаю 400более подходящим.
Зельфир Кальцталь
184

Я не уверен, что есть установленный стандарт, но я бы использовал 400 Bad Request , которые в последней спецификации HTTP (от 2014 года) представлены следующим образом :

6.5.1. ошибка 400, неверный запрос

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

Герт Гренандер
источник
65
400 Bad Requestпредназначен для обозначения проблем на уровне протокола, а не семантических ошибок. Если мы собираемся перехватить коды состояния HTTP, чтобы указать ошибки уровня приложения (а не уровня протокола), почему бы не пройти весь путь и просто использовать 412?
Мэтт Жуковски
36
Реализация Google OAuth 1.0 согласна с этим ответом. Ответ 400 дается, когда параметры POST отсутствуют или не поддерживаются: code.google.com/apis/accounts/docs/OAuth_ref.html
Том
1
@ matt-zukowski: «412: предварительное условие, заданное в одном или нескольких полях заголовка запроса, оценивается как ложное при тестировании на сервере». из RFC2616 - Если это POST, параметры находятся в теле запроса, а не в полях заголовка запроса. Технически, метод GET отправляет свои параметры в заголовки запроса, но вместо этого я предпочел бы иметь некоторую согласованность?
Toong
6
@MattZukowski 400 - это код состояния уровня приложения. Если вы посмотрите на формулировку в черновой версии RFC 7231, вы увидите это. К сожалению, формулировка в последней версии не так понятна, потому что автор последних изменений также изобрел 422.
Darrel Miller
9
@DarrelMiller прав ( прямая ссылка ): «Код состояния 400 ( неверный запрос) указывает на то, что сервер не может или не будет обрабатывать запрос из-за чего-то, что воспринимается как ошибка клиента (например, синтаксис некорректного запроса, сообщение о неверном запросе). кадрирование или ввод в заблуждение маршрутизацией). " В зависимости от семантики и ожиданий расширяемости (когда-нибудь можно будет выполнить запрос без параметра?), Тогда только 400 и 404 кажутся подходящими в стандартном HTTP. Иначе, придумайте новый код для вашего API, но не перегружайте семантику.
TNE
31

WCF API в .NET ручках недостающие параметры, возвращая HTTP 404«Endpoint Not Found» ошибка при использовании WebHttpBinding .

Это 404 Not Foundможет иметь смысл, если учесть имя метода веб-службы вместе с сигнатурой его параметра. То есть, если вы предоставляете метод веб-службы LoginUser(string, string)и запрашиваете LoginUser(string), последний не найден.

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

10.4.5 404 Не найдено

Сервер не нашел ничего, соответствующего Request-URI. Не указано, является ли состояние временным или постоянным.

400 Bad Request, Как и предложил Герт , остается действительным код ответа, но я думаю , что это, как правило , используется для обозначения проблемы низкого уровня. Он может быть легко интерпретирован как неверно сформированный HTTP-запрос, может быть отсутствующим или недействительным HTTP-заголовком или подобным.

10.4.1 400 неправильных запросов

Сервер не может понять запрос из-за неправильного синтаксиса. Клиент НЕ ДОЛЖЕН повторять запрос без изменений.

Даниэль Вассалло
источник
Это то, что CherryPy делает по умолчанию.
Дерек Лиц
А как насчет обработки почтового запроса, когда вы принимаете модель, а часть модели отсутствует? В этом случае вы не получите 404. Вместо этого вы получите модель, которая недействительна, если я не ошибаюсь, и вы должны решить, что делать сейчас.
Шейн Кортрилл
1
Эта интерпретация кажется натянутой и выражает RPC, а не REST pov. URI - это идентификатор, и он существует и был найден. То, что отправлено в теле, не является частью идентификатора ресурса. 422 больше подходит.
Иона
404 - правильный ответ, просто отредактируйте некоторые URL-адреса в Интернете, чтобы найти консенсус!
Дженсон Баттон-событие
8

Вы можете отправить код ошибки 400. Это один из более универсальных кодов состояния 4xx, поэтому вы можете использовать его для обозначения того, что вы намерены: клиент отправляет запрос, в котором отсутствует информация / параметры, которые требуются вашему приложению для правильной обработки.

BoltClock
источник
7

В одном из наших проектов API мы решили установить статус 409 для какого-то запроса, когда мы не можем полностью заполнить его на 100% из-за отсутствующего параметра.

Код состояния HTTP «Конфликт 409» был для нас хорошей попыткой, поскольку его определение требует включения достаточного количества информации, чтобы пользователь мог распознать источник конфликта.

Ссылка: w3.org/Protocols/

Поэтому среди других ответов, таких как 400 или 404, мы выбрали 409, чтобы обеспечить необходимость просмотра некоторых примечаний в запросе, полезных для настройки нового и правильного запроса.

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

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

gabrielem
источник
2
Это совершенно неправильно. 409 предназначен для проблем параллелизма, поскольку @ MaximeGélinas указывает на ИЛИ ситуации, когда ресурс уже присутствует и дубликаты не допускаются.
gimlichael
Согласно спецификации, «Код состояния 409 (Конфликт) указывает, что запрос не может быть выполнен из-за конфликта с текущим состоянием целевого ресурса». , Использовать его для отсутствующего параметра просто неправильно; это совершенно другой вид ошибки.
Марк Амери
5

Обычно я выбираю 422 (необработанный объект), если что-то в требуемых параметрах не соответствует требуемой конечной точке API (например, слишком короткий пароль), но для пропущенного параметра я выберу 406 (неприемлемо).

Элад Мейдар
источник
8
Хорошо, 406 Недопустимо используется с заголовком Accept (если сервер не может отправить ответ, клиент поймет). «Ресурс, идентифицированный запросом, способен генерировать только объекты ответа, которые имеют характеристики контента, неприемлемые в соответствии с заголовками принятия, отправленными в запросе». , Я застрял с 422, так как нет «правильного» выбора с текущей спецификацией: - /
JakubKnejzlik
Использовать 406 для этого неправильно. Код 406 не означает, что запрос не был принят; это означает, что вы не можете удовлетворить запрос, потому что ответы, которые вы можете обслуживать, - это ответы, которые клиент сочтет неприемлемыми, основываясь на заголовках Accept, которые он отправил в запросе. (Например, включенный запрос Accept-Language: de, указывающий, что он будет принимать ответы только на немецком языке, но единственные версии запрашиваемого документа, доступные вашему серверу, представлены на английском или французском языке.) Использование его для указания отсутствующего параметра в запросе является неправильным, согласно определению в спец.
Марк Амери
3

Для интересующихся Spring MVC (по крайней мере, 3.x) возвращает 400 в этом случае, что мне кажется неправильным.

Я протестировал несколько URL-адресов Google (accounts.google.com) и удалил обязательные параметры, и в этом случае они обычно возвращают 404.

Я бы скопировал гугл.

Neromancer
источник
18
Поскольку Google делает это, это не означает, что Google делает это правильно!
RVE
4
Я согласен, не обязательно «правильно», но иногда то, что правильно и что разумно, - это две разные вещи. Во всяком случае .. до читателя :)
Neromancer
Некоторые API Google возвращают 400, например, github.com/google/google-api-nodejs-client/issues/404
Деннис,
что не так (и почему Spring MVC не соответствует Jax-RS)
Дженсон-Баттон-событие
3

Можно утверждать, что 404 Not Foundследует использовать, поскольку указанный ресурс не может быть найден.

луч
источник
3
Это поведение по умолчанию Java JAX-RS, когда параметр запроса не может быть преобразован в правильный тип данных. Я не согласен с этим, хотя. Ресурс БЫЛ найден: параметры запроса предназначены для фильтрации ресурса, и один из фильтров получил недопустимое значение. Я думаю, что это соответствует 422 ближайших непроцессируемых сущностей и 400 ближайших недопустимых запросов.
Райан
это поведение по умолчанию jax-rs, потому что это правильное поведение!
Дженсон Баттон-событие
Использование 404 целесообразно, когда параметр строки запроса предназначен для идентификации ресурса, задано значение, но это значение не соответствует существующему ресурсу, например, если вы запрашиваете example.com/show-user. -profile? user_id = 123, а пользователь 123 не существует. Но это не то, о чем этот вопрос задан; речь шла о сценарии, где обязательный параметр опускается полностью. Я не вижу, как это соответствует указанному ресурсу, не найденному.
Марк Амери
2

Я часто использую 403 Запрещенную ошибку. Причина в том, что запрос был понят, но я не собираюсь делать то, что просили (потому что все не так). Сущность ответа объясняет, что не так, поэтому, если ответ является HTML-страницей, сообщения об ошибках находятся на странице. Если это ответ в формате JSON или XML, информация об ошибке находится там.

От rfc2616 :

10.4.4 403 Запрещено

Сервер понял запрос, но отказывается его выполнить.
Авторизация не поможет и запрос НЕ ДОЛЖЕН повторяться.
Если метод запроса не был HEAD и сервер желает
обнародовать, почему запрос не был выполнен, он ДОЛЖЕН описать причину отказа в объекте. Если сервер не желает предоставлять эту информацию клиенту,
вместо него можно использовать код состояния 404 (не найден).

cdeszaq
источник
4
Сначала звучит хорошо, хотя я, естественно, связываю это с ошибками аутентификации или разрешениями. Кроме того, спецификация намекает на это, где говорится «если сервер не хочет предоставлять эту информацию клиенту». Кроме того, 404 может быть лучшим вариантом. Я бы направлялся к 404 или 400, а не к 403.
tonyhb
21
Это ужасная идея, даже если технически обоснованная. 403 универсально используется для ответов об ошибках аутентификации, и вы запутаете своих клиентов, если попытаетесь использовать это для индикации ошибок параметров. Например, это делает Twitter - 403 используется как при предоставлении неверных учетных данных OAuth, так и когда в запросе есть что-то семантически неправильное, и это является постоянным источником путаницы для клиентов API.
Мэтт Жуковски
1
@MattZukowski ну это просто неправильно. В спецификации сказано Authorization will not help, что Twitter не должен отправлять это для недействительных учетных данных OAuth.
Торвин
@torvin Twitter должен отправлять 401 Unauthorizedвместо этого. Тем не менее, вы можете понять, почему они этого не делают, если вы посмотрите описания MDN-документов этих двух кодов, которые очень похожи.
Agi Hammerthief
-1

Просто для использования ASP.NET Core в качестве ссылки или примера, ASP.NET Core позволяет создать контроллер с действиями, именно так выглядит действие «Подробности».

    // GET: Cars/Details/5
    public async Task<IActionResult> Details(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var car = await _context.Cars.FirstOrDefaultAsync(m => m.CarId == id);
        if (car == null)
        {
            return NotFound();
        }

        return View(car);
    }

Если параметр idне задан, возвращается 404 Not Found.

Фред
источник
-5

Вернуть 404 - это означает, что ресурс не может быть найден.

Попробуйте изменить URL-адрес сайта, который содержит идентификатор. Я попробовал несколько:

  • вопрос репозитория gitub
  • страница слияния
  • вид продукции Amazon
  • список ebay
  • новостная статья BBC

Все возвращают 404, потому что те разработчики правильно интерпретируют стандарт, а ответ здесь и многие другие - нет!

Jenson кнопки-событие
источник
1
Я полагаю, что большинство разработчиков определяют «параметр» как одну из пар имя / значение в строке запроса или теле формы POST. Запрос на выпуск репозитория Github не содержит этого.
Кельвин
@Kelvin, которые мы разработчики, также включают параметры пути в список. если ЛЮБОЙ параметр url является обязательным, представляет местоположение ресурса и не включен, то должно быть возвращено 404. Это исключает requestBody.
Дженсон Баттон: событие
-6

Я бы пошел с 403.

Из RFC 2616 - протокол передачи гипертекста - HTTP / 1.1

403 Запрещено

Сервер понял запрос, но отказывается его выполнить. Авторизация не поможет и запрос НЕ ДОЛЖЕН повторяться. Если метод запроса не был HEAD и сервер желает сообщить, почему запрос не был выполнен, он ДОЛЖЕН описать причину отказа в объекте. Если сервер не желает предоставлять эту информацию клиенту, вместо него можно использовать код состояния 404 (не найден).

Вы должны описать причину отказа в своем ответе. Если вы предпочитаете не делать этого, просто используйте 404.

Франсиско Коста
источник
3
отрицательно, потому что это дублированный ответ. Попробуйте добавить свое последнее предложение в качестве комментария к более старому ответу, который предлагает использовать 403
пользователь