it-swarm.com.de

REST API-Fehlercodes geben Struktur zurück

Ich schreibe eine REST -API und bin auf ein Problem gestoßen. Was ist der beste Weg, um die Validierungsfehler zurückzugeben.

Bisher habe ich die Fehlermeldungen in einem allgemeinen Fehlercode ausgegeben (zum Beispiel eine schlechte Anfrage).

{
    "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\""
         ]
    }

)

Ich habe ein wenig mehr darüber nachgeforscht, wie eine gute API-Antwort aussehen sollte, und mir die folgenden Optionen überlegt:

  1. Halten Sie beim ersten aufgetretenen Fehler an und geben Sie eine Antwort mit dem entsprechenden Fehlercode zurück

    {
       "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"
        }
    )
    
  2. Analysieren Sie alle Anforderungsdaten und geben Sie mehrere Feldvalidierungsfehler zurück.

    {
      "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"
                   }
                       }
          }
      }
    

Meiner Meinung nach wäre Option 2 der richtige Weg (es gibt den Entwicklern/Endbenutzern nützlichere Informationen und die Serverlast könnte geringer sein) (weniger Anfragen/keine Notwendigkeit, gültige Daten erneut zu validieren/keine Notwendigkeit, die Signatur zu berechnen und den Benutzer zu authentifizieren )), aber ich frage mich, was die besten Praktiken sind und ob es einen anderen Weg gibt, um diese Art von Problemen zu behandeln.

Ich denke auch, dass Option 1 immer noch gültig ist, wenn im Ablauf des Skripts ein einzelner schwerwiegender Fehler auftritt (keine Überprüfungsfehler).

Bitte beachten Sie, dass der Code nur ein einfaches Array ist, damit er leichter zu befolgen ist. Das Antwortformat ist JSON oder XML.

26
Sekundes

Schauen wir uns Facebooks Graph API an. Das ist hart getroffen, und sehr viele Fehler werden höchstwahrscheinlich erzeugt. Facebook gibt bei einem API-Fehler Folgendes zurück:

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

Sie versuchen, die Graph-API so nützlich wie möglich zu gestalten, aber sie scheinen einen bestimmten Fehler mit einem Code und einem Subcode ( Ref ) zurückzugeben. Die Tatsache, dass jeder Fehler einen eigenen Code hat, erleichtert die Suche nach diesem Code oder dieser Nachricht als Ausgangspunkt für das Debuggen. Das ist wahrscheinlich der Grund, warum sie in ihrer offiziellen Fehlerantwort keine Fehlermeldungen anhäufen. Wenn es gut genug und praktisch für Facebook ist, ist es wahrscheinlich gut genug für uns.

Beispielfehlerantworten:

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

und

"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
}

Dann gibt es JSend welches "eine Spezifikation ist, die einige Regeln festlegt, wie JSON-Antworten von Webservern formatiert werden sollen." Ihr Ziel ist:

Es gibt viele Webdienste, die JSON-Daten bereitstellen, und jeder hat seine eigene Art, Antworten zu formatieren. Außerdem erfinden Entwickler, die für JavaScript-Frontends schreiben, das Rad für die Datenübertragung von ihren Servern immer wieder neu. Zwar gibt es viele gängige Muster für die Strukturierung dieser Daten, es gibt jedoch keine Konsistenz in Bezug auf die Benennung oder die Art der Antworten. Dies trägt auch dazu bei, das Glück und die Einheit zwischen Backend-Entwicklern und Frontend-Designern zu fördern, da jeder einen gemeinsamen Ansatz für die Interaktion miteinander erwarten kann.

Hier ist eine Beispielfehlermeldung:

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

Es sieht so aus, als würden sich Facebook und diese Gruppe, die versuchen, einen Industriestandard zu setzen, für Ihre erste Wahl entscheiden.


Kopfgeldfrage

Als Antwort auf die Bounty-Anfrage "Wenn jemand auf Platz 2 gegangen ist und vielleicht Verbesserungen vorgenommen hat?" Gibt es ein Entwurfsmuster von Pragmatic RESTful API , das besagt:

Validierungsfehler erfordern eine Aufschlüsselung der Felder. Dies lässt sich am besten modellieren, indem ein fester Fehlercode der obersten Ebene für Validierungsfehler verwendet und die detaillierten Fehler in einem zusätzlichen Fehlerfeld wie folgt angegeben werden:

{
  "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"
    }
  ]
}
21
Drakes

Ich habe selbst ein paar Mal # 2 benutzt. Ist es besser als # 1? Ich denke, das hängt davon ab, wofür Ihre API verwendet wird.

Ich mag # 2, weil es einem Entwickler, der die API mit einigen Testaufrufen testet, einen schnellen Überblick über alle Fehler/Fehler gibt, die er in einer Anfrage gemacht hat, sodass er sofort weiß, welche Fehler/Fehler er beheben muss, um diese Anfrage gültig zu machen . Wenn Sie die Fehler einzeln zurücksenden (wie in Nr. 1), müssen Sie die Anfrage immer wieder wiederholen und die Daumen drücken, in der Hoffnung, dass sie diesmal gültig sind.

Aber wie gesagt, # 2 ist sehr nützlich für Entwickler, aber die Gründe gelten nicht wirklich für Endbenutzer. Endbenutzer kümmern sich normalerweise nicht darum, wie es implementiert wird. Gibt an, ob die Software 1 Anforderung ausführt, die 5 Fehler zurückgibt, oder 5 nachfolgende Anforderungen, die jeweils 1 Fehler zurückgeben.
Solange es im Client gut gehandhabt wird, sollte der Endbenutzer den Unterschied nicht bemerken. Wie damit umgegangen wird, hängt natürlich stark davon ab, was der Client tatsächlich ist .

Neben der Beschleunigung der Entwicklung besteht ein weiterer Vorteil von # 2 (in der Produktion) darin, dass weniger Anforderungen gestellt werden müssen, was natürlich die Serverlast verringert.


Ich würde gerne wissen, ob jemand auf Platz 2 gegangen ist und vielleicht irgendwelche Verbesserungen daran vorgenommen hat, also habe ich ein Kopfgeld eröffnet.

Klar, es gibt noch Verbesserungsbedarf. So wie es ist, gibt es einige Daten im Körper, die weggelassen werden können.

{
  "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"
                )
            }
)

Bei HTTP-Antworten sollte der Statuscode nicht im Hauptteil, sondern im Header stehen. Dies bedeutet, dass hier "status": 400 und "message": "Bad Request" weggelassen werden können. 400 sollte der Statuscode der Antwort sein und 400 bedeutet Bad Request. Es ist ein HTTP-Standard und muss nicht in der Antwort erklärt werden. Auch "developer_message": "Field validation errors." ist eine Art Duplikat, da die spezifischen Fehler bereits in jedem einzelnen Fehler enthalten sind, sodass wir das weglassen könnten.

Das geht

{
  "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",

Diese beiden Zeilen ergeben jetzt keinen Sinn mehr. Sie sind auch nicht erforderlich, da jeder Fehler über einen eigenen Code und einen eigenen Infolink verfügt. Daher werden diese Zeilen möglicherweise ebenfalls entfernt

{
  "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"
                )
            }
)

Der Statuscode 400 zeigt bereits an, dass ein Fehler aufgetreten ist, sodass Sie "error": {error details} nicht mehr angeben müssen, da wir bereits wissen, dass ein Fehler aufgetreten ist. Die Fehlerliste kann einfach zum Stammobjekt werden:

[
    {
        "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"
    }
]

Alles, was jetzt im Körper übrig bleibt, ist einfach eine Liste von Fehlern.

Der Statuscode wird im Antwortheader angegeben.
Die Details sind im Antworttext angegeben.

3
Tim Castelijns

Ich habe kürzlich gegen eine Rest-API gearbeitet, die mehrere Warnungen oder Fehler in den Ergebnissen zurückgibt. Ausgehend von Beispiel 2 würde ich es wie folgt ändern:

{
  "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\""
           }
      }
  }

Auf diese Weise können Sie Ergebnisse mit mehreren Warnungen oder Fehlern bereitstellen, die in Ihrer Antwort benötigt werden.

Und ja, das hat zwar einiges an Aufblähen in der Struktur, bietet aber auch eine einfache Oberfläche, über die Entwickler ihre Daten immer wieder in derselben Struktur abrufen können.

Ich würde auch die folgenden Elemente entfernen, wie IMHO sie in den API-Dokumenten sein sollten (wie Hilfe unter Verwendung eines Fehlercodes zu finden ist), anstatt bei jedem Fehler:

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

In diesem Sinne bin ich mir nicht sicher, ob Sie sowohl die Nachricht als auch developer_message benötigen. Sie scheinen redundant zu sein und als ob Sie versuchen, Benutzerfehlermeldungen von der API bereitzustellen, wenn der Aufrufer die Daten nicht korrekt bereitstellen konnte.

1
Martin Noreke

Zunächst hätten Sie den Kunden die Dokumentation der Rest-API-Methoden zur Verfügung gestellt. Daher wird vom Kunden/Entwickler erwartet, dass er gültige Daten für die Parameter bereitstellt.

Nun, nachdem wir gesagt haben, dass # 1 der beste Weg ist, um die Rest API zu machen. Die Verantwortung eines Entwicklers besteht darin, die Servernutzung so weit wie möglich zu reduzieren. Wenn Sie also auf einen schwerwiegenden Fehler stoßen, erstellen Sie eine Antwort mit dem entsprechenden Fehlercode und der entsprechenden Fehlermeldung und geben Sie diese zurück.

Darüber hinaus können wir nicht sicher sein, dass es nach dem aufgetretenen Fehler weitere gibt. Es macht also keinen Sinn, den Rest der Daten zu analysieren. Es wird im schlimmsten Fall nicht gut funktionieren.

0
Kamal Kannan