Подтвердить что ты не робот

Существует ли обычный способ возврата статусов ошибок из веб-служб JSON?

У меня есть обработчик .NET.ashx, который получает сообщение jQuery AJAX, форматирует запрос веб-службы сторонней службе и потребляет результат. При успехе он создает анонимный объект с соответствующей информацией и форматирует строку ответа JSON.

В случае ошибки веб-службы я делаю следующее:

context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.StatusDescription = wsResult.ErrorCode;

Это делает код и описание состояния легко доступным для обратного вызова ошибки jQuery AJAX; однако способ, которым я это реализовал, довольно произволен.

После некоторого чтения я не могу найти окончательный ответ на следующий вопрос: существует ли принятое универсальное соглашение (или - даже - спецификация) для возврата состояний ошибок на вызовы AJAX на основе JSON, что позволяет потребитель знать, чего ожидать, или это как произвольное, как возвращаемый тип для любого другого вызова функции?

Итак, это вполне приемлемый способ возврата статуса ошибки в вызывающий AJAX или есть "правильный" способ форматирования ответа об ошибке JSON?

4b9b3361

Ответ 1

Как говорили другие, нет универсального соглашения. Сообщество REST "все еще находится в процессе нахождения определенного консенсуса в таких вопросах - консенсуса никогда не будет найдено. Чтобы привести несколько примеров:

Код состояния

По умолчанию ServiceStack.NET, широко используемая инфраструктура веб-службы С# REST library, возвращает объект (или пустой ответ) с кодом состояния, например:

201 Created

Или:

200 OK

В случае ошибки проверки (например, ArgumentException) это может быть, например:

400 Bad Request

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

Некоторые предпочитают 422 Unprocessable Entity для ошибок проверки, расширение WebDAV для протокола HTTP, но все же вполне приемлемое технически.

Другие думают, что вы должны просто взять один из кодов состояния ошибок, не используемых в HTTP-протоколе, например. 461. Twitter сделал это с (среди прочих) 420 Enhance Your Calm, чтобы уведомить клиента о том, что они сейчас ограничены скоростью, даже если есть (на поверхности) допустимый (и рекомендованный) код состояния 429 Too Many Requests для этой цели уже.

Etc. Все это вопрос философии.

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

Приведите нас к чему (если что-либо), чтобы вернуться в результате JSON? То же самое...

ответ

200 OK может быть вполне достаточно для ответа на, например, запрос на удаление ресурса, если ошибка не возникла. Точно так же 404 Not Found достаточно, чтобы сообщить клиенту, что запрошенное удаление не может быть выполнено, потому что объект для удаления не найден. В других случаях вам может потребоваться больше.

Некоторые люди думают, что вы должны включить как можно больше необходимой информации в заголовки ответов, часто имея пустой ответ только с заголовками. Например, при создании возвратите 201 Created и поместите созданный идентификатор объекта (в качестве URI ресурса) в Content-Location. Не требуется никакого содержимого ответа.

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

HTTP/1.1 404 Not found
Content-Type: application/json; charset=utf-8
...

{
   'Success': false,
   'Message': 'The user Mr. Gone wasn't found.'
}

(На самом деле я не добавляю свойство Success, но, возможно, захочу, в зависимости от моего настроения при разработке API).

При запуске в режиме DEBUG я также включаю строковое представление внутреннего вызова службы - например. 'Request': 'GetUser { id: 5 }', метку времени и трассировку стека. Впрочем, все дело в удобстве. Это достаточно просто, чтобы закодировать клиента с надлежащими удобными сообщениями об ошибках просто на основе 404 Not Found. Однако некоторые другие ошибки (например, проверка) могут потребовать больше контекста. Например:

HTTP/1.1 422 Validation Error
Content-Type: application/json; charset=utf-8
...

{
   'Success': false,
   'Message': 'The request had validation errors.',
   'Errors':
   {
       'UserName': 'The user name must be provided.',
       'Email': 'The email address is already in use.'
   }
}

ServiceStack.NET делает что-то вроде этого по умолчанию, но с немного разными свойствами и контентом. Microsoft собственная среда веб-API делает что-то подобное. Спецификация JSend, связанная в вопросе , является еще одним вариантом.

И так далее.

