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

Структура возврата ошибок API REST API

Я пишу REST API, и я наткнулся на проблему. Каков наилучший способ вернуть ошибки проверки.

До сих пор я возвращал сообщения об ошибках, сбрасываемые в общий код ошибки (например, скажем, плохой запрос)

{
    "status": 400,
    "error": {
        "code": 1, // General bad request code
        "message": [
                "The Key \"a\" is missing",
                "The Key \"b\" is missing",
                "The Key \"c\" is missing",
                "Incorrect Format for field \"y\""
         ]
    }

)

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

  • Остановитесь при первой обнаруженной ошибке и верните ответ с конкретным кодом ошибки

    {
       "status": 400, //Same as the HTTP header returned
       "error" {
            "code": 1, // Specific field validation error code
            "message": "Field \"x\" is missing from the array structure",
            "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}",
            "more_info" => "www.api.com/help/errors/1"
        }
    )
    
  • Проанализируйте все данные запроса и верните несколько ошибок проверки поля.

    {
      "status": 400,
      "error": {
        "code": 1 //General bad Request code
        "message": "Bad Request",
        "developer_message": "Field validation errors."
        "more_info": "www.api.com/help/errors/1",
        "error_details": {
                0: {
                        "code": 2 // Specific field validation error code
                        "message": "Field \"x\" is missing from the array structure",
                        "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}",
                        "more_info": "www.api.com/help/errors/2"
                    },
    
                1: {
                        "code": 3 // Specific field validation error code
                        "message": "Incorrect Format for field \"y\"",
                        "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"",
                        "more_info": "www.api.com/help/errors/3"
                   }
                       }
          }
      }
    

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

Также я думаю, что вариант 1 по-прежнему действителен, если я получаю одну фатальную ошибку в потоке script. (не ошибки проверки)

Обратите внимание, что код - это просто простой массив, поэтому его легче отслеживать. Формат ответа будет JSON или XML.

4b9b3361

Ответ 1

Посмотрите API графиков Facebook. Это сильно ударило, и, скорее всего, возникло множество ошибок. Вот что возвращает Facebook по ошибке API:

 {
   "error": {
     "message": "Message describing the error", 
     "type": "OAuthException", 
     "code": 190,
     "error_subcode": 460,
     "error_user_title": "A title",
     "error_user_msg": "A message"
   }
 }

Они пытаются сделать API-интерфейс Графа максимально полезным, но они, похоже, возвращают определенную ошибку с кодом и субкодом (Ref), Тот факт, что каждая ошибка имеет свой собственный код, облегчает поиск указанного кода или сообщения в качестве отправной точки для отладки. Вероятно, поэтому они не накапливают сообщения об ошибках в их официальном сообщении об ошибке. Если это достаточно удобно и удобно для Facebook, это, вероятно, достаточно для нас.

Примеры ответов об ошибках:

{
  "error": {
    "message": "(#200) Must have a valid access_token to access this endpoint", 
    "type": "OAuthException", 
    "code": 200
  }
}

и

"error": {
  "message": "(#604) Your statement is not indexable. The WHERE clause must contain 
   an indexable column. Such columns are marked with * in the tables linked from
   http://developers.facebook.com/docs/reference/fql ", 
  "type": "OAuthException", 
  "code": 604
}

Затем существует JSend, который "является спецификацией, которая устанавливает некоторые правила для того, как отформатировать ответы JSON с веб-серверов". Их цель:

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

Вот пример сообщения об ошибке:

{
    "status" : "fail",
    "data" : { "title" : "A title is required" }
}

Похоже на Facebook, и эта группа, пытающаяся установить как отраслевой стандарт, выбирает ваш выбор # 1.


Вопрос о голосе

В ответ на запрос на раздачу "если кто-то пошел # 2 и, возможно, имеет какие-то улучшения на нем?", есть шаблон дизайна из Pragmatic RESTful API, который гласит:

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

{
  "code" : 1024,
  "message" : "Validation Failed",
  "errors" : [
    {
      "code" : 5432,
      "field" : "first_name",
      "message" : "First name cannot have fancy characters"
    },
    {
       "code" : 5622,
       "field" : "password",
       "message" : "Password cannot be blank"
    }
  ]
}

Ответ 2

Я использовал # 2 сам пару раз. Это лучше, чем # 1? Я думаю, это зависит от того, для чего используется ваш API.

Мне нравится # 2, потому что он дает разработчику, который тестирует API с некоторыми тестовыми вызовами, быстро просматривает все ошибки/ошибки, которые он сделал в запросе, поэтому он сразу знает, какие ошибки/ошибки он должен исправить, чтобы сделать этот запрос действителен. Если вы возвращаете ошибки один за другим (например, в # 1), вы должны продолжать повторять запрос и перекрестные пальцы, надеясь, что он будет действителен на этот раз.

Но, как я сказал, # 2 очень полезен для разработчиков, но причины на самом деле не применимы к конечным пользователям. Конечным пользователям, как правило, не важно, как это реализовано. Независимо от того, выполняет ли программа 1 запрос, который возвращает 5 ошибок или 5 последующих запросов, которые возвращают 1 ошибку каждый.
До тех пор, пока он хорошо обрабатывается клиентом, конечный пользователь не должен замечать разницу. Как справиться с этим, конечно, очень многое зависит от того, что на самом деле клиент.

Помимо ускорения разработки, еще одно преимущество №2 (в производстве) заключается в том, что для этого требуется меньше запросов, что, конечно же, снижает нагрузку на сервер.


Я хотел бы знать, пошел ли кто-нибудь №2 и, возможно, какие-то улучшения, поэтому я открыл щедрость.

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

