Fejlhåndtering

I denne artikel:


Attention   

 

Introduktion

Når der opstår fejl, svarer API'et med detaljeret information omkring hvad der gik galt, samt hvilken del af forespørgslen der forårsagede fejlen. Et fejl-response kan høre under en af følgende to kategorier: Interne fejl og valideringsfejl.

Uanset typen af fejl, vil svaret altid være struktureret på samme måde, og indeholde en message som beskriver fejlen, samt en category som beskriver fejltypen, og en locations entry som beskriver hvilket sted i forespørgslen fejlen opstod. Ligeledes suppleres med path, som viser stien til forespørgslen eller mutationen i den pågældende forespørgsel som skabte fejlen –dette kan være nyttigt hvis flere forespørgsler eller mutationer er samlet i én forespørgsel.

 

Fejl under afvikling af mutationer

Hvis der opstår fejl under en mutation, annulleres alle ændringer som udføres af den pågældende request. Derfor vil, uanset grunden til fejlen, alle data forblive uændret, som hvis mutationen slet ikke var blevet eksekveret. Dette sikrer integriteten af dine data, og gør systemets aktuelle tilstand gennemskuelig på alle tidspunkter.

 

Interne fejl

Opstår en serverfejl, vil du blive præsenteret for en fejl i stil med denne:

{
  "errors": [
    {
      "message": "Internal server error",
      "category": "internal",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "orders"
      ]
    }
  ],
  "data": []
}

 

Valideringsfejl

Når en forespørgsel eller mutation, som tager input udføres, valideres det suplerede input for at sikre gyldigheden af de supplerede data, for ideelt set at gøre det umuligt, sætte din løsning i en ugyldig eller korrumperet tilstand. Hvis dit input anses for at være ugyldigt, vil content feltet af resultatet være null, og detaljer omkring valideringsfejlen være suppleret i errors feltet.

Alle fejl i et hvert errors felt af et payload implementerer ClientErrorInterface interfacet:


    interface ClientErrorInterface {
        field: [String!]!
        message: String!
        name: String!
    }
    

Typer der implementerer dette interface grupperes efter forretningsdomæne, så relaterede forespørgsler og mutationer bruger den samme konkrete fejltype. Dette demonstreres i følgende eksempel med PageTreeClientError som den konkrete type.

Hvert af disse felter uddybes nærmere i de følgende eksempler.

Eksempel: Oprettelse af en side

I dette eksempel forsøger vi at oprette en ny side.

Vores GraphQL forespørgsel ser således ud:

 

QUERY


            
    mutation pageCreate($input: PageCreateInput!) {
      pageCreate(input: $input) {
        content {
          id
        }
        errors {
          field
          message
          name
          code
          id
        }
      }
    }
    

VARIABLES


            
    {
        "input": {
            "folderId": 1,
            "parentId": 1,
            "languageLayerAccess": [
                1,
                2
            ],
            "menuDisplaySettings": [
                1
            ],
            "translations": [
                {
                    "languageId": 1,
                    "data": {
                        "link": "pageLink1"
                    }
                },
                {
                    "languageId": 2,
                    "data": {
                        "title": "pageTitle2"
                    }
                }
            ],
            "type": "TEXT",
            "userAccessSettings": [
                1
            ]
        }
    }
    

Response


        
    {
        "data": {
            "content": null,
            "errors": [
                {
                    "field": [
                        "input",
                        "folderId"
                    ],
                    "message": "Unexpected 'folderId'. Expected exactly one of: ['folderId', 'parentId'].",
                    "name": "EXCLUSIVE_OR_UNEXPECTED_ERROR",
                    "code": "EXCLUSIVE_OR_UNEXPECTED_ERROR",
                    "id": "EXCLUSIVE_OR_UNEXPECTED_ERROR"
                },
                {
                    "field": [
                        "input",
                        "parentId"
                    ],
                    "message": "Unexpected 'parentId'. Expected exactly one of: ['folderId', 'parentId'].",
                    "name": "EXCLUSIVE_OR_UNEXPECTED_ERROR",
                    "code": "EXCLUSIVE_OR_UNEXPECTED_ERROR",
                    "id": "EXCLUSIVE_OR_UNEXPECTED_ERROR"
                },
                {
                    "field": [
                        "input",
                        "parentId"
                    ],
                    "message": "Page with id '123' does not exist.",
                    "name": "ENTITY_NOT_FOUND_ERROR",
                    "code": "ENTITY_NOT_FOUND_ERROR",
                    "id": "ENTITY_NOT_FOUND_ERROR"
                },
                {
                    "field": [
                        "input",
                        "translations"
                    ],
                    "message": "Missing required 'title' in primary language: 1",
                    "name": "MISSING_PRIMARY_TITLE_ERROR",
                    "code": "MISSING_PRIMARY_TITLE_ERROR",
                    "id": "MISSING_PRIMARY_TITLE_ERROR"
                }
            ]
        }
    }
    

Dette betyder således, at vores input overtræder 4 forskellige (men ikke unikke) begrænsninger:

  1. input.folderId: Der forventes nøjagtigt ét af folderId og parentId felterne.
  2. input.parentId: Der forventes nøjagtigt ét af folderId og parentId felterne.
  3. input.parentId: Det angivne ID 123 referer ikke til en eksisterende side.
  4. input.translations: Vi supplerede ikke en title oversættelse til det primære sprog, i dette tilfælde sproget med ID 1.

Følgende bør noteres i denne sammenhæng:

Mens 4 begrænsninger for inputtet blev overtrådt, så blev både (2) og (3) associeret med det samme felt i inputtet, og to af overtrædelserne skyldes den samme begrænsning, men på to forskellige felter. Endelig, mens fraværet af en "titel" til oversættelsen af det primære sprog kunne have haft sit felt opført som "input.translations.0", var dette ikke tilfældet; dette er sådan, selvom der ikke gives oversættelser til primær-sproget, for at sammenhængen med overtrædelsen stadigt er gennemskuelig.

Hvad dette ligeledes demonstrerer er, at typen PageTreeClientError inkluderer yderligere to felter som ikke er til stede i ClientErrorInterface: name og id.

Den fulde definition af PageTreeClientError er:


    interface ClientErrorInterface {
        field: [String!]!
        message: String!
        name: String!
    }
    

id-feltet indeholder en unik maskinlæsbar identifikator for fejltypen. I øjeblikket vil dette have den samme værdi som feltet name i mange tilfælde, dog vil dette være et UUID i fremtiden.

code-feltet indeholder fejlkoden for fejl af denne type og er en optælling, der giver udviklere mulighed for at inspicere skemaet og vide nøjagtigt, hvilke fejl der kan forventes fra en given forespørgsel eller mutation.

Selvom det kan synes overflødigt at have både name og code felterne, er begrundelsen bag dette, at have en tekstversion af code feltet tillader API-klienter at skrive generelle fragmenterede selects, såsom:


    fragment ClientErrorFields on ClientErrorInterface {
      field
      message
      name
    }
    

Dette kan derefter benyttes til at forenkle ovenstående pageCreate mutation:


    mutation pageCreate($input: PageCreateInput!) {
      pageCreate(input: $input) {
        content {
          id
        }
        errors {
          ...ClientErrorFields
          code
          id
        }
      }
    }

    fragment ClientErrorFields on ClientErrorInterface {
      field
      message
      name
    }
    

 

Valideringsfejl (udfaset)

En anden type fejl, der kan opstå, er en valideringsfejl. Dette sker, hvis nogle af de leverede data er ugyldige. Følgende eksempel demonstrerer dette ved at forsøge at oprette en side inde i en mappe, der ikke findes:

POST {your_shop}.mywebshop.io/api/graphql


mutation {
  pageCreate(input: {folderId: 123, type: text}) {
    id
  }
}

Response


{
  "errors": [
    {
      "message": "The given data was invalid.",
      "category": "graphql",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "pageCreate"
      ],
      "validation": {
        "input.folderId": [
          "validation.exists"
        ]
      }
    }
  ],
  "data": []
}

I tilfælde af valideringsfejl indeholder errors delen af responset ligeledes et validation afsnit, der enumererer alle valideringsfejl, indekseret af stien til de ugyldige data i inputtet.