Короче говоря, нет, нет универсального соглашения - пока нет, по крайней мере. Многие люди (вкладывая в это больше внимания, чем я) работают над этим. Но все равно никогда не будет. И ваш метод вполне приемлем.

(Да, это было очень долго - в основном потому, что я искал для такого же "универсального соглашения" какое-то время).

Подробнее о кодах состояния это отличная статья (слишком длинная для цитаты здесь)

Ответ 2

Нет, нет ни одного крупного стандарта, хотя это может быть приятно. Было бы полезно, если бы вы стали стандартом для включения success и details, но это зависит от того, как вы его используете. Я думаю, что большим преимуществом является то, что вы реализуете стандарт, по крайней мере, во всем своем собственном коде для согласованности, например. http://ricardocovo.com/2012/03/08/asp-net-mvc-using-json-standard-responses-for-your-ajax-calls/

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

Ответ 3

Мои 2 цента:

Я бы сказал, что прежде всего код состояния, который вы отправляете обратно в качестве ответа, является лучшим индикатором ошибки и дает множество опций в диапазоне 4xx и 5xx... (Даже когда вы пытаетесь HttpGET кофе из чайника, вы можете использовать 418: D)

Как что-либо, что не является 200, является какой-то ошибкой, а коды состояния http хорошо документированы, и в этом случае они должны использоваться, любое дальнейшее сообщение об ошибке не обязательно (описание ошибки подразумевается кодом состояния). Браузеры выполняют запросы, и они не заботятся об ошибке, только код состояния.

Любые дополнительные ошибки могут также просто удалить слишком много информации о возможных попытках взлома. Я имею в виду, что для возвращения 403 Forbidden достаточно информации сама по себе, вы также не должны возвращать сообщение с сообщением "Не разрешено, используйте вместо этого" 1234 "в качестве пароля:)

Ответ 4

Руководство по стилю Google JSON использует data xor error объектов...

Чтобы поддерживать согласованный интерфейс через API, объекты JSON должны следовать структуре, описанной ниже. Эта структура применяется как к запросам, так и к ответам, сделанным с помощью JSON.
               .,.
Объект JSON имеет несколько свойств верхнего уровня, за которыми следует либо data объект или error, но не оба.

пример...

{
  "apiVersion": "2.0",
  "error": {
    "code": 404,
    "message": "File Not Found",
    "errors": [{
      "domain": "Calendar",
      "reason": "ResourceNotFoundException",
      "message": "File Not Found
    }]
  }
}

Ответ 5

Как правило, я принимаю имена, структуру и содержимое серверной системы.

Эта практика гарантирует, что интерфейсные разработчики свяжутся с внутренними разработчиками, используя словарь, который они уже понимают, и не устанавливает стандарт/прецедент, в соответствии с которым разработчикам back-end поручается внедрение новых форматов в качестве интерфейсных разработчиков и дизайнеры придумывают новые концепции (ошибка - это ошибка, не позволяющая разделить волосы на "тип" и "мета", которые являются лишь атрибутами любой заданной ошибки.)

Итак, например, если я возвращаю данные об ошибках "клиенту JSON", а конечная точка службы реализована с использованием С#, я хотел бы вернуть документ JSON, который выглядит так:

{ 
  "Message": "An error has occurred.", 
  "ExceptionMessage": "Index was outside the bounds of the array.", 
  "ExceptionType": "System.IndexOutOfRangeException", 
  "StackTrace": "   at WebApiTest.TestController.Post(Uri uri) in c:\\Temp\\WebApiTest\\WebApiTest\\TestController.cs:line 18\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClassf.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)\r\n   at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)",
}

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

Это может не иметь значения для вас сейчас, но в течение 2, 3 или 5 лет обслуживания вы можете начать заботу, и вам может показаться, что вам нужно "переучиваться" в долгосрочной перспективе, когда вы сталкиваетесь с другими разработчиками, которые охватывают подобная практика соответствия, и вы единственный парень в команде, все еще пытающийся изобретать новые форматы (когда это не нужно).

ПРИМЕЧАНИЕ. Чтобы быть ясным, я не предлагаю вам сериализовать исключения до клиента. Хотя это может быть вполне допустимым вариантом во многих сценариях, включая отладку, защиту частных облаков или отсутствие конфиденциальных данных /IP и т.д.