{
  "status": 400,
  "error": {
    "code": 1 //General bad Request code
    "message": "Bad Request",
    "developer_message": "Field validation errors."
    "more_info": "www.api.com/help/errors/1",
    "error_details": {
            0: {
                    "code": 2 // Specific field validation error code
                    "message": "Field \"x\" is missing from the array structure",
                    "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}",
                    "more_info": "www.api.com/help/errors/2"
                },

            1: {
                (
                    "code": 3 // Specific field validation error code
                    "message": "Incorrect Format for field \"y\"",
                    "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"",
                    "more_info": "www.api.com/help/errors/3"
                )
            }
)

С ответами HTTP код состояния не должен находиться в теле, но в заголовке. Это означает, что "status": 400 и "message": "Bad Request" здесь можно опустить. 400 должен быть кодом статуса ответа, а 400 означает "плохой запрос". Это стандарт HTTP и не нуждается в объяснении в ответе. Кроме того, "developer_message": "Field validation errors." является разновидностью дубликата, поскольку конкретные ошибки уже включены в каждую отдельную ошибку, поэтому мы могли бы оставить это.

Это оставляет

{
  "error": {
    "code": 1 //General bad Request code
    "more_info": "www.api.com/help/errors/1",
    "error_details": {
            0: {
                    "code": 2 // Specific field validation error code
                    "message": "Field \"x\" is missing from the array structure",
                    "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}",
                    "more_info": "www.api.com/help/errors/2"
                },

            1: {
                (
                    "code": 3 // Specific field validation error code
                    "message": "Incorrect Format for field \"y\"",
                    "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"",
                    "more_info": "www.api.com/help/errors/3"
                )
            }
)

"code": 1 //General bad Request code
"more_info": "www.api.com/help/errors/1",

Эти 2 строки больше не имеют смысла. Они также не требуются, поскольку каждая ошибка имеет собственный код и информационную ссылку, поэтому мы можем также лишить эти строки, оставив это

{
  "error": {
    "error_details": {
            0: {
                    "code": 2 // Specific field validation error code
                    "message": "Field \"x\" is missing from the array structure",
                    "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}",
                    "more_info": "www.api.com/help/errors/2"
                },

            1: {
                (
                    "code": 3 // Specific field validation error code
                    "message": "Incorrect Format for field \"y\"",
                    "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"",
                    "more_info": "www.api.com/help/errors/3"
                )
            }
)

Код состояния 400 уже указывает на наличие ошибки, поэтому вам больше не нужно указывать "error": {error details}, потому что мы уже знаем, что произошла ошибка. Список ошибок может просто стать корневым объектом:

[
    {
        "code": 2//Specificfieldvalidationerrorcode
        "message": "Field \"x\" is missing from the array structure",
        "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}",
        "more_info": "www.api.com/help/errors/2"
    },
    {
        "code": 3//Specificfieldvalidationerrorcode
        "message": "Incorrect Format for field \"y\"",
        "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"",
        "more_info": "www.api.com/help/errors/3"
    }
]

Итак, все, что осталось в теле, теперь просто список ошибок.

Код статуса указан в заголовке ответа.
Детали указаны в теле ответа.

Ответ 3

Недавно я работал против API Rest, который возвращал несколько предупреждений или ошибок в результатах. Начиная с вашего примера № 2, я бы изменил его следующим образом:

{
  "status": 400,
  "results" : null,
  "warnings": {
        0: {
                // Build a warning message here, sample text to show concept
                "code": 1 // Specific field validation error code
                "message": "It is no longer neccessary to put .js on the URL"
           }
  }
  "errors": {
        0: {
                "code": 2 // Specific field validation error code
                "message": "Field \"x\" is missing from the array structure"
                "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}",
            },
        1: {
                "code": 3 // Specific field validation error code
                "message": "Incorrect Format for field \"y\"",
                "developer_message": "The field \"y\" must be in the form of \"Y-m-d\""
           }
      }
  }

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

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

Я также удалю следующие элементы как IMHO, они должны быть в документах API (как найти справку, используя код ошибки), а не при каждой ошибке:

"more_info": "www.api.com/help/errors/2"
"more_info": "www.api.com/help/errors/3"

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

Ответ 4

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

Ответ 5

Лично я бы предоставил пользователям меньше деталей и ошибки дампа, необходимые разработчикам в таблице журналов базы данных или системных журналах. Из-за того, что вы используете JSON, и это наиболее часто встречается на серверах Apache, и ваш код выглядит скорее php (но примером вашего кода с фигурными фигурными скобками может быть несколько языков, происходящих из PASCAL, например C, С# PERL, PHP, CSharp). Вот как поместить выходные пользовательские ошибки в системные журналы, если вы еще не знаете, как в php http://php.net/manual/en/function.syslog.php. Если вы используете более редкую конфигурацию IIS с JSON и CSharp, для .NET тоже есть библиотеки .NET. Если вы дадите своим пользователям слишком много информации при возникновении ошибки, вы также дадите хакеру в будущем способ изучения вашего сайта.

Ответ 6

Прежде всего, вы предоставили документацию для методов Rest API для клиентов. Таким образом, от клиента/разработчика ожидается предоставление достоверных данных для параметров.

Теперь, сказав, что # 1 - лучший способ сделать Rest API. Ответственность разработчика заключается в максимально возможном сокращении использования сервера. Поэтому, если вы столкнулись с какой-либо фатальной ошибкой, создайте ответ с соответствующим кодом ошибки и сообщением об ошибке и верните его.